升级Chakra2.2.1后matchMedia mock失效致Jest测试报错
问题原因
- Chakra UI 从2.2.0版本开始重构了响应式断点的底层实现,替换为基于
@zag-js/breakpoint的逻辑,新实现不再仅依赖window.matchMedia返回的基础事件方法,初始化时会遍历所有断点对应的媒体查询,找到匹配项后挂载包含断点规则的details对象。旧mock统一给所有查询返回matches: false,导致逻辑遍历完所有断点后找不到任何匹配项,拿不到带details属性的断点实例,最终触发类型错误。 - 2.2之前的版本中,
useBreakpointValue存在隐式降级逻辑,所有断点都不匹配时会自动fallback到base断点的值,新版本移除了这个隐式逻辑,完全依赖matchMedia的实际匹配结果确定激活断点。 - 部分测试用例未在渲染时包裹
ChakraProvider,2.2版本后断点上下文完全依赖Provider注入,缺失Provider时内部断点状态直接为undefined,也会触发同类报错。
修复方案
方案一:使用Chakra官方测试工具(推荐,维护成本最低)
Chakra官方在test-utils中提供了专门适配新版本的断点mock,不需要手动维护matchMedia逻辑,直接在Jest全局配置的setup文件中引入即可:
// jest.setup.js/ts import { mockBreakpoint } from '@chakra-ui/react/test-utils' // 全局默认mock为base断点,所有useBreakpointValue默认返回base对应的值 mockBreakpoint()
如果需要测试特定断点下的渲染逻辑,不需要修改全局mock,直接在对应单测中传入断点名即可:
test('lg断点下渲染桌面端样式', () => { mockBreakpoint('lg') // 渲染组件、断言逻辑 })
方案二:修正自定义matchMedia mock
如果不想引入官方测试工具,可以调整原有mock逻辑,同时补全测试用例的必要包裹:
- 所有使用
useBreakpointValue的组件,测试渲染时必须包裹ChakraProvider,保证断点上下文能正常注入:
import { render } from '@testing-library/react' import { ChakraProvider } from '@chakra-ui/react' import TargetComponent from './TargetComponent' test('组件正常渲染', () => { render( <ChakraProvider> <TargetComponent /> </ChakraProvider> ) // 后续断言 })
- 替换原有matchMedia mock,调整匹配逻辑保证base断点默认命中:
// 替换jest.setup中旧的matchMedia mock代码 Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockImplementation(query => { // Chakra默认base断点对应min-width: 0px,默认返回匹配状态 const matchBase = query === '(min-width: 0px)' return { matches: matchBase, media: query, onchange: null, addListener: jest.fn(), removeListener: jest.fn(), addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), } }), })
如果需要测试其他断点的渲染结果,在对应单测中修改mock的返回规则,让目标断点对应的媒体查询返回matches: true即可。
注意:如果项目中自定义了Chakra主题的breakpoint配置,需要同步调整mock中的媒体查询判断规则,否则会出现断点匹配不符合预期的问题。
内容的提问来源于stack exchange,提问作者Joel
相关产品推荐
相关产品推荐

