ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

从 Jest 28 升级到 Jest 29:配置迁移与破坏性变更完整指南

从 Jest 28 升级到 Jest 29:配置迁移与破坏性变更完整指南 从 Jest 28 升级到 Jest 29配置迁移与破坏性变更完整指南【免费下载链接】jestDelightful JavaScript Testing.项目地址: https://gitcode.com/gh_mirrors/je/jest本指南基于 jest 仓库中官方升级文档 UpgradingToJest29.md 整理而成面向正在从 Jest 28 升级到 Jest 29 的开发者系统梳理快照格式、jsdom、类型导出与jest.mocked()等破坏性变更的迁移要点。读完本文你将能对照仓库源码逐项理解 v29 变更背后的实现原理并掌握具体的配置文件改写与测试代码重构方案。升级前的兼容性检查Jest 29 官方支持的 Node 版本为14.15、16.10、18.0 及以上。升级前请先确认运行环境满足该要求否则可能出现运行时兼容性问题。如果你是跨多个大版本升级例如从 v27 直接跳到 v29建议先参考 v27 升级到 v28 的迁移指南 完成中间步骤再按本文处理 v28 → v29 的差异。完整的变更列表可查阅仓库根目录的 CHANGELOG.md。快照格式变更新默认值{escapeString: false, printBasicPrototype: false}Jest 29 最大的破坏性变更之一是默认快照格式化选项发生了改变。正如 Jest 28 发布时预告的那样v29 将默认快照格式切换为{escapeString: false, printBasicPrototype: false}这一变更会直接影响既有快照文件的渲染结果导致toMatchSnapshot()、toMatchInlineSnapshot()等断言在首次运行后产生 diff需要jest -u重新生成快照。底层实现证据从当前仓库源码可以看到这一默认值被固化在 jest-config 的默认配置中packages/jest-config/src/Defaults.ts 中定义snapshotFormat: {escapeString: false, printBasicPrototype: false},在配置归一化阶段packages/jest-config/src/normalize.ts用户传入的snapshotFormat会与默认值做浅合并{...DEFAULT_CONFIG.snapshotFormat, ...oldOptions[key]}因此你可以只覆盖其中一个字段另一个字段仍取新默认值。快照状态管理packages/jest-snapshot/src/State.ts会保存该配置并用于序列化其类型定义在 packages/jest-snapshot/src/types.ts 中为OmitPrettyFormatOptions, compareKeys即完整继承 pretty-format 的格式化选项。选项含义选项默认值v28默认值v29效果escapeStringtruefalse字符串中的引号/换行是否被转义输出printBasicPrototypetruefalse是否打印数组与对象的原型信息如Array []、Object {}对应地pretty-format 内部的默认选项仍是escapeString: true、printBasicPrototype: true见 packages/pretty-format/src/index.tsJest 只是在快照场景下通过snapshotFormat显式覆盖为更简洁的渲染方式。如何保留旧的快照行为如果团队暂时不想更新既有快照可以在 jest 配置中显式恢复旧格式// jest.config.js module.exports { testEnvironment: node, snapshotFormat: { escapeString: true, printBasicPrototype: true } };需要提醒的是这只是一个兼容性过渡方案。快照格式的简化不再转义字符串、不再输出Object {}等原型标记让快照文件更紧凑、更易读建议尽快通过jest -u迁移到新格式。jsdom 升级v19 → v20jest-environment-jsdom在 Jest 29 中随附的jsdom从 v19 升级到 v20。对大多数用户而言最值得注意的能力变化是jsdom20原生支持crypto.getRandomValues()。这意味着在 Jest 28 下无法正常工作、需要额外 polyfill 的uuid、nanoid等依赖 Web Crypto 的库在 Jest 29 中可以直接运行。// 在 Jest 29 jest-environment-jsdom 中可直接使用 import {nanoid} from nanoid; test(generates id, () { expect(nanoid()).toEqual(expect.any(String)); });使用注意如果使用jest-environment-jsdom官方文档要求TypeScript 最低版本为 4.5由 jsdom v20 的类型声明决定。升级后应关注 jsdom 自身的破坏性变更。以当前仓库的依赖声明为例packages/jest-environment-jsdom/package.json 已将jsdom提升到^26.1.0说明该项目在后续版本中持续跟进 jsdom 主版本每次大版本升级都可能引入 DOM 行为差异建议升级 Jest 后完整跑一遍涉及 DOM 的测试集。pretty-format移除ConvertAnsi插件Jest 29 从pretty-format包中移除了ConvertAnsi插件用于把 ANSI 转义序列转换为可读标记。在当前仓库的插件目录 packages/pretty-format/src/plugins 中已不再包含该插件与文档所述一致。该能力的替代方案是社区维护的jest-serializer-ansi-escapes快照序列化器。如果你依赖ConvertAnsi来序列化带颜色/控制字符的输出迁移方式为安装jest-serializer-ansi-escapes在 jest 配置的snapshotSerializers中加入该序列化器module.exports { snapshotSerializers: [jest-serializer-ansi-escapes], };jest-mock类型导出变更jest-mock包中Mocked*工具类型的导出发生了重命名与收敛MaybeMockedDeep更名为MockedMaybeMocked更名为MockedShallowMockedClass、MockedFunction、MockedObject只保留深 mockdeep mocked变体不再导出浅层变体。从当前仓库源码 packages/jest-mock/src/index.ts 可以清楚看到这两套类型的分工export type MockedClassT extends ClassLike MockInstance (...args: ConstructorParametersT) MockedInstanceTypeT MockedObjectT; export type MockedFunctionT extends FunctionLike MockInstanceT MockedObjectT; export type MockedObjectT extends object { [K in keyof T]: T[K] extends ClassLike ? MockedClassT[K] : T[K] extends FunctionLike ? MockedFunctionT[K] : T[K] extends object ? MockedObjectT[K] : T[K]; } T; export type MockedT T extends ClassLike ? MockedClassT : T extends FunctionLike ? MockedFunctionT : T extends object ? MockedObjectT : T; export type MockedShallowT /* …浅层 mock 变体… */;可以看到深 mock 类型MockedT会递归地把嵌套的类、函数、对象成员都包装成 mock 实例类型而MockedShallowT只处理顶层成员。因此升级时如果你手动引用了MaybeMockedDeep/MaybeMocked需要做如下替换- import type {MaybeMockedDeep, MaybeMocked} from jest-mock; import type {Mocked, MockedShallow} from jest-mock; - let deep: MaybeMockedDeepFoo; let deep: MockedFoo; - let shallow: MaybeMockedFoo; let shallow: MockedShallowFoo;TypeScript 与jest.mocked()的默认行为变化先决条件显式导入 Jest API本部分涉及的 TypeScript 示例仅在显式导入 Jest API时才按文档方式工作import {expect, jest, test} from jest/globals;如果尚未配置 Jest 的 TypeScript 支持请参考 Getting Started 的 TypeScript 章节该注意事项的原文保存在 website/versioned_docs/version-30.4/_TypeScriptExamplesNote.md。jest.mocked()现在默认深包装类型jest.mocked()助手方法在 v29 中改为默认包装传入对象深层成员的类型。如果你此前以true作为第二个参数调用过它必须删除该参数否则会产生类型错误- const mockedObject jest.mocked(someObject, true); const mockedObject jest.mocked(someObject);如果想要保留旧的浅层 mock 行为则传入{shallow: true}作为第二个参数- const mockedObject jest.mocked(someObject); const mockedObject jest.mocked(someObject, {shallow: true});这一行为在源码中有明确对应mocked()方法提供了重载签名packages/jest-mock/src/index.ts当{shallow: true}时返回MockedShallowT否则返回深层的MockedT。迁移示例以文档 MockFunctionAPI.md 中的官方示例为参考export const song { one: { more: { time: (t: number) { return t; }, }, }, };import {expect, jest, test} from jest/globals; import {song} from ./song; jest.mock(./song); jest.spyOn(console, log); // v29默认深包装song.one.more.time 直接具备 mock 类型 const mockedSong jest.mocked(song); test(deep method is typed correctly, () { mockedSong.one.more.time.mockReturnValue(12); expect(mockedSong.one.more.time(10)).toBe(12); expect(mockedSong.one.more.time.mock.calls).toHaveLength(1); });在上述示例中mockedSong.one.more.time无需任何断言即可直接访问.mockReturnValue与.mock.calls这正是深包装默认开启带来的类型收益。如果你的代码依赖旧的浅层行为只 mock 顶层成员、深层成员保持原类型请显式传入{shallow: true}。迁移检查清单完成 v28 → v29 升级时建议按以下顺序逐项核对Node 版本确认 ≥ 14.15 / 16.10 / 18.0快照格式运行jest -u重新生成快照或在配置中临时恢复snapshotFormat: {escapeString: true, printBasicPrototype: true}作为过渡jsdom 用户确认 TypeScript ≥ 4.5并回归测试依赖 Web Crypto 的库uuid、nanoid等pretty-format 用户若依赖 ANSI 序列化改用jest-serializer-ansi-escapes类型导出将MaybeMockedDeep/MaybeMocked替换为Mocked/MockedShallowjest.mocked()删除true第二参数默认深包装需要旧行为时改为{shallow: true}回归验证全量运行测试与类型检查重点观察快照 diff 和 TS 编译错误。以上每项变更都能在仓库源码中找到对应实现升级过程中如遇具体报错可对照前文给出的源码路径深入排查。【免费下载链接】jestDelightful JavaScript Testing.项目地址: https://gitcode.com/gh_mirrors/je/jest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表