mlpcardgame/src/testing/EventHook.ts

64 lines
1.7 KiB
TypeScript

import EventEmitter from "eventemitter3";
import { withTimeout } from "@/utils";
interface HookedEvent {
date: Date;
arguments: any[];
}
const defaultCmp = () => {};
export class EventHook extends EventEmitter {
public backlog: Record<string, HookedEvent[]> = {};
public hookEmitter(emitter: EventEmitter, event: string, id: string) {
emitter.on(event, this._receivedEmitter.bind(this, id));
}
public expect(
id: string,
timeout: number = 1000,
cmp: (...args: any) => void = defaultCmp
): Promise<void> {
// Build promise
const promise = new Promise<void>((resolve, reject) => {
const getLastEvent = () => {
// Take first element in the backlog
let event = this.backlog[id].shift();
if (!event) {
// Should never happen
return reject(`undefined event in list (??)`);
}
// Send to check function, then resolve
resolve(cmp(...event.arguments));
return;
};
if (this.backlog[id] && this.backlog[id].length > 0) {
// Event is already in the backlog
getLastEvent();
} else {
// If the event hasn't fired yet, subscribe to the next time it will
this.once(id, getLastEvent);
}
});
// Return promise with added timeout
return withTimeout(promise, timeout);
}
// When events are received
private _receivedEmitter(id: string, ...args: any) {
const event: HookedEvent = {
date: new Date(),
arguments: args
};
// Create backlog if it doesn't exist
if (!this.backlog[id]) {
this.backlog[id] = [];
}
// Push to backlog and emit event (for pending expects)
this.backlog[id].push(event);
this.emit(id, event);
}
}