import SharedReference from "../../utils/reference"; import type { CancellationSignal } from "../../utils/task_canceller"; import { makeMockedClass } from "../../utils/test-utils"; import type CorePlaybackObserver from "../core_playback_observer"; import type MediaElementPlaybackObserver from "../media_element_playback_observer"; import type { IReadOnlyPlaybackObserver } from "../types"; import type ObservationPosition from "../utils/observation_position"; /** * Construct a class implementing the `MediaElementPlaybackObserver` interface. * @class DummyMediaElementPlaybackObserver */ export const DummyMediaElementPlaybackObserver = makeMockedClass( { attachMediaElement: notImplemented("attachMediaElement"), getCurrentTime: notImplemented("getCurrentTime"), getIsPaused: notImplemented("getIsPaused"), getPendingSeekInformation: notImplemented("getPendingSeekInformation"), getPlaybackRate: notImplemented("getPlaybackRate"), getReadyState: notImplemented("getReadyState"), getReference: notImplemented("getReference"), stop: notImplemented("stop"), blockSeeking: notImplemented("blockSeeking"), unblockSeeking: notImplemented("unblockSeeking"), isSeekingBlocked: notImplemented("isSeekingBlocked"), setCurrentTime: notImplemented("setCurrentTime"), setPlaybackRate: notImplemented("setPlaybackRate"), listen: notImplemented("listen"), deriveReadOnlyObserver: notImplemented("deriveReadOnlyObserver"), }, {}, ); /** * Construct a class implementing the `CorePlaybackObserver` interface. * @class DummyCorePlaybackObserver */ export const DummyCorePlaybackObserver = makeMockedClass( { getCurrentTime: notImplemented("getCurrentTime"), getIsPaused: notImplemented("getIsPaused"), getPlaybackRate: notImplemented("getPlaybackRate"), getReadyState: notImplemented("getReadyState"), getReference: notImplemented("getReference"), setPlaybackRate: notImplemented("setPlaybackRate"), listen: notImplemented("listen"), deriveReadOnlyObserver: notImplemented("deriveReadOnlyObserver"), }, {}, ); /** * Object facilitation the usage of a IReadOnlyPlaybackObserver`. * /!\ Do not forget to call `reset` when done to ensure no memory leak. */ export interface IMockedReadOnlyPlaybackObserver { /** * The `IReadOnlyPlaybackObserver` itself. */ observer: IReadOnlyPlaybackObserver; /** * Allows to trigger new observations through `observer`. */ emit: (data: TObservationData) => void; /** * Reset `observer` to its initial observation, also removing all observation * listener it potentially had. * * Intended to be called between each test to clean-up. */ reset: () => void; } /** * Allows to create any `IReadOnlyPlaybackObserver` with TypeScript typechecking * and to obtain a function to emit new observations. * @param {Object} initialData - The initial observation emitted. * @returns {Object} res * @returns {IReadOnlyPlaybackObserver} res.observer - The * `IReadOnlyPlaybackObserver` instance. * @returns {Function} res.emit - A function allowing to emit new observations. * @returns {Function} res.reset - Reset the playback observer to its initial * state, also removing all its listeners. Call this between tests. */ export function makeReadyOnlyPlaybackObserver( initialData: TObservationData, ): IMockedReadOnlyPlaybackObserver { let ref = new SharedReference(initialData); const ret = { observer: makeObserver(), emit: (data: TObservationData) => { ref.setValue(data); }, reset: () => { ref.finish(); ref = new SharedReference(initialData); }, }; return ret; function makeObserver(): IReadOnlyPlaybackObserver { const klass = makeMockedClass>( { getCurrentTime: notImplemented("getCurrentTime"), getIsPaused: notImplemented("getIsPaused"), getPlaybackRate: notImplemented("getPlaybackRate"), getReadyState: notImplemented("getReadyState"), getReference: () => ref, listen( cb: (observation: TObservationData, stopListening: () => void) => void, params: { includeLastObservation?: boolean | undefined; clearSignal: CancellationSignal; }, ) { if (params.clearSignal.isCancelled()) { return; } ref.onUpdate(cb, { clearSignal: params.clearSignal, emitCurrentValue: params.includeLastObservation, }); }, deriveReadOnlyObserver: notImplemented("deriveReadOnlyObserver"), }, {}, ); return new klass(); } } /** * Construct a class implementing the `ObservationPosition` interface. * @class DummyObservationPosition */ export const DummyObservationPosition = makeMockedClass( { serialize: notImplemented("serialize"), getPolled: notImplemented("getPolled"), getWanted: notImplemented("getWanted"), forceWantedPosition: notImplemented("forceWantedPosition"), isAwaitingFuturePosition: notImplemented("isAwaitingFuturePosition"), }, {}, ); function notImplemented(name: string): () => never { return () => { throw new Error(`${name} not implemented`); }; }