Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/e2e event testing update #459

Merged
merged 4 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions e2e/src/tests/Ads.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import { TestScope } from 'cavy';
import { AdDescription, AdEventType, PlayerEventType, SourceDescription, AdEvent } from 'react-native-theoplayer';
import hls from '../res/hls.json';
import ads from '../res/ads.json';
import { AdEventType, PlayerEventType, AdEvent } from 'react-native-theoplayer';
import { getTestPlayer } from '../components/TestableTHEOplayerView';
import { waitForPlayerEvents, waitForPlayerEventTypes } from '../utils/Actions';
import { TestSourceDescription, TestSources } from '../utils/SourceUtils';

function extendSourceWithAds(source: SourceDescription, ad: AdDescription): SourceDescription {
return { ...source, ads: [ad] };
}

export default function (spec: TestScope) {
TestSources()
.withAds()
Expand All @@ -26,7 +20,7 @@ export default function (spec: TestScope) {

// Start autoplay
player.autoplay = true;
player.source = extendSourceWithAds(hls[0], ads[0] as AdDescription);
player.source = testSource.source;

// Expect events.
await playEventsPromise;
Expand Down
2 changes: 1 addition & 1 deletion e2e/src/tests/Connector.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default function (spec: TestScope) {
{},
{
customerKey: 'testCustomerKey',
gatewayUrl: 'testGgatewayUrl',
gatewayUrl: 'testGatewayUrl',
},
);
},
Expand Down
2 changes: 1 addition & 1 deletion e2e/src/tests/PresentationMode.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default function (spec: TestScope) {
const inlinePromise = waitForPlayerEvent(player, {
type: PlayerEventType.PRESENTATIONMODE_CHANGE,
presentationMode: PresentationMode.inline,
previousPresentationMode: PresentationMode.inline,
previousPresentationMode: PresentationMode.fullscreen,
} as PresentationModeChangeEvent);
player.presentationMode = PresentationMode.inline;

Expand Down
72 changes: 46 additions & 26 deletions e2e/src/utils/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const waitForPlayerEvent = async <EType extends Event<PlayerEventType>>(
return waitForPlayerEvents(player, [expectedEvent], false, options);
};

let eventListIndex = 0; // increments for every playerEvent list that is evaluated.
export const waitForPlayerEvents = async <EType extends Event<PlayerEventType>>(
player: THEOplayer,
expectedEvents: Partial<EType>[],
Expand All @@ -73,39 +74,58 @@ export const waitForPlayerEvents = async <EType extends Event<PlayerEventType>>(
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;

const TAG: string = `[waitForPlayerEvents] eventList ${eventListIndex}:`;
eventListIndex += 1;

let unReceivedEvents = [...expectedEvents];
const uniqueEventTypes = [...new Set(unReceivedEvents.map((event) => event.type))];
uniqueEventTypes.forEach((eventType) => {
const onEvent = (receivedEvent: Event<PlayerEventType>) => {
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);
if (inOrder && unReceivedEvents.length) {
const expectedEvent = unReceivedEvents[0];
console.debug(TAG, `Handling received event ${JSON.stringify(receivedEvent)}`);
console.debug(TAG, `Was waiting for ${JSON.stringify(expectedEvent)}`);

// Received events must either not be in the expected, or be the first
const index = unReceivedEvents.findIndex((e) => propsMatch(e, receivedEvent));
if (index > 0) {
const err = `Expected '${expectedEvent.type}' event but received '${receivedEvent.type} event'`;
console.error(TAG, err);
reject(err);
} else {
console.debug(TAG, `Received ${receivedEvent.type} event is allowed.`);
}
}
eventMap = eventMap.filter((entry) => {
if (entry.event.type === expectedEvent.type) {
player.removeEventListener(expectedEvent.type, entry.onEvent);

unReceivedEvents = unReceivedEvents.filter((event) => {
// When found, remove the listener
if (propsMatch(event, receivedEvent)) {
console.debug(TAG, ` -> removing: ${JSON.stringify(event)}`);
return false;
}
return entry.event.type !== expectedEvent.type;
// Only keep the unreceived events
console.debug(TAG, ` -> keeping: ${JSON.stringify(event)}`);
return true;
});
if (!eventMap.length) {
// Done

// remove listener if no other unreceived events require it.
if (!unReceivedEvents.find((event) => event.type === receivedEvent.type)) {
console.debug(TAG, `Removing listener for ${receivedEvent.type} from player`);
player.removeEventListener(receivedEvent.type, onEvent);
}

if (!unReceivedEvents.length) {
// Finished
resolve(receivedEvents);
}
},
}));
};

player.addEventListener(eventType as PlayerEventType, onEvent);
console.debug(TAG, `Added listener for ${eventType} to the player`);
});
player.addEventListener(PlayerEventType.ERROR, onError);
eventMap.forEach(({ event, onEvent }) => player.addEventListener(event.type, onEvent));
}),
options.timeout,
expectedEvents,
Expand Down
Loading