import { Observable } from 'rxjs'; import { AddObservableSpyMethods, AddPromiseSpyMethods, Func, AddAccessorsSpies, CreateSyncAutoSpy, CreateObservableAutoSpy, CreatePromiseAutoSpy, } from '@hirez_io/auto-spies-core'; export type Spy = AddJestAutoSpies & AddAccessorsSpies; type AddJestAutoSpies = { [Key in keyof ClassToSpyOn /* if it's a method */]: ClassToSpyOn[Key] extends Func ? AddSpyMethodsByReturnTypes : // if it's a property of type Observable ClassToSpyOn[Key] extends Observable ? ClassToSpyOn[Key] & AddObservableSpyMethods : // If not a method or an observable, leave as is ClassToSpyOn[Key]; }; // Wrap the return type of the given function type with the appropriate spy methods export type AddSpyMethodsByReturnTypes = Method & (Method extends (...args: any[]) => infer ReturnType ? // returns a Promise ReturnType extends Promise ? CreatePromiseAutoSpy< jest.MockedFunction, AddPromiseSpyMethods, Method > : // returns an Observable ReturnType extends Observable ? CreateObservableAutoSpy< jest.MockedFunction, AddObservableSpyMethods, Method > : // for any other type CreateSyncAutoSpy< Method, jest.MockedFunction, AddCalledWithToJestFunctionSpy > : never); export interface AddCalledWithToJestFunctionSpy { calledWith(...args: Parameters): { mockReturnValue: (value: ReturnType) => void; }; mustBeCalledWith(...args: Parameters): { mockReturnValue: (value: ReturnType) => void; }; }