web-dev-qa-db-ja.com

Dateオブジェクトを使用するコンポーネントは、異なるタイムゾーンで異なるスナップショットを作成します

Enzyme with enzyme-to-json to Jest スナップショットテストReactコンポーネント。現在の範囲(たとえば_5/20/2016 - 7/18/2016_)で表示フィールドをレンダリングするDateRangeコンポーネントと、DateInput値を選択できる2つのDateコンポーネントの浅いスナップショットをテストしています。これは、スナップショットにDateプロパティとテキスト表現でコンポーネントに渡すDateInputsが含まれていることを意味します。テストでは、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}
_

日付からタイムゾーンオフセットを削除しようとしましたが、スナップショットの表示フィールド値が異なり、ローカルのタイムゾーン依存の表現が使用されています。

_- value={5/20/2016 - 7/18/2016}
+ value={5/19/2016 - 7/17/2016}
_

テストを実行するタイムゾーンに関係なく、スナップショットで同じDatesを生成するにはどうすればよいですか?

35
hon2a

私はこれに数時間/数日間苦労しましたが、これだけが私のために働きました:

1)テストで:

Date.now = jest.fn(() => new Date(Date.UTC(2017, 7, 9, 8)).valueOf())

2)次に、テストを実行する前にTZ env varを変更します。だから私のpackage.jsonのスクリプト:

  • MacおよびLinuxのみ

    "test": "TZ=America/New_York react-scripts test --env=jsdom",
    
  • Windows

    "test": "set TZ=America/New_York && react-scripts test --env=jsdom",
    
55
morgs32

最終的に、2つの部分で構成されるソリューションになりました。

  1. タイムゾーンに依存した方法で、テストでDateオブジェクトを作成しないでください。読み取り可能なテストコードを得るためにタイムスタンプを直接使用したくない場合は、_Date.UTC_を使用します。

    _new Date(Date.UTC(1995, 4, 23))
    _
  2. Datesを表示値に変換するために使用される日付フォーマッターをモックし、タイムゾーンに依存しない表現を返します。 Date::toISOString()を使用します。 幸いなことに、私のローカリゼーションモジュールでformatDate関数をモックする必要があるので、これは私の場合は簡単でした。コンポーネントが何らかの形でDatesをそれ自体で文字列に変換している場合は、より困難になる可能性があります。

上記のソリューションに到達する前に、スナップショットの作成方法を何らかの方法で変更しようとしました。酵素とjsonがtoISOString()のローカルコピーを保存するためItいので、__.cloneDeepWith_を使用してすべてのDatesを変更する必要がありました。テストにはタイムスタンプからのDate作成のケース(コンポーネントは上記で説明したものよりもかなり複雑です)とそれらと作成中の日付との相互作用が含まれていたため、とにかくうまくいきませんでしたテストで明示的に。そのため、最初にすべての日付定義が同じタイムゾーンを参照し、残りが続くことを確認する必要がありました。


更新(11/3/2017):最近_enzyme-to-json_をチェックしたとき、toISOString()のローカル保存を見つけることができなかったので、それはもはや問題ではなく、m笑される可能性があります。私も歴史でそれを見つけることができなかったので、たぶん、どのライブラリがそれをやったかを間違って指摘しただけかもしれません。あなた自身の危険でテストしてください:)

4
hon2a

toLocaleString(または使用しているtoStringメソッド)プロトタイプをモックすることで、これを回避することになりました。 sinonを使用して:

var toLocaleString;

beforeAll(() => {
    toLocaleString = sinon.stub(Date.prototype, 'toLocaleString', () => 'fake time')
})

afterAll(() => {
    toLocaleString.restore()
})

この方法でDateオブジェクトから文字列を直接生成している場合でも大丈夫です。

1
Matt