You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。这种方法属于“兜底方案”,可能存在边缘情况,但可以快速解决问题:

  1. 在项目根目录创建一个自定义序列化器文件,比如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"');
  }
};
  1. 在package.json的snapshotSerializers中把自定义序列化器放在原序列化器前面:
"snapshotSerializers": [
  "./jest-serializer-html-fix.js",
  "jest-serializer-html-string"
]

注意事项

  • 优先选择方案一,因为它从渲染源头控制属性输出,逻辑更清晰,不会出现意外的替换问题。
  • 如果是因为依赖版本升级导致的行为变化,建议查看preact-render-to-string的版本更新日志,确认是否有相关的配置项可以全局禁用属性转换。

内容的提问来源于stack exchange,提问作者Muho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 17:42:45