import { Emitter } from "../../../src/api"; import { Logger } from "../../../src/core"; type ResolveFunction = () => void; type RejectFunction = (reason: Error) => void; export interface EmitterSpy extends jasmine.Spy { wait(value?: T): Promise; } export function makeEmitterSpy(emitter: Emitter, logger: Logger): EmitterSpy { let waitingForEmitPromise: Promise | undefined; let waitingForEmitResolve: ResolveFunction | undefined; let waitingForEmitReject: RejectFunction | undefined; let waitingForEmit: T | undefined; const emit = { listener: (value: T): boolean => { const v = String(value); logger.log(`Emitted ${v}`); if (!waitingForEmitResolve) { return false; } if (waitingForEmit !== undefined && waitingForEmit !== value) { return false; } waitingForEmitResolve(); waitingForEmitPromise = undefined; waitingForEmitResolve = undefined; waitingForEmitReject = undefined; waitingForEmit = undefined; return true; } }; const emitTimeout = (): void => { if (waitingForEmitReject) { waitingForEmitReject(new Error("Timed out waiting for emit.")); } waitingForEmitPromise = undefined; waitingForEmitResolve = undefined; waitingForEmitReject = undefined; waitingForEmit = undefined; }; const spy = Object.assign( spyOn(emit, "listener").and.callThrough(), { wait: async (value?: T): Promise => { if (waitingForEmitPromise) { throw new Error("Already waiting for emit."); } waitingForEmitPromise = new Promise((resolve, reject) => { waitingForEmitResolve = resolve; waitingForEmitReject = reject; }); waitingForEmit = value; return waitingForEmitPromise; } } ); emitter.on(emit.listener); return spy; }