-
Notifications
You must be signed in to change notification settings - Fork 0
/
spy.js
93 lines (87 loc) · 2.05 KB
/
spy.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
/**
* Simple spying utility.
*
* Simple utility to spy on object methods. By not bothering with error checking
* (e.g.: Does the object exist? Does the method exist?), and keeping
* interactions with the spy to a minimum, we can make this very small and
* simple.
*
* The function returns a spy object, which tracks calls made to the method, and
* can be used to restore the original method implementation.
*
* No mocking or pattern matching is supported; it's up to the caller to
* implement those.
*
* @module jsutils/wunit/spy
*/
function spyOn(obj, method) {
let calls = [];
const {
configurable,
enumerable,
get,
set,
writable,
value,
} = Object.getOwnPropertyDescriptor(obj, method);
const isGetterSetter = get && set;
if (isGetterSetter) {
Object.defineProperty(obj, method, {
configurable,
enumerable,
get: () => {
const returnValue = get.apply(obj);
calls.push({ returnValue, args: [] });
return returnValue;
},
set: (...args) => {
set.apply(obj, args);
calls.push({ returnValue: undefined, args });
},
});
} else {
const realMethod = obj[method];
Object.defineProperty(obj, method, {
configurable,
enumerable,
writable: false,
value: (...args) => {
const returnValue = realMethod.apply(obj, args);
calls.push({ returnValue, args });
return returnValue;
},
});
}
return {
calls() {
return calls;
},
lastCall() {
return calls.length > 0 ? calls[calls.length - 1] : undefined;
},
wasCalled() {
return calls.length > 0;
},
reset() {
calls = [];
},
restore() {
if (isGetterSetter) {
Object.defineProperty(obj, method, {
configurable,
enumerable,
get,
set,
});
} else {
Object.defineProperty(obj, method, {
configurable,
enumerable,
writable,
value,
});
}
},
};
}
module.exports = spyOn;