oojspec 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
}());
|