-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtoMock.js
161 lines (129 loc) · 4.19 KB
/
toMock.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
Object.defineProperty(exports, '__esModule', {
value: true
});
const MOCKED_PROTOTYPE_CHAIN = Symbol('mockedPrototypeChain');
let globalKeepUnmock = null;
let globalMockMethod = () => {
return function mockMethod() {};
};
function toMock(arg, keepUnmock) {
if (typeof arg === 'function') {
return mockClass(arg, keepUnmock);
}
if (typeof arg === 'object') {
return mockObject(arg, keepUnmock);
}
throw new TypeError(
`The toMock method support object and ES6 class.` +
` You give ${typeof arg}. You may add other types and send pull request.`
);
}
function toMockedInstance(arg, overrides = {}, keepUnmock) {
let mockedArg = toMock(arg, keepUnmock);
if (typeof mockedArg === 'function') {
let instance = Reflect.construct(mockedArg, []);
return Object.assign(instance, overrides);
}
return Object.assign(mockedArg, overrides);
}
function mockClass(ClassConstructor, keepUnmock) {
class Mock {}
Reflect.setPrototypeOf(Mock.prototype, ClassConstructor.prototype);
Reflect.setPrototypeOf(Mock, ClassConstructor);
mockPrototypeChain(Mock.prototype, keepUnmock);
mockStatic(ClassConstructor, Mock, keepUnmock);
return Mock;
}
function mockObject(object, keepUnmock) {
let newObject = Object.create(object);
mockPrototypeChain(newObject, keepUnmock);
return newObject;
}
function mockStatic(ClassConstructor, Mock, keepUnmock) {
while (ClassConstructor && Mock) {
mockOwnProperties(ClassConstructor, Mock, keepUnmock);
ClassConstructor = Reflect.getPrototypeOf(ClassConstructor);
Mock = Reflect.getPrototypeOf(Mock);
}
}
function mockPrototypeChain(prototype, keepUnmock) {
let originalPrototype = prototype;
while (prototype) {
let clonePrototype = Object.create(prototype, {
[MOCKED_PROTOTYPE_CHAIN]: {
value: true,
enumerable: false
}
});
mockOwnProperties(prototype, clonePrototype, keepUnmock);
Reflect.setPrototypeOf(originalPrototype, clonePrototype);
if (
originalPrototype[MOCKED_PROTOTYPE_CHAIN] &&
prototype[MOCKED_PROTOTYPE_CHAIN] &&
originalPrototype !== prototype
) {
return;
}
originalPrototype = prototype;
prototype = Reflect.getPrototypeOf(prototype);
}
}
function mockOwnProperties(original, mock, keepUnmock) {
const isKeepUnMockDefined = keepUnmock && typeof keepUnmock === 'function';
const isGlobalKeepUnMockDefined =
globalKeepUnmock && typeof globalKeepUnmock === 'function';
Object.entries(Object.getOwnPropertyDescriptors(original)).forEach(
([property, descriptor]) => {
try {
const keepUnmockArgs = { property, descriptor, original, mock };
if (
(isKeepUnMockDefined && keepUnmock(keepUnmockArgs)) ||
(isGlobalKeepUnMockDefined && globalKeepUnmock(keepUnmockArgs))
) {
return;
}
if (
typeof descriptor.get === 'function' ||
typeof descriptor.set === 'function'
) {
let _mockedValue = undefined;
Object.defineProperty(
mock,
property,
Object.assign({}, descriptor, {
get: () => _mockedValue,
set: value => {
_mockedValue = value;
}
})
);
} else if (typeof original[property] === 'function') {
mock[property] = globalMockMethod();
}
} catch (_) {} // eslint-disable-line no-empty
}
);
}
function setGlobalKeepUnmock(callback) {
globalKeepUnmock = callback;
}
function setGlobalMockMethod(mockMethod) {
globalMockMethod = mockMethod;
}
function objectKeepUnmock({ original }) {
return original === Object.prototype;
}
function functionKeepUnmock({ original }) {
return original === Function.prototype;
}
exports.default = toMock;
exports.toMock = toMock;
exports.toMockedInstance = toMockedInstance;
exports.mockClass = mockClass;
exports.mockObject = mockObject;
exports.mockPrototypeChain = mockPrototypeChain;
exports.mockOwnProperties = mockOwnProperties;
exports.setGlobalKeepUnmock = setGlobalKeepUnmock;
exports.setGlobalMockMethod = setGlobalMockMethod;
exports.objectKeepUnmock = objectKeepUnmock;
exports.functionKeepUnmock = functionKeepUnmock;