0

I using jest for running my unit test but I am getting an error.

TypeError: Cannot read properties of undefined (reading 'getVideoTracks')

Any suggestions on how to test the below line in jest

[videoTrack] = (await navigator.mediaDevices.getUserMedia({video: true})).getVideoTracks();

My unit test file -

import { Track } from './Track';
import { } from '../index';

const mockMediaDevices = {
    getUserMedia: jest.fn()
};

Object.defineProperty(window.navigator, 'mediaDevices', {
    writable: true,
    value: mockMediaDevices,
});

Object.defineProperty(navigator.mediaDevices.getUserMedia, 'getVideoTracks', {
    writable: true,
    value: jest.fn(),
});

describe('Track', () => {
    describe('applyConstraints()', () => {
        let track: Track;
        let videoTrack: MediaStreamTrack;

        beforeEach(async () => {
            [videoTrack] = (await navigator.mediaDevices.getUserMedia({ video: true })).getVideoTracks();
            track = new Track(videoTrack as MediaStreamTrack);
        });

        it('should have applyConstraints method', () => {
            expect(typeof track.applyConstraints).toEqual('function');
        });
    });
});

Detailed Error -

TypeError: Cannot read properties of undefined (reading 'getVideoTracks')

      67 |
      68 |     beforeEach(async () => {
    > 69 |       [videoTrack] = (await navigator.mediaDevices.getUserMedia({video: true})).getVideoTracks();
         |                                                                                 ^
      70 |       track = new Track(videoTrack as MediaStreamTrack);
      71 |     });
      72 |

      at Object.<anonymous> (Media/Track/Track.test.ts:69:81)

I have tried this code -

const mockMediaDevices = {
  getUserMedia: jest.fn().mockReturnValue({ getVideoTracks: jest.fn() })
};
Object.defineProperty(navigator, 'mediaDevices', {
  writable: true,
  value: mockMediaDevices,
});

But this gives an error -

TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))

      73 |
      74 |     beforeEach(async () => {
    > 75 |       [videoTrack] = (await navigator.mediaDevices.getUserMedia({video: true})).getVideoTracks();
Javascript Coder
  • 5,691
  • 8
  • 52
  • 98
  • 1
    `getUserMedia: jest.fn().mockReturnValue({ getVideoTracks: jest.fn() })` – hoangdv Apr 04 '22 at 13:30
  • @hoangdv Thanks for comment, `const mockMediaDevices = { getUserMedia: jest.fn().mockReturnValue({ getVideoTracks: jest.fn() }) }; Object.defineProperty(window.navigator, 'mediaDevices', { writable: true, value: mockMediaDevices, });` I am trying to use this as you suggested, It's giving error - `TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))` – Javascript Coder Apr 04 '22 at 15:06
  • @hoangdv, Anything yo want to point out.. – Javascript Coder Apr 04 '22 at 17:04
  • [This SO question has the answer](https://stackoverflow.com/questions/65112057/jest-spyon-navigator-mediadevices). – Ted Stresen-Reuter Sep 28 '22 at 09:26

1 Answers1

0

Try to mock mediaDevices like this

Object.defineProperty(global.navigator, 'mediaDevices', {
            configurable: true,
            writable: true,
            value: {
                getUserMedia: jest.fn().mockResolvedValueOnce(mockMediaStreamObject),
            },
        });

And for the getUserMedia you can mock function with return value where you can implement your version of getVideoTracks method.

export const mockMediaStreamObject: MediaStream = {
    getVideoTracks(): MediaStreamTrack[] {
        return [];
    },
...
}
Chiril
  • 59
  • 5