oojspec 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.2.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: 2014-09-17 00:00:00.000000000 Z
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/buster-assertions.js
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.2.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
- }());