oojspec 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/assets/javascripts/oojspec/runner.js.coffee +14 -7
- data/lib/oojspec/version.rb +1 -1
- data/vendor/assets/javascripts/buster/all.js.coffee +2 -0
- data/vendor/assets/javascripts/buster/bane.js +174 -0
- data/vendor/assets/javascripts/buster/buster-core.js +6 -5
- data/vendor/assets/javascripts/buster/expect.js +39 -35
- data/vendor/assets/javascripts/buster/formatio.js +215 -0
- data/vendor/assets/javascripts/buster/lodash.js +5163 -0
- data/vendor/assets/javascripts/buster/referee.js +692 -0
- data/vendor/assets/javascripts/buster/samsam.js +399 -0
- metadata +8 -5
- data/vendor/assets/javascripts/buster/buster-assertions.js +0 -782
- data/vendor/assets/javascripts/buster/buster-format.js +0 -199
@@ -0,0 +1,399 @@
|
|
1
|
+
((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
|
2
|
+
(typeof module === "object" &&
|
3
|
+
function (m) { module.exports = m(); }) || // Node
|
4
|
+
function (m) { this.samsam = m(); } // Browser globals
|
5
|
+
)(function () {
|
6
|
+
var o = Object.prototype;
|
7
|
+
var div = typeof document !== "undefined" && document.createElement("div");
|
8
|
+
|
9
|
+
function isNaN(value) {
|
10
|
+
// Unlike global isNaN, this avoids type coercion
|
11
|
+
// typeof check avoids IE host object issues, hat tip to
|
12
|
+
// lodash
|
13
|
+
var val = value; // JsLint thinks value !== value is "weird"
|
14
|
+
return typeof value === "number" && value !== val;
|
15
|
+
}
|
16
|
+
|
17
|
+
function getClass(value) {
|
18
|
+
// Returns the internal [[Class]] by calling Object.prototype.toString
|
19
|
+
// with the provided value as this. Return value is a string, naming the
|
20
|
+
// internal class, e.g. "Array"
|
21
|
+
return o.toString.call(value).split(/[ \]]/)[1];
|
22
|
+
}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* @name samsam.isArguments
|
26
|
+
* @param Object object
|
27
|
+
*
|
28
|
+
* Returns ``true`` if ``object`` is an ``arguments`` object,
|
29
|
+
* ``false`` otherwise.
|
30
|
+
*/
|
31
|
+
function isArguments(object) {
|
32
|
+
if (getClass(object) === 'Arguments') { return true; }
|
33
|
+
if (typeof object !== "object" || typeof object.length !== "number" ||
|
34
|
+
getClass(object) === "Array") {
|
35
|
+
return false;
|
36
|
+
}
|
37
|
+
if (typeof object.callee == "function") { return true; }
|
38
|
+
try {
|
39
|
+
object[object.length] = 6;
|
40
|
+
delete object[object.length];
|
41
|
+
} catch (e) {
|
42
|
+
return true;
|
43
|
+
}
|
44
|
+
return false;
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* @name samsam.isElement
|
49
|
+
* @param Object object
|
50
|
+
*
|
51
|
+
* Returns ``true`` if ``object`` is a DOM element node. Unlike
|
52
|
+
* Underscore.js/lodash, this function will return ``false`` if ``object``
|
53
|
+
* is an *element-like* object, i.e. a regular object with a ``nodeType``
|
54
|
+
* property that holds the value ``1``.
|
55
|
+
*/
|
56
|
+
function isElement(object) {
|
57
|
+
if (!object || object.nodeType !== 1 || !div) { return false; }
|
58
|
+
try {
|
59
|
+
object.appendChild(div);
|
60
|
+
object.removeChild(div);
|
61
|
+
} catch (e) {
|
62
|
+
return false;
|
63
|
+
}
|
64
|
+
return true;
|
65
|
+
}
|
66
|
+
|
67
|
+
/**
|
68
|
+
* @name samsam.keys
|
69
|
+
* @param Object object
|
70
|
+
*
|
71
|
+
* Return an array of own property names.
|
72
|
+
*/
|
73
|
+
function keys(object) {
|
74
|
+
var ks = [], prop;
|
75
|
+
for (prop in object) {
|
76
|
+
if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
|
77
|
+
}
|
78
|
+
return ks;
|
79
|
+
}
|
80
|
+
|
81
|
+
/**
|
82
|
+
* @name samsam.isDate
|
83
|
+
* @param Object value
|
84
|
+
*
|
85
|
+
* Returns true if the object is a ``Date``, or *date-like*. Duck typing
|
86
|
+
* of date objects work by checking that the object has a ``getTime``
|
87
|
+
* function whose return value equals the return value from the object's
|
88
|
+
* ``valueOf``.
|
89
|
+
*/
|
90
|
+
function isDate(value) {
|
91
|
+
return typeof value.getTime == "function" &&
|
92
|
+
value.getTime() == value.valueOf();
|
93
|
+
}
|
94
|
+
|
95
|
+
/**
|
96
|
+
* @name samsam.isNegZero
|
97
|
+
* @param Object value
|
98
|
+
*
|
99
|
+
* Returns ``true`` if ``value`` is ``-0``.
|
100
|
+
*/
|
101
|
+
function isNegZero(value) {
|
102
|
+
return value === 0 && 1 / value === -Infinity;
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
* @name samsam.equal
|
107
|
+
* @param Object obj1
|
108
|
+
* @param Object obj2
|
109
|
+
*
|
110
|
+
* Returns ``true`` if two objects are strictly equal. Compared to
|
111
|
+
* ``===`` there are two exceptions:
|
112
|
+
*
|
113
|
+
* - NaN is considered equal to NaN
|
114
|
+
* - -0 and +0 are not considered equal
|
115
|
+
*/
|
116
|
+
function identical(obj1, obj2) {
|
117
|
+
if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
|
118
|
+
return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
|
123
|
+
/**
|
124
|
+
* @name samsam.deepEqual
|
125
|
+
* @param Object obj1
|
126
|
+
* @param Object obj2
|
127
|
+
*
|
128
|
+
* Deep equal comparison. Two values are "deep equal" if:
|
129
|
+
*
|
130
|
+
* - They are equal, according to samsam.identical
|
131
|
+
* - They are both date objects representing the same time
|
132
|
+
* - They are both arrays containing elements that are all deepEqual
|
133
|
+
* - They are objects with the same set of properties, and each property
|
134
|
+
* in ``obj1`` is deepEqual to the corresponding property in ``obj2``
|
135
|
+
*
|
136
|
+
* Supports cyclic objects.
|
137
|
+
*/
|
138
|
+
function deepEqualCyclic(obj1, obj2) {
|
139
|
+
|
140
|
+
// used for cyclic comparison
|
141
|
+
// contain already visited objects
|
142
|
+
var objects1 = [],
|
143
|
+
objects2 = [],
|
144
|
+
// contain pathes (position in the object structure)
|
145
|
+
// of the already visited objects
|
146
|
+
// indexes same as in objects arrays
|
147
|
+
paths1 = [],
|
148
|
+
paths2 = [],
|
149
|
+
// contains combinations of already compared objects
|
150
|
+
// in the manner: { "$1['ref']$2['ref']": true }
|
151
|
+
compared = {};
|
152
|
+
|
153
|
+
/**
|
154
|
+
* used to check, if the value of a property is an object
|
155
|
+
* (cyclic logic is only needed for objects)
|
156
|
+
* only needed for cyclic logic
|
157
|
+
*/
|
158
|
+
function isObject(value) {
|
159
|
+
|
160
|
+
if (typeof value === 'object' && value !== null &&
|
161
|
+
!(value instanceof Boolean) &&
|
162
|
+
!(value instanceof Date) &&
|
163
|
+
!(value instanceof Number) &&
|
164
|
+
!(value instanceof RegExp) &&
|
165
|
+
!(value instanceof String)) {
|
166
|
+
|
167
|
+
return true;
|
168
|
+
}
|
169
|
+
|
170
|
+
return false;
|
171
|
+
}
|
172
|
+
|
173
|
+
/**
|
174
|
+
* returns the index of the given object in the
|
175
|
+
* given objects array, -1 if not contained
|
176
|
+
* only needed for cyclic logic
|
177
|
+
*/
|
178
|
+
function getIndex(objects, obj) {
|
179
|
+
|
180
|
+
var i;
|
181
|
+
for (i = 0; i < objects.length; i++) {
|
182
|
+
if (objects[i] === obj) {
|
183
|
+
return i;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
return -1;
|
188
|
+
}
|
189
|
+
|
190
|
+
// does the recursion for the deep equal check
|
191
|
+
return (function deepEqual(obj1, obj2, path1, path2) {
|
192
|
+
var type1 = typeof obj1;
|
193
|
+
var type2 = typeof obj2;
|
194
|
+
|
195
|
+
// == null also matches undefined
|
196
|
+
if (obj1 === obj2 ||
|
197
|
+
isNaN(obj1) || isNaN(obj2) ||
|
198
|
+
obj1 == null || obj2 == null ||
|
199
|
+
type1 !== "object" || type2 !== "object") {
|
200
|
+
|
201
|
+
return identical(obj1, obj2);
|
202
|
+
}
|
203
|
+
|
204
|
+
// Elements are only equal if identical(expected, actual)
|
205
|
+
if (isElement(obj1) || isElement(obj2)) { return false; }
|
206
|
+
|
207
|
+
var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
|
208
|
+
if (isDate1 || isDate2) {
|
209
|
+
if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
|
210
|
+
return false;
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
|
215
|
+
if (obj1.toString() !== obj2.toString()) { return false; }
|
216
|
+
}
|
217
|
+
|
218
|
+
var class1 = getClass(obj1);
|
219
|
+
var class2 = getClass(obj2);
|
220
|
+
var keys1 = keys(obj1);
|
221
|
+
var keys2 = keys(obj2);
|
222
|
+
|
223
|
+
if (isArguments(obj1) || isArguments(obj2)) {
|
224
|
+
if (obj1.length !== obj2.length) { return false; }
|
225
|
+
} else {
|
226
|
+
if (type1 !== type2 || class1 !== class2 ||
|
227
|
+
keys1.length !== keys2.length) {
|
228
|
+
return false;
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
232
|
+
var key, i, l,
|
233
|
+
// following vars are used for the cyclic logic
|
234
|
+
value1, value2,
|
235
|
+
isObject1, isObject2,
|
236
|
+
index1, index2,
|
237
|
+
newPath1, newPath2;
|
238
|
+
|
239
|
+
for (i = 0, l = keys1.length; i < l; i++) {
|
240
|
+
key = keys1[i];
|
241
|
+
if (!o.hasOwnProperty.call(obj2, key)) {
|
242
|
+
return false;
|
243
|
+
}
|
244
|
+
|
245
|
+
// Start of the cyclic logic
|
246
|
+
|
247
|
+
value1 = obj1[key];
|
248
|
+
value2 = obj2[key];
|
249
|
+
|
250
|
+
isObject1 = isObject(value1);
|
251
|
+
isObject2 = isObject(value2);
|
252
|
+
|
253
|
+
// determine, if the objects were already visited
|
254
|
+
// (it's faster to check for isObject first, than to
|
255
|
+
// get -1 from getIndex for non objects)
|
256
|
+
index1 = isObject1 ? getIndex(objects1, value1) : -1;
|
257
|
+
index2 = isObject2 ? getIndex(objects2, value2) : -1;
|
258
|
+
|
259
|
+
// determine the new pathes of the objects
|
260
|
+
// - for non cyclic objects the current path will be extended
|
261
|
+
// by current property name
|
262
|
+
// - for cyclic objects the stored path is taken
|
263
|
+
newPath1 = index1 !== -1
|
264
|
+
? paths1[index1]
|
265
|
+
: path1 + '[' + JSON.stringify(key) + ']';
|
266
|
+
newPath2 = index2 !== -1
|
267
|
+
? paths2[index2]
|
268
|
+
: path2 + '[' + JSON.stringify(key) + ']';
|
269
|
+
|
270
|
+
// stop recursion if current objects are already compared
|
271
|
+
if (compared[newPath1 + newPath2]) {
|
272
|
+
return true;
|
273
|
+
}
|
274
|
+
|
275
|
+
// remember the current objects and their pathes
|
276
|
+
if (index1 === -1 && isObject1) {
|
277
|
+
objects1.push(value1);
|
278
|
+
paths1.push(newPath1);
|
279
|
+
}
|
280
|
+
if (index2 === -1 && isObject2) {
|
281
|
+
objects2.push(value2);
|
282
|
+
paths2.push(newPath2);
|
283
|
+
}
|
284
|
+
|
285
|
+
// remember that the current objects are already compared
|
286
|
+
if (isObject1 && isObject2) {
|
287
|
+
compared[newPath1 + newPath2] = true;
|
288
|
+
}
|
289
|
+
|
290
|
+
// End of cyclic logic
|
291
|
+
|
292
|
+
// neither value1 nor value2 is a cycle
|
293
|
+
// continue with next level
|
294
|
+
if (!deepEqual(value1, value2, newPath1, newPath2)) {
|
295
|
+
return false;
|
296
|
+
}
|
297
|
+
}
|
298
|
+
|
299
|
+
return true;
|
300
|
+
|
301
|
+
}(obj1, obj2, '$1', '$2'));
|
302
|
+
}
|
303
|
+
|
304
|
+
var match;
|
305
|
+
|
306
|
+
function arrayContains(array, subset) {
|
307
|
+
if (subset.length === 0) { return true; }
|
308
|
+
var i, l, j, k;
|
309
|
+
for (i = 0, l = array.length; i < l; ++i) {
|
310
|
+
if (match(array[i], subset[0])) {
|
311
|
+
for (j = 0, k = subset.length; j < k; ++j) {
|
312
|
+
if (!match(array[i + j], subset[j])) { return false; }
|
313
|
+
}
|
314
|
+
return true;
|
315
|
+
}
|
316
|
+
}
|
317
|
+
return false;
|
318
|
+
}
|
319
|
+
|
320
|
+
/**
|
321
|
+
* @name samsam.match
|
322
|
+
* @param Object object
|
323
|
+
* @param Object matcher
|
324
|
+
*
|
325
|
+
* Compare arbitrary value ``object`` with matcher.
|
326
|
+
*/
|
327
|
+
match = function match(object, matcher) {
|
328
|
+
if (matcher && typeof matcher.test === "function") {
|
329
|
+
return matcher.test(object);
|
330
|
+
}
|
331
|
+
|
332
|
+
if (typeof matcher === "function") {
|
333
|
+
return matcher(object) === true;
|
334
|
+
}
|
335
|
+
|
336
|
+
if (typeof matcher === "string") {
|
337
|
+
matcher = matcher.toLowerCase();
|
338
|
+
var notNull = typeof object === "string" || !!object;
|
339
|
+
return notNull &&
|
340
|
+
(String(object)).toLowerCase().indexOf(matcher) >= 0;
|
341
|
+
}
|
342
|
+
|
343
|
+
if (typeof matcher === "number") {
|
344
|
+
return matcher === object;
|
345
|
+
}
|
346
|
+
|
347
|
+
if (typeof matcher === "boolean") {
|
348
|
+
return matcher === object;
|
349
|
+
}
|
350
|
+
|
351
|
+
if (typeof(matcher) === "undefined") {
|
352
|
+
return typeof(object) === "undefined";
|
353
|
+
}
|
354
|
+
|
355
|
+
if (matcher === null) {
|
356
|
+
return object === null;
|
357
|
+
}
|
358
|
+
|
359
|
+
if (getClass(object) === "Array" && getClass(matcher) === "Array") {
|
360
|
+
return arrayContains(object, matcher);
|
361
|
+
}
|
362
|
+
|
363
|
+
if (matcher && typeof matcher === "object") {
|
364
|
+
if (matcher === object) {
|
365
|
+
return true;
|
366
|
+
}
|
367
|
+
var prop;
|
368
|
+
for (prop in matcher) {
|
369
|
+
var value = object[prop];
|
370
|
+
if (typeof value === "undefined" &&
|
371
|
+
typeof object.getAttribute === "function") {
|
372
|
+
value = object.getAttribute(prop);
|
373
|
+
}
|
374
|
+
if (matcher[prop] === null || typeof matcher[prop] === 'undefined') {
|
375
|
+
if (value !== matcher[prop]) {
|
376
|
+
return false;
|
377
|
+
}
|
378
|
+
} else if (typeof value === "undefined" || !match(value, matcher[prop])) {
|
379
|
+
return false;
|
380
|
+
}
|
381
|
+
}
|
382
|
+
return true;
|
383
|
+
}
|
384
|
+
|
385
|
+
throw new Error("Matcher was not a string, a number, a " +
|
386
|
+
"function, a boolean or an object");
|
387
|
+
};
|
388
|
+
|
389
|
+
return {
|
390
|
+
isArguments: isArguments,
|
391
|
+
isElement: isElement,
|
392
|
+
isDate: isDate,
|
393
|
+
isNegZero: isNegZero,
|
394
|
+
identical: identical,
|
395
|
+
deepEqual: deepEqualCyclic,
|
396
|
+
match: match,
|
397
|
+
keys: keys
|
398
|
+
};
|
399
|
+
});
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oojspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo Rosenfeld Rosas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coffee-rails
|
@@ -65,12 +65,15 @@ files:
|
|
65
65
|
- lib/tasks/oojspec_tasks.rake
|
66
66
|
- vendor/assets/images/buster/logo.png
|
67
67
|
- vendor/assets/javascripts/buster/all.js.coffee
|
68
|
-
- vendor/assets/javascripts/buster/
|
68
|
+
- vendor/assets/javascripts/buster/bane.js
|
69
69
|
- vendor/assets/javascripts/buster/buster-core.js
|
70
70
|
- vendor/assets/javascripts/buster/buster-event-emitter.js
|
71
|
-
- vendor/assets/javascripts/buster/buster-format.js
|
72
71
|
- vendor/assets/javascripts/buster/expect.js
|
72
|
+
- vendor/assets/javascripts/buster/formatio.js
|
73
73
|
- vendor/assets/javascripts/buster/html.js
|
74
|
+
- vendor/assets/javascripts/buster/lodash.js
|
75
|
+
- vendor/assets/javascripts/buster/referee.js
|
76
|
+
- vendor/assets/javascripts/buster/samsam.js
|
74
77
|
- vendor/assets/javascripts/buster/stack-filter.js
|
75
78
|
- vendor/assets/stylesheets/buster/buster-test.css
|
76
79
|
homepage: http://github.com/rosenfeld/oojspec
|
@@ -92,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
95
|
version: '0'
|
93
96
|
requirements: []
|
94
97
|
rubyforge_project:
|
95
|
-
rubygems_version: 2.
|
98
|
+
rubygems_version: 2.4.5
|
96
99
|
signing_key:
|
97
100
|
specification_version: 4
|
98
101
|
summary: Object-oriented client-side testing
|
@@ -1,782 +0,0 @@
|
|
1
|
-
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
|
2
|
-
/*global buster, require, module*/
|
3
|
-
(function () {
|
4
|
-
var isCommonJS = typeof require == "function" && typeof module == "object";
|
5
|
-
if (isCommonJS) buster = require("buster-core");
|
6
|
-
var toString = Object.prototype.toString;
|
7
|
-
var slice = Array.prototype.slice;
|
8
|
-
var assert, refute, ba = buster.assertions = buster.eventEmitter.create();
|
9
|
-
|
10
|
-
if (isCommonJS) {
|
11
|
-
module.exports = buster.assertions;
|
12
|
-
}
|
13
|
-
|
14
|
-
function countAssertion() {
|
15
|
-
if (typeof ba.count != "number") {
|
16
|
-
ba.count = 0;
|
17
|
-
}
|
18
|
-
|
19
|
-
ba.count += 1;
|
20
|
-
}
|
21
|
-
|
22
|
-
ba.count = countAssertion;
|
23
|
-
|
24
|
-
function assertEnoughArguments(name, args, num) {
|
25
|
-
if (args.length < num) {
|
26
|
-
ba.fail("[" + name + "] Expected to receive at least " +
|
27
|
-
num + " argument" + (num > 1 ? "s" : ""));
|
28
|
-
return false;
|
29
|
-
}
|
30
|
-
|
31
|
-
return true;
|
32
|
-
}
|
33
|
-
|
34
|
-
function defineAssertion(type, name, func, fl, messageValues) {
|
35
|
-
ba[type][name] = function () {
|
36
|
-
var fullName = type + "." + name;
|
37
|
-
countAssertion();
|
38
|
-
if (!assertEnoughArguments(fullName, arguments, fl || func.length)) return;
|
39
|
-
|
40
|
-
var failed = false;
|
41
|
-
|
42
|
-
var ctx = {
|
43
|
-
fail: function () {
|
44
|
-
failed = true;
|
45
|
-
var failArgs = [type, name].concat(slice.call(arguments));
|
46
|
-
fail.apply(this, failArgs);
|
47
|
-
return true;
|
48
|
-
}
|
49
|
-
};
|
50
|
-
|
51
|
-
var args = slice.call(arguments, 0);
|
52
|
-
|
53
|
-
if (typeof messageValues == "function") {
|
54
|
-
args = messageValues.apply(this, args);
|
55
|
-
}
|
56
|
-
|
57
|
-
if (!func.apply(ctx, arguments)) {
|
58
|
-
return fail.apply(ctx, [type, name, "message"].concat(args));
|
59
|
-
}
|
60
|
-
|
61
|
-
if (!failed) {
|
62
|
-
ba.emit.apply(ba, ["pass", fullName].concat(args));
|
63
|
-
}
|
64
|
-
};
|
65
|
-
}
|
66
|
-
|
67
|
-
ba.add = function (name, options) {
|
68
|
-
var refuteArgs;
|
69
|
-
|
70
|
-
if (options.refute) {
|
71
|
-
refuteArgs = options.refute.length;
|
72
|
-
} else {
|
73
|
-
refuteArgs = options.assert.length;
|
74
|
-
options.refute = function () {
|
75
|
-
return !options.assert.apply(this, arguments);
|
76
|
-
};
|
77
|
-
}
|
78
|
-
|
79
|
-
var values = options && options.values; // TODO: Remove
|
80
|
-
defineAssertion("assert", name, options.assert, options.assert.length, values);
|
81
|
-
defineAssertion("refute", name, options.refute, refuteArgs, values);
|
82
|
-
|
83
|
-
assert[name].message = options.assertMessage;
|
84
|
-
refute[name].message = options.refuteMessage;
|
85
|
-
|
86
|
-
if (options.expectation) {
|
87
|
-
if (ba.expect && ba.expect.wrapAssertion) {
|
88
|
-
ba.expect.wrapAssertion(name, options.expectation);
|
89
|
-
} else {
|
90
|
-
assert[name].expectationName = options.expectation;
|
91
|
-
refute[name].expectationName = options.expectation;
|
92
|
-
}
|
93
|
-
}
|
94
|
-
};
|
95
|
-
|
96
|
-
function interpolate(string, property, value) {
|
97
|
-
return string.replace(new RegExp("\\$\\{" + property + "\\}", "g"), value);
|
98
|
-
}
|
99
|
-
|
100
|
-
function interpolatePosArg(message, values) {
|
101
|
-
var value;
|
102
|
-
values = values || [];
|
103
|
-
|
104
|
-
for (var i = 0, l = values.length; i < l; i++) {
|
105
|
-
message = interpolate(message, i, ba.format(values[i]));
|
106
|
-
}
|
107
|
-
|
108
|
-
return message;
|
109
|
-
}
|
110
|
-
|
111
|
-
function interpolateProperties(msg, properties) {
|
112
|
-
for (var prop in properties) {
|
113
|
-
msg = interpolate(msg, prop, ba.format(properties[prop]));
|
114
|
-
}
|
115
|
-
|
116
|
-
return msg || "";
|
117
|
-
}
|
118
|
-
|
119
|
-
function fail(type, assertion, msg) {
|
120
|
-
delete this.fail;
|
121
|
-
var message = interpolateProperties(
|
122
|
-
interpolatePosArg(ba[type][assertion][msg] || msg,
|
123
|
-
[].slice.call(arguments, 3)), this);
|
124
|
-
ba.fail("[" + type + "." + assertion + "] " + message);
|
125
|
-
}
|
126
|
-
|
127
|
-
function isDate(value) {
|
128
|
-
// Duck typed dates, allows objects to take on the role of dates
|
129
|
-
// without actually being dates
|
130
|
-
return typeof value.getTime == "function" &&
|
131
|
-
value.getTime() == value.valueOf();
|
132
|
-
}
|
133
|
-
|
134
|
-
ba.isDate = isDate;
|
135
|
-
|
136
|
-
// Fixes NaN === NaN (should be true) and
|
137
|
-
// -0 === +0 (should be false)
|
138
|
-
// http://wiki.ecmascript.org/doku.php?id=harmony:egal
|
139
|
-
function egal(x, y) {
|
140
|
-
if (x === y) {
|
141
|
-
// 0 === -0, but they are not identical
|
142
|
-
return x !== 0 || 1 / x === 1 / y;
|
143
|
-
}
|
144
|
-
|
145
|
-
// NaN !== NaN, but they are identical.
|
146
|
-
// NaNs are the only non-reflexive value, i.e., if x !== x,
|
147
|
-
// then x is a NaN.
|
148
|
-
// isNaN is broken: it converts its argument to number, so
|
149
|
-
// isNaN("foo") => true
|
150
|
-
return x !== x && y !== y;
|
151
|
-
}
|
152
|
-
|
153
|
-
function areEqual(expected, actual) {
|
154
|
-
if (egal(expected, actual)) {
|
155
|
-
return true;
|
156
|
-
}
|
157
|
-
|
158
|
-
// Elements are only equal if expected === actual
|
159
|
-
if (buster.isElement(expected) || buster.isElement(actual)) {
|
160
|
-
return false;
|
161
|
-
}
|
162
|
-
|
163
|
-
// null and undefined only pass for null === null and
|
164
|
-
// undefined === undefined
|
165
|
-
/*jsl: ignore*/
|
166
|
-
if (expected == null || actual == null) {
|
167
|
-
return actual === expected;
|
168
|
-
}
|
169
|
-
/*jsl: end*/
|
170
|
-
|
171
|
-
if (isDate(expected) || isDate(actual)) {
|
172
|
-
return isDate(expected) && isDate(actual) &&
|
173
|
-
expected.getTime() == actual.getTime();
|
174
|
-
}
|
175
|
-
|
176
|
-
var useCoercingEquality = typeof expected != "object" || typeof actual != "object";
|
177
|
-
|
178
|
-
if (expected instanceof RegExp && actual instanceof RegExp) {
|
179
|
-
if (expected.toString() != actual.toString()) {
|
180
|
-
return false;
|
181
|
-
}
|
182
|
-
|
183
|
-
useCoercingEquality = false;
|
184
|
-
}
|
185
|
-
|
186
|
-
// Arrays can only be equal to arrays
|
187
|
-
var expectedStr = toString.call(expected);
|
188
|
-
var actualStr = toString.call(actual);
|
189
|
-
|
190
|
-
// Coerce and compare when primitives are involved
|
191
|
-
if (useCoercingEquality) {
|
192
|
-
return expectedStr != "[object Array]" && actualStr != "[object Array]" &&
|
193
|
-
expected == actual;
|
194
|
-
}
|
195
|
-
|
196
|
-
var expectedKeys = ba.keys(expected);
|
197
|
-
var actualKeys = ba.keys(actual);
|
198
|
-
|
199
|
-
if (isArguments(expected) || isArguments(actual)) {
|
200
|
-
if (expected.length != actual.length) {
|
201
|
-
return false;
|
202
|
-
}
|
203
|
-
} else {
|
204
|
-
if (typeof expected != typeof actual || expectedStr != actualStr ||
|
205
|
-
expectedKeys.length != actualKeys.length) {
|
206
|
-
return false;
|
207
|
-
}
|
208
|
-
}
|
209
|
-
|
210
|
-
var key;
|
211
|
-
|
212
|
-
for (var i = 0, l = expectedKeys.length; i < l; i++) {
|
213
|
-
key = expectedKeys[i];
|
214
|
-
|
215
|
-
if (!Object.prototype.hasOwnProperty.call(actual, key) ||
|
216
|
-
!areEqual(expected[key], actual[key])) {
|
217
|
-
return false;
|
218
|
-
}
|
219
|
-
}
|
220
|
-
|
221
|
-
return true;
|
222
|
-
}
|
223
|
-
|
224
|
-
ba.deepEqual = areEqual;
|
225
|
-
|
226
|
-
assert = ba.assert = function assert(actual, message) {
|
227
|
-
countAssertion();
|
228
|
-
if (!assertEnoughArguments("assert", arguments, 1)) return;
|
229
|
-
|
230
|
-
if (!actual) {
|
231
|
-
var val = ba.format(actual);
|
232
|
-
ba.fail(message || "[assert] Expected " + val + " to be truthy");
|
233
|
-
} else {
|
234
|
-
ba.emit("pass", "assert", message || "", actual);
|
235
|
-
}
|
236
|
-
};
|
237
|
-
|
238
|
-
assert.toString = function () {
|
239
|
-
return "buster.assert";
|
240
|
-
};
|
241
|
-
|
242
|
-
refute = ba.refute = function (actual, message) {
|
243
|
-
countAssertion();
|
244
|
-
if (!assertEnoughArguments("refute", arguments, 1)) return;
|
245
|
-
|
246
|
-
if (actual) {
|
247
|
-
var val = ba.format(actual);
|
248
|
-
ba.fail(message || "[refute] Expected " + val + " to be falsy");
|
249
|
-
} else {
|
250
|
-
ba.emit("pass", "refute", message || "", actual);
|
251
|
-
}
|
252
|
-
};
|
253
|
-
|
254
|
-
assert.message = "[assert] Expected ${0} to be truthy";
|
255
|
-
ba.count = 0;
|
256
|
-
|
257
|
-
ba.fail = function (message) {
|
258
|
-
var exception = new Error(message);
|
259
|
-
exception.name = "AssertionError";
|
260
|
-
|
261
|
-
try {
|
262
|
-
throw exception;
|
263
|
-
} catch (e) {
|
264
|
-
ba.emit("failure", e);
|
265
|
-
}
|
266
|
-
|
267
|
-
if (typeof ba.throwOnFailure != "boolean" || ba.throwOnFailure) {
|
268
|
-
throw exception;
|
269
|
-
}
|
270
|
-
};
|
271
|
-
|
272
|
-
ba.format = function (object) {
|
273
|
-
return "" + object;
|
274
|
-
};
|
275
|
-
|
276
|
-
function msg(message) {
|
277
|
-
if (!message) { return ""; }
|
278
|
-
return message + (/[.:!?]$/.test(message) ? " " : ": ");
|
279
|
-
}
|
280
|
-
|
281
|
-
function actualAndExpectedMessageValues(actual, expected, message) {
|
282
|
-
return [actual, expected, msg(message)]
|
283
|
-
}
|
284
|
-
|
285
|
-
function actualMessageValues(actual) {
|
286
|
-
return [actual, msg(arguments[1])];
|
287
|
-
}
|
288
|
-
|
289
|
-
function actualAndTypeOfMessageValues(actual) {
|
290
|
-
return [actual, typeof actual, msg(arguments[1])];
|
291
|
-
}
|
292
|
-
|
293
|
-
ba.add("same", {
|
294
|
-
assert: function (actual, expected) {
|
295
|
-
return egal(actual, expected);
|
296
|
-
},
|
297
|
-
refute: function (actual, expected) {
|
298
|
-
return !egal(actual, expected);
|
299
|
-
},
|
300
|
-
assertMessage: "${2}${0} expected to be the same object as ${1}",
|
301
|
-
refuteMessage: "${2}${0} expected not to be the same object as ${1}",
|
302
|
-
expectation: "toBe",
|
303
|
-
values: actualAndExpectedMessageValues
|
304
|
-
});
|
305
|
-
|
306
|
-
function multiLineStringDiff(actual, expected, message) {
|
307
|
-
if (actual == expected) return true;
|
308
|
-
|
309
|
-
var message = interpolatePosArg(assert.equals.multiLineStringHeading, [message]),
|
310
|
-
actualLines = actual.split("\n"),
|
311
|
-
expectedLines = expected.split("\n"),
|
312
|
-
lineCount = Math.max(expectedLines.length, actualLines.length),
|
313
|
-
lines = [];
|
314
|
-
|
315
|
-
for (var i = 0; i < lineCount; ++i) {
|
316
|
-
if (expectedLines[i] != actualLines[i]) {
|
317
|
-
lines.push("line " + (i + 1) + ": " + (expectedLines[i] || "") +
|
318
|
-
"\nwas: " + (actualLines[i] || ""));
|
319
|
-
}
|
320
|
-
}
|
321
|
-
|
322
|
-
ba.fail("[assert.equals] " + message + lines.join("\n\n"));
|
323
|
-
return false;
|
324
|
-
}
|
325
|
-
|
326
|
-
ba.add("equals", {
|
327
|
-
assert: function (actual, expected) {
|
328
|
-
if (typeof actual == "string" && typeof expected == "string" &&
|
329
|
-
(actual.indexOf("\n") >= 0 || expected.indexOf("\n") >= 0)) {
|
330
|
-
var message = msg(arguments[2]);
|
331
|
-
return multiLineStringDiff.call(this, actual, expected, message);
|
332
|
-
}
|
333
|
-
|
334
|
-
return areEqual(actual, expected);
|
335
|
-
},
|
336
|
-
|
337
|
-
refute: function (actual, expected) {
|
338
|
-
return !areEqual(actual, expected);
|
339
|
-
},
|
340
|
-
|
341
|
-
assertMessage: "${2}${0} expected to be equal to ${1}",
|
342
|
-
refuteMessage: "${2}${0} expected not to be equal to ${1}",
|
343
|
-
expectation: "toEqual",
|
344
|
-
values: actualAndExpectedMessageValues
|
345
|
-
});
|
346
|
-
|
347
|
-
assert.equals.multiLineStringHeading = "${0}Expected multi-line strings to be equal:\n";
|
348
|
-
|
349
|
-
ba.add("greater", {
|
350
|
-
assert: function (actual, expected) {
|
351
|
-
return actual > expected;
|
352
|
-
},
|
353
|
-
|
354
|
-
assertMessage: "${2}Expected ${0} to be greater than ${1}",
|
355
|
-
refuteMessage: "${2}Expected ${0} to be less than or equal to ${1}",
|
356
|
-
expectation: "toBeGreaterThan",
|
357
|
-
values: actualAndExpectedMessageValues
|
358
|
-
});
|
359
|
-
|
360
|
-
ba.add("less", {
|
361
|
-
assert: function (actual, expected) {
|
362
|
-
return actual < expected;
|
363
|
-
},
|
364
|
-
|
365
|
-
assertMessage: "${2}Expected ${0} to be less than ${1}",
|
366
|
-
refuteMessage: "${2}Expected ${0} to be greater than or equal to ${1}",
|
367
|
-
expectation: "toBeLessThan",
|
368
|
-
values: actualAndExpectedMessageValues
|
369
|
-
});
|
370
|
-
|
371
|
-
ba.add("defined", {
|
372
|
-
assert: function (actual) {
|
373
|
-
return typeof actual != "undefined";
|
374
|
-
},
|
375
|
-
assertMessage: "${2}Expected to be defined",
|
376
|
-
refuteMessage: "${2}Expected ${0} (${1}) not to be defined",
|
377
|
-
expectation: "toBeDefined",
|
378
|
-
values: actualAndTypeOfMessageValues
|
379
|
-
});
|
380
|
-
|
381
|
-
ba.add("isNull", {
|
382
|
-
assert: function (actual) {
|
383
|
-
return actual === null;
|
384
|
-
},
|
385
|
-
assertMessage: "${1}Expected ${0} to be null",
|
386
|
-
refuteMessage: "${1}Expected not to be null",
|
387
|
-
expectation: "toBeNull",
|
388
|
-
values: actualMessageValues
|
389
|
-
});
|
390
|
-
|
391
|
-
function match(object, matcher) {
|
392
|
-
if (matcher && typeof matcher.test == "function") {
|
393
|
-
return matcher.test(object);
|
394
|
-
}
|
395
|
-
|
396
|
-
if (typeof matcher == "function") {
|
397
|
-
return matcher(object) === true;
|
398
|
-
}
|
399
|
-
|
400
|
-
if (typeof matcher == "string") {
|
401
|
-
matcher = matcher.toLowerCase();
|
402
|
-
return !!object && ("" + object).toLowerCase().indexOf(matcher) >= 0;
|
403
|
-
}
|
404
|
-
|
405
|
-
if (typeof matcher == "number") {
|
406
|
-
return matcher == object;
|
407
|
-
}
|
408
|
-
|
409
|
-
if (typeof matcher == "boolean") {
|
410
|
-
return matcher === object;
|
411
|
-
}
|
412
|
-
|
413
|
-
if (matcher && typeof matcher == "object") {
|
414
|
-
for (var prop in matcher) {
|
415
|
-
if (!match(object[prop], matcher[prop])) {
|
416
|
-
return false;
|
417
|
-
}
|
418
|
-
}
|
419
|
-
|
420
|
-
return true;
|
421
|
-
}
|
422
|
-
|
423
|
-
throw new Error("Matcher (" + ba.format(matcher) + ") was not a " +
|
424
|
-
"string, a number, a function, a boolean or an object");
|
425
|
-
}
|
426
|
-
|
427
|
-
ba.match = match;
|
428
|
-
|
429
|
-
ba.add("match", {
|
430
|
-
assert: function (actual, matcher) {
|
431
|
-
var passed;
|
432
|
-
|
433
|
-
try {
|
434
|
-
passed = match(actual, matcher);
|
435
|
-
} catch (e) {
|
436
|
-
return this.fail("exceptionMessage", e.message, msg(arguments[2]));
|
437
|
-
}
|
438
|
-
|
439
|
-
return passed;
|
440
|
-
},
|
441
|
-
|
442
|
-
refute: function (actual, matcher) {
|
443
|
-
var passed;
|
444
|
-
|
445
|
-
try {
|
446
|
-
passed = match(actual, matcher);
|
447
|
-
} catch (e) {
|
448
|
-
return this.fail("exceptionMessage", e.message);
|
449
|
-
}
|
450
|
-
|
451
|
-
return !passed;
|
452
|
-
},
|
453
|
-
|
454
|
-
assertMessage: "${2}${0} expected to match ${1}",
|
455
|
-
refuteMessage: "${2}${0} expected not to match ${1}",
|
456
|
-
expectation: "toMatch",
|
457
|
-
values: actualAndExpectedMessageValues
|
458
|
-
});
|
459
|
-
|
460
|
-
assert.match.exceptionMessage = "${1}${0}";
|
461
|
-
refute.match.exceptionMessage = "${1}${0}";
|
462
|
-
|
463
|
-
ba.add("isObject", {
|
464
|
-
assert: function (actual) {
|
465
|
-
return typeof actual == "object" && !!actual;
|
466
|
-
},
|
467
|
-
assertMessage: "${2}${0} (${1}) expected to be object and not null",
|
468
|
-
refuteMessage: "${2}${0} expected to be null or not an object",
|
469
|
-
expectation: "toBeObject",
|
470
|
-
values: actualAndTypeOfMessageValues
|
471
|
-
});
|
472
|
-
|
473
|
-
ba.add("isFunction", {
|
474
|
-
assert: function (actual) {
|
475
|
-
return typeof actual == "function";
|
476
|
-
},
|
477
|
-
assertMessage: "${2}${0} (${1}) expected to be function",
|
478
|
-
refuteMessage: "${2}${0} expected not to be function",
|
479
|
-
expectation: "toBeFunction",
|
480
|
-
values: function (actual) {
|
481
|
-
return [("" + actual).replace("\n", ""), typeof actual, msg(arguments[1])];
|
482
|
-
}
|
483
|
-
});
|
484
|
-
|
485
|
-
ba.add("isTrue", {
|
486
|
-
assert: function (actual) {
|
487
|
-
return actual === true;
|
488
|
-
},
|
489
|
-
assertMessage: "${1}Expected ${0} to be true",
|
490
|
-
refuteMessage: "${1}Expected ${0} to not be true",
|
491
|
-
expectation: "toBeTrue",
|
492
|
-
values: actualMessageValues
|
493
|
-
});
|
494
|
-
|
495
|
-
ba.add("isFalse", {
|
496
|
-
assert: function (actual) {
|
497
|
-
return actual === false;
|
498
|
-
},
|
499
|
-
assertMessage: "${1}Expected ${0} to be false",
|
500
|
-
refuteMessage: "${1}Expected ${0} to not be false",
|
501
|
-
expectation: "toBeFalse",
|
502
|
-
values: actualMessageValues
|
503
|
-
});
|
504
|
-
|
505
|
-
ba.add("isString", {
|
506
|
-
assert: function (actual) {
|
507
|
-
return typeof actual == "string";
|
508
|
-
},
|
509
|
-
assertMessage: "${2}Expected ${0} (${1}) to be string",
|
510
|
-
refuteMessage: "${2}Expected ${0} not to be string",
|
511
|
-
expectation: "toBeString",
|
512
|
-
values: actualAndTypeOfMessageValues
|
513
|
-
});
|
514
|
-
|
515
|
-
ba.add("isBoolean", {
|
516
|
-
assert: function (actual) {
|
517
|
-
return typeof actual == "boolean";
|
518
|
-
},
|
519
|
-
assertMessage: "${2}Expected ${0} (${1}) to be boolean",
|
520
|
-
refuteMessage: "${2}Expected ${0} not to be boolean",
|
521
|
-
expectation: "toBeBoolean",
|
522
|
-
values: actualAndTypeOfMessageValues
|
523
|
-
});
|
524
|
-
|
525
|
-
ba.add("isNumber", {
|
526
|
-
assert: function (actual) {
|
527
|
-
return typeof actual == "number" && !isNaN(actual);
|
528
|
-
},
|
529
|
-
assertMessage: "${2}Expected ${0} (${1}) to be a non-NaN number",
|
530
|
-
refuteMessage: "${2}Expected ${0} to be NaN or another non-number value",
|
531
|
-
expectation: "toBeNumber",
|
532
|
-
values: actualAndTypeOfMessageValues
|
533
|
-
});
|
534
|
-
|
535
|
-
ba.add("isNaN", {
|
536
|
-
assert: function (actual) {
|
537
|
-
return typeof actual == "number" && isNaN(actual);
|
538
|
-
},
|
539
|
-
assertMessage: "${2}Expected ${0} to be NaN",
|
540
|
-
refuteMessage: "${2}Expected not to be NaN",
|
541
|
-
expectation: "toBeNaN",
|
542
|
-
values: actualAndTypeOfMessageValues
|
543
|
-
});
|
544
|
-
|
545
|
-
ba.add("isArray", {
|
546
|
-
assert: function (actual) {
|
547
|
-
return toString.call(actual) == "[object Array]";
|
548
|
-
},
|
549
|
-
assertMessage: "${2}Expected ${0} to be array",
|
550
|
-
refuteMessage: "${2}Expected ${0} not to be array",
|
551
|
-
expectation: "toBeArray",
|
552
|
-
values: actualAndTypeOfMessageValues
|
553
|
-
});
|
554
|
-
|
555
|
-
function isArrayLike(object) {
|
556
|
-
return toString.call(object) == "[object Array]" ||
|
557
|
-
(!!object && typeof object.length == "number" &&
|
558
|
-
typeof object.splice == "function") ||
|
559
|
-
ba.isArguments(object);
|
560
|
-
}
|
561
|
-
|
562
|
-
ba.isArrayLike = isArrayLike;
|
563
|
-
|
564
|
-
ba.add("isArrayLike", {
|
565
|
-
assert: function (actual) {
|
566
|
-
return isArrayLike(actual);
|
567
|
-
},
|
568
|
-
assertMessage: "${2}Expected ${0} to be array like",
|
569
|
-
refuteMessage: "${2}Expected ${0} not to be array like",
|
570
|
-
expectation: "toBeArrayLike",
|
571
|
-
values: actualAndTypeOfMessageValues
|
572
|
-
});
|
573
|
-
|
574
|
-
function captureException(callback) {
|
575
|
-
try {
|
576
|
-
callback();
|
577
|
-
} catch (e) {
|
578
|
-
return e;
|
579
|
-
}
|
580
|
-
|
581
|
-
return null;
|
582
|
-
}
|
583
|
-
|
584
|
-
ba.captureException = captureException;
|
585
|
-
|
586
|
-
assert.exception = function (callback, exception, message) {
|
587
|
-
countAssertion();
|
588
|
-
if (!assertEnoughArguments("assert.exception", arguments, 1)) return
|
589
|
-
|
590
|
-
if (!callback) {
|
591
|
-
return;
|
592
|
-
}
|
593
|
-
|
594
|
-
var err = captureException(callback);
|
595
|
-
message = msg(message);
|
596
|
-
|
597
|
-
if (!err) {
|
598
|
-
if (exception) {
|
599
|
-
return fail.call({}, "assert", "exception", "typeNoExceptionMessage",
|
600
|
-
message, exception);
|
601
|
-
} else {
|
602
|
-
return fail.call({}, "assert", "exception", "message",
|
603
|
-
message, exception);
|
604
|
-
}
|
605
|
-
}
|
606
|
-
|
607
|
-
if (exception && err.name != exception) {
|
608
|
-
if (typeof window != "undefined" && typeof console != "undefined") {
|
609
|
-
console.log(err);
|
610
|
-
}
|
611
|
-
|
612
|
-
return fail.call({}, "assert", "exception", "typeFailMessage",
|
613
|
-
message, exception, err.name, err.message);
|
614
|
-
}
|
615
|
-
|
616
|
-
ba.emit("pass", "assert.exception", message, callback, exception);
|
617
|
-
};
|
618
|
-
|
619
|
-
assert.exception.typeNoExceptionMessage = "${0}Expected ${1} but no exception was thrown";
|
620
|
-
assert.exception.message = "${0}Expected exception";
|
621
|
-
assert.exception.typeFailMessage = "${0}Expected ${1} but threw ${2} (${3})";
|
622
|
-
assert.exception.expectationName = "toThrow";
|
623
|
-
|
624
|
-
refute.exception = function (callback) {
|
625
|
-
countAssertion();
|
626
|
-
if (!assertEnoughArguments("refute.exception", arguments, 1)) return;
|
627
|
-
|
628
|
-
var err = captureException(callback);
|
629
|
-
|
630
|
-
if (err) {
|
631
|
-
fail.call({}, "refute", "exception", "message",
|
632
|
-
msg(arguments[1]), err.name, err.message, callback);
|
633
|
-
} else {
|
634
|
-
ba.emit("pass", "refute.exception", callback);
|
635
|
-
}
|
636
|
-
};
|
637
|
-
|
638
|
-
refute.exception.message = "${0}Expected not to throw but threw ${1} (${2})";
|
639
|
-
refute.exception.expectationName = "toThrow";
|
640
|
-
|
641
|
-
ba.add("near", {
|
642
|
-
assert: function (actual, expected, delta) {
|
643
|
-
return Math.abs(actual - expected) <= delta;
|
644
|
-
},
|
645
|
-
assertMessage: "${3}Expected ${0} to be equal to ${1} +/- ${2}",
|
646
|
-
refuteMessage: "${3}Expected ${0} not to be equal to ${1} +/- ${2}",
|
647
|
-
expectation: "toBeNear",
|
648
|
-
values: function (actual, expected, delta, message) {
|
649
|
-
return [actual, expected, delta, msg(message)];
|
650
|
-
}
|
651
|
-
});
|
652
|
-
|
653
|
-
ba.add("hasPrototype", {
|
654
|
-
assert: function (actual, protoObj) {
|
655
|
-
return protoObj.isPrototypeOf(actual);
|
656
|
-
},
|
657
|
-
assertMessage: "${2}Expected ${0} to have ${1} on its prototype chain",
|
658
|
-
refuteMessage: "${2}Expected ${0} not to have ${1} on its prototype chain",
|
659
|
-
expectation: "toHavePrototype",
|
660
|
-
values: actualAndExpectedMessageValues
|
661
|
-
});
|
662
|
-
|
663
|
-
ba.add("contains", {
|
664
|
-
assert: function (haystack, needle) {
|
665
|
-
for (var i = 0; i < haystack.length; i++) {
|
666
|
-
if (haystack[i] === needle) {
|
667
|
-
return true;
|
668
|
-
}
|
669
|
-
}
|
670
|
-
return false;
|
671
|
-
},
|
672
|
-
assertMessage: "${2}Expected [${0}] to contain ${1}",
|
673
|
-
refuteMessage: "${2}Expected [${0}] not to contain ${1}",
|
674
|
-
expectation: "toContain",
|
675
|
-
values: actualAndExpectedMessageValues
|
676
|
-
});
|
677
|
-
|
678
|
-
ba.add("tagName", {
|
679
|
-
assert: function (element, tagName) {
|
680
|
-
if (!element.tagName) {
|
681
|
-
return this.fail("noTagNameMessage", tagName, element, msg(arguments[2]));
|
682
|
-
}
|
683
|
-
|
684
|
-
return tagName.toLowerCase &&
|
685
|
-
tagName.toLowerCase() == element.tagName.toLowerCase();
|
686
|
-
},
|
687
|
-
assertMessage: "${2}Expected tagName to be ${0} but was ${1}",
|
688
|
-
refuteMessage: "${2}Expected tagName not to be ${0}",
|
689
|
-
expectation: "toHaveTagName",
|
690
|
-
values: function (element, tagName, message) {
|
691
|
-
return [tagName, element.tagName, msg(message)];
|
692
|
-
}
|
693
|
-
});
|
694
|
-
|
695
|
-
assert.tagName.noTagNameMessage = "${2}Expected ${1} to have tagName property";
|
696
|
-
refute.tagName.noTagNameMessage = "${2}Expected ${1} to have tagName property";
|
697
|
-
|
698
|
-
function indexOf(arr, item) {
|
699
|
-
for (var i = 0, l = arr.length; i < l; i++) {
|
700
|
-
if (arr[i] == item) {
|
701
|
-
return i;
|
702
|
-
}
|
703
|
-
}
|
704
|
-
|
705
|
-
return -1;
|
706
|
-
}
|
707
|
-
|
708
|
-
ba.add("className", {
|
709
|
-
assert: function (element, className) {
|
710
|
-
if (typeof element.className == "undefined") {
|
711
|
-
return this.fail("noClassNameMessage", className, element, msg(arguments[2]));
|
712
|
-
}
|
713
|
-
|
714
|
-
var expected = typeof className == "string" ? className.split(" ") : className;
|
715
|
-
var actual = element.className.split(" ");
|
716
|
-
|
717
|
-
for (var i = 0, l = expected.length; i < l; i++) {
|
718
|
-
if (indexOf(actual, expected[i]) < 0) {
|
719
|
-
return false;
|
720
|
-
}
|
721
|
-
}
|
722
|
-
|
723
|
-
return true;
|
724
|
-
},
|
725
|
-
assertMessage: "${2}Expected object's className to include ${0} but was ${1}",
|
726
|
-
refuteMessage: "${2}Expected object's className not to include ${0}",
|
727
|
-
expectation: "toHaveClassName",
|
728
|
-
values: function (element, className, message) {
|
729
|
-
return [className, element.className, msg(message)];
|
730
|
-
}
|
731
|
-
});
|
732
|
-
|
733
|
-
assert.className.noClassNameMessage = "${2}Expected object to have className property";
|
734
|
-
refute.className.noClassNameMessage = "${2}Expected object to have className property";
|
735
|
-
|
736
|
-
if (typeof module != "undefined") {
|
737
|
-
ba.expect = function () {
|
738
|
-
ba.expect = require("./buster-assertions/expect");
|
739
|
-
return ba.expect.apply(exports, arguments);
|
740
|
-
};
|
741
|
-
}
|
742
|
-
|
743
|
-
function isArguments(obj) {
|
744
|
-
if (typeof obj != "object" || typeof obj.length != "number" ||
|
745
|
-
toString.call(obj) == "[object Array]") {
|
746
|
-
return false;
|
747
|
-
}
|
748
|
-
|
749
|
-
if (typeof obj.callee == "function") {
|
750
|
-
return true;
|
751
|
-
}
|
752
|
-
|
753
|
-
try {
|
754
|
-
obj[obj.length] = 6;
|
755
|
-
delete obj[obj.length];
|
756
|
-
} catch (e) {
|
757
|
-
return true;
|
758
|
-
}
|
759
|
-
|
760
|
-
return false;
|
761
|
-
}
|
762
|
-
|
763
|
-
ba.isArguments = isArguments;
|
764
|
-
|
765
|
-
if (Object.keys) {
|
766
|
-
ba.keys = function (obj) {
|
767
|
-
return Object.keys(obj)
|
768
|
-
};
|
769
|
-
} else {
|
770
|
-
ba.keys = function (object) {
|
771
|
-
var keys = [];
|
772
|
-
|
773
|
-
for (var prop in object) {
|
774
|
-
if (Object.prototype.hasOwnProperty.call(object, prop)) {
|
775
|
-
keys.push(prop);
|
776
|
-
}
|
777
|
-
}
|
778
|
-
|
779
|
-
return keys;
|
780
|
-
}
|
781
|
-
}
|
782
|
-
}());
|