rx-player
Version:
Canal+ HTML5 Video Player
176 lines (156 loc) • 4.86 kB
text/typescript
import { afterEach, describe, expect, it, vi } from "vitest";
import type { IManifestMetadata } from "../../../../manifest";
import type {
IPlaybackObservation,
IReadOnlyPlaybackObserver,
} from "../../../../playback_observer";
import { SeekingState } from "../../../../playback_observer";
import SharedReference from "../../../../utils/reference";
import type { CancellationSignal } from "../../../../utils/task_canceller";
import TaskCanceller from "../../../../utils/task_canceller";
import StreamEventsEmitter from "../stream_events_emitter/stream_events_emitter";
describe("init - StreamEventsEmitter", () => {
afterEach(() => {
vi.useRealTimers();
});
it("should not send skipped events for positions crossed while the media is not ready", () => {
vi.useFakeTimers();
const observationRef = new SharedReference(generateObservation(4));
const playbackObserver = createPlaybackObserver(observationRef);
const streamEventsEmitter = new StreamEventsEmitter(playbackObserver);
const skippedEvents: unknown[] = [];
const regularEvents: unknown[] = [];
const stopCanceller = new TaskCanceller("test");
streamEventsEmitter.addEventListener(
"event",
(evt) => {
regularEvents.push(evt);
},
stopCanceller.signal,
);
streamEventsEmitter.addEventListener(
"eventSkip",
(evt) => {
skippedEvents.push(evt);
},
stopCanceller.signal,
);
streamEventsEmitter.start(generateManifest());
streamEventsEmitter.pause();
observationRef.setValue(generateObservation(9));
vi.advanceTimersByTime(200);
streamEventsEmitter.resume();
observationRef.setValue(generateObservation(9.1));
vi.advanceTimersByTime(200);
expect(regularEvents).toHaveLength(0);
expect(skippedEvents).toHaveLength(0);
streamEventsEmitter.stop("test end");
stopCanceller.cancel("test end");
});
it("should compare from the current position immediately after resuming", () => {
vi.useFakeTimers();
const observationRef = new SharedReference(generateObservation(4));
const playbackObserver = createPlaybackObserver(observationRef);
const streamEventsEmitter = new StreamEventsEmitter(playbackObserver);
const regularEvents: unknown[] = [];
const stopCanceller = new TaskCanceller("test");
streamEventsEmitter.addEventListener(
"event",
(evt) => {
regularEvents.push(evt);
},
stopCanceller.signal,
);
streamEventsEmitter.start(generateManifest());
streamEventsEmitter.pause();
observationRef.setValue(generateObservation(4.5));
streamEventsEmitter.resume();
observationRef.setValue(generateObservation(8.5));
vi.advanceTimersByTime(200);
expect(regularEvents).toHaveLength(1);
streamEventsEmitter.stop("test end");
stopCanceller.cancel("test end");
});
});
function createPlaybackObserver(
observationRef: SharedReference<IPlaybackObservation>,
): IReadOnlyPlaybackObserver<IPlaybackObservation> {
return {
getCurrentTime() {
return observationRef.getValue().position.getPolled();
},
getPlaybackRate() {
return 1;
},
getReadyState() {
return 4;
},
getIsPaused() {
return false;
},
getReference() {
return observationRef;
},
listen(
cb: (observation: IPlaybackObservation, stopListening: () => void) => void,
options: {
includeLastObservation?: boolean | undefined;
clearSignal: CancellationSignal;
},
) {
observationRef.onUpdate(cb, {
clearSignal: options.clearSignal,
emitCurrentValue: options.includeLastObservation,
});
},
deriveReadOnlyObserver() {
throw new Error("unused in this test");
},
};
}
function generateManifest(): IManifestMetadata {
return {
periods: [
{
start: 0,
streamEvents: [
{
start: 5,
end: 8,
id: "evt",
data: {
type: "dash-event-stream",
value: {
schemeIdUri: "urn:test",
timescale: 1,
xmlData: { data: "<Event />", namespaces: [] },
},
},
},
],
},
],
} as unknown as IManifestMetadata;
}
function generateObservation(currentTime: number): IPlaybackObservation {
return {
event: "timeupdate",
seeking: SeekingState.None,
rebuffering: null,
freezing: null,
duration: 100,
ended: false,
paused: false,
playbackRate: 1,
readyState: 4,
bufferGap: 10,
fullyLoaded: false,
currentRange: { start: 0, end: 20 },
buffered: {} as TimeRanges,
position: {
getPolled() {
return currentTime;
},
} as IPlaybackObservation["position"],
};
}