64 lines
1.7 KiB
TypeScript
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);
|
||
|
}
|
||
|
}
|