import { ConstructorFunction, FunctionsOnly, IMocked, OperatorFunction } from './contracts.js'; import { addMatchers } from './matchers.js'; import { defineProperty, defineStaticProperty, setupConstructor, setupFunction, setupProperty, setupStaticFunction, setupStaticProperty, } from './operators.js'; import { createConstructorParameterVerifier, createFunctionParameterVerifier, createFunctionVerifier, } from './verifiers.js'; export class Mock { public static create = never>(): IMocked { addMatchers(); const mocked: IMocked = { constructorCallLookup: {}, functionCallLookup: {}, setterCallLookup: {}, getterCallLookup: {}, staticFunctionCallLookup: {}, staticSetterCallLookup: {}, staticGetterCallLookup: {}, functionReplacementLookup: {}, mock: {} as T, mockConstructor: class MockConstructor {} as C, setup: (...operators: OperatorFunction[]) => { let operatorMocked = mocked; operators.forEach((operator) => (operatorMocked = operator(mocked))); return operatorMocked; }, setupConstructor: () => { setupConstructor()(mocked); return mocked.withConstructor(); }, setupFunction: >(functionName: K, mockFunction?: any) => { setupFunction(functionName, mockFunction)(mocked); return mocked.withFunction(functionName); }, setupProperty: (propertyName: K, value?: T[K]) => { setupProperty(propertyName, value)(mocked); return { getter: mocked.withGetter(propertyName), setter: mocked.withSetter(propertyName) }; }, defineProperty: ( propertyName: K, getter?: () => T[K], setter?: (value: T[K]) => void, ) => { defineProperty(propertyName, getter, setter)(mocked); return { getter: mocked.withGetter(propertyName), setter: mocked.withSetter(propertyName) }; }, setupStaticFunction: >(functionName: K, mockFunction?: any) => { setupStaticFunction(functionName, mockFunction)(mocked); return mocked.withStaticFunction(functionName); }, setupStaticProperty: (propertyName: K, value?: C[K]) => { setupStaticProperty(propertyName, value)(mocked); return { getter: mocked.withStaticGetter(propertyName), setter: mocked.withStaticSetter(propertyName) }; }, defineStaticProperty: ( propertyName: K, getter?: () => C[K], setter?: (value: C[K]) => void, ) => { defineStaticProperty(propertyName, getter, setter)(mocked); return { getter: mocked.withStaticGetter(propertyName), setter: mocked.withStaticSetter(propertyName) }; }, withConstructor: () => createConstructorParameterVerifier(mocked), withFunction: >(functionName: U) => createFunctionParameterVerifier(mocked, 'function', functionName), withSetter: (functionName: U) => createFunctionParameterVerifier(mocked, 'setter', functionName), withGetter: (functionName: U) => createFunctionVerifier(mocked, 'getter', functionName), withStaticFunction: >(functionName: U) => createFunctionParameterVerifier(mocked, 'staticFunction', functionName), withStaticSetter: (functionName: U) => createFunctionParameterVerifier(mocked, 'staticSetter', functionName), withStaticGetter: (functionName: U) => createFunctionVerifier(mocked, 'staticGetter', functionName), }; mocked.mockConstructor.prototype = mocked.mock as any; return mocked; } }