Skip to content

Commit 95b94e8

Browse files
authored
feat(jest-mock): Export Mock, MockInstance, SpyInstance types (#10138)
1 parent 504cace commit 95b94e8

File tree

2 files changed

+57
-52
lines changed

2 files changed

+57
-52
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
### Features
44

5+
- `[jest-mock]` Export `Mock`, `MockInstance`, `SpyInstance` types ([#10138](https://github.com/facebook/jest/pull/10138))
56
- `[jest-config]` Support config files exporting (`async`) `function`s ([#10001](https://github.com/facebook/jest/pull/10001))
67
- `[jest-cli, jest-core]` Add `--selectProjects` CLI argument to filter test suites by project name ([#8612](https://github.com/facebook/jest/pull/8612))
78
- `[jest-cli, jest-init]` Add `coverageProvider` to `jest --init` prompts ([#10044](https://github.com/facebook/jest/pull/10044))

packages/jest-mock/src/index.ts

Lines changed: 56 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,39 @@ namespace JestMock {
3333
value?: T;
3434
length?: number;
3535
};
36+
37+
export interface Mock<T, Y extends Array<unknown> = Array<unknown>>
38+
extends Function,
39+
MockInstance<T, Y> {
40+
new (...args: Y): T;
41+
(...args: Y): T;
42+
}
43+
44+
export interface SpyInstance<T, Y extends Array<unknown>>
45+
extends MockInstance<T, Y> {}
46+
47+
export interface MockInstance<T, Y extends Array<unknown>> {
48+
_isMockFunction: true;
49+
_protoImpl: Function;
50+
getMockName(): string;
51+
getMockImplementation(): Function | undefined;
52+
mock: MockFunctionState<T, Y>;
53+
mockClear(): this;
54+
mockReset(): this;
55+
mockRestore(): void;
56+
mockImplementation(fn: (...args: Y) => T): this;
57+
mockImplementation(fn: () => Promise<T>): this;
58+
mockImplementationOnce(fn: (...args: Y) => T): this;
59+
mockImplementationOnce(fn: () => Promise<T>): this;
60+
mockName(name: string): this;
61+
mockReturnThis(): this;
62+
mockReturnValue(value: T): this;
63+
mockReturnValueOnce(value: T): this;
64+
mockResolvedValue(value: T): this;
65+
mockResolvedValueOnce(value: T): this;
66+
mockRejectedValue(value: T): this;
67+
mockRejectedValueOnce(value: T): this;
68+
}
3669
}
3770

3871
/**
@@ -87,38 +120,6 @@ type FunctionPropertyNames<T> = {
87120
}[keyof T] &
88121
string;
89122

90-
interface Mock<T, Y extends Array<unknown> = Array<unknown>>
91-
extends Function,
92-
MockInstance<T, Y> {
93-
new (...args: Y): T;
94-
(...args: Y): T;
95-
}
96-
97-
interface SpyInstance<T, Y extends Array<unknown>> extends MockInstance<T, Y> {}
98-
99-
interface MockInstance<T, Y extends Array<unknown>> {
100-
_isMockFunction: true;
101-
_protoImpl: Function;
102-
getMockName(): string;
103-
getMockImplementation(): Function | undefined;
104-
mock: MockFunctionState<T, Y>;
105-
mockClear(): this;
106-
mockReset(): this;
107-
mockRestore(): void;
108-
mockImplementation(fn: (...args: Y) => T): this;
109-
mockImplementation(fn: () => Promise<T>): this;
110-
mockImplementationOnce(fn: (...args: Y) => T): this;
111-
mockImplementationOnce(fn: () => Promise<T>): this;
112-
mockName(name: string): this;
113-
mockReturnThis(): this;
114-
mockReturnValue(value: T): this;
115-
mockReturnValueOnce(value: T): this;
116-
mockResolvedValue(value: T): this;
117-
mockResolvedValueOnce(value: T): this;
118-
mockRejectedValue(value: T): this;
119-
mockRejectedValueOnce(value: T): this;
120-
}
121-
122123
const MOCK_CONSTRUCTOR_NAME = 'mockConstructor';
123124

124125
const FUNCTION_NAME_RESERVED_PATTERN = /[\s!-\/:-@\[-`{-~]/;
@@ -363,7 +364,10 @@ function isReadonlyProp(object: any, prop: string): boolean {
363364

364365
class ModuleMockerClass {
365366
private _environmentGlobal: Global;
366-
private _mockState: WeakMap<Mock<any, any>, MockFunctionState<any, any>>;
367+
private _mockState: WeakMap<
368+
JestMock.Mock<any, any>,
369+
MockFunctionState<any, any>
370+
>;
367371
private _mockConfigRegistry: WeakMap<Function, MockFunctionConfig>;
368372
private _spyState: Set<() => void>;
369373
private _invocationCallCounter: number;
@@ -430,7 +434,7 @@ class ModuleMockerClass {
430434
}
431435

432436
private _ensureMockConfig<T, Y extends Array<unknown>>(
433-
f: Mock<T, Y>,
437+
f: JestMock.Mock<T, Y>,
434438
): MockFunctionConfig {
435439
let config = this._mockConfigRegistry.get(f);
436440
if (!config) {
@@ -441,7 +445,7 @@ class ModuleMockerClass {
441445
}
442446

443447
private _ensureMockState<T, Y extends Array<unknown>>(
444-
f: Mock<T, Y>,
448+
f: JestMock.Mock<T, Y>,
445449
): MockFunctionState<T, Y> {
446450
let state = this._mockState.get(f);
447451
if (!state) {
@@ -495,7 +499,7 @@ class ModuleMockerClass {
495499
private _makeComponent<T, Y extends Array<unknown>>(
496500
metadata: JestMock.MockFunctionMetadata<T, Y, 'function'>,
497501
restore?: () => void,
498-
): Mock<T, Y>;
502+
): JestMock.Mock<T, Y>;
499503
private _makeComponent<T, Y extends Array<unknown>>(
500504
metadata: JestMock.MockFunctionMetadata<T, Y>,
501505
restore?: () => void,
@@ -505,7 +509,7 @@ class ModuleMockerClass {
505509
| RegExp
506510
| T
507511
| undefined
508-
| Mock<T, Y> {
512+
| JestMock.Mock<T, Y> {
509513
if (metadata.type === 'object') {
510514
return new this._environmentGlobal.Object();
511515
} else if (metadata.type === 'array') {
@@ -617,7 +621,7 @@ class ModuleMockerClass {
617621
const f = (this._createMockFunction(
618622
metadata,
619623
mockConstructor,
620-
) as unknown) as Mock<T, Y>;
624+
) as unknown) as JestMock.Mock<T, Y>;
621625
f._isMockFunction = true;
622626
f.getMockImplementation = () => this._ensureMockConfig(f).mockImpl;
623627

@@ -673,7 +677,7 @@ class ModuleMockerClass {
673677

674678
f.mockImplementationOnce = (
675679
fn: ((...args: Y) => T) | (() => Promise<T>),
676-
): Mock<T, Y> => {
680+
): JestMock.Mock<T, Y> => {
677681
// next function call will use this mock implementation return value
678682
// or default mock implementation return value
679683
const mockConfig = this._ensureMockConfig(f);
@@ -683,7 +687,7 @@ class ModuleMockerClass {
683687

684688
f.mockImplementation = (
685689
fn: ((...args: Y) => T) | (() => Promise<T>),
686-
): Mock<T, Y> => {
690+
): JestMock.Mock<T, Y> => {
687691
// next function call will use mock implementation return value
688692
const mockConfig = this._ensureMockConfig(f);
689693
mockConfig.mockImpl = fn;
@@ -789,9 +793,9 @@ class ModuleMockerClass {
789793
| RegExp
790794
| T
791795
| undefined
792-
| Mock<T, Y>;
796+
| JestMock.Mock<T, Y>;
793797
},
794-
): Mock<T, Y> {
798+
): JestMock.Mock<T, Y> {
795799
// metadata not compatible but it's the same type, maybe problem with
796800
// overloading of _makeComponent and not _generateMock?
797801
// @ts-expect-error
@@ -822,7 +826,7 @@ class ModuleMockerClass {
822826
mock.prototype.constructor = mock;
823827
}
824828

825-
return mock as Mock<T, Y>;
829+
return mock as JestMock.Mock<T, Y>;
826830
}
827831

828832
/**
@@ -832,7 +836,7 @@ class ModuleMockerClass {
832836
*/
833837
generateFromMetadata<T, Y extends Array<unknown>>(
834838
_metadata: JestMock.MockFunctionMetadata<T, Y>,
835-
): Mock<T, Y> {
839+
): JestMock.Mock<T, Y> {
836840
const callbacks: Array<Function> = [];
837841
const refs = {};
838842
const mock = this._generateMock(_metadata, callbacks, refs);
@@ -913,13 +917,13 @@ class ModuleMockerClass {
913917
return metadata;
914918
}
915919

916-
isMockFunction<T>(fn: any): fn is Mock<T> {
920+
isMockFunction<T>(fn: any): fn is JestMock.Mock<T> {
917921
return !!fn && fn._isMockFunction === true;
918922
}
919923

920924
fn<T, Y extends Array<unknown>>(
921925
implementation?: (...args: Y) => T,
922-
): Mock<T, Y> {
926+
): JestMock.Mock<T, Y> {
923927
const length = implementation ? implementation.length : 0;
924928
const fn = this._makeComponent<T, Y>({length, type: 'function'});
925929
if (implementation) {
@@ -932,19 +936,19 @@ class ModuleMockerClass {
932936
object: T,
933937
methodName: M,
934938
accessType: 'get',
935-
): SpyInstance<T[M], []>;
939+
): JestMock.SpyInstance<T[M], []>;
936940

937941
spyOn<T extends {}, M extends NonFunctionPropertyNames<T>>(
938942
object: T,
939943
methodName: M,
940944
accessType: 'set',
941-
): SpyInstance<void, [T[M]]>;
945+
): JestMock.SpyInstance<void, [T[M]]>;
942946

943947
spyOn<T extends {}, M extends FunctionPropertyNames<T>>(
944948
object: T,
945949
methodName: M,
946950
): T[M] extends (...args: Array<any>) => any
947-
? SpyInstance<ReturnType<T[M]>, Parameters<T[M]>>
951+
? JestMock.SpyInstance<ReturnType<T[M]>, Parameters<T[M]>>
948952
: never;
949953

950954
spyOn<T extends {}, M extends NonFunctionPropertyNames<T>>(
@@ -999,7 +1003,7 @@ class ModuleMockerClass {
9991003
obj: T,
10001004
propertyName: M,
10011005
accessType: 'get' | 'set' = 'get',
1002-
): Mock<T> {
1006+
): JestMock.Mock<T> {
10031007
if (typeof obj !== 'object' && typeof obj !== 'function') {
10041008
throw new Error(
10051009
'Cannot spyOn on a primitive value; ' + this._typeOf(obj) + ' given',
@@ -1058,7 +1062,7 @@ class ModuleMockerClass {
10581062
Object.defineProperty(obj, propertyName, descriptor!);
10591063
});
10601064

1061-
(descriptor[accessType] as Mock<T>).mockImplementation(function (
1065+
(descriptor[accessType] as JestMock.Mock<T>).mockImplementation(function (
10621066
this: unknown,
10631067
) {
10641068
// @ts-expect-error
@@ -1067,7 +1071,7 @@ class ModuleMockerClass {
10671071
}
10681072

10691073
Object.defineProperty(obj, propertyName, descriptor);
1070-
return descriptor[accessType] as Mock<T>;
1074+
return descriptor[accessType] as JestMock.Mock<T>;
10711075
}
10721076

10731077
clearAllMocks() {

0 commit comments

Comments
 (0)