UNPKG

airbridge-react-native-sdk

Version:

Airbridge SDK for React Native

113 lines (95 loc) 3.68 kB
type ArrowFunction<Return = any, Parameters extends any[] = any[]> = (...args: Parameters) => Return type And<Condition0 extends boolean, Condition1 extends boolean> = Condition0 extends true ? (Condition1 extends true ? true : false) : false type Not<Condition extends boolean> = Condition extends true ? false : true type IsAny<Type> = (any extends Type ? true : false) extends true ? true : false type Is<Type, Expect> = Not<IsAny<Type>> extends true ? (Type extends Expect ? true : false) : false type Opt<Type, Condition extends boolean> = Condition extends true ? Type : never type Cast<Type, Condition> = Type extends Condition ? Type : never type PropertyValue<Type> = { [Key in keyof Type as Opt<Key, Not<Is<Type[Key], object | ArrowFunction>>>]: Type[Key] } type PropertyObject<Type> = { [Key in keyof Type as Opt<Key, And<Is<Type[Key], object>, Not<Is<Type[Key], ArrowFunction>>>>]: Type[Key] } type Interface<Type> = { [Key in keyof Type as Opt<Key, Is<Type[Key], ArrowFunction>>]: Cast<Type[Key], ArrowFunction> } type MockPropertyValue<Type> = PropertyValue<Type> & { readonly [Key in 'getMock' as Opt<Key, Is<keyof PropertyValue<Type>, string>>]: { readonly [Key in keyof PropertyValue<Type>]: jest.Mock<PropertyValue<Type>[Key], []> } } & { readonly [Key in 'setMock' as Opt<Key, Is<keyof PropertyValue<Type>, string>>]: { readonly [Key in keyof PropertyValue<Type>]: jest.Mock<void, [PropertyValue<Type>[Key]]> } } type MockPropertyObject<Type> = { readonly [Key in keyof PropertyObject<Type>]: Mock<PropertyObject<Type>[Key]> } type MockInterface<Type> = { readonly [Key in keyof Interface<Type>]: jest.Mock<ReturnType<Interface<Type>[Key]>, Parameters<Interface<Type>[Key]>> } export type Mock<Type> = MockPropertyValue<Type> & MockPropertyObject<Type> & MockInterface<Type> export const createMock = <Type>(): Mock<Type> => { const values: Record<string, any> = {} const mocks: Record<string, any> = {} const prepareValue = (name: string) => { if (!(name in values)) { values[name] = { value: undefined, getMock: jest.fn(() => { return values[name].value }), setMock: jest.fn((value) => { values[name].value = value }), } } } const getMock = new Proxy({}, { get: (_, name: string) => { prepareValue(name) return values[name].getMock }, set: () => { return false }, }) const setMock = new Proxy({}, { get: (_, name: string) => { prepareValue(name) return values[name].setMock }, set: () => { return false }, }) return new Proxy(jest.fn(), { apply: (call: any, _, argument) => { return call(...argument) }, get: (call: any, name: string) => { if (name in call || name === 'calls') { return call[name] } if (name in values) { return values[name].getMock() } if (name === 'getMock') { return getMock } if (name === 'setMock') { return setMock } if (!(name in mocks)) { mocks[name] = createMock() } return mocks[name] }, set: (_, name: string, value: any) => { prepareValue(name) values[name].setMock(value) return true }, }) as any as Mock<Type> }