jest spyOn navigator.mediaDevices
Asked Answered
T

1

1

I am writing a small library at the moment to help with connecting to media devices, it would be nice if I could unit test the library, I have a function in my typescript library that looks like this,

static connectAudioDevice(device?: InputDeviceInfo) : Promise<MediaStream> {
    return new Promise<MediaStream>((resolve, reject) => {
        navigator.mediaDevices.getUserMedia({audio: true})
            .then(stream => {
                resolve(stream);
            })
            .catch(error => {
                resolve(error);
            })
    })
}

I want to use jest.spyOn to mock the getUserMedia is this possible? Something like,

import devices from '@/assets/lib/devices.ts';

test('Resolves with valid audio mediaStream', () => {

    const audioStream = {};
    let promise = devices.connectAudioDevice();

    jest.spyOn(window.navigator.mediaDevices, 'getUserMedia', promise);

})

But I am getting the error:

Cannot spyOn on a primitive value; undefined given

Can anyone offer me some help?

Trishatriskelion answered 2/12, 2020 at 16:22 Comment(0)
I
6

The navigator.mediaDevices is not implemented by JSDOM. So window.navigator.mediaDevices is undefined, that's why you got the error. Take a look at Mocking methods which are not implemented in JSDOM.

The solution is:

device.ts:

export default class Devices {
  public static connectAudioDevice(device?: InputDeviceInfo): Promise<MediaStream> {
    return new Promise<MediaStream>((resolve, reject) => {
      navigator.mediaDevices
        .getUserMedia({ audio: true })
        .then((stream) => {
          resolve(stream);
        })
        .catch((error) => {
          resolve(error);
        });
    });
  }
}

device.test.ts:

import devices from './deivce';

describe('65112057', () => {
  test('Resolves with valid audio mediaStream', async () => {
    const mockMediaDevices = {
      getUserMedia: jest.fn().mockResolvedValueOnce('fake data' as any),
    };
    Object.defineProperty(window.navigator, 'mediaDevices', {
      writable: true,
      value: mockMediaDevices,
    });
    const actual = await devices.connectAudioDevice();
    expect(actual).toBe('fake data');
    expect(mockMediaDevices.getUserMedia).toBeCalledWith({ audio: true });
  });
});

unit test result:


 PASS  src/stackoverflow/65112057/device.test.ts
  65112057
    ✓ Resolves with valid audio mediaStream (7ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |       80 |      100 |       75 |       80 |                   |
 deivce.ts |       80 |      100 |       75 |       80 |                10 |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.994s, estimated 13s
Institutive answered 3/12, 2020 at 5:14 Comment(1)
can you help me with this one. #71737124Scrope

© 2022 - 2024 — McMap. All rights reserved.