/** * Doubles for the browser capture APIs the recorders rely on, none of which * jsdom implements: `navigator.mediaDevices`, `MediaStream`, `MediaRecorder`, * and the playback methods of `HTMLMediaElement`. * * Shared by the audio and the video recorder specs. The Web Audio doubles * (`AudioContext`, `AudioWorkletNode`, `Worker`) sit in the second half of this * file, behind `installWebAudioHarness`: only `useAudioRecorder` needs them, * but both of its specs do. */ /** A track the component can stop to release the device. */ export declare function fakeTrack(kind?: 'audio' | 'video'): MediaStreamTrack; /** * `MediaStream` has to exist as a constructor, not just as a shape: * narrows with `srcObject instanceof MediaStream` before * resetting it. */ export declare class FakeMediaStream { id: string; private tracks; constructor(tracks?: MediaStreamTrack[]); static created: number; getTracks(): MediaStreamTrack[]; } export type FakeMediaStreamInstance = FakeMediaStream & MediaStream; /** Records what the component asked of it, and lets a test push data back. */ export declare class FakeMediaRecorder { static instances: FakeMediaRecorder[]; /** Mime types rejected by `isTypeSupported`, to exercise the fallbacks. */ static unsupported: string[]; state: 'inactive' | 'recording' | 'paused'; ondataavailable: ((event: { data: Blob; }) => void) | null; onerror: ((event: unknown) => void) | null; readonly stream: MediaStream; readonly mimeType: string; readonly start: import('vitest').Mock<(timeslice?: number) => void>; readonly stop: import('vitest').Mock<() => void>; readonly requestData: import('vitest').Mock<(...args: any[]) => any>; timeslice?: number; constructor(stream: MediaStream, options?: { mimeType?: string; }); static isTypeSupported(type: string): boolean; /** Hands a chunk to the component, as the browser would every timeslice. */ emitData(blob: Blob): void; emitError(event?: unknown): void; } export type MediaHarness = { /** The stream handed over by `getUserMedia`. */ stream: FakeMediaStreamInstance; getUserMedia: ReturnType; enumerateDevices: ReturnType; createObjectURL: ReturnType; revokeObjectURL: ReturnType; /** Every MediaRecorder built since the harness was installed. */ recorders: FakeMediaRecorder[]; /** The recorder currently in use, i.e. the last one built. */ recorder: () => FakeMediaRecorder; }; export declare function videoInput(deviceId: string, label?: string): MediaDeviceInfo; export declare function audioInput(deviceId?: string): MediaDeviceInfo; /** * Installs every double on the global scope. Call from `beforeEach`; the stubs * are torn down by the `restoreMocks`/`unstubGlobals` handling of the runner, * so nothing has to be undone by hand. * * @param devices what `enumerateDevices` should report * @param stream the stream `getUserMedia` should resolve to */ export declare function installMediaHarness({ devices, stream, }?: { devices?: MediaDeviceInfo[]; stream?: FakeMediaStreamInstance; }): MediaHarness; /** * Replaces the playback methods jsdom leaves unimplemented, and makes * `currentTime` writable so the components can rewind their media element. */ export declare function installMediaElementStubs(): void; export declare class FakeAudioWorkletNode { readonly context: FakeAudioContext; readonly processorName: string; static instances: FakeAudioWorkletNode[]; readonly connect: import('vitest').Mock<(...args: any[]) => any>; readonly disconnect: import('vitest').Mock<(...args: any[]) => any>; /** * The `MessagePort` is driven by hand: the hook subscribes with * `addEventListener`, so the listeners are replayed by `emitSamples`. */ readonly port: { addEventListener: import('vitest').Mock<(...args: any[]) => any>; removeEventListener: import('vitest').Mock<(...args: any[]) => any>; close: import('vitest').Mock<(...args: any[]) => any>; start: import('vitest').Mock<(...args: any[]) => any>; postMessage: import('vitest').Mock<(...args: any[]) => any>; }; constructor(context: FakeAudioContext, processorName: string); /** Replays a block of samples, as the AudioWorkletProcessor would. */ emitSamples(inputs: unknown): void; } export declare class FakeAudioContext { static instances: FakeAudioContext[]; /** Replaceable, to exercise the addModule failure path. */ static addModule: import('vitest').Mock<(moduleURL: string) => Promise>; readonly sampleRate: number; /** Writable: the hook reads it to compute the elapsed recording time. */ currentTime: number; readonly destination: { connect: import('vitest').Mock<(...args: any[]) => any>; disconnect: import('vitest').Mock<(...args: any[]) => any>; }; readonly close: import('vitest').Mock<(...args: any[]) => any>; readonly suspend: import('vitest').Mock<(...args: any[]) => any>; readonly resume: import('vitest').Mock<(...args: any[]) => any>; readonly createMediaStreamSource: import('vitest').Mock<() => { connect: import('vitest').Mock<(...args: any[]) => any>; disconnect: import('vitest').Mock<(...args: any[]) => any>; }>; readonly audioWorklet: { addModule: (path: string) => Promise; }; constructor(options?: { sampleRate?: number; }); } export declare class FakeWorker { readonly url: string; static instances: FakeWorker[]; readonly postMessage: import('vitest').Mock<(...args: any[]) => any>; readonly terminate: import('vitest').Mock<(...args: any[]) => any>; onmessage: ((event: { data: unknown; }) => void) | null; constructor(url: string); /** Answers the last `postMessage`, as the encoder worker would. */ emit(data: unknown): void; /** The payload of the last message the hook sent, e.g. ['wav', …]. */ lastMessage(): any; } export type WebAudioHarness = { /** The context opened by the current recording. */ context: () => FakeAudioContext; /** The worklet node processing the current recording. */ workletNode: () => FakeAudioWorkletNode; /** The encoder worker, created once on mount. */ worker: () => FakeWorker; addModule: typeof FakeAudioContext.addModule; }; /** * Installs the Web Audio doubles. Combine with `installMediaHarness`, which * provides `getUserMedia` and the blob URL factory the encoder result needs. */ export declare function installWebAudioHarness(): WebAudioHarness;