How can I mock the JavaScript window object using Jest? How can I mock the JavaScript window object using Jest? javascript javascript

How can I mock the JavaScript window object using Jest?


The following method worked for me. This approach allowed me to test some code that should work both in the browser and in Node.js, as it allowed me to set window to undefined.

This was with Jest 24.8 (I believe):

let windowSpy;beforeEach(() => {  windowSpy = jest.spyOn(window, "window", "get");});afterEach(() => {  windowSpy.mockRestore();});it('should return https://example.com', () => {  windowSpy.mockImplementation(() => ({    location: {      origin: "https://example.com"    }  }));  expect(window.location.origin).toEqual("https://example.com");});it('should be undefined.', () => {  windowSpy.mockImplementation(() => undefined);  expect(window).toBeUndefined();});


Instead of window use global

it('correct url is called', () => {  global.open = jest.fn();  statementService.openStatementsReport(111);  expect(global.open).toBeCalled();});

you could also try

const open = jest.fn()Object.defineProperty(window, 'open', open);


There are a couple of ways to mock globals in Jest:

  1. Use the mockImplementation approach (the most Jest-like way), but it will work only for those variables which has some default implementation provided by jsdom. window.open is one of them:

    test('it works', () => {  // Setup  const mockedOpen = jest.fn();  // Without making a copy, you will have a circular dependency problem  const originalWindow = { ...window };  const windowSpy = jest.spyOn(global, "window", "get");  windowSpy.mockImplementation(() => ({    ...originalWindow, // In case you need other window properties to be in place    open: mockedOpen  }));  // Tests  statementService.openStatementsReport(111)  expect(mockedOpen).toBeCalled();  // Cleanup  windowSpy.mockRestore();});
  2. Assign the value directly to the global property. It is the most straightforward, but it may trigger error messages for some window variables, e.g. window.href.

    test('it works', () => {  // Setup  const mockedOpen = jest.fn();  const originalOpen = window.open;  window.open = mockedOpen;  // Tests  statementService.openStatementsReport(111)  expect(mockedOpen).toBeCalled();  // Cleanup  window.open = originalOpen;});
  3. Don't use globals directly (requires a bit of refactoring)

    Instead of using the global value directly, it might be cleaner to import it from another file, so mocking will became trivial with Jest.

File ./test.js

jest.mock('./fileWithGlobalValueExported.js');import { windowOpen } from './fileWithGlobalValueExported.js';import { statementService } from './testedFile.js';// Teststest('it works', () => {  statementService.openStatementsReport(111)  expect(windowOpen).toBeCalled();});

File ./fileWithGlobalValueExported.js

export const windowOpen = window.open;

File ./testedFile.js

import { windowOpen } from './fileWithGlobalValueExported.js';export const statementService = {  openStatementsReport(contactIds) {    windowOpen(`a_url_${contactIds}`);  }}