@fakes/media-devices
Version:
A interactive fake implementation of MediaDevices interface in the browser for testing
130 lines (129 loc) • 4.67 kB
JavaScript
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,
};