3

I wrote some tests in my Create React App application that passed locally but failed in CI due to differences in timezone. So I need a way to set the timezone to UTC for all tests in my application. I tried the suggestions on this question, but they didn't work, likely due to Create React App:

Things that I have tried:

  • changing test script from react-scripts test to TZ=UTC && react-scripts test
  • Adding the following snippet to setupTests.js:
module.exports = async () => {
    process.env.TZ = 'UTC';
};
Keith Murgic
  • 347
  • 4
  • 8
  • `but failed in CI due to differences in timezone` sounds like you wrote bad (brittle) tests. Rather than mucking with the timezone, you should probably fix the tests so they pass independent of timezone. – Adam Jenkins Feb 18 '21 at 13:21
  • @Adam In this case the utility being tested formatted the time based on the user's current timezone. So it makes the most sense to me to have the test say given that the user is in a certain timezone, this utility should return x, which means mocking the timezone somehow. I also could arguably have mocked out the Date.toLocaleString function that relies on timezone, which was an option I considered, but I preferred to write some tests to make sure my code was properly integrated with that method. – Keith Murgic Feb 22 '21 at 13:13
  • Pass the timezone in as an argument and then you can mock it however you want. Set the default value for that argument to be `navigator.language`. – Adam Jenkins Feb 22 '21 at 13:18

3 Answers3

3

It should be "test": "TZ=UTC react-scripts test", (without &&).

Note that it's working only when you run it from the terminal (because I'm running sometimes tests from IDE and then you have to change it separate in IDE tests config).

Alan Wołejko
  • 442
  • 2
  • 5
  • 20
  • Thanks! This worked for me. It would be nicer to have a solution that set the timezone in the test file so that it would work without having to change the test command, but this is good enough for now. – Keith Murgic Feb 22 '21 at 13:19
0

I'll add this as an answer even though one has already been accepted.

All you're trying to do is mock something, as you've pointed out. All you need to do is just make it a little bit easier to mock.

If you had a function like this:

const formatTime = (time) => new Date(time).toLocaleString()

Then just modify it to look like this:

const formatTime = (time, timezone) => new Date(time).toLocaleString(timezone)

and voila! Testing this becomes trivial because now you can just pass in an argument to your function to verify it's functionality. No messing with testing environments or anything. Can't get much easier than testing a pure function.

You don't need to test that toLocaleString uses the default time zone when non is supplied because that's not your code - it's a spec that you are adhering to.

Adam Jenkins
  • 51,445
  • 11
  • 72
  • 100
0

For a cross-platform solution, you can create a .env.test (if not already created) file and add TZ=UTC to the environment variables there.

Andy Garcia
  • 354
  • 4
  • 13