Jest快照中htmlFor被转为for:如何保留原属性名?
如何在Jest快照中保留
htmlFor属性而非转为for? 我完全理解你的困扰——之前快照里的htmlFor属性能原样保留,现在却被转成了原生HTML的for,导致快照更新不符合预期。这个问题的根源其实不在jest-serializer-html-string,而是preact-render-to-string在渲染时会自动把Preact的htmlFor属性转换为HTML标准的for属性,大概率是你近期升级了这个库的版本,默认行为发生了变化。
下面给你两种可行的解决方案,优先推荐第一种从源头解决的方式:
方案一:自定义Preact渲染时的属性转换逻辑
直接使用preact-render-to-string的renderToString方法,并通过配置自定义属性转换规则,强制保留htmlFor的属性名:
import { renderToString } from 'preact-render-to-string'; import SomeComponent from './SomeComponent'; it(`renders markup correctly`, () => { const renderedHtml = renderToString(<SomeComponent />, { transformAttrs: (attrName, attrValue) => { // 对htmlFor属性,保留原属性名;其他属性使用默认转换规则 if (attrName === 'htmlFor') { return [attrName, attrValue]; } // 返回undefined会触发默认的属性转换逻辑 return undefined; } }); expect(renderedHtml).toMatchSnapshot(); });
这样渲染出来的HTML字符串会直接保留htmlFor属性,后续jest-serializer-html-string序列化时就会把它写入快照,不会再出现for的情况。
方案二:自定义Jest序列化器(事后替换)
如果你不想修改渲染逻辑,可以创建一个自定义序列化器,把快照里的for属性替换回htmlFor。这种方法属于“兜底方案”,可能存在边缘情况,但可以快速解决问题:
- 在项目根目录创建一个自定义序列化器文件,比如
jest-serializer-html-fix.js:
const baseSerializer = require('jest-serializer-html-string'); module.exports = { // 继承原序列化器的测试逻辑 test(val) { return baseSerializer.test(val); }, // 重写print方法,替换属性名 print(val) { const baseResult = baseSerializer.print(val); // 全局替换for="xxx"为htmlFor="xxx" return baseResult.replace(/for="([^"]+)"/g, 'htmlFor="$1"'); } };
- 在
package.json的snapshotSerializers中把自定义序列化器放在原序列化器前面:
"snapshotSerializers": [ "./jest-serializer-html-fix.js", "jest-serializer-html-string" ]
注意事项
- 优先选择方案一,因为它从渲染源头控制属性输出,逻辑更清晰,不会出现意外的替换问题。
- 如果是因为依赖版本升级导致的行为变化,建议查看
preact-render-to-string的版本更新日志,确认是否有相关的配置项可以全局禁用属性转换。
内容的提问来源于stack exchange,提问作者Muho
相关产品推荐
相关产品推荐

