Search code examples
typescriptunit-testingjestjsnavigatorts-jest

How to mock window.navigator.language in jest 27


I've got a function like

export function formatDate(date: string){
    return new Intl.DateTimeFormat(navigator.language).format(new Date(date))
}

I'm attempting to write a unit test in vanilla jest (not using jsdom library), but as you can see I need to be able to mock window.navigator.language.

I've so far tried,

test('UK date format', () => {
  Object.defineProperty(window.navigator, 'language', {value: 'en-GB', configurable: true})
  expect(window.navigator.language).toBe('en-GB')
})

but I cannot for the life of my understand how you're supposed to mock window.navigator in jest.

Ideally I'd like to be able to mock a new value for window.navigator.language on each test. So I could have a test for en-US, fr etc etc

Any help to understand how you're supposed to mock this would be greatly appreciated.


Solution

  • You can mock window.navigator.language using Jest as follows:

    let windowSpy: jest.SpyInstance;;
    
    beforeEach(() => {
        // Spy on the read-only window function which
        // returns a reference to the current window.
        windowSpy = jest.spyOn(window, 'window', 'get');
    });
    
    // Clean-up the spy after every test
    afterEach(() => windowSpy.mockRestore());
    
    const setMockLanguage = (language: string) =>
        // Set how you want window.navigator.language to behave
        windowSpy.mockImplementation(() => ({
            navigator: {
                language
            }
        }));
    
    test('UK date format', () => {
        setMockLanguage('en-GB');
    
        expect(window.navigator.language).toBe('en-GB');
    });
    
    test('US date format', () => {
        setMockLanguage('en-US');
    
        expect(window.navigator.language).toBe('en-US');
    });
    

    I've included some comments in the code to help.

    You can see it working here.