| 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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 |
1x
47x
47x
47x
47x
15x
15x
28x
15x
15x
27x
47x
47x
4x
43x
1x
42x
8x
34x
73x
73x
73x
73x
14x
20x
135x
475x
168x
307x
307x
50x
257x
3x
254x
254x
254x
3x
251x
251x
21x
108x
254x
332x
2x
330x
135x
195x
79x
115x
24x
24x
91x
| import {isEqual} from 'lodash';
export const toDeepEqualMatcher = {
toDeepEqual: (util) => {
return {
compare: function(actuals, expecteds) {
const test = compareArrays(actuals, expecteds);
const result = { pass: (test === 'pass'), message: `compareArrays say: ${test}` + '\n\n' };
if (!result.pass && Array.isArray(actuals) && Array.isArray(expecteds)) {
result.message += 'Actual \n';
actuals.forEach(function(x) {
result.message += stringify(x) + '\n';
});
result.message += '\nExpected \n';
expecteds.forEach(function(x) {
result.message += stringify(x) + '\n';
});
}
return result;
}
};
}
};
function compareArrays(actuals, expecteds): any {
if ((actuals !== null && expecteds === null) || (actuals === null && expecteds !== null)) {
return 'Failed: Non-null does not compare to null';
}
if (actuals.length !== expecteds.length) {
return 'Failed: Arrays not the same length';
}
if (!Array.isArray(actuals) || !Array.isArray(expecteds)) {
return compareValues(expecteds, actuals, -1);
}
for (let idx = 0; idx < expecteds.length; idx++ ) {
const expected = expecteds[idx];
const actual = actuals[idx];
const result = compareValues(actual, expected, idx);
if (result !== 'pass') {
return result;
}
};
return 'pass';
}
/*
Compares objects irrespective of the property ordering
and only compares those properties supplied in 'expected'
Saves a bit of refactoring in tests when 'actual' property order changes,
or new properties are added that are irrelevent to the test
*/
function compareProperties(actual, expected, idx): any {
for (const key in expected) {
if (typeof expected[key] === 'function') {
continue; // ignore function properties
}
const value = expected[key];
if (value === undefined) {
continue;
}
if (!actual.hasOwnProperty(key)) {
return `Index: ${idx}, Actual has no property '${key}'`;
}
const otherValue = actual[key];
const types = compareTypes(value, otherValue, key, idx);
if (types !== 'pass') {
return types;
}
const values = compareValues(value, otherValue, idx);
if (values !== 'pass') {
return values;
}
}
return 'pass';
}
function compareTypes(value, otherValue, key, idx): any {
return typeof value === typeof otherValue ? 'pass'
: `Index: ${idx}, Key: '${key}', Types differ ('${typeof value}' vs '${typeof otherValue}')`;
}
function compareValues(value, otherValue, idx): any {
if ((value !== null && otherValue === null) || (value === null && otherValue !== null)) {
return 'Failed: Non-null does not compare to null';
}
if (typeof value === 'object') {
return compareProperties(value, otherValue, idx);
}
return value === otherValue ? 'pass'
: `Index: ${idx}, Not objects, values differ (${value} vs ${otherValue})`;
}
function stringify(x) {
return JSON.stringify(x, function(key, value) {
if (Array.isArray(value)) {
return '[' + value
.map(function(i) {
return '\n\t' + stringify(i);
}) + '\n]';
}
return value;
})
.replace(/\\"/g, '"')
.replace(/\\t/g, '\t')
.replace(/\\n/g, '\n');
}
|