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