mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 10:06:15 -08:00
fix(videojs): harden MPEG-TS reset lifecycle
This commit is contained in:
1 parent
7de979a4b1
commit
3dd71d7d05
5 files changed
+72
-3
No files matched your search
@@ -64,6 +64,24 @@ describe('VjsMpegTsSession', () => {
|
||||
expect(mpegTsPlayer.play).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('handles an asynchronous autoplay rejection', () => {
|
||||
const catchRejection = jest.fn();
|
||||
const mpegTsPlayer = createMpegTsPlayer();
|
||||
mpegTsPlayer.play.mockReturnValue({
|
||||
catch: catchRejection,
|
||||
} as unknown as Promise<void>);
|
||||
createPlayerMock.mockReturnValue(mpegTsPlayer);
|
||||
const video = document.createElement('video');
|
||||
const { session } = createSession();
|
||||
|
||||
session.start('https://example.test/live/stream.ts', video);
|
||||
|
||||
expect(catchRejection).toHaveBeenCalledWith(expect.any(Function));
|
||||
expect(
|
||||
catchRejection.mock.calls[0][0](new Error('autoplay blocked'))
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('normalizes VOD duration from seekable and then buffered ranges', async () => {
|
||||
const mpegTsPlayer = createMpegTsPlayer();
|
||||
createPlayerMock.mockReturnValue(mpegTsPlayer);
|
||||
|
||||
@@ -80,7 +80,10 @@ export class VjsMpegTsSession {
|
||||
}
|
||||
engine.on(mpegts.Events.ERROR, this.errorListener);
|
||||
engine.load();
|
||||
void engine.play();
|
||||
const playResult = engine.play();
|
||||
if (playResult) {
|
||||
void playResult.catch(() => undefined);
|
||||
}
|
||||
}
|
||||
|
||||
syncDuration(): void {
|
||||
|
||||
@@ -21,6 +21,18 @@ describe('VjsPlayerResetCoordinator', () => {
|
||||
expect(harness.reset).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('captures the latest engine volume after an asynchronous pause', () => {
|
||||
const harness = createHarness(false, 0.3);
|
||||
const coordinator = createCoordinator(harness);
|
||||
|
||||
coordinator.requestReset();
|
||||
harness.player.volume(0.8);
|
||||
harness.paused = true;
|
||||
coordinator.handlePause();
|
||||
|
||||
expect(coordinator.handlePlayerReset()).toBe(0.8);
|
||||
});
|
||||
|
||||
it('snapshots actual engine volume and suppresses reset-generated changes', () => {
|
||||
const harness = createHarness(true, 0.3);
|
||||
const coordinator = createCoordinator(harness, 0.8);
|
||||
|
||||
@@ -24,7 +24,6 @@ export class VjsPlayerResetCoordinator {
|
||||
}
|
||||
this.requested = true;
|
||||
|
||||
this.captureVolume();
|
||||
try {
|
||||
this.config.player().pause();
|
||||
} catch {
|
||||
@@ -99,6 +98,7 @@ export class VjsPlayerResetCoordinator {
|
||||
return;
|
||||
}
|
||||
|
||||
this.captureVolume();
|
||||
this.requested = false;
|
||||
this.inFlight = true;
|
||||
try {
|
||||
|
||||
@@ -32,6 +32,7 @@ describe('VjsPlayerComponent reset lifecycle', () => {
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
localStorage.removeItem('volume');
|
||||
playerHarness = createVideoJsPlayerHarness();
|
||||
videoJsMock
|
||||
.mockReset()
|
||||
@@ -150,6 +151,34 @@ describe('VjsPlayerComponent reset lifecycle', () => {
|
||||
expect(playerHarness.reset).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('restores a volume input that changes while reset waits for pause', () => {
|
||||
localStorage.setItem('volume', '0.3');
|
||||
fixture.componentRef.setInput('options', {
|
||||
sources: [{ src: 'https://example.test/movie.mp4' }],
|
||||
});
|
||||
fixture.componentRef.setInput('volume', 0.3);
|
||||
fixture.detectChanges();
|
||||
playerHarness.ready();
|
||||
playerHarness.paused = false;
|
||||
playerHarness.pauseCompletesImmediately = false;
|
||||
|
||||
fixture.componentRef.setInput('options', { sources: [] });
|
||||
fixture.detectChanges();
|
||||
fixture.componentRef.setInput('volume', 0.8);
|
||||
fixture.detectChanges();
|
||||
playerHarness.emit('volumechange');
|
||||
|
||||
playerHarness.paused = true;
|
||||
playerHarness.emit('pause');
|
||||
playerHarness.volume(1);
|
||||
playerHarness.emit('volumechange');
|
||||
playerHarness.currentVideo = document.createElement('video');
|
||||
playerHarness.emit('playerreset');
|
||||
|
||||
expect(localStorage.getItem('volume')).toBe('0.8');
|
||||
expect(playerHarness.volume).toHaveBeenLastCalledWith(0.8);
|
||||
});
|
||||
|
||||
it('restores the latest normal source after an already-started reset', () => {
|
||||
fixture.componentRef.setInput('options', {
|
||||
sources: [{ src: 'https://example.test/movie.mp4' }],
|
||||
@@ -259,6 +288,7 @@ describe('VjsPlayerComponent reset lifecycle', () => {
|
||||
|
||||
function createVideoJsPlayerHarness() {
|
||||
const listeners = new Map<string, Set<() => void>>();
|
||||
let volume = 0.5;
|
||||
const harness = {
|
||||
currentVideo: document.createElement('video'),
|
||||
paused: true,
|
||||
@@ -272,6 +302,12 @@ function createVideoJsPlayerHarness() {
|
||||
}),
|
||||
reset: jest.fn(),
|
||||
src: jest.fn(),
|
||||
volume: jest.fn((value?: number) => {
|
||||
if (value !== undefined) {
|
||||
volume = value;
|
||||
}
|
||||
return volume;
|
||||
}),
|
||||
emit(event: string) {
|
||||
for (const listener of listeners.get(event) ?? []) {
|
||||
listener();
|
||||
@@ -300,7 +336,7 @@ function createVideoJsPlayerHarness() {
|
||||
reset: harness.reset,
|
||||
src: harness.src,
|
||||
tech: jest.fn(() => ({ el: () => harness.currentVideo })),
|
||||
volume: jest.fn(() => 0.5),
|
||||
volume: harness.volume,
|
||||
dispose: jest.fn(),
|
||||
qualitySelectorHls: jest.fn(),
|
||||
aspectRatioPanel: jest.fn(),
|
||||
|
||||
Reference in new issue
Block a user