UNPKG

3.97 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");
9function 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}
20exports.default = explain;
21function 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}
32function 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}
44function 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}
50function 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}
68function 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}
77function testdoubleDescription(testDouble, stubs, calls) {
78 return `This test double ${stringifyName(testDouble)}has ${stubs.length} stubbings and ${calls.length} invocations.`;
79}
80function 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}
85function 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}
93function 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}
99function 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}
104function stringifyName(testDouble) {
105 const name = store_1.default.for(testDouble).name;
106 return name ? `\`${name}\` ` : '';
107}