React-Resizable 测试驱动开发:Jest单元测试与快照测试
【免费下载链接】react-resizableA simple React component that is resizable with a handle.项目地址: https://gitcode.com/gh_mirrors/re/react-resizable
React-Resizable 是一个简单的 React 组件,允许用户通过拖动手柄调整元素大小。本文将深入探讨如何使用 Jest 和 React Testing Library 为 React-Resizable 组件构建全面的测试套件,包括单元测试和快照测试,确保组件在各种场景下的可靠性和稳定性。
测试环境搭建
React-Resizable 项目采用 Jest 作为测试运行器,配合 React Testing Library 进行组件测试。项目的测试文件主要集中在__tests__目录下,包括Resizable.test.js和ResizableBox.test.js两个核心测试文件。
要开始测试,首先需要克隆项目仓库:
git clone https://gitcode.com/gh_mirrors/re/react-resizable cd react-resizable npm install npm test单元测试策略
React-Resizable 的单元测试覆盖了组件的各种功能和边界情况,主要包括以下几个方面:
组件渲染测试
基础渲染测试确保组件能够正确渲染并应用指定的属性。例如,在Resizable.test.js中,测试验证组件是否正确应用了className属性,并渲染了指定的子元素:
test('with correct props', () => { const {container} = render(<Resizable {...props}>{resizableBoxChildren}</Resizable>); // 检查类名和子元素是否存在 expect(container.querySelector('.test-classname')).toBeInTheDocument(); expect(container.querySelector('.test-classname .children')).toBeInTheDocument(); });调整手柄测试
调整手柄是 Resizable 组件的核心功能,测试覆盖了不同类型手柄的渲染和交互:
- 默认手柄:验证东南(se)和东(e)等默认手柄的渲染
- 自定义手柄:测试通过函数或组件自定义手柄的场景
- 手柄数量:确保渲染的手柄数量与配置一致
test('renders all specified handles', () => { const allHandles = ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw']; const {container} = render( <Resizable {...props} resizeHandles={allHandles}> {resizableBoxChildren} </Resizable> ); allHandles.forEach(handle => { expect(container.querySelector(`.react-resizable-handle-${handle}`)).toBeInTheDocument(); }); });尺寸约束测试
测试验证组件是否遵守最小和最大尺寸约束:
test('minConstraints prevents sizing below minimum', () => { // 尝试将尺寸调整到小于最小值 seHandler(mockEvent, { node, deltaX: -40, deltaY: -40 }); // 验证尺寸被约束在最小值 expect(props.onResize).toHaveBeenLastCalledWith( mockEvent, expect.objectContaining({ size: { width: 30, // 被约束到最小值 height: 30, // 被约束到最小值 }, }) ); });轴向限制测试
测试验证组件在不同轴向设置下的行为:
axis="x":只允许水平调整axis="y":只允许垂直调整axis="none":完全禁用调整
test('axis="x" only allows horizontal resizing', () => { // 尝试同时调整宽度和高度 seHandler(mockEvent, { node, deltaX: 10, deltaY: 20 }); // 验证只有宽度变化,高度保持不变 expect(props.onResize).toHaveBeenLastCalledWith( mockEvent, expect.objectContaining({ size: { width: 60, // 变化 height: 50, // 不变 }, }) ); });快照测试实践
快照测试是确保 UI 一致性的有效方法,React-Resizable 项目广泛使用快照测试来捕获组件的渲染状态。
基础快照测试
在Resizable.test.js和ResizableBox.test.js中,都包含了基础快照测试:
test('snapshot default props', () => { const {container} = render(<Resizable {...props}>{resizableBoxChildren}</Resizable>); expect(container.firstChild).toMatchSnapshot(); });快照文件存储在__tests__/__snapshots__目录下,如Resizable.test.js.snap和ResizableBox.test.js.snap。
快照更新策略
当组件的预期外观发生变化时,需要更新快照:
npm test -- -u这将更新所有过时的快照,确保测试与最新的组件渲染结果保持一致。
事件处理测试
React-Resizable 组件提供了丰富的事件回调,测试确保这些回调被正确触发并传递预期参数:
调整事件测试
测试验证onResize、onResizeStart和onResizeStop回调的触发:
test('onResizeStop reports correct size', () => { // 模拟调整开始 startHandler(mockEvent, { node, deltaX: 0, deltaY: 0 }); // 模拟拖动调整 dragHandler(mockEvent, { node, deltaX: 10, deltaY: 10 }); // 模拟调整停止 stopHandler(mockEvent, { node, deltaX: 0, deltaY: 0 }); // 验证 onResizeStop 被调用并传递正确的尺寸 expect(onResizeStop).toHaveBeenCalledWith( mockEvent, expect.objectContaining({ size: { width: 60, height: 60 }, handle: 'se', }) ); });事件持久化测试
测试确保事件对象在需要时被正确持久化:
test('calls event.persist when available', () => { const mockEvent = { persist: jest.fn() }; startHandler(mockEvent, { node, deltaX: 0, deltaY: 0 }); expect(mockEvent.persist).toHaveBeenCalled(); });高级测试场景
缩放变换测试
当组件应用了 CSS 变换(如缩放)时,测试确保调整行为仍然正确:
test('use of < 1 transformScale', () => { render( <Resizable {...customProps} transformScale={0.5} ref={resizableRef}> {resizableBoxChildren} </Resizable> ); // 验证缩放变换下的尺寸计算 expect(props.onResize).toHaveBeenLastCalledWith( mockEvent, expect.objectContaining({ size: { height: 30, // 缩放后计算的正确高度 width: 40, // 缩放后计算的正确宽度 }, }) ); });宽高比锁定测试
测试验证当锁定宽高比时,组件是否保持正确的比例:
test('lockAspectRatio preserves aspect ratio', () => { render( <Resizable {...customProps} lockAspectRatio={true} ref={resizableRef}> {resizableBoxChildren} </Resizable> ); // 尝试非等比例调整 seHandler(mockEvent, { node, deltaX: 10, deltaY: 5 }); // 验证尺寸保持等比例 expect(props.onResize).toHaveBeenLastCalledWith( mockEvent, expect.objectContaining({ size: { height: 60, // 取较大的变化值 width: 60, // 取较大的变化值 }, }) ); });测试最佳实践
测试组织
React-Resizable 的测试采用清晰的层次结构,使用describe块组织相关测试,使测试套件易于维护:
describe('render Resizable', () => { describe('Handles', () => { test('with handle function', () => { ... }); test('with handle component', () => { ... }); }); describe('axis restrictions', () => { test('axis="x" only allows horizontal resizing', () => { ... }); test('axis="y" only allows vertical resizing', () => { ... }); }); // 更多测试组... });模拟与清理
每个测试前都会清理模拟函数,确保测试之间的独立性:
beforeEach(() => { jest.clearAllMocks(); });真实 DOM 交互
使用 React Testing Library 的render和act确保测试模拟真实用户交互:
act(() => { boxRef.current.onResize(fakeEvent, data); });总结
通过 Jest 和 React Testing Library,React-Resizable 项目构建了全面的测试套件,覆盖了组件的各种功能和边界情况。单元测试确保了组件的核心功能正常工作,而快照测试则保障了 UI 的一致性。这种测试驱动的开发方式不仅提高了代码质量,也为后续维护和扩展提供了信心。
无论是处理调整手柄、尺寸约束,还是处理各种事件回调,完善的测试 coverage 确保了 React-Resizable 组件在各种使用场景下的可靠性和稳定性。对于希望为自己的 React 组件构建测试套件的开发者来说,React-Resizable 的测试策略提供了一个优秀的参考范例。
【免费下载链接】react-resizableA simple React component that is resizable with a handle.项目地址: https://gitcode.com/gh_mirrors/re/react-resizable
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考