-
Notifications
You must be signed in to change notification settings - Fork 10
/
toHave.js
132 lines (114 loc) · 4.23 KB
/
toHave.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
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
121
122
123
124
125
126
127
128
129
130
131
132
(function() {
function testKeyList(keys, object, testFn) {
for (var i = 0, len = keys.length; i < len; i += 1) {
if (!testFn(object, keys[i])) {
return false;
}
}
return true;
}
function testKeyObject(referenceObject, object, testFn) {
if (typeof object != 'object') {
return false;
}
for (var key in referenceObject) {
if (typeof object[key] == 'object') {
if (!testKeyObject(referenceObject[key], object[key], testFn)) {
return false;
}
} else {
if (!testFn(object, key, referenceObject[key])) {
return false;
}
}
}
return true;
}
function hasProperty(object, key) {
return key in object;
}
function hasOwnProperty(object, key) {
return {}.hasOwnProperty.call(object, key);
}
function hasPropertyWithValue(object, key, value) {
return JSON.stringify(object[key]) === JSON.stringify(value);
}
function hasOwnPropertyWithValue(object, key, value) {
return hasOwnProperty(object, key) && hasPropertyWithValue(object, key, value);
}
function cloneArray(arr) {
return Array.prototype.slice.call(arr, 0);
}
function removeElementFromArray(arr, index) {
return arr.slice(0, index).concat(arr.slice(index + 1))
}
beforeEach(function() {
this.addMatchers({
toHaveBeenCalledXTimes: function(count) {
var callCount = this.actual.callCount;
var not = this.isNot ? "NOT " : "";
this.message = function() {
return 'Expected spy "' + this.actual.identity + '" ' + not + ' to have been called ' + count + ' times, but was ' + callCount + '.';
};
return callCount == count;
},
toHaveEnumerableProperties: function(properties) {
var propsToFind = cloneArray(properties);
var propsFound = [];
for (var propName in this.actual) {
var propFoundAt = propsToFind.indexOf(propName);
if (propFoundAt > -1) {
propsFound.push(propName);
propsToFind = removeElementFromArray(propsToFind, propFoundAt);
}
}
var not = this.isNot ? "NOT " : "";
this.message = function() {
return 'Expected object "' + this.actual + '" ' + not + ' to have enumerable properties "' + (not?propsFound:propsToFind).join(', ') + '".';
};
return propsToFind.length == 0;
},
toHaveLength: function(length) {
var not = this.isNot ? " NOT" : "";
this.message = function() {
return 'Expected ' + JSON.stringify(this.actual) + not + ' to have length ' + length + ' but was ' + this.actual.length;
};
return this.actual.length === length;
},
toHaveOwnProperties: function(name0, name1, name2) {
var array = Array.isArray(name0) ? name0 : arguments;
return testKeyList(array, this.actual, hasOwnProperty);
},
toHaveOwnPropertiesWithValues: function(obj) {
return testKeyObject(obj, this.actual, hasOwnPropertyWithValue);
},
toHaveProperties: function(name0, name1, name2) {
var array = Array.isArray(name0) ? name0 : arguments;
return testKeyList(array, this.actual, hasProperty);
},
toHavePropertiesWithValues: function(obj) {
var hasProps = testKeyObject(obj, this.actual, hasPropertyWithValue);
var not = this.isNot ? " NOT" : "";
this.message = function() {
// Show only the values we compare, which are all keys given in obj.
var keys = Object.keys(obj);
var allActuals = this.actual;
var actual = {};
keys.forEach(function(key) {
actual[key] = typeof allActuals != 'undefined' ? allActuals[key] : undefined
});
return 'Expected properties with values ' + JSON.stringify(actual) + not + ' to be ' + JSON.stringify(obj) + '.';
};
return hasProps;
},
toExactlyHaveProperties: function(name0, name1, name2) {
var actual = this.actual;
var numArguments = arguments.length;
for (var i = 0; i < numArguments; i += 1) {
if (!hasOwnProperty(actual, arguments[i])) { return false; }
}
return Object.keys(actual).length === numArguments;
}
});
});
}());