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.
@@ -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
- }());