更新:如果您想动态更改 TZ,这不会产生确定性结果,但如果您只需要一个 TZ,它将起作用。它可能是在脚本级别指定的替代方法,但我认为这将是更好的答案。
问题在于,通过在运行时设置 process.env.TZ,它会在常规 Jest 测试运行期间在测试中产生不确定性行为(副作用)。如果您使用连续运行测试的--runInBand,它可能可以工作,但我不会指望它。
我还在 Node 中发现了一个关于动态时区的旧存档问题,它看起来像 dynamically adjusting it won't work in general。
相反,在启动 jest 之前,我可能会得到多个脚本,每个脚本都设置为 TZ。
对于我的用例,我实际上想针对特定的基于日期的边缘情况在不同的时区运行测试。有时用户会遇到基于时区的错误,我们希望在我们的测试套件中轻松解决这一问题。
默认情况下,我们使用此处建议的答案之一运行项目中的所有测试,方法是在 npm 脚本中设置 TZ=UTC(例如 TZ=UTC npm run jest。这会在 UTC 时区下运行所有测试。
然后,我们利用 testEnvironment 配置,该配置可以使用 JSDoc pragma @jest-environment 在测试套件级别设置。使用这个自定义测试环境,我们可以使用像@timezone 这样的“自定义文档块编译指示”来读取套件所需的时区。这可以实现每个测试套件的时区自定义,它不如每个测试理想,但对于我们的目的来说已经足够了。
jsdom-with-timezone.js
const JSDOMEnvironment = require('jest-environment-jsdom');
/**
* Timezone-aware jsdom Jest environment. Supports `@timezone` JSDoc
* pragma within test suites to set timezone.
*
* You'd make another copy of this extending the Node environment,
* if needed for Node server environment-based tests.
*/
module.exports = class TimezoneAwareJSDOMEnvironment extends JSDOMEnvironment
{
constructor(config, context) {
// Allow test suites to change timezone, even if TZ is passed in a script.
// Falls back to existing TZ environment variable or UTC if no timezone is specified.
// IMPORTANT: This must happen before super(config) is called, otherwise
// it doesn't work.
process.env.TZ = context.docblockPragmas.timezone || process.env.TZ || 'UTC';
super(config);
}
};
tz-eastern.test.js
/**
* @timezone America/New_York
*/
describe('timezone: eastern', () => {
it('should be America/New_York timezone', () => {
expect(process.env.TZ).toBe('America/New_York');
expect(new Date().getTimezoneOffset()).toBe(300 /* 5 hours */);
});
});
jest.config.js
module.exports = {
"testEnvironment": "<rootDir>/jsdom-with-timezone.js"
}
将此方法与jest.useFakeTimers('modern'); 和jest.setSystemTime() 一起使用足以进行更强大的日期测试,所以我想我会分享这种方法,让其他人从中受益!由于 pragma 处理是自定义的,因此您可以根据自己的用例以任何您喜欢的方式对其进行自定义。
来源: