Skip to content

Commit

Permalink
Merge pull request #28 from Roaders/exposeLookupTypes
Browse files Browse the repository at this point in the history
Expose lookup types
  • Loading branch information
Roaders authored Jan 4, 2021
2 parents fc708d8 + c2bccf5 commit b5d9c1b
Show file tree
Hide file tree
Showing 11 changed files with 916 additions and 1,063 deletions.
5 changes: 5 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

coverage:
precision: 2
round: down
range: "80...100"
1 change: 1 addition & 0 deletions main/helper/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './property-replacement-helper';
export * from './module-helper';
export * from './jest-helper';
export * from './lookup-helper';
22 changes: 22 additions & 0 deletions main/helper/lookup-helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ConstructorFunction, FunctionCallLookup, IMocked, LookupType } from '../mock';

export function getLookup<T, C extends ConstructorFunction<T>, U extends LookupType>(
mock: IMocked<T, C>,
lookupType: U,
): FunctionCallLookup<T, C, U> {
switch (lookupType) {
case 'function':
return mock.functionCallLookup as FunctionCallLookup<T, C, U>;
case 'getter':
return mock.getterCallLookup as FunctionCallLookup<T, C, U>;
case 'setter':
return mock.setterCallLookup as FunctionCallLookup<T, C, U>;
case 'staticFunction':
return mock.staticFunctionCallLookup as FunctionCallLookup<T, C, U>;
case 'staticGetter':
return mock.staticGetterCallLookup as FunctionCallLookup<T, C, U>;
case 'staticSetter':
return mock.staticSetterCallLookup as FunctionCallLookup<T, C, U>;
}
throw new Error(`Unknown lookup type: ${lookupType}`);
}
55 changes: 39 additions & 16 deletions main/mock/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ export type MatchFunction<T> = (passedValue: T) => boolean;
// tslint:disable-next-line:ban-types
export type FunctionsOnly<T> = Pick<T, { [K in keyof T]: Required<T>[K] extends Function ? K : never }[keyof T]>;

// tslint:disable-next-line:ban-types
export type PropertiesOnly<T> = Pick<T, { [K in keyof T]: Required<T>[K] extends Function ? never : K }[keyof T]>;

/**
* Allows custom logic to verify that a function parameter has the expected value.
*/
Expand All @@ -31,26 +34,44 @@ export type FunctionParameterMatchers<T extends any[]> = {
[P in keyof T]: T[P] extends FunctionOrConstructor ? IParameterMatcher<T[P]> : ParameterMatcher<T[P]>;
};

export type FunctionCallLookup = { [key: string]: any[][] };
export type FunctionCallLookup<T, C extends ConstructorFunction<T>, U extends LookupType> = {
[P in FunctionName<T, C, U>]?: LookupParams<T, C, U, P>[];
};

export type LookupParams<
T,
C extends ConstructorFunction<T>,
U extends LookupType,
K extends FunctionName<T, C, U>
> = U extends FunctionTypes
? FunctionParams<VerifierTarget<T, C, U>[K]>
: U extends SetterTypes
? [VerifierTarget<T, C, U>[K]]
: [];
export type FunctionParams<T> = T extends (...args: infer P) => any ? P : never;

export type ConstructorFunction<T> = new (...args: any[]) => T;

export type StaticFunctionTypes = 'staticFunction' | 'staticGetter' | 'staticSetter';
export type InstanceFunctionTypes = 'function' | 'getter' | 'setter';
export type StaticLookupTypes = 'staticFunction' | 'staticGetter' | 'staticSetter';
export type InstanceLookupTypes = 'function' | 'getter' | 'setter';
export type SetterTypes = 'staticSetter' | 'setter';
export type GetterTypes = 'staticGetter' | 'getter';
export type FunctionTypes = 'staticFunction' | 'function';
export type LookupType = StaticLookupTypes | InstanceLookupTypes;

export type VerifierTarget<T, C extends ConstructorFunction<T>, U extends FunctionType> = U extends StaticFunctionTypes
? C
export type VerifierTarget<T, C extends ConstructorFunction<T>, U extends LookupType> = U extends StaticLookupTypes
? U extends FunctionTypes
? FunctionsOnly<C>
: C
: U extends FunctionTypes
? FunctionsOnly<T>
: T;
export type FunctionType = StaticFunctionTypes | InstanceFunctionTypes;
export type FunctionName<T, C extends ConstructorFunction<T>, U extends FunctionType> = keyof VerifierTarget<T, C, U>;
export type FunctionName<T, C extends ConstructorFunction<T>, U extends LookupType> = keyof VerifierTarget<T, C, U>;

export interface IFunctionWithParametersVerification<
P extends Array<any>,
T,
U extends FunctionType,
U extends LookupType,
C extends new (...args: any[]) => T = never
> extends IFunctionVerifier<T, U, C> {
/**
Expand Down Expand Up @@ -89,15 +110,15 @@ export interface IFunctionWithParametersVerification<
withParametersEqualTo(...args: FunctionParameterMatchers<P>): IStrictFunctionVerification<T, U, C>;
}

export interface IStrictFunctionVerification<T, U extends FunctionType, C extends new (...args: any[]) => T = never>
export interface IStrictFunctionVerification<T, U extends LookupType, C extends new (...args: any[]) => T = never>
extends IFunctionVerifier<T, U, C> {
/**
* verify that the function has been called ONLY with the specified parameters and never without
*/
strict(): IFunctionVerifier<T, U, C>;
}

export interface IFunctionVerifier<T, U extends FunctionType, C extends new (...args: any[]) => T = never> {
export interface IFunctionVerifier<T, U extends LookupType, C extends new (...args: any[]) => T = never> {
type: U;
functionName: FunctionName<T, C, U>;
parameterMatchers?: (MatchFunction<any> | IParameterMatcher<any>)[];
Expand All @@ -116,13 +137,15 @@ export interface IMocked<T, C extends new (...args: any[]) => T = never> {
*/
mockConstructor: C;

functionCallLookup: FunctionCallLookup;
setterCallLookup: FunctionCallLookup;
getterCallLookup: FunctionCallLookup;
functionCallLookup: FunctionCallLookup<T, C, 'function'>;
setterCallLookup: FunctionCallLookup<T, C, 'setter'>;
getterCallLookup: FunctionCallLookup<T, C, 'getter'>;

staticFunctionCallLookup: FunctionCallLookup<T, C, 'staticFunction'>;
staticSetterCallLookup: FunctionCallLookup<T, C, 'staticSetter'>;
staticGetterCallLookup: FunctionCallLookup<T, C, 'staticGetter'>;

staticFunctionCallLookup: FunctionCallLookup;
staticSetterCallLookup: FunctionCallLookup;
staticGetterCallLookup: FunctionCallLookup;
functionReplacementLookup: Partial<Record<LookupType, Record<string, ((...args: any[]) => any) | undefined>>>;

/**
* Used to setup the mock with multiple operators.
Expand Down
6 changes: 4 additions & 2 deletions main/mock/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export class Mock {
staticSetterCallLookup: {},
staticGetterCallLookup: {},

functionReplacementLookup: {},

mock: {} as T,
// tslint:disable-next-line:no-empty
mockConstructor: ((..._args: any[]) => {}) as any,
Expand Down Expand Up @@ -66,13 +68,13 @@ export class Mock {
return mocked.withStaticGetter(propertyName);
},

withFunction: <U extends keyof T>(functionName: U) =>
withFunction: <U extends keyof FunctionsOnly<T>>(functionName: U) =>
createFunctionParameterVerifier(mocked, 'function', functionName),
withSetter: <U extends keyof T>(functionName: U) =>
createFunctionParameterVerifier(mocked, 'setter', functionName),
withGetter: <U extends keyof T>(functionName: U) => createFunctionVerifier(mocked, 'getter', functionName),

withStaticFunction: <U extends keyof C>(functionName: U) =>
withStaticFunction: <U extends keyof FunctionsOnly<C>>(functionName: U) =>
createFunctionParameterVerifier(mocked, 'staticFunction', functionName),
withStaticSetter: <U extends keyof C>(functionName: U) =>
createFunctionParameterVerifier(mocked, 'staticSetter', functionName),
Expand Down
Loading

0 comments on commit b5d9c1b

Please sign in to comment.