How do I mock Date.toLocaleDateString in jest?
Asked Answered
D

5

13

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.

Dang answered 15/4, 2020 at 9:6 Comment(0)
C
8

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();
});
Cribbs answered 22/3, 2021 at 16:17 Comment(2)
What if you need to have a mock implementation? I mean, the implementation be depends on the actual date?Dissepiment
I think you could use mockImplementation instead. (jestjs.io/docs/mock-function-api#mockfnmockimplementationfn) The above example would change to jest.spyOn(Date.prototype, 'toLocaleTimeString').mockImplementation(() => { /* Your code to use the current date in constructing the formatted text. */ });Lag
S
2

Can you wrap

new Date(createDate).toLocaleDateString()

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

Scuff answered 15/4, 2020 at 9:28 Comment(2)
can't I just define the function in the same component and just call it from within render? why pass it as a prop from a parent component?Dang
I thought you are unit testing presentational component and the only concern would be 'ensure the value is displayed'.Wendywendye
K
2

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.

Kallick answered 12/12, 2023 at 13:51 Comment(1)
Thanks for this... couldn't quite get it working properly in Vitest but it led me in the right direction which I posted below.Elayne
E
0

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)
        },
    })
})

Elayne answered 7/3 at 5:0 Comment(0)
H
-1

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;
Hermanhermann answered 15/4, 2020 at 9:30 Comment(1)
I get "Method Date.prototype.toLocaleDateString called on incompatible receiver function Date() { [native code] } at Function.toLocaleDateString (<anonymous>)" on running the test.Dang

© 2022 - 2024 — McMap. All rights reserved.