"Jesting with JavaScript: Thou shall be warned, for undefined does

While running my unit tests with jest, I encountered an error:

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

Can anyone provide suggestions on how to properly test the following line using jest?

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

This is what I have in 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');
        });
    });
});

The detailed error message is:

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 attempted to use this code as well:

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

However, this resulted in 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();

Answer №1

Consider making a change to the following code:

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(),
});

In the edited version (v2):

const mockMediaDevices = {
  getUserMedia: () => Promise.resolve({
    getVideoTracks: () => [jest.fn()],
  }),
};

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


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

The reason for this change is that when you destructure the result of getVideoTracks(), you are trying to access an element at the 0 index. However, jest.fn() is not an array and cannot be destructured like this: [videoTrack] = (await ....

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

SignalR blocking axios requests (In a Waiting State)

I am currently developing a project that involves bidding on products in Auctions with real-time updates of the bid price. With potentially thousands or even millions of users worldwide participating in the bidding process. We have implemented SignalR for ...

Master the art of utilizing angular-filter

Encountering some challenges while attempting to utilize angular-filter: The following links have been imported into the HTML file: <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script> <script src=" ...

We are creating a table in JavaScript and mistakenly adding an unnecessary tbody

I am currently utilizing a combination of plain JavaScript and Jquery in order to dynamically generate a table. The issue arises when I attempt to use a for loop to iterate through the data obtained from an Ajax request, as it fails to create new rows. To ...

Expecting function to return an undefined response object

My experience with async/await is limited, but I have used these keywords in a function that retrieves or posts data to a MongoDB database. However, it seems like the await keyword does not wait for the promise to be fulfilled and instead returns an undefi ...

Struggling to make partial updates to a field within my CRUD update function

Currently, I am working on developing a CRUD application using NodeJS and Express to enhance my backend programming skills. The database being used for this project is MongoDB. This particular project serves as a back office for a shop without any frontend ...

Refresh the page twice using ajax/jQuery and setTimeout function

When it comes to Ajax, Java script or CSS, I must confess that I struggle a bit. So please bear with me as I ask for some assistance. I am currently working on a CMS wrapped in Jquery mobile and unable to use meta refresh methods. How can I adjust the code ...

Utilize the sortable script for dynamically loaded items via AJAX

For the drag and drop feature on my website, I am using jQuery sortable. I have a button that displays results with items on the screen. These items can be dragged and dropped into various sections. The issue I'm facing is that if I include the sort ...

Dealing with Error TS2769 in Visual Studio Code when passing props to a custom component in Vue 2 with Typescript

I've encountered an issue with a Vue JS component that involves passing a custom prop. I am utilizing the Vue Options API without utilizing the class component syntax. Whenever I pass ANY prop to my custom component the-header, I receive an error sta ...

What could be causing my React Redux state to not trigger a re-render?

Having trouble with my redux state not triggering a re-render when using a selector. I'm new to react-redux and typescript, and despite following advice online about returning a new object from the reducer, my object is still not re-rendering even tho ...

Crafting an interactive saturation effect for mouseover interactions in a circular design

I'm looking to create a unique hover effect for my images. I have both a desaturated version and a full color version of the same image. My idea is to have mousing over the desaturated image reveal a circle spotlighting the color version underneath, a ...

Using jQuery to update the parent element from within an iframe

Below is a simplified test scenario: a.html <!DOCTYPE html> <html> <body> <input type="text" id="myinput"> <iframe id="frame" src="b.html" style="width:100%;height:100%" frameBorder="0"></iframe> </bod ...

Angular 8: Bridging the gap between two players with a shared singleton service

I've been working on creating a multiplayer Battleships game, and although the basic functionality is there, I'm struggling to connect two players to the same game. Any assistance would be greatly appreciated! My goal is to create a service that ...

displaying an image that has been uploaded inside a div element

Is it possible to display the uploaded image within a red box? Here is the code snippet: http://codepen.io/anon/pen/ZWXmpd <div class="upload-image"> <div class="upload-image-preview"></div> <input type="file" name="file" val ...

Forwarding images from a server to a client using socket.io and node.js

I am encountering an issue where I am trying to receive an image via socket.io in node.js and then forward it to a client (browser). However, the image sent through the message to the browser is not being recognized or displayed. Interestingly, if I save ...

Internet Explorer does not return results when using AJAX during the onchange event (specifically for IE only

My code is functioning correctly on other browsers, however in IE it does not provide any result when I select the dropdown button. Instead, it changes and displays an empty result. This is my AJAX: $("#book").change(function(){ var DOMBULK = $(" ...

What causes the accordion class to activate panels with varying names?

Why are some of my accordions triggering other accordions when they have different names? I've been working on resolving the issue where opening the second accordion in the second, third, or fourth panel closes the second accordion in the first panel ...

Ensure the Image URL is valid before modifying the State in React/Next

This code snippet is written in React/Next.js with styled-components. Hey there, I have a component that displays a blog banner using a background-image. The URL for the image comes from a state variable that currently holds a default image path. const [b ...

Seeking specific parameter in a JSON array using JavaScript: A guide

Currently, I am working on a project that involves retrieving Facebook news feed data using the graph API. Upon receiving the JSON object, I display it on the page. The "Likes" section is presented as an array of JSON objects like this: data.likes: { ...

What is the Vue.js alternative to using appendChild for dynamically inserting new elements or components?

When working with Vue.js, I have successfully created a var app = new Vue({...}); and defined a component Vue.component('mycomponent', .... I am able to use this component by directly adding <mycomponent></mycomponent> in my HTML. How ...

Differences between JSX and creating instances of component classes

Could someone please clarify the distinction between the following two statements? let instance1 = new CustomComponent(); and let instance2 = <CustomComponent /> When checking in the Chrome debugger, I see the following: for instance1 CustomComp ...