From aa1205e94d68bd6276a999fbc96040d86fd789ea Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Mon, 25 Nov 2024 10:59:34 +0100 Subject: [PATCH] Add extra logging during error --- e2e/src/utils/Actions.ts | 98 ++++++++++++++++++++---------------- e2e/src/utils/PlayerUtils.ts | 10 ++++ 2 files changed, 64 insertions(+), 44 deletions(-) create mode 100644 e2e/src/utils/PlayerUtils.ts diff --git a/e2e/src/utils/Actions.ts b/e2e/src/utils/Actions.ts index 86aa56d21..d3dbc5279 100644 --- a/e2e/src/utils/Actions.ts +++ b/e2e/src/utils/Actions.ts @@ -2,6 +2,7 @@ import { ErrorEvent, type Event, PlayerEventType, SourceDescription, THEOplayer } from 'react-native-theoplayer'; import { getTestPlayer } from '../components/TestableTHEOplayerView'; +import { logPlayerBuffer } from './PlayerUtils'; export interface TestOptions { timeout: number; @@ -66,51 +67,52 @@ export const waitForPlayerEvents = async >( options = defaultTestOptions, ): Promise[]> => { const receivedEvents: Event[] = []; - return withEventTimeOut( - new Promise[]>((resolve, reject) => { - const onError = (err: ErrorEvent) => { - console.error('[waitForPlayerEvents]', err); - player.removeEventListener(PlayerEventType.ERROR, onError); - reject(err); - }; - let eventMap = expectedEvents.map((_expected: Partial) => ({ - event: _expected as Event, - onEvent(receivedEvent: Event) { - if (!eventMap.length) { - // No more events expected - return; + const eventsPromise = new Promise[]>((resolve, reject) => { + const onError = (err: ErrorEvent) => { + console.error('[waitForPlayerEvents]', err); + player.removeEventListener(PlayerEventType.ERROR, onError); + reject(err); + }; + let eventMap = expectedEvents.map((_expected: Partial) => ({ + event: _expected as Event, + onEvent(receivedEvent: Event) { + if (!eventMap.length) { + // No more events expected + return; + } + const expectedEvent = eventMap[0].event; + receivedEvents.push(receivedEvent); + console.debug('[waitForPlayerEvents]', `Received event ${JSON.stringify(receivedEvent.type)} - waiting for ${expectedEvent.type}`); + const index = eventMap.findIndex((e) => propsMatch(e.event, receivedEvent)); + const isExpected = index <= 0; + + // Check order + if (inOrder && eventMap.length && !isExpected) { + const err = `Expected event '${expectedEvent.type}' but received '${receivedEvent.type}'`; + console.error('[waitForPlayerEvents]', err); + reject(err); + } + eventMap = eventMap.filter((entry) => { + if (entry.event.type === expectedEvent.type) { + player.removeEventListener(expectedEvent.type, entry.onEvent); } - const expectedEvent = eventMap[0].event; - receivedEvents.push(receivedEvent); - console.debug('[waitForPlayerEvents]', `Received event ${JSON.stringify(receivedEvent.type)} - waiting for ${expectedEvent.type}`); - const index = eventMap.findIndex((e) => propsMatch(e.event, receivedEvent)); - const isExpected = index <= 0; - - // Check order - if (inOrder && eventMap.length && !isExpected) { - const err = `Expected event '${expectedEvent.type}' but received '${receivedEvent.type}'`; - console.error('[waitForPlayerEvents]', err); - reject(err); - } - eventMap = eventMap.filter((entry) => { - if (entry.event.type === expectedEvent.type) { - player.removeEventListener(expectedEvent.type, entry.onEvent); - } - return entry.event.type !== expectedEvent.type; - }); - if (!eventMap.length) { - // Done - resolve(receivedEvents); - } - }, - })); - player.addEventListener(PlayerEventType.ERROR, onError); - eventMap.forEach(({ event, onEvent }) => player.addEventListener(event.type, onEvent)); - }), - options.timeout, - expectedEvents, - receivedEvents, - ); + return entry.event.type !== expectedEvent.type; + }); + if (!eventMap.length) { + // Done + resolve(receivedEvents); + } + }, + })); + player.addEventListener(PlayerEventType.ERROR, onError); + eventMap.forEach(({ event, onEvent }) => player.addEventListener(event.type, onEvent)); + }); + + // Add rejection on time-out + const timeOutPromise = withEventTimeOut(eventsPromise, options.timeout, expectedEvents, receivedEvents); + + // Add extra logging on error + return withPlayerStateLogOnError(player, timeOutPromise); }; const withEventTimeOut = >( @@ -137,6 +139,14 @@ const withEventTimeOut = >( }); }; +const withPlayerStateLogOnError = async (player: THEOplayer, promise: Promise) => { + try { + return await promise; + } catch (e) { + throw e + ` buffer: ${logPlayerBuffer(player)};` + ` currenTime: ${player.currentTime};` + ` paused: ${player.paused};`; + } +}; + export function expect(actual: any, desc?: string) { const descPrefix = desc ? `${desc}: ` : ''; diff --git a/e2e/src/utils/PlayerUtils.ts b/e2e/src/utils/PlayerUtils.ts new file mode 100644 index 000000000..db4d43cca --- /dev/null +++ b/e2e/src/utils/PlayerUtils.ts @@ -0,0 +1,10 @@ +import { THEOplayer } from 'react-native-theoplayer'; + +export function logPlayerBuffer(player: THEOplayer): string { + let buffer = '[ '; + for (let i = 0; i < player.buffered.length; i++) { + buffer += `${player.buffered[i].start} - ${player.buffered[i].end} ${i === player.buffered.length - 1 ? '' : ', '}`; + } + buffer += ']'; + return buffer; +}