Skip to content

Instantly share code, notes, and snippets.

@bbshih
Forked from lededje/gist:44aeddf1dc2a5e6064e3b29dc35a7a2d
Last active February 22, 2023 18:27
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bbshih/1cac2e30e5884102a66a07fbe464b50c to your computer and use it in GitHub Desktop.
Save bbshih/1cac2e30e5884102a66a07fbe464b50c to your computer and use it in GitHub Desktop.
Jest Mocking Moment to same time zone for tests
// To mock globally in all your tests, add to setupTestFrameworkScriptFile in config:
// https://facebook.github.io/jest/docs/en/configuration.html#setuptestframeworkscriptfile-string
jest.mock('moment', () => {
const moment = require.requireActual('moment-timezone');
moment.tz.setDefault('America/Los_Angeles'); // Whatever timezone you want
return moment;
});
@dandigangi
Copy link

dandigangi commented Dec 19, 2017

Do you have more info on how to add this to your setupTestFrameworkScriptFile?

We're using the built-in located in the node_modules folder for Jest referenced by our Jest config file. cc @RDP07

Is it just adding a JS file to this like so in our Jest config?

"setupFiles": [
      "<rootDir>/config/enzyme.js",
      "<rootDir>/config/testing/moment.js" // <----
    ],

@astrotim
Copy link

"setupFiles": [
  "<rootDir>/config/enzyme.js"
],
"setupTestFrameworkScriptFile": "<rootDir>/config/momentMock.js",

@testacode
Copy link

Hi there! I encounter an issue. I'm getting a TypeError: Cannot read property 'setDefault' of undefined. What I did was just add your snippet to my setupTestFrameworkScriptFile.

@c58
Copy link

c58 commented Mar 22, 2018

@testacode I have the same issue, and this works for me...

const moment = require.requireActual('moment-timezone');
jest.doMock('moment', () => {
  moment.tz.setDefault('Asia/Yekaterinburg');
  return moment;
});

@nol13
Copy link

nol13 commented Mar 22, 2018

@ecbrodie
Copy link

@bbshih this gist is lit!!! Thank you.

@ifiokjr
Copy link

ifiokjr commented Jun 18, 2018

Thanks @c58 your update fixed it for me! It seems when updating to Jest 23 the original method stops working and you have to use doMock.

Anyone know the reason?

@duranmla
Copy link

duranmla commented Sep 6, 2018

I just use it as @c58 says and works perfectly, thank you

@joeheyming
Copy link

I had an issue related to this and wanted to share my problem:
In my jest.config, I had
'^moment': '/node_modules/moment'

But it was too permissive and matched moment-timezone as well. Needless to say, great confusion occurred.
The correct config is and exact match regular expression:
'^moment$': '/node_modules/moment'

Hope this helps others.

@KhalilZaidoun
Copy link

KhalilZaidoun commented Nov 6, 2018

Using jest.doMock instead of jest.mock has helped me.

// To mock globally in all your tests, add to setupTestFrameworkScriptFile in config:
// https://facebook.github.io/jest/docs/en/configuration.html#setuptestframeworkscriptfile-string
jest.doMock('moment', () => {
  const moment = require.requireActual('moment-timezone');
  moment.tz.setDefault('America/Los_Angeles'); // Whatever timezone you want
  return moment;
});

@rosinghal
Copy link

Nice one. Thanks.

@vmakarevich
Copy link

Is it right solution to use separate package for setting timezone? I don't understand from where moment gets timezone, tried to mock Date.prototype.getTimezoneOffset , but looks like moment don't uses it. Also founded that for negative offset tests not fails, only if my offset is more than 0 tests fails.

@valoricDe
Copy link

I had to use require instead of requireActual otherwise I would get moment.tz === undefined

const moment = require('moment-timezone');
jest.doMock('moment', () => {
  moment.tz.setDefault('Asia/Yekaterinburg');
  return moment;
});

@soorajshankar
Copy link

Add the following before describe in your test
const moment = require.requireActual('moment-timezone').tz.setDefault('America/Los_Angeles');

@adica
Copy link

adica commented Jan 6, 2020

If you are using guess to check use current timezone, you also need to mock it:

jest.mock('moment-timezone', () => {
    const momentMock = require.requireActual('moment-timezone');
    momentMock.tz.setDefault('America/Los_Angeles'); // Whatever timezone you want
    momentMock.tz.guess = () => 'America/Los_Angeles'; // Whatever timezone you want
    return momentMock;
});

@a-reda
Copy link

a-reda commented Feb 26, 2020

I noticed that requireActual of module A (in our case moment-timezone) inside the mock of module B (moment) returns an empty object.

jest.mock('moment', () => {
  const moment = require.requireActual('moment-timezone')
  console.log(require.requireActual('moment-timezone')) // logs {}
  console.log(require.requireActual('moment')) // logs the actual moment library 
})

Anybody facing the same problem ?

@dwilhel1
Copy link

@adica - that code worked for me! The only issue I ran into thereafter (removed my manual import of moment-timezone in the spec file) was not being able to call moment() for new dates in my spec file; ended up using a different approach there.

@pimlie
Copy link

pimlie commented Jun 10, 2020

Had the same error as @a-reda, the following code worked for me:

// setup.js
const moment = require('moment-timezone')
moment.tz.setDefault('Antarctica/Vostok') // Whatever timezone you want
jest.setMock('moment', moment)

@jinujj
Copy link

jinujj commented May 13, 2021

This gist was of great help to me. I found another way of mocking the timezone with a fixed value.

jest.mock('moment', () => () => (jest.requireActual('moment-timezone')).tz('2021-01-01T00:00:00.000Z', 'GMT'));

@samatha034
Copy link

samatha034 commented Sep 9, 2021

Hi i tried const moment = require('moment-timezone')
moment.tz.setDefault('Antarctica/Vostok') // Whatever timezone you want
jest.setMock('moment', moment)
it is giving me original user's time zone not the mocked one
any one please help me

export class DateTzPipe implements PipeTransform {
transform(x: any) {
const y = moment.tz(x, 'America/Panama').format();
const errorDate = new Date(y);
const timeZoneString = moment.tz.guess() === 'Pacific/Port_Moresby' ? 'CHST' : moment.tz(moment.tz.guess()).format('z');
return (moment.tz(errorDate,moment.tz.guess()).format('MM/DD/YYYY - hh:mm:ss A') + " " + timeZoneString);

}

test:
const moment = require('moment-timezone')
moment.tz.setDefault('America/New_york') // Whatever timezone you want
jest.setMock('moment', moment)
describe('transform', () => {
let datePipe:DateTzPipe;

beforeEach(() => {
  
  datePipe=new DateTzPipe();
});



it('Should transform measures without a strat expression', () => {
      expect(datePipe.transform('2021-09-07T19:23:44.309871')).toBe('09/07/2021 - 08:23:44 PM EDT');
});

@AndrejJurkin
Copy link

If you're still struggling with timezones, try this https://www.npmjs.com/package/timezone-mock it saved my day.

@Pacheco95
Copy link

@pimlie thank you! Your solution works

@stevenirby
Copy link

None of these worked for me. I realized this is simply the wrong approach (depending on what you need).

I ended up doing this instead:

test('test thing', () => {
  jest.useFakeTimers();
  jest.setSystemTime(new Date('2023-01-01'));
  expect(fn).toEqual(thing);
  jest.setSystemTime(new Date());
});

IMHO, it is best to avoid monkey-patching moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment