Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest: test Intl.DateTimeFormat

I would like to test a filter function I wrote which return a date formatted using Intl.DateTimeFormat('en-GB', options):

// module "date.js"
export default function (dateISOString) {
    const options = {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        timeZone: 'UTC'
    };
    let d = new Date(dateISOString);
    return new Intl.DateTimeFormat('en-GB', options).format(d);
};

This is my test, using Jest:

import date from '@/filters/date';
describe('date', () => {
    it('should format the date into dd/mm/yyyy', () => {
        expect(date('2014-02-11')).toEqual('11/02/2014');
    });
});

but it fails with:

Expected value to equal:
  "11/02/2014"
Received:
  "02/11/2014"

Is it possible to test (or mock) the Intl API with Jest? It looks like the problem is due to a different behaviour of the Impl API in the browser and in a Node environment.

like image 755
Matteo Piazza Avatar asked Mar 01 '18 15:03

Matteo Piazza


People also ask

Is jest enough for testing?

Despite what many may think, Jest is not just a test runner—it is a complete testing framework that has brought testing to another level. It's powerful but easy to use, so give it a try.

Is jest good for node JS?

This also provides an added advantage to the users in the way that they can add any new features without breaking any other part of their application. For your NodeJS applications, Jest can be used for Unit Testing.

What type of tests are jest?

Jest is a delightful JavaScript Testing Framework with a focus on simplicity. It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!

Is jest a runner test?

Jest is a JavaScript test runner, that is, a JavaScript library for creating, running, and structuring tests. Jest ships as an NPM package, you can install it in any JavaScript project. Jest is one of the most popular test runner these days, and the default choice for React projects.


2 Answers

The only solution that I managed to find to this problem was to install full-icu which seemed to provide the right locales to node during the testing process.

That package is needed because node by default only ships with a limited set of locales, explained here: https://nodejs.org/docs/latest-v9.x/api/intl.html

With that package installed, the additional step that I had to take was to change my test command to use:

"test": "NODE_ICU_DATA=node_modules/full-icu jest --config jest.config.js"

I ran into this problem in a couple of different environments. When running the tests locally on Mac OS and also when running the tests inside a Docker container during CI.

Interestingly, I don't need to use the export when running the tests via WebStorm's Jest integration. It definitely seems like the behaviour of the Intl library is far from stable in node.

like image 120
Steve Vaughan Avatar answered Sep 16 '22 17:09

Steve Vaughan


Just found a solution if you want to change the zone per test.

The benefit here is minimal change to the Intl object since we are just using the normal api to set a default

const timezoneMock = function(zone: string) {
    const DateTimeFormat = Intl.DateTimeFormat
    jest
    .spyOn(global.Intl, 'DateTimeFormat')
    .mockImplementation((locale, options) => new DateTimeFormat(locale, {...options, timeZone: zone}))
  }

  afterEach(() => {
    jest.restoreAllMocks();
  })

and then

  describe('when Europe/London', () => {
    it('returns local time', () => {
      timezoneMock('Europe/London')
   //etc.... 
like image 39
aaronmgdr Avatar answered Sep 18 '22 17:09

aaronmgdr