Как имитировать навигатор mediaDevices для Jest

У меня есть тест, в котором нужно использовать navigator.mediaDevices, но я не могу заставить корректно работать какие-либо макеты.

Я использую create-react-app.

Вот мой тест:

import getConnectedDevices from "./getConnectedDevices";

describe("getConnectedDevices", () => {
  it("Should work", () => {
    console.log(navigator);              // Navigator {}
    console.log(navigator.mediaDevices); // undefined
  });
});

Я попытался добавить макет, как указано здесь, в документации по шутке

// tests/navigator.mock
Object.defineProperty(window, "navigator", {
  writable: true,
  value: {
    mediaDevices: {
      enumerateDevices: jest.fn(),
    },
  },
});

import "../../tests/navigator.mock"; // <- Mock added

import getConnectedDevices from "./getConnectedDevices";

describe("getConnectedDevices", () => {
  it("Should work", () => {
    console.log(navigator);              // Navigator {}
    console.log(navigator.mediaDevices); // undefined
  });
});

Я также пробовал инициализировать тестовую среду в соответствии с к документам приложения create-реагировать.

// src/setupTests.ts

// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom";

const navigatorMock = {
  mediaDevices: {
    enumerateDevices: jest.fn(),
  },
};

global.navigator = navigatorMock;

Что я делаю не так?


person Karl Taylor    schedule 09.12.2020    source источник


Ответы (2)


Я сделал это в машинописи:

const mockGetUserMedia = jest.fn(async () => {
    return new Promise<void>(resolve => {
        resolve()
    })
})

Object.defineProperty(global.navigator, 'mediaDevices', {
    value: {
        getUserMedia: mockGetUserMedia,
    },
})
person Rodrigo Gonçalves    schedule 26.04.2021

Похоже, поскольку объект navigator уже существует, его невозможно повторно назначить.

Благодаря этому ответу stackoverflow вы имитируете объект внутри navigator и назначаете его существующему объекту навигатора.

// src/setupTests.ts

const mediaDevicesMock = {
  enumerateDevices: jest.fn(),
};

global.navigator.mediaDevices = mediaDevicesMock; // here

Примечание. Это вызовет ошибку TSC Cannot assign to 'mediaDevices' because it is a read-only property.ts(2540). Все еще пытаюсь понять это.

person Karl Taylor    schedule 09.12.2020
comment
Вы можете использовать Object.defineProperty() и не забудьте добавить { writable: true }, если вы собираетесь перезаписать его позже в каком-то тесте. - person futuredayv; 07.05.2021