1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const lodash_1 = require("./wrap/lodash");
|
4 | const proxy_safe_clone_deep_with_1 = require("./wrap/proxy-safe-clone-deep-with");
|
5 | const calls_1 = require("./store/calls");
|
6 | const store_1 = require("./store");
|
7 | const arguments_1 = require("./stringify/arguments");
|
8 | const stubbings_1 = require("./store/stubbings");
|
9 | function explain(testDouble) {
|
10 | if (lodash_1.default.isFunction(testDouble)) {
|
11 | return explainFunction(testDouble);
|
12 | }
|
13 | else if (lodash_1.default.isObject(testDouble)) {
|
14 | return explainObject(testDouble);
|
15 | }
|
16 | else {
|
17 | return explainNonTestDouble(testDouble);
|
18 | }
|
19 | }
|
20 | exports.default = explain;
|
21 | function explainObject(obj) {
|
22 | const { explanations, children } = explainChildren(obj);
|
23 | return {
|
24 | name: null,
|
25 | callCount: 0,
|
26 | calls: [],
|
27 | description: describeObject(explanations),
|
28 | children,
|
29 | isTestDouble: explanations.length > 0
|
30 | };
|
31 | }
|
32 | function explainChildren(thing) {
|
33 | const explanations = [];
|
34 | const children = proxy_safe_clone_deep_with_1.default(thing, (val, key, obj, stack) => {
|
35 | if (lodash_1.default.isFunction(val) && stack) {
|
36 | return lodash_1.default.tap(explainFunction(val), (explanation) => {
|
37 | if (explanation.isTestDouble)
|
38 | explanations.push(explanation);
|
39 | });
|
40 | }
|
41 | });
|
42 | return { explanations, children };
|
43 | }
|
44 | function describeObject(explanations) {
|
45 | const count = explanations.length;
|
46 | if (count === 0)
|
47 | return 'This object contains no test doubles';
|
48 | return `This object contains ${count} test double function${count > 1 ? 's' : ''}: [${lodash_1.default.map(explanations, e => `"${e.name}"`).join(', ')}]`;
|
49 | }
|
50 | function explainFunction(testDouble) {
|
51 | if (store_1.default.for(testDouble, false) == null) {
|
52 | return explainNonTestDouble(testDouble);
|
53 | }
|
54 | const calls = calls_1.default.for(testDouble);
|
55 | const stubs = stubbings_1.default.for(testDouble);
|
56 | const { children } = explainChildren(testDouble);
|
57 | return {
|
58 | name: store_1.default.for(testDouble).name,
|
59 | callCount: calls.length,
|
60 | calls,
|
61 | description: testdoubleDescription(testDouble, stubs, calls) +
|
62 | stubbingDescription(stubs) +
|
63 | callDescription(calls),
|
64 | children,
|
65 | isTestDouble: true
|
66 | };
|
67 | }
|
68 | function explainNonTestDouble(thing) {
|
69 | return ({
|
70 | name: undefined,
|
71 | callCount: 0,
|
72 | calls: [],
|
73 | description: `This is not a test double${lodash_1.default.isFunction(thing) ? ' function' : ''}.`,
|
74 | isTestDouble: false
|
75 | });
|
76 | }
|
77 | function testdoubleDescription(testDouble, stubs, calls) {
|
78 | return `This test double ${stringifyName(testDouble)}has ${stubs.length} stubbings and ${calls.length} invocations.`;
|
79 | }
|
80 | function stubbingDescription(stubs) {
|
81 | return stubs.length > 0
|
82 | ? lodash_1.default.reduce(stubs, (desc, stub) => desc + `\n - when called with \`(${arguments_1.default(stub.args)})\`, then ${planFor(stub)} ${argsFor(stub)}.`, '\n\nStubbings:')
|
83 | : '';
|
84 | }
|
85 | function planFor(stub) {
|
86 | switch (stub.config.plan) {
|
87 | case 'thenCallback': return 'callback';
|
88 | case 'thenResolve': return 'resolve';
|
89 | case 'thenReject': return 'reject';
|
90 | default: return 'return';
|
91 | }
|
92 | }
|
93 | function argsFor(stub) {
|
94 | switch (stub.config.plan) {
|
95 | case 'thenCallback': return `\`(${arguments_1.default(stub.stubbedValues, ', ')})\``;
|
96 | default: return arguments_1.default(stub.stubbedValues, ', then ', '`');
|
97 | }
|
98 | }
|
99 | function callDescription(calls) {
|
100 | return calls.length > 0
|
101 | ? lodash_1.default.reduce(calls, (desc, call) => desc + `\n - called with \`(${arguments_1.default(call.cloneArgs)})\`.`, '\n\nInvocations:')
|
102 | : '';
|
103 | }
|
104 | function stringifyName(testDouble) {
|
105 | const name = store_1.default.for(testDouble).name;
|
106 | return name ? `\`${name}\` ` : '';
|
107 | }
|