使用Date对象的组件在不同的时区中生成不同的快照

hon*_*n2a 38 javascript reactjs jestjs enzyme

我正在使用-json对我的React组件进行Jest快照测试.我正在测试DateRange组件的浅快照,该组件呈现具有当前范围的显示字段(例如5/20/2016 - 7/18/2016)和DateInput允许选择Date值的两个组件.这意味着我的快照包含Date我在DateInput道具中传递给组件的s 以及它自己解析的文本表示.在我的测试中,我正在使用创建一些固定日期new Date(1995, 4, 23).

当我在不同时区运行测试时,会生成不同的快照,因为Date(year, month, ...)构造函数会在本地时区创建日期.例如,使用new Date()在我的本地时区和CI服务器上的运行之间产生快照差异.

- value={1995-05-22T22:00:00.000Z}
+ value={1995-05-23T00:00:00.000Z}
Run Code Online (Sandbox Code Playgroud)

我尝试从日期中删除时区偏移量,但随后快照在显示字段值中不同,其中使用了与本地时区相关的表示.

- value={5/20/2016 - 7/18/2016}
+ value={5/19/2016 - 7/17/2016}
Run Code Online (Sandbox Code Playgroud)

如何使我的测试Date在快照中生成相同的s,而不管它们运行的​​时区是什么?

mor*_*s32 57

我挣扎了好几个小时/天,只有这对我有用:

1)在你的测试中:

Date.now = jest.fn(() => new Date(Date.UTC(2017, 7, 9, 8)).valueOf())
Run Code Online (Sandbox Code Playgroud)

2)然后TZ在运行测试之前更改env var.所以我的package.json中的脚本:

  • 这个(IMO)应该是公认的答案.具体来说,步骤#2对我来说已经足够了.我刚刚在我的测试脚本声明中添加了一个快速的"TZ"环境变量,它就像一个魅力.我甚至不必模拟任何Date函数. (13认同)
  • 这是我现在使用的整个行“ test”:“ TZ = America / New_York jest”,`。仅此而已。谢谢! (2认同)
  • 指定 `TZ=...` 也对我有用!作为参考,http://www.timezoneconverter.com/cgi-bin/tzc 有一个应该全部有效的时区值列表。 (2认同)
  • 你拯救了我的日子!@Devid 对于所有环境(之前安装跨环境包): `"test": "cross-env TZ=America/New_York && react-scripts test --env=jsdom"` (2认同)

hon*_*n2a 5

我最终得到了一个由两部分组成的解决方案。

  1. Date切勿以与时区相关的方式在测试中创建对象。如果您不想直接使用时间戳来获得可读的测试代码,请使用Date.UTC,例如

    new Date(Date.UTC(1995, 4, 23))
    
    Run Code Online (Sandbox Code Playgroud)
  2. 模拟用于将Dates 转换为显示值的日期格式化程序,以便它返回与时区无关的表示形式,例如 use Date::toISOString()幸运的是,这对我来说很容易,因为我只需要在本地化模块中模拟该函数。formatDate如果组件以某种方式Date自行将 s 转换为字符串,则可能会更困难。

在找到上述解决方案之前,我尝试以某种方式更改快照的创建方式。这很丑陋,因为酶转 json 保存了 的本地副本toISOString(),所以我必须使用_.cloneDeepWith和修改所有Dates。无论如何,它对我来说不起作用,因为我的测试还包含Date从时间戳创建的情况(该组件比我上面描述的要复杂得多)以及这些情况与我在测试中明确创建的日期之间的交互。因此,我首先必须确保所有日期定义都引用相同的时区,其余部分遵循。


更新(11/3/2017):当我enzyme-to-json最近检查时,我无法找到 的本地保存toISOString(),所以也许这不再是问题,并且可以被嘲笑。我也无法在历史中找到它,所以也许我只是错误地指出了哪个图书馆做了它。测试后果自负:)


mig*_*elr 5

我通过使用来做到这一点timezone-mock,它在内部替换了全局Date对象,这是我能找到的最简单的解决方案。

该软件包支持一些测试时区。

import timezoneMock from 'timezone-mock';

describe('when in PT timezone', () => {
  beforeAll(() => {
    timezoneMock.register('US/Pacific');
  });

  afterAll(() => {
    timezoneMock.unregister();
  });

  // ...
Run Code Online (Sandbox Code Playgroud)

https://www.npmjs.com/package/timezone-mock