npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

webrtc-mock

v1.2.3

Published

Classes and functions mock webrtc api for tests

Readme

webrtc-mock

npm npm bundle size

Mock WebRTC / Media Capture APIs for unit and integration tests in Node.js (and browser-like test environments).

The library replaces navigator.mediaDevices and MediaStream with controllable mocks, so you can test camera/mic flows, device enumeration, constraints, and error scenarios without real hardware.

Features

  • Mock navigator.mediaDevices (getUserMedia, getDisplayMedia, enumerateDevices, devicechange)
  • Mock MediaStream / MediaStreamTrack with events (addtrack, removetrack, ended, mute, …)
  • Simulate device availability, permissions, busy devices, and not-found errors
  • Configurable track capabilities (width / height)
  • Helpers for canvas / AudioContext-like tracks and stream snapshots for assertions
  • Dual package: ESM + CJS, TypeScript types included

Install

npm install webrtc-mock
yarn add webrtc-mock

Peer dependencies: events-constructor, @types/dom-mediacapture-transform.

Quick start

Jest / Vitest setup file

Install mocks once globally (typical setupTests.ts / setupFilesAfterEnv):

import { doMock } from 'webrtc-mock';

// Ensure navigator exists in Node test environments
// @ts-expect-error — Node may not declare navigator
global.navigator ??= {};

doMock();

After that, media APIs are available on global:

const stream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true,
});

const devices = await navigator.mediaDevices.enumerateDevices();

doMock() sets:

| Global | Default | | ---------------------------------------------------------------------------- | -------------------------------------- | | MediaStream | MediaStreamMock | | navigator.mediaDevices | MediaDevicesMock instance | | COUNT_DEVICES_AVAILABLE | 1 video / 1 audioinput / 1 audiooutput | | DEVICES_USER_NOT_ACCESS | all false | | DEVICES_BUSY / DEVICES_NOT_FOUND / DEVICES_PERMISSION_DENIED_BY_SYSTEM | empty |

Usage examples

Create a call media stream in beforeEach

Common pattern for VoIP / peer-connection tests: build a stream with exact device ids and pass it into the API under test.

import { createMediaStreamMock } from 'webrtc-mock';

let mediaStream: MediaStream;

beforeEach(() => {
  mediaStream = createMediaStreamMock({
    audio: { deviceId: { exact: 'audioDeviceId' } },
    video: { deviceId: { exact: 'videoDeviceId' } },
  });
});

it('passes audio then video to the peer connection', async () => {
  const peerConnection = await call({ number: '10000', mediaStream });

  expect(peerConnection.getSenders()[0]?.track?.kind).toBe('audio');
  expect(peerConnection.getSenders()[1]?.track?.kind).toBe('video');
  expect(mediaStream.getAudioTracks()).toHaveLength(1);
  expect(mediaStream.getVideoTracks()).toHaveLength(1);
});

Extract a single presentation / content video track

When you need only a video track (screen share, presentation, content stream):

import { createMediaStreamMock } from 'webrtc-mock';

const videoTrack = createMediaStreamMock({
  video: { deviceId: { exact: 'videoDeviceId' } },
}).getVideoTracks()[0] as MediaStreamVideoTrack;

await startPresentation(videoTrack);

Audio-only or video-only streams work the same way — omit the unused constraint key:

const audioOnly = createMediaStreamMock({
  audio: { deviceId: { exact: 'audioDeviceId' } },
});

const videoOnly = createMediaStreamMock({
  video: { deviceId: { exact: 'videoDeviceId' } },
});

Build a multi-track stream with constructors

Useful for store / user-media unit tests where tracks are assigned individually:

import { MediaStreamMock, MediaStreamTrackMock } from 'webrtc-mock';

const cameraTrack = new MediaStreamTrackMock('video');
const avatarTrack = new MediaStreamTrackMock('video');
const micTrack = new MediaStreamTrackMock('audio');

const mediaStream = new MediaStreamMock([cameraTrack, avatarTrack, micTrack]);

userMediaStore.videoTrack.setTrack(mediaStream.getVideoTracks()[0]);

expect(getVideoTrackForPresentation()).toBeDefined();
expect(getVideoTrackForPresentation()).not.toBe(userMediaStore.videoTrackReal);

Video track with fixed resolution constraints

import { createVideoMediaStreamTrackMock } from 'webrtc-mock';

const videoTrack = createVideoMediaStreamTrackMock({
  constraints: { width: 1920, height: 1080 },
}) as MediaStreamVideoTrack;

expect(videoTrack.getSettings()).toMatchObject({
  width: 1920,
  height: 1080,
});

Dynamic getSettings() (resolution changes in tests)

Override getSettings when the code under test reacts to resolution changes (for example a video sending balancer / track monitor):

import { createVideoMediaStreamTrackMock } from 'webrtc-mock';

const createMockTrack = (initialWidth: number) => {
  let width = initialWidth;

  const track = createVideoMediaStreamTrackMock({
    constraints: { width, height: 480 },
  });

  Object.defineProperty(track, 'getSettings', {
    value: jest.fn(() => {
      return { width, height: 480 };
    }),
  });

  const setWidth = (newWidth: number) => {
    width = newWidth;
  };

  return { track, setWidth };
};

const { track, setWidth } = createMockTrack(640);

expect(track.getSettings().width).toBe(640);

setWidth(320);
expect(track.getSettings().width).toBe(320);

Compose tracks into a custom stream

import {
  createAudioMediaStreamTrackMock,
  createVideoMediaStreamTrackMock,
  MediaStreamMock,
} from 'webrtc-mock';

const videoTrack = createVideoMediaStreamTrackMock({
  id: 'cam-1',
  constraints: { width: { ideal: 1280 }, height: { ideal: 720 } },
});

const stream = new MediaStreamMock([videoTrack, createAudioMediaStreamTrackMock({ id: 'mic-1' })]);

Canvas / AudioContext-like streams

import {
  getCanvasMediaStreamMock,
  getAudioContextMediaStreamMock,
  createMediaStreamMock,
} from 'webrtc-mock';

const canvasStream = await getCanvasMediaStreamMock();
const audioContextStream = await getAudioContextMediaStreamMock();

const mixed = createMediaStreamMock({}, { fromCanvas: true, fromAudioContext: true });

Simulate device errors and access restrictions

After doMock(), navigator.mediaDevices exposes helpers for test scenarios:

const { mediaDevices } = navigator;

// Change how many devices enumerateDevices() returns (fires devicechange)
mediaDevices.setCountVideoDevicesAvailable(2);
mediaDevices.setCountAudioInDevicesAvailable(0);

// Deny permission / access
mediaDevices.setUserNotAccessVideo(true);
mediaDevices.setUserNotAccessAudioIn(true);
mediaDevices.setUserNotAccessAll(true);

// Per-device failure modes for getUserMedia
mediaDevices.setBusyVideoDevice('videoinputDeviceId'); // NotReadableError
mediaDevices.setNotFoundVideoDevice('videoinputDeviceId'); // NotFoundError
mediaDevices.setPermissionDeniedBySystem('videoinputDeviceId');

// Reset restrictions
mediaDevices.unsetBusyVideoDevice('videoinputDeviceId');
mediaDevices.unsetAllRestrictions();

Track capabilities

import {
  setCapabilities,
  setMaxWidthCapabilities,
  setMaxHeightCapabilities,
  resetCapabilities,
} from 'webrtc-mock';

setMaxWidthCapabilities(1920);
setMaxHeightCapabilities(1080);

setCapabilities({
  width: { min: 320, max: 1920 },
  height: { min: 240, max: 1080 },
});

resetCapabilities();

Assert on stream shape

import { parseMediaStream, parseMediaStreamWithoutId, parseTracks } from 'webrtc-mock';

const snapshot = parseMediaStream(stream);
const withoutIds = parseMediaStreamWithoutId(stream);
const tracks = parseTracks(stream.getTracks());

Public API

| Export | Description | | ------------------------------------------------------------------------------------------------------ | ------------------------------------------- | | doMock | Install mocks on global / navigator | | MediaStreamMock | MediaStream implementation | | MediaStreamTrackMock | MediaStreamTrack implementation | | createMediaStreamMock | Build a stream from constraints | | createAudioMediaStreamTrackMock / createVideoMediaStreamTrackMock | Track factories | | createCanvasVideoMediaStreamTrackMock / createAudioContextAudioMediaStreamTrackMock | Special track factories | | getCanvasMediaStreamMock / getAudioContextMediaStreamMock | Ready-made streams | | getAvailableDevices / getAvailableDevicesWithResolutions | Device lists (+ resolutions / access flags) | | resolutionsList | CIF, 360p, 720p, 1080p presets | | setCapabilities / resetCapabilities / setMin*Capabilities / setMax*Capabilities | Control getCapabilities() | | parseMediaStream / parseMediaStreamWithoutId / parseTracks / parseObject / resolveParseArray | Helpers for snapshots / comparisons | | MediaStreamUnionTrack, TGlobal | TypeScript types |

Development

yarn install
yarn build   # Vite library build → dist/ (ESM + CJS + .d.ts)
yarn lint    # TypeScript check + ESLint

Published package contents: dist/ only (prepublishOnly runs yarn build).

Maintainer

Krivega Dmitriy

  • Website: https://krivega.com
  • GitHub: @Krivega

Contributing

Issues and feature requests are welcome: GitHub Issues.

License

Copyright © 2021–2026 Krivega Dmitriy.
This project is MIT licensed.