// @ts-nocheck import * as Context from './context'; type FunctionPropertyNames = { [K in Exclude]: T[K] extends ( ...args: Array ) => any ? K : never; }[Exclude]; export interface SpyHandle> extends jest.SpiedFunction { original: T[M]; waitForCall: ( matching?: (args: Parameters, ret: ReturnType) => boolean, ) => Promise; } export interface SpyContextManager< T extends {}, M extends FunctionPropertyNames, > { [Context.enter]: () => SpyHandle; [Context.exit]: (spy: SpyHandle) => void; } export function spyContext>( object: T, method: M, ): SpyContextManager { return { [Context.enter]: () => { const spy: jest.SpiedFunction = jest.spyOn(object, method); return Object.assign(spy, { original: object[method], waitForCall, }); }, [Context.exit]: spy => spy.mockRestore(), }; } function waitForCall>( this: SpyHandle, matching?: (args: Parameters, ret: ReturnType) => boolean, ): Promise { return new Promise(resolve => { this.mockImplementationOnce((...args) => { const result = this.original(...args); if (!matching || matching(args, result)) { resolve(); } return result; }); }); }