moment: Moment Doesn't work With Jest

Describe the bug When imported into a development setting import moment from 'moment' allows moment to work effectively and does everything I want it to. However when running jest tests that run over the code that calls moment() I get the following error:
“TypeError: moment_1.default is not a function” Strangely, Importing it in this way: import * as moment from 'moment' allows functionality in test but not in production. I have looked all through jest’s issues and this has been a reported issue however the Jest team is confident the issue is on moment’s side.

To Reproduce Steps to reproduce the behaviour:

  1. make a simple function in a react app which calls moment()
  2. add a jest test which will traverse this path.
  3. run the test.
  4. See error

Expected behaviour Moment should be callable in both test and production in the same way.

Desktop (please complete the following information):

  • OS: macOS Mojave
  • Testing: Jest -v 24.8.0

Moment-specific environment moment -v 2.24.0

  • Other libraries in use: TypeScript

Please run the following code in your environment and include the output: console output when moment is imported the way development expects i.e. import moment from ‘moment’

console.log src/resources/timestamping.tsx:4
      Tue Jul 16 2019 10:58:16 GMT-0400 (Eastern Daylight Time)
    console.log src/resources/timestamping.tsx:5
      7/16/2019, 10:58:16 AM
    console.log src/resources/timestamping.tsx:6
      240
TypeError: Cannot read property 'version' of undefined.

console output when moment is imported the way it functions in test i.e. import * as moment from ‘moment’

console.log src/resources/timestamping.tsx:4
      Tue Jul 16 2019 11:02:46 GMT-0400 (Eastern Daylight Time)
    console.log src/resources/timestamping.tsx:5
      7/16/2019, 11:02:46 AM
    console.log src/resources/timestamping.tsx:6
      240
    console.log src/resources/timestamping.tsx:8
      2.24.0

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 8
  • Comments: 15 (2 by maintainers)

Most upvoted comments

after some more searching found the solution here https://github.com/aurelia/skeleton-navigation/issues/606#issuecomment-397051406

need to pass in "esModuleInterop": true under compilerOptions in tsconfig.json

Still having this problem with jest@28.1.0 and moment@2.29.2 I didn’t want to change any source or test files so my solution was to add the following mock to setupFilesAfterEnv file:

jest.mock('moment', () => ({
  default: jest.requireActual('moment')
}))

const moment = require("moment").default || require("moment") is what I came up with, but it only allows use to use moment as a function. // edit

import * as mom from "moment";
const moment = require("moment").default || require("moment");

Fixes angular / jest problem. But it’s still a hack.

This hack worked for me and Eslint is not complaining.

import moment = require("moment");

I’ve found 2 ways to use moment in Jest. ( for the note: I use Angular). I needed to test a component method that uses ‘moment()’. 1)

//    spec.ts file (my testing file)
import moment from 'moment'; 
// import exactly like this, not like   import * as moment from 'moment'.  Otherwise you'll get error "moment is not a function".

beforeEach(() => {
   // Pick any timestamp.  This fix works since moment() uses Date.now() under the hood.
    dateNowSpy = jest.spyOn(Date, 'now').mockImplementation(() => 1487076708000); 
}

afterEach(() => {
    dateNowSpy.mockRestore();
});

it('should call myMethod with moment()', () => {
        const selectSpy = spyOn(myComponent, 'myMethod');
        ... // trigger here the call to myMethod.
        expect(selectSpy).toHaveBeenCalledWith(moment()); // moment() will be called with our mocked date
});

The second option uses npm package MockDate https://www.npmjs.com/package/mockdate Briefly, it’s as follows (apply beforeEach/afterEach yourself)

import moment from 'moment';
import * as MockDate from 'MockDate';

MockDate.set(1434319925275);
expect(selectSpy).toHaveBeenCalledWith(moment());
MockDate.reset();

hmmm… it already seems to be part of the FAQ https://github.com/moment/moment/blob/develop/FAQ.md

I was facing this issue when i was using ts-jest for working with typescript and jest. I ended up using babel for typescript support with jest instead and I don’t face it anymore. Perhaps the ts-jest library may be doing something under the hood

FWIW, I updated my import to use moment-timezone and Jest is happy now:

import moment from 'moment-timezone';

Not sure what the regular moment package is having issues with.

It seems I only get this error when I set esModuleInterop to true… @KonradLinkowski - the hack helped though 😃

blem. But it’s still a hack.

Thank you sir, that helped.