Skip to content

Commit

Permalink
Add extra logging during error
Browse files Browse the repository at this point in the history
  • Loading branch information
tvanlaerhoven committed Nov 25, 2024
1 parent f174edc commit 5ba5b3e
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 44 deletions.
98 changes: 54 additions & 44 deletions e2e/src/utils/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -66,51 +67,52 @@ export const waitForPlayerEvents = async <EType extends Event<PlayerEventType>>(
options = defaultTestOptions,
): Promise<Event<PlayerEventType>[]> => {
const receivedEvents: Event<PlayerEventType>[] = [];
return withEventTimeOut(
new Promise<Event<PlayerEventType>[]>((resolve, reject) => {
const onError = (err: ErrorEvent) => {
console.error('[waitForPlayerEvents]', err);
player.removeEventListener(PlayerEventType.ERROR, onError);
reject(err);
};
let eventMap = expectedEvents.map((_expected: Partial<EType>) => ({
event: _expected as Event<PlayerEventType>,
onEvent(receivedEvent: Event<PlayerEventType>) {
if (!eventMap.length) {
// No more events expected
return;
const eventsPromise = new Promise<Event<PlayerEventType>[]>((resolve, reject) => {
const onError = (err: ErrorEvent) => {
console.error('[waitForPlayerEvents]', err);
player.removeEventListener(PlayerEventType.ERROR, onError);
reject(err);
};
let eventMap = expectedEvents.map((_expected: Partial<EType>) => ({
event: _expected as Event<PlayerEventType>,
onEvent(receivedEvent: Event<PlayerEventType>) {
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 = <EType extends Event<PlayerEventType>>(
Expand All @@ -137,6 +139,14 @@ const withEventTimeOut = <EType extends Event<PlayerEventType>>(
});
};

const withPlayerStateLogOnError = async (player: THEOplayer, promise: Promise<any>) => {
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}: ` : '';

Expand Down
10 changes: 10 additions & 0 deletions e2e/src/utils/PlayerUtils.ts
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit 5ba5b3e

Please sign in to comment.