Skip to content

Commit

Permalink
Fix DeepMockProxy not properly producing type when the nested fields …
Browse files Browse the repository at this point in the history
…are both a function and object
  • Loading branch information
Allen Francis committed Jul 8, 2022
1 parent e98bc1e commit c68bcda
Showing 1 changed file with 18 additions and 7 deletions.
25 changes: 18 additions & 7 deletions src/Mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,22 @@ export interface CalledWithMock<T, Y extends any[]> extends jest.Mock<T, Y> {
export type MockProxy<T> = {
// This supports deep mocks in the else branch
[K in keyof T]: T[K] extends (...args: infer A) => infer B ? CalledWithMock<B, A> : T[K];
} &
T;
} & T;

// Make a type by omitting keys which match Condition
export type OmitType<Base, Condition> = Omit<
Base,
{
[Key in keyof Base]: Base[Key] extends Condition ? never : Key;
}[keyof Base]
>;

export type DeepMockProxy<T> = {
// This supports deep mocks in the else branch
[K in keyof T]: T[K] extends (...args: infer A) => infer B ? CalledWithMock<B, A> : DeepMockProxy<T[K]>;
} &
T;
[K in keyof T]: T[K] extends (...args: infer A) => infer B
? CalledWithMock<B, A> & DeepMockProxy<OmitType<T[K], (...args: any) => any>>
: DeepMockProxy<T[K]>;
} & T;

export interface MockOpts {
deep?: boolean;
Expand Down Expand Up @@ -89,7 +97,7 @@ export const mockReset = (mock: MockProxy<any>) => {
}
};

export const mockDeep = <T>(mockImplementation?: DeepPartial<T>): DeepMockProxy<T> & T => mock(mockImplementation, { deep: true });
export const mockDeep = <T>(mockImplementation?: DeepPartial<T>) => mock<T, DeepMockProxy<T> & T>(mockImplementation, { deep: true });

const overrideMockImp = (obj: DeepPartial<any>, opts?: MockOpts) => {
const proxy = new Proxy<MockProxy<any>>(obj, handler(opts));
Expand Down Expand Up @@ -154,7 +162,10 @@ const handler = (opts?: MockOpts) => ({
},
});

const mock = <T>(mockImplementation: DeepPartial<T> = {} as DeepPartial<T>, opts?: MockOpts): MockProxy<T> & T => {
const mock = <T, MockedReturn extends MockProxy<T> & T = MockProxy<T> & T>(
mockImplementation: DeepPartial<T> = {} as DeepPartial<T>,
opts?: MockOpts
): MockedReturn => {
// @ts-ignore private
mockImplementation!._isMockObject = true;
return overrideMockImp(mockImplementation, opts);
Expand Down

0 comments on commit c68bcda

Please sign in to comment.