@@ -20,87 +20,101 @@ export type MockFunctionMetadataType =
20
20
export type MockFunctionMetadata <
21
21
T ,
22
22
Y extends Array < unknown > ,
23
- Type = MockFunctionMetadataType ,
23
+ MetadataType = MockFunctionMetadataType ,
24
24
> = {
25
25
ref ?: number ;
26
26
members ?: Record < string , MockFunctionMetadata < T , Y > > ;
27
27
mockImpl ?: ( ...args : Y ) => T ;
28
28
name ?: string ;
29
29
refID ?: number ;
30
- type ?: Type ;
30
+ type ?: MetadataType ;
31
31
value ?: T ;
32
32
length ?: number ;
33
33
} ;
34
34
35
- export type MockableFunction = ( ...args : Array < any > ) => any ;
36
- export type MethodKeysOf < T > = {
37
- [ K in keyof T ] : T [ K ] extends MockableFunction ? K : never ;
35
+ export type ConstructorLike = { new ( ...args : Array < any > ) : any } ;
36
+
37
+ export type MethodLike = ( ...args : Array < any > ) => any ;
38
+
39
+ export type ConstructorLikeKeys < T > = {
40
+ [ K in keyof T ] : T [ K ] extends ConstructorLike ? K : never ;
38
41
} [ keyof T ] ;
39
- export type PropertyKeysOf < T > = {
40
- [ K in keyof T ] : T [ K ] extends MockableFunction ? never : K ;
42
+
43
+ export type MethodLikeKeys < T > = {
44
+ [ K in keyof T ] : T [ K ] extends MethodLike ? K : never ;
41
45
} [ keyof T ] ;
42
46
43
- export type ArgumentsOf < T > = T extends ( ...args : infer A ) => any ? A : never ;
47
+ export type PropertyLikeKeys < T > = {
48
+ [ K in keyof T ] : T [ K ] extends MethodLike
49
+ ? never
50
+ : T [ K ] extends ConstructorLike
51
+ ? never
52
+ : K ;
53
+ } [ keyof T ] ;
44
54
45
- export type ConstructorArgumentsOf < T > = T extends new ( ...args : infer A ) => any
46
- ? A
55
+ // TODO Figure out how to replace this with TS ConstructorParameters utility type
56
+ // https://www.typescriptlang.org/docs/handbook/utility-types.html#constructorparameterstype
57
+ type ConstructorParameters < T > = T extends new ( ...args : infer P ) => any
58
+ ? P
47
59
: never ;
60
+
48
61
export type MaybeMockedConstructor < T > = T extends new (
49
62
...args : Array < any >
50
63
) => infer R
51
- ? MockInstance < R , ConstructorArgumentsOf < T > >
64
+ ? MockInstance < R , ConstructorParameters < T > >
52
65
: T ;
53
- export type MockedFunction < T extends MockableFunction > = MockWithArgs < T > & {
66
+
67
+ export interface MockWithArgs < T extends MethodLike >
68
+ extends MockInstance < ReturnType < T > , Parameters < T > > {
69
+ new ( ...args : ConstructorParameters < T > ) : T ;
70
+ ( ...args : Parameters < T > ) : ReturnType < T > ;
71
+ }
72
+
73
+ export type MockedFunction < T extends MethodLike > = MockWithArgs < T > & {
54
74
[ K in keyof T ] : T [ K ] ;
55
75
} ;
56
- export type MockedFunctionDeep < T extends MockableFunction > = MockWithArgs < T > &
76
+
77
+ export type MockedFunctionDeep < T extends MethodLike > = MockWithArgs < T > &
57
78
MockedObjectDeep < T > ;
79
+
58
80
export type MockedObject < T > = MaybeMockedConstructor < T > & {
59
- [ K in MethodKeysOf < T > ] : T [ K ] extends MockableFunction
81
+ [ K in MethodLikeKeys < T > ] : T [ K ] extends MethodLike
60
82
? MockedFunction < T [ K ] >
61
83
: T [ K ] ;
62
- } & { [ K in PropertyKeysOf < T > ] : T [ K ] } ;
84
+ } & { [ K in PropertyLikeKeys < T > ] : T [ K ] } ;
85
+
63
86
export type MockedObjectDeep < T > = MaybeMockedConstructor < T > & {
64
- [ K in MethodKeysOf < T > ] : T [ K ] extends MockableFunction
87
+ [ K in MethodLikeKeys < T > ] : T [ K ] extends MethodLike
65
88
? MockedFunctionDeep < T [ K ] >
66
89
: T [ K ] ;
67
- } & { [ K in PropertyKeysOf < T > ] : MaybeMockedDeep < T [ K ] > } ;
90
+ } & { [ K in PropertyLikeKeys < T > ] : MaybeMockedDeep < T [ K ] > } ;
68
91
69
- export type MaybeMockedDeep < T > = T extends MockableFunction
70
- ? MockedFunctionDeep < T >
92
+ export type MaybeMocked < T > = T extends MethodLike
93
+ ? MockedFunction < T >
71
94
: T extends object
72
- ? MockedObjectDeep < T >
95
+ ? MockedObject < T >
73
96
: T ;
74
97
75
- export type MaybeMocked < T > = T extends MockableFunction
76
- ? MockedFunction < T >
98
+ export type MaybeMockedDeep < T > = T extends MethodLike
99
+ ? MockedFunctionDeep < T >
77
100
: T extends object
78
- ? MockedObject < T >
101
+ ? MockedObjectDeep < T >
79
102
: T ;
80
103
81
- export type ArgsType < T > = T extends ( ...args : infer A ) => any ? A : never ;
82
104
export type Mocked < T > = {
83
- [ P in keyof T ] : T [ P ] extends ( ... args : Array < any > ) => any
84
- ? MockInstance < ReturnType < T [ P ] > , ArgsType < T [ P ] > >
85
- : T [ P ] extends Constructable
105
+ [ P in keyof T ] : T [ P ] extends MethodLike
106
+ ? MockInstance < ReturnType < T [ P ] > , Parameters < T [ P ] > >
107
+ : T [ P ] extends ConstructorLike
86
108
? MockedClass < T [ P ] >
87
109
: T [ P ] ;
88
110
} & T ;
89
- export type MockedClass < T extends Constructable > = MockInstance <
111
+
112
+ export type MockedClass < T extends ConstructorLike > = MockInstance <
90
113
InstanceType < T > ,
91
114
T extends new ( ...args : infer P ) => any ? P : never
92
115
> & {
93
116
prototype : T extends { prototype : any } ? Mocked < T [ 'prototype' ] > : never ;
94
117
} & T ;
95
- export interface Constructable {
96
- new ( ...args : Array < any > ) : any ;
97
- }
98
-
99
- export interface MockWithArgs < T extends MockableFunction >
100
- extends MockInstance < ReturnType < T > , ArgumentsOf < T > > {
101
- new ( ...args : ConstructorArgumentsOf < T > ) : T ;
102
- ( ...args : ArgumentsOf < T > ) : ReturnType < T > ;
103
- }
104
118
105
119
export interface Mock < T , Y extends Array < unknown > = Array < unknown > >
106
120
extends Function ,
@@ -109,8 +123,9 @@ export interface Mock<T, Y extends Array<unknown> = Array<unknown>>
109
123
( ...args : Y ) : T ;
110
124
}
111
125
112
- export interface SpyInstance < T , Y extends Array < unknown > >
113
- extends MockInstance < T , Y > { }
126
+ // TODO Replace with Awaited utility type when minimum supported TS version will be 4.5 or above
127
+ //https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#the-awaited-type-and-promise-improvements
128
+ type Unpromisify < T > = T extends Promise < infer R > ? R : never ;
114
129
115
130
export interface MockInstance < T , Y extends Array < unknown > > {
116
131
_isMockFunction : true ;
@@ -137,7 +152,8 @@ export interface MockInstance<T, Y extends Array<unknown>> {
137
152
mockRejectedValueOnce ( value : unknown ) : this;
138
153
}
139
154
140
- type Unpromisify < T > = T extends Promise < infer R > ? R : never ;
155
+ export interface SpyInstance < T , Y extends Array < unknown > >
156
+ extends MockInstance < T , Y > { }
141
157
142
158
type MockFunctionResultIncomplete = {
143
159
type : 'incomplete' ;
@@ -200,20 +216,6 @@ type MockFunctionConfig = {
200
216
specificMockImpls : Array < Function > ;
201
217
} ;
202
218
203
- // see https://github.com/Microsoft/TypeScript/issues/25215
204
- type NonFunctionPropertyNames < T > = {
205
- [ K in keyof T ] : T [ K ] extends ( ...args : Array < any > ) => any ? never : K ;
206
- } [ keyof T ] &
207
- string ;
208
- type FunctionPropertyNames < T > = {
209
- [ K in keyof T ] : T [ K ] extends ( ...args : Array < any > ) => any ? K : never ;
210
- } [ keyof T ] &
211
- string ;
212
- type ConstructorPropertyNames < T > = {
213
- [ K in keyof T ] : T [ K ] extends new ( ...args : Array < any > ) => any ? K : never ;
214
- } [ keyof T ] &
215
- string ;
216
-
217
219
const MOCK_CONSTRUCTOR_NAME = 'mockConstructor' ;
218
220
219
221
const FUNCTION_NAME_RESERVED_PATTERN = / [ \s ! -\/ : - @ \[ - ` { -~ ] / ;
@@ -1036,34 +1038,34 @@ export class ModuleMocker {
1036
1038
return fn ;
1037
1039
}
1038
1040
1039
- spyOn < T extends object , M extends NonFunctionPropertyNames < T > > (
1041
+ spyOn < T extends object , M extends PropertyLikeKeys < T > > (
1040
1042
object : T ,
1041
1043
methodName : M ,
1042
1044
accessType : 'get' ,
1043
1045
) : SpyInstance < T [ M ] , [ ] > ;
1044
1046
1045
- spyOn < T extends object , M extends NonFunctionPropertyNames < T > > (
1047
+ spyOn < T extends object , M extends PropertyLikeKeys < T > > (
1046
1048
object : T ,
1047
1049
methodName : M ,
1048
1050
accessType : 'set' ,
1049
1051
) : SpyInstance < void , [ T [ M ] ] > ;
1050
1052
1051
- spyOn < T extends object , M extends ConstructorPropertyNames < T > > (
1053
+ spyOn < T extends object , M extends ConstructorLikeKeys < T > > (
1052
1054
object : T ,
1053
1055
methodName : M ,
1054
- ) : T [ M ] extends new ( ... args : Array < any > ) => any
1056
+ ) : T [ M ] extends ConstructorLike
1055
1057
? SpyInstance < InstanceType < T [ M ] > , ConstructorParameters < T [ M ] > >
1056
1058
: never ;
1057
1059
1058
- spyOn < T extends object , M extends FunctionPropertyNames < T > > (
1060
+ spyOn < T extends object , M extends MethodLikeKeys < T > > (
1059
1061
object : T ,
1060
1062
methodName : M ,
1061
- ) : T [ M ] extends ( ... args : Array < any > ) => any
1063
+ ) : T [ M ] extends MethodLike
1062
1064
? SpyInstance < ReturnType < T [ M ] > , Parameters < T [ M ] > >
1063
1065
: never ;
1064
1066
1065
1067
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
1066
- spyOn < T extends object , M extends NonFunctionPropertyNames < T > > (
1068
+ spyOn < T extends object , M extends PropertyLikeKeys < T > > (
1067
1069
object : T ,
1068
1070
methodName : M ,
1069
1071
accessType ?: 'get' | 'set' ,
@@ -1134,10 +1136,11 @@ export class ModuleMocker {
1134
1136
return object [ methodName ] ;
1135
1137
}
1136
1138
1137
- private _spyOnProperty <
1138
- T extends object ,
1139
- M extends NonFunctionPropertyNames < T > ,
1140
- > ( obj : T , propertyName : M , accessType : 'get' | 'set' = 'get' ) : Mock < T > {
1139
+ private _spyOnProperty < T extends object , M extends PropertyLikeKeys < T > > (
1140
+ obj : T ,
1141
+ propertyName : M ,
1142
+ accessType : 'get' | 'set' = 'get' ,
1143
+ ) : Mock < T > {
1141
1144
if ( typeof obj !== 'object' && typeof obj !== 'function' ) {
1142
1145
throw new Error (
1143
1146
'Cannot spyOn on a primitive value; ' + this . _typeOf ( obj ) + ' given' ,
0 commit comments