如何用react-testing-library测试动态导入SVG的Icon组件
解决方案
问题根源
线上环境的打包工具(如Webpack/Vite)已配置SVG转React组件的加载规则,所以require返回合法组件实例;但Jest默认不识别.svg格式的导入,require返回值为undefined,所以始终渲染占位span,该问题和异步加载、ref使用没有任何关系。
具体修复步骤
第一步:安装对应转换工具
如果你的项目用@svgr/webpack处理SVG转组件,安装配套的Jest转换器:
npm install @svgr/jest --save-dev
如果没有使用svgr,可以用通用静态资源stub工具:
npm install jest-transform-stub --save-dev
第二步:修改Jest配置
在jest.config.js或package.json的jest字段中添加SVG转换规则:
- 使用@svgr/jest的配置:
module.exports = { // 保留原有其他配置 transform: { "^.+\\.(js|jsx|ts|tsx)$": "babel-jest", "^.+\\.svg$": "@svgr/jest" } }
- 使用jest-transform-stub的配置:
module.exports = { // 保留原有其他配置 transform: { "^.+\\.(js|jsx|ts|tsx)$": "babel-jest", "^.+\\.svg$": "jest-transform-stub" } }
第三步:简化测试用例
你添加的定时器逻辑完全多余,SVG导入并非异步操作,直接删除定时器相关代码即可:
it('matches snapshot of each icon', () => { const type = 'check'; const { getByTestId } = render(<Icon type={type} />); expect(getByTestId('icon')).toMatchSnapshot(); });
组件优化建议
当前组件里的useState、useEffect逻辑冗余,className可以直接读取props默认值,不需要存入state,简化后组件逻辑更清晰,也不会带来额外的渲染开销:
const Icon: FC<IconProps> = ({ type, onClick, tooltip, className = 'icon' }: IconProps) => { const SVG = require(`../../svg/${type}.svg`).default; const spanClassName = "svg-icon-wrapper"; if (SVG) { const iconEl = <SVG className={className} onClick={onClick} data-testid="icon" />; if (tooltip) { const tooltipDelay: [number, number] = [800, 0]; return ( <Tooltip title={tooltip.title} delay={tooltip.delay ? tooltipDelay : 0}> <i className={spanClassName}>{iconEl}</i> </Tooltip> ); } return iconEl; } return <span className={spanClassName} data-testid="span" />; }; export default Icon;
内容的提问来源于stack exchange,提问作者Tsuina
相关产品推荐
相关产品推荐

