-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: followup to jest-mock TS migration #7850
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,6 +53,16 @@ type MockFunctionConfig = { | |
specificMockImpls: Array<Function>; | ||
}; | ||
|
||
// see https://github.com/Microsoft/TypeScript/issues/25215 | ||
type NonFunctionPropertyNames<T> = { | ||
[K in keyof T]: T[K] extends (...args: any[]) => any ? never : K | ||
}[keyof T] & | ||
string; | ||
type FunctionPropertyNames<T> = { | ||
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never | ||
}[keyof T] & | ||
string; | ||
|
||
interface Mock<T, Y extends unknown[] = unknown[]> | ||
extends Function, | ||
MockInstance<T, Y> { | ||
|
@@ -328,12 +338,12 @@ function isReadonlyProp(object: any, prop: string): boolean { | |
} | ||
|
||
class ModuleMockerClass { | ||
_environmentGlobal: Global; | ||
_mockState: WeakMap<Mock<any, any>, MockFunctionState<any, any>>; | ||
_mockConfigRegistry: WeakMap<Function, MockFunctionConfig>; | ||
_spyState: Set<() => void>; | ||
private _environmentGlobal: Global; | ||
private _mockState: WeakMap<Mock<any, any>, MockFunctionState<any, any>>; | ||
private _mockConfigRegistry: WeakMap<Function, MockFunctionConfig>; | ||
private _spyState: Set<() => void>; | ||
private _invocationCallCounter: number; | ||
ModuleMocker: typeof ModuleMockerClass; | ||
_invocationCallCounter: number; | ||
|
||
/** | ||
* @see README.md | ||
|
@@ -349,7 +359,7 @@ class ModuleMockerClass { | |
this._invocationCallCounter = 1; | ||
} | ||
|
||
_getSlots(object?: Object): Array<string> { | ||
private _getSlots(object?: Object): Array<string> { | ||
if (!object) { | ||
return []; | ||
} | ||
|
@@ -396,7 +406,9 @@ class ModuleMockerClass { | |
return Array.from(slots); | ||
} | ||
|
||
_ensureMockConfig<T, Y extends unknown[]>(f: Mock<T, Y>): MockFunctionConfig { | ||
private _ensureMockConfig<T, Y extends unknown[]>( | ||
f: Mock<T, Y>, | ||
): MockFunctionConfig { | ||
let config = this._mockConfigRegistry.get(f); | ||
if (!config) { | ||
config = this._defaultMockConfig(); | ||
|
@@ -405,7 +417,7 @@ class ModuleMockerClass { | |
return config; | ||
} | ||
|
||
_ensureMockState<T, Y extends unknown[]>( | ||
private _ensureMockState<T, Y extends unknown[]>( | ||
f: Mock<T, Y>, | ||
): MockFunctionState<T, Y> { | ||
let state = this._mockState.get(f); | ||
|
@@ -416,7 +428,7 @@ class ModuleMockerClass { | |
return state; | ||
} | ||
|
||
_defaultMockConfig(): MockFunctionConfig { | ||
private _defaultMockConfig(): MockFunctionConfig { | ||
return { | ||
defaultReturnValue: undefined, | ||
isReturnValueLastSet: false, | ||
|
@@ -427,7 +439,7 @@ class ModuleMockerClass { | |
}; | ||
} | ||
|
||
_defaultMockState<T, Y extends unknown[]>(): MockFunctionState<T, Y> { | ||
private _defaultMockState<T, Y extends unknown[]>(): MockFunctionState<T, Y> { | ||
return { | ||
calls: [], | ||
instances: [], | ||
|
@@ -436,31 +448,31 @@ class ModuleMockerClass { | |
}; | ||
} | ||
|
||
_makeComponent<T, Y extends unknown[]>( | ||
private _makeComponent<T, Y extends unknown[]>( | ||
metadata: Mocks.MockFunctionMetadata<T, Y, 'object'>, | ||
restore?: () => void, | ||
): Object; | ||
_makeComponent<T, Y extends unknown[]>( | ||
private _makeComponent<T, Y extends unknown[]>( | ||
metadata: Mocks.MockFunctionMetadata<T, Y, 'array'>, | ||
restore?: () => void, | ||
): Array<unknown>; | ||
_makeComponent<T, Y extends unknown[]>( | ||
private _makeComponent<T, Y extends unknown[]>( | ||
metadata: Mocks.MockFunctionMetadata<T, Y, 'regexp'>, | ||
restore?: () => void, | ||
): RegExp; | ||
_makeComponent<T, Y extends unknown[]>( | ||
private _makeComponent<T, Y extends unknown[]>( | ||
metadata: Mocks.MockFunctionMetadata< | ||
T, | ||
Y, | ||
'constant' | 'collection' | 'null' | 'undefined' | ||
>, | ||
restore?: () => void, | ||
): T; | ||
_makeComponent<T, Y extends unknown[]>( | ||
private _makeComponent<T, Y extends unknown[]>( | ||
metadata: Mocks.MockFunctionMetadata<T, Y, 'function'>, | ||
restore?: () => void, | ||
): Mock<T, Y>; | ||
_makeComponent<T, Y extends unknown[]>( | ||
private _makeComponent<T, Y extends unknown[]>( | ||
metadata: Mocks.MockFunctionMetadata<T, Y>, | ||
restore?: () => void, | ||
): Object | Array<unknown> | RegExp | T | undefined | Mock<T, Y> { | ||
|
@@ -706,7 +718,7 @@ class ModuleMockerClass { | |
} | ||
} | ||
|
||
_createMockFunction<T, Y extends unknown[]>( | ||
private _createMockFunction<T, Y extends unknown[]>( | ||
metadata: Mocks.MockFunctionMetadata<T, Y>, | ||
mockConstructor: Function, | ||
): Function { | ||
|
@@ -766,7 +778,7 @@ class ModuleMockerClass { | |
return createConstructor(mockConstructor); | ||
} | ||
|
||
_generateMock<T, Y extends unknown[]>( | ||
private _generateMock<T, Y extends unknown[]>( | ||
metadata: Mocks.MockFunctionMetadata<T, Y>, | ||
callbacks: Array<Function>, | ||
refs: { | ||
|
@@ -899,7 +911,7 @@ class ModuleMockerClass { | |
return metadata; | ||
} | ||
|
||
isMockFunction(fn: any): boolean { | ||
isMockFunction<T, Y extends unknown[]>(fn: any): fn is Mock<T, Y> { | ||
return !!fn && fn._isMockFunction === true; | ||
} | ||
|
||
|
@@ -912,26 +924,26 @@ class ModuleMockerClass { | |
return fn; | ||
} | ||
|
||
spyOn<T extends {}, M extends keyof T>( | ||
spyOn<T extends {}, M extends NonFunctionPropertyNames<T>>( | ||
object: T, | ||
methodName: M, | ||
accessType: 'get', | ||
): SpyInstance<T[M], []>; | ||
|
||
spyOn<T extends {}, M extends keyof T>( | ||
spyOn<T extends {}, M extends NonFunctionPropertyNames<T>>( | ||
object: T, | ||
methodName: M, | ||
accessType: 'set', | ||
): SpyInstance<void, [T[M]]>; | ||
|
||
spyOn<T extends {}, M extends keyof T>( | ||
spyOn<T extends {}, M extends FunctionPropertyNames<T>>( | ||
object: T, | ||
methodName: M, | ||
): T[M] extends (...args: any[]) => any | ||
? SpyInstance<ReturnType<T[M]>, ArgsType<T[M]>> | ||
: never; | ||
|
||
spyOn<T extends {}, M extends keyof T>( | ||
spyOn<T extends {}, M extends NonFunctionPropertyNames<T>>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. heh, not this is not entirely true because this generic I don't really understand why a function even needs type definitions when it's overloaded like this. Generated types are only for the definitions as well, so that seems really counterintuitive, not to mention it causes headaches on "how to fit all the typings in this def and make TS happy, even though it may be a lie" 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. heh, yeah. we might want to add actual tests on the types at some point (e.g. https://www.npmjs.com/package/tsd-check or https://www.npmjs.com/package/dts-jest) |
||
object: T, | ||
methodName: M, | ||
accessType?: 'get' | 'set', | ||
|
@@ -973,7 +985,7 @@ class ModuleMockerClass { | |
return object[methodName]; | ||
} | ||
|
||
_spyOnProperty<T extends {}, M extends keyof T>( | ||
private _spyOnProperty<T extends {}, M extends NonFunctionPropertyNames<T>>( | ||
obj: T, | ||
propertyName: M, | ||
accessType: 'get' | 'set' = 'get', | ||
|
@@ -1060,7 +1072,7 @@ class ModuleMockerClass { | |
this._spyState = new Set(); | ||
} | ||
|
||
_typeOf(value: any): string { | ||
private _typeOf(value: any): string { | ||
return value == null ? '' + value : typeof value; | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this makes sense or not
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Y is optional and
unknown[]
by default, so you can omit that. Docs say that type gruard performs runtime check, but I don't see a change in the build output. Anyway, it makes sense to meThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the built output is the same, this is just us telling the type system that if the function returns
true
what the type is. Basically atypeof