-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcreate-spy.js
88 lines (71 loc) · 2.49 KB
/
create-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
import { dequal } from "dequal";
import * as operations from "./operations.js";
import { startEspionage } from "./start-espionage.js";
export function spyFactory(configuration) {
const espionage = startEspionage(configuration);
const spy = new Proxy(function () {}, {
get: (target, property) => {
if (property === "then") return undefined;
if (typeof property != "symbol" && property in operations)
return operations[property](espionage, spy);
if (property === "bind") {
return (context) => {
espionage.update(({ instances }) => instances.push(context));
return spyFactory(configuration);
};
}
const hasKey = Reflect.has(target, property);
const value = hasKey
? Reflect.get(target, property)
: spyFactory(configuration);
if (!hasKey) {
target[property] = value;
espionage.update(({ readCount }) => (readCount[property] = 0));
}
espionage.update(({ readCount }) => readCount[property]++);
return value;
},
construct(target, args) {
const newSpy = spyFactory(configuration);
espionage.update(({ instances }) => instances.push(newSpy));
espionage.update(({ calls }) => calls.push(args));
return newSpy;
},
apply: function (_, __, argumentsList) {
espionage.update(({ calls }) => calls.push(argumentsList));
const hasQueuedReturns = espionage.report.oneTime.length !== 0;
const rehearsal = espionage.report.rehearsals.find(({ given }) =>
dequal(given, argumentsList)
);
const returnCondition =
rehearsal !== undefined
? "callIsRehearsed"
: hasQueuedReturns
? "oneTime"
: typeof espionage.report.returnValue == "function"
? "returnValue"
: "spy";
let result;
switch (returnCondition) {
case "callIsRehearsed":
result = rehearsal.finalValue(...argumentsList);
break;
case "oneTime":
const queuedReturn = espionage.report.oneTime.shift();
result = queuedReturn(...argumentsList);
break;
case "spy":
result = spyFactory(configuration);
break;
case "returnValue":
result = espionage.report.returnValue(...argumentsList);
break;
default:
result = spyFactory(configuration);
}
espionage.update(({ results }) => results.push(result));
return result;
},
});
return spy;
}