Как обмануть объект окна JavaScript с помощью Jest?

Мне нужно проверить функцию, которая открывает новую вкладку в браузере

  openStatementsReport(contactIds) {
    window.open(`a_url_${contactIds}`);
  }

Я хотел бы высмеять функцию открытия окна, чтобы проверить, правильно ли URL передан в открытую функцию.

Используя Jest, я не знаю, как насмехаться над окном. Я попытался установить window.open с функцией mock, но этот способ не работает. Ниже приведен тестовый пример

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

но это дает мне ошибку

expect(jest.fn())[.not].toBeCalled()

    jest.fn() value must be a mock function or spy.
    Received:
      function: [Function anonymous]

что мне делать с тестовым случаем? любые предложения или намеки приветствуются

Ответ 1

Вместо window используйте global

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

вы также можете попробовать

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

Ответ 2

Мы также можем определить это с помощью global в setupTests

// setupTests.js
global.open = jest.fn()

И назовите это используя global в реальном тесте:

// yourtest.test.js
it('correct url is called', () => {
    statementService.openStatementsReport(111);
    expect(global.open).toBeCalled();
});

Ответ 3

Метод, который работал для меня, был следующим. Этот подход позволил мне протестировать некоторый код, который должен работать как в браузере, так и в Node, так как он позволил мне установить window в undefined.

Это было с Jest 24,8 (я верю):

let windowSpy;

beforeEach(() => {
  windowSpy = jest.spyOn(global, '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();
});

Ответ 4

Вы можете попробовать это:

import * as _Window from "jsdom/lib/jsdom/browser/Window";

window.open = jest.fn().mockImplementationOnce(() => {
    return new _Window({ parsingMode: "html" });
});

it("correct url is called", () => {
    statementService.openStatementsReport(111);
    expect(window.open).toHaveBeenCalled();
});

Ответ 5

В вашем jest config добавьте setupFilesAfterEnv: ["./setupTests.js"], создайте этот файл и добавьте код, который вы хотите запустить перед тестами

//setupTests.js
window.crypto = {
   .....
};

Ссылка: https://jestjs.io/docs/en/configuration#setupfilesafterenv-array

Ответ 6

Если это похоже на проблему местоположения окна в https://github.com/facebook/jest/issues/890, вы можете попробовать [отрегулирован]

delete global.window.open;
global.window = Object.create(window);
global.window.open = jest.fn();