schlingel
schlingel

Reputation: 1694

How do I mock Date.toLocaleDateString in jest?

I have this codepiece in my React component, which renders an HTML in the end:

new Date(createDate).toLocaleDateString()

My local machine and our build machine have different locales set, so the result of this function is not coherent. So as you'd expect, the unit test passes on my machine and fails on build machine, or vice versa.

I want to mock "toLocalDateString" so that it always uses the same locale, say 'en-US', or at least it always returns the same string. Our test framework is jest. How do I achieve this goal?

I tried this in my test.spec.js but it didn't have any effect at all:

Date.prototype.toLocaleDateString = jest.fn().mockReturnValue('2020-04-15')
expect(component).toMatchSnapshot()

I still get the same old toLocalDateString implementation in the snapshot, my mockReturnValue is not taken into account.

Upvotes: 13

Views: 11319

Answers (5)

K3TH3R
K3TH3R

Reputation: 759

I couldn't get Jamund Ferguson's answer to work with Vitest because their .spyOn mechanism seems to be slightly different. However, by adding a new file to my setupFiles with the following code, I was able to get this working properly:

const origDate = Date.prototype.toLocaleDateString

beforeAll(() => {
    // eslint-disable-next-line no-extend-native
    Object.defineProperty(Date.prototype, 'toLocaleDateString', {
        value() {
            return origDate.call(this, 'en-AU')
        },
    })
})

afterAll(() => {
    // eslint-disable-next-line no-extend-native
    Object.defineProperty(Date.prototype, 'toLocaleDateString', {
        value() {
            return origDate.call(this)
        },
    })
})

Upvotes: 0

Jamund Ferguson
Jamund Ferguson

Reputation: 17014

If you want to respond to the current date, but choose an alternative (fixed) locale I found this works pretty well. You can place it in the test file or in the setupTests.js/ts file to apply it:

const origDate = global.Date.prototype.toLocaleDateString;
jest.spyOn(global.Date.prototype, 'toLocaleDateString').mockImplementation(function () { 
  return origDate.call(this, 'en-US');
});

This example will fix all localeDateString output to en-US. Note you have to use function(){} and not ()=>{} because you're relying on this to be set correctly by the caller.

Upvotes: 4

Tarun Kolla
Tarun Kolla

Reputation: 1014

I may be a bit late but hope it helps someone

let mockDate;

beforeAll(() => {
  mockDate = jest.spyOn(Date.prototype, 'toLocaleTimeString').mockReturnValue('2020-04-15');
});

afterAll(() => {
  mockDate.mockRestore();
});

Upvotes: 8

Alperen Turkoz
Alperen Turkoz

Reputation: 29

Would the below code work well for you? I am mocking the date object this way.

const realDateToLocaleDateString = Date.prototype.toLocaleDateString.bind(global.Date);
const toLocaleDateStringStub = jest.fn(() => '2020-04-15');
global.Date.prototype.toLocaleDateString = toLocaleDateStringStub;

const date = new Date();
console.log(date.toLocaleDateString()); // returns 2020-04-15

global.Date.prototype.toLocaleDateString = realDateToLocaleDateString;

Upvotes: -1

Józef Podlecki
Józef Podlecki

Reputation: 11283

Can you wrap

new Date(createDate).toLocaleDateString()

in a function, pass it as prop to component and then mock it?

Upvotes: 2

Related Questions