Skip to content

Commit

Permalink
chore: reduce possible race-conditions when running tests and calling…
Browse files Browse the repository at this point in the history
… player methods
  • Loading branch information
rolandkakonyi committed Dec 7, 2023
1 parent d977d88 commit b97d304
Showing 1 changed file with 22 additions and 13 deletions.
35 changes: 22 additions & 13 deletions integration_test/playertesting/PlayerTestWorld.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default class PlayerTestWorld {
private player_: Player | undefined;
private isFinished_: boolean = false;
private eventListeners: { [key: string]: (event: Event) => void } = {};
private isPlayerInitialized: boolean = false;

static get shared(): PlayerTestWorld {
if (PlayerTestWorld.shared_ === undefined) {
Expand All @@ -42,6 +43,7 @@ export default class PlayerTestWorld {

private set player(player: Player | undefined) {
this.player_ = player;
this.isPlayerInitialized = false;
this.reRender();
}

Expand Down Expand Up @@ -72,10 +74,6 @@ export default class PlayerTestWorld {
player.initialize();
this.player = player;

// Trick to wait for the player to be initialized
// otherwise initial events might be missed
await player.isPlaying();

await fn().finally(() => {
player.destroy();
this.isFinished_ = true;
Expand All @@ -85,7 +83,7 @@ export default class PlayerTestWorld {
};

callPlayer = async <T>(fn: (player: Player) => Promise<T>): Promise<T> => {
return await fn(this.ensurePlayer());
return await fn(await this.ensurePlayer());
};

expectEvent = async <T extends Event>(
Expand All @@ -110,7 +108,7 @@ export default class PlayerTestWorld {
return await this.expectEventCalling<E>(
expectationConvertible,
timeoutSeconds,
() => fn(this.ensurePlayer())
async () => fn(await this.ensurePlayer())
);
};

Expand All @@ -122,7 +120,7 @@ export default class PlayerTestWorld {
return await this.expectEventsCalling(
expectationsConvertible,
timeoutSeconds,
() => fn(this.ensurePlayer())
async () => fn(await this.ensurePlayer())
);
};

Expand All @@ -143,7 +141,8 @@ export default class PlayerTestWorld {
time: number,
timeoutSeconds: number
): Promise<TimeChangedEvent> => {
const currentTime = await this.ensurePlayer().getCurrentTime();
const player = await this.ensurePlayer();
const currentTime = await player.getCurrentTime();
const targetTime = currentTime + time;
return await this.playUntil(targetTime, timeoutSeconds);
};
Expand All @@ -164,13 +163,14 @@ export default class PlayerTestWorld {
);
};

private ensurePlayer = (): Player => {
private ensurePlayer = async (): Promise<Player> => {
if (this.player !== undefined) {
if (this.player.isDestroyed) {
throw new Error(
'Player was destroyed. Did you forget to call "startPlayerTest" again?'
);
}
await this.ensurePlayerInitialized();
return this.player;
}
throw new Error("It seems you forgot to call 'startPlayerTest' first.");
Expand All @@ -186,7 +186,7 @@ export default class PlayerTestWorld {
private expectEventCalling = async <T extends Event>(
expectationConvertible: SingleEventExpectation | EventType,
timeoutSeconds: number,
afterListenerAttached: () => void = () => {}
afterListenerAttached: () => Promise<void> = async () => Promise.resolve()
): Promise<T> => {
let actualExpectation: SingleEventExpectation;
if (expectationConvertible instanceof SingleEventExpectation) {
Expand All @@ -211,7 +211,7 @@ export default class PlayerTestWorld {
reject(new Error(`Expectation was not met: ${actualExpectation}`));
}
}, timeoutSeconds * 1000);
afterListenerAttached();
await afterListenerAttached();
return future.then((event) => {
clearTimeout(timeoutHandle);
removeListener();
Expand All @@ -222,7 +222,7 @@ export default class PlayerTestWorld {
private expectEventsCalling = async (
expectationsConvertible: MultipleEventsExpectation | EventType[],
timeoutSeconds: number,
afterListenerAttached: () => void = () => {}
afterListenerAttached: () => Promise<void> = async () => Promise.resolve()
): Promise<Event[]> => {
let actualExpectation: MultipleEventsExpectation;
if (expectationsConvertible instanceof MultipleEventsExpectation) {
Expand Down Expand Up @@ -259,7 +259,7 @@ export default class PlayerTestWorld {
reject(new Error(`Expectation was not met: ${actualExpectation}`));
}
}, timeoutSeconds * 1000);
afterListenerAttached();
await afterListenerAttached();
return future.then((events) => {
clearTimeout(timeoutHandle);
removeListener();
Expand All @@ -276,4 +276,13 @@ export default class PlayerTestWorld {
delete this.eventListeners[key];
};
};

private ensurePlayerInitialized = async (): Promise<void> => {
if (this.isPlayerInitialized === false) {
// Trick to make sure the player is initialized,
// otherwise method calls might have no effect.
await new Promise((resolve) => setTimeout(resolve, 100));
this.isPlayerInitialized = true;
}
};
}

0 comments on commit b97d304

Please sign in to comment.