UNPKG

@fakes/media-devices

Version:

A interactive fake implementation of MediaDevices interface in the browser for testing

130 lines (129 loc) 4.67 kB
export { anyMicrophone, anyCamera, anyDevice, anySpeaker } from './DeviceMother'; export { RequestedMediaInput } from './UserConsentTracker'; import { MediaDevicesFake } from './MediaDevicesFake'; import { ThrowingNotImplemented } from './not-implemented'; import { OpenMediaTracks } from './OpenMediaTracks'; import { PermissionsFake } from './permissions/PermissionsFake'; import { DefaultReporter, NoopReporter } from './reporter'; import { allConstraintsFalse, existingDevice, noDeviceWithDeviceId, passUndefined, requestedDeviceTypeNotAttached, scenarios as all, } from './Scenarios'; import { UserConsentTracker } from './UserConsentTracker'; export const stillHaveToAskForDeviceAccess = (additional = {}) => { return { microphone: 'prompt', camera: 'prompt', ...additional, }; }; export const allAccessGranted = (additional = {}) => { return { microphone: 'granted', camera: 'granted', ...additional, }; }; export const allAccessDenied = (additional = {}) => { return { microphone: 'denied', camera: 'denied', ...additional, }; }; export const forgeMediaDevices = (initial = {}) => { const camera = initial.camera ?? 'prompt'; const microphone = initial.microphone ?? 'prompt'; const logLevel = initial.logLevel ?? 'off'; const reporter = logLevel === 'off' ? new NoopReporter() : new DefaultReporter(); const notImplemented = new ThrowingNotImplemented(reporter); const context = { notImplemented, reporter, }; const consentTracker = new UserConsentTracker(context, { camera, microphone }); const openMediaTracks = new OpenMediaTracks(); const mediaDevicesFake = new MediaDevicesFake(context, consentTracker, openMediaTracks); const permissionsFake = new PermissionsFake(context, consentTracker); const attachedDevices = initial.attachedDevices ?? []; attachedDevices.forEach((device) => mediaDevicesFake.attach(device)); const _setPermissionFor = (type, state) => { consentTracker.setPermissionFor(type, state); if (state === 'granted') { return; } openMediaTracks.allFor(type).forEach((fake) => { fake.permissionRevoked(); }); }; return new (class { constructor() { this._target = null; this._mediaDevicesBackup = null; this._permissionBackup = null; } get mediaDevices() { return mediaDevicesFake; } get permissions() { return permissionsFake; } installInto(target) { this._target = target; this._mediaDevicesBackup = target.navigator.mediaDevices; this._permissionBackup = target.navigator.permissions; Object.assign(this._target.navigator, { mediaDevices: mediaDevicesFake, permissions: permissionsFake }); } uninstall() { if (this._target === null) { // nothing to restore return; } Object.assign(this._target.navigator, { mediaDevices: this._mediaDevicesBackup, permissions: this._permissionBackup, }); this._target = null; this._mediaDevicesBackup = null; this._permissionBackup = null; } attach(...toAdd) { let array = toAdd; if (toAdd.length === 1) { const singleElement = toAdd[0]; if (Array.isArray(singleElement)) { array = singleElement; } } array.forEach((it) => mediaDevicesFake.attach(it)); } remove(toRemove) { if ('all' === toRemove) { mediaDevicesFake.noDevicesAttached(); return; } mediaDevicesFake.remove(toRemove); } deviceAccessPrompt() { return consentTracker.deviceAccessPrompt(); } setPermissionFor(...permissionSetup) { if (permissionSetup.length === 2) { _setPermissionFor(...permissionSetup); return; } const [{ camera, microphone }] = permissionSetup; if (camera) { _setPermissionFor('camera', camera); } if (microphone) { _setPermissionFor('microphone', microphone); } } })(); }; export const scenarios = { all, passUndefined, existingDevice, allConstraintsFalse, requestedDeviceTypeNotAttached, noDeviceWithDeviceId, };