teaspoon-mocha 2.2.4 → 2.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1285 @@
1
+ (function (global, module) {
2
+
3
+ var exports = module.exports;
4
+
5
+ /**
6
+ * Exports.
7
+ */
8
+
9
+ module.exports = expect;
10
+ expect.Assertion = Assertion;
11
+
12
+ /**
13
+ * Exports version.
14
+ */
15
+
16
+ expect.version = '0.3.1';
17
+
18
+ /**
19
+ * Possible assertion flags.
20
+ */
21
+
22
+ var flags = {
23
+ not: ['to', 'be', 'have', 'include', 'only']
24
+ , to: ['be', 'have', 'include', 'only', 'not']
25
+ , only: ['have']
26
+ , have: ['own']
27
+ , be: ['an']
28
+ };
29
+
30
+ function expect (obj) {
31
+ return new Assertion(obj);
32
+ }
33
+
34
+ /**
35
+ * Constructor
36
+ *
37
+ * @api private
38
+ */
39
+
40
+ function Assertion (obj, flag, parent) {
41
+ this.obj = obj;
42
+ this.flags = {};
43
+
44
+ if (undefined != parent) {
45
+ this.flags[flag] = true;
46
+
47
+ for (var i in parent.flags) {
48
+ if (parent.flags.hasOwnProperty(i)) {
49
+ this.flags[i] = true;
50
+ }
51
+ }
52
+ }
53
+
54
+ var $flags = flag ? flags[flag] : keys(flags)
55
+ , self = this;
56
+
57
+ if ($flags) {
58
+ for (var i = 0, l = $flags.length; i < l; i++) {
59
+ // avoid recursion
60
+ if (this.flags[$flags[i]]) continue;
61
+
62
+ var name = $flags[i]
63
+ , assertion = new Assertion(this.obj, name, this)
64
+
65
+ if ('function' == typeof Assertion.prototype[name]) {
66
+ // clone the function, make sure we dont touch the prot reference
67
+ var old = this[name];
68
+ this[name] = function () {
69
+ return old.apply(self, arguments);
70
+ };
71
+
72
+ for (var fn in Assertion.prototype) {
73
+ if (Assertion.prototype.hasOwnProperty(fn) && fn != name) {
74
+ this[name][fn] = bind(assertion[fn], assertion);
75
+ }
76
+ }
77
+ } else {
78
+ this[name] = assertion;
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Performs an assertion
86
+ *
87
+ * @api private
88
+ */
89
+
90
+ Assertion.prototype.assert = function (truth, msg, error, expected) {
91
+ var msg = this.flags.not ? error : msg
92
+ , ok = this.flags.not ? !truth : truth
93
+ , err;
94
+
95
+ if (!ok) {
96
+ err = new Error(msg.call(this));
97
+ if (arguments.length > 3) {
98
+ err.actual = this.obj;
99
+ err.expected = expected;
100
+ err.showDiff = true;
101
+ }
102
+ throw err;
103
+ }
104
+
105
+ this.and = new Assertion(this.obj);
106
+ };
107
+
108
+ /**
109
+ * Check if the value is truthy
110
+ *
111
+ * @api public
112
+ */
113
+
114
+ Assertion.prototype.ok = function () {
115
+ this.assert(
116
+ !!this.obj
117
+ , function(){ return 'expected ' + i(this.obj) + ' to be truthy' }
118
+ , function(){ return 'expected ' + i(this.obj) + ' to be falsy' });
119
+ };
120
+
121
+ /**
122
+ * Creates an anonymous function which calls fn with arguments.
123
+ *
124
+ * @api public
125
+ */
126
+
127
+ Assertion.prototype.withArgs = function() {
128
+ expect(this.obj).to.be.a('function');
129
+ var fn = this.obj;
130
+ var args = Array.prototype.slice.call(arguments);
131
+ return expect(function() { fn.apply(null, args); });
132
+ };
133
+
134
+ /**
135
+ * Assert that the function throws.
136
+ *
137
+ * @param {Function|RegExp} callback, or regexp to match error string against
138
+ * @api public
139
+ */
140
+
141
+ Assertion.prototype['throw'] =
142
+ Assertion.prototype.throwError =
143
+ Assertion.prototype.throwException = function (fn) {
144
+ expect(this.obj).to.be.a('function');
145
+
146
+ var thrown = false
147
+ , not = this.flags.not;
148
+
149
+ try {
150
+ this.obj();
151
+ } catch (e) {
152
+ if (isRegExp(fn)) {
153
+ var subject = 'string' == typeof e ? e : e.message;
154
+ if (not) {
155
+ expect(subject).to.not.match(fn);
156
+ } else {
157
+ expect(subject).to.match(fn);
158
+ }
159
+ } else if ('function' == typeof fn) {
160
+ fn(e);
161
+ }
162
+ thrown = true;
163
+ }
164
+
165
+ if (isRegExp(fn) && not) {
166
+ // in the presence of a matcher, ensure the `not` only applies to
167
+ // the matching.
168
+ this.flags.not = false;
169
+ }
170
+
171
+ var name = this.obj.name || 'fn';
172
+ this.assert(
173
+ thrown
174
+ , function(){ return 'expected ' + name + ' to throw an exception' }
175
+ , function(){ return 'expected ' + name + ' not to throw an exception' });
176
+ };
177
+
178
+ /**
179
+ * Checks if the array is empty.
180
+ *
181
+ * @api public
182
+ */
183
+
184
+ Assertion.prototype.empty = function () {
185
+ var expectation;
186
+
187
+ if ('object' == typeof this.obj && null !== this.obj && !isArray(this.obj)) {
188
+ if ('number' == typeof this.obj.length) {
189
+ expectation = !this.obj.length;
190
+ } else {
191
+ expectation = !keys(this.obj).length;
192
+ }
193
+ } else {
194
+ if ('string' != typeof this.obj) {
195
+ expect(this.obj).to.be.an('object');
196
+ }
197
+
198
+ expect(this.obj).to.have.property('length');
199
+ expectation = !this.obj.length;
200
+ }
201
+
202
+ this.assert(
203
+ expectation
204
+ , function(){ return 'expected ' + i(this.obj) + ' to be empty' }
205
+ , function(){ return 'expected ' + i(this.obj) + ' to not be empty' });
206
+ return this;
207
+ };
208
+
209
+ /**
210
+ * Checks if the obj exactly equals another.
211
+ *
212
+ * @api public
213
+ */
214
+
215
+ Assertion.prototype.be =
216
+ Assertion.prototype.equal = function (obj) {
217
+ this.assert(
218
+ obj === this.obj
219
+ , function(){ return 'expected ' + i(this.obj) + ' to equal ' + i(obj) }
220
+ , function(){ return 'expected ' + i(this.obj) + ' to not equal ' + i(obj) });
221
+ return this;
222
+ };
223
+
224
+ /**
225
+ * Checks if the obj sortof equals another.
226
+ *
227
+ * @api public
228
+ */
229
+
230
+ Assertion.prototype.eql = function (obj) {
231
+ this.assert(
232
+ expect.eql(this.obj, obj)
233
+ , function(){ return 'expected ' + i(this.obj) + ' to sort of equal ' + i(obj) }
234
+ , function(){ return 'expected ' + i(this.obj) + ' to sort of not equal ' + i(obj) }
235
+ , obj);
236
+ return this;
237
+ };
238
+
239
+ /**
240
+ * Assert within start to finish (inclusive).
241
+ *
242
+ * @param {Number} start
243
+ * @param {Number} finish
244
+ * @api public
245
+ */
246
+
247
+ Assertion.prototype.within = function (start, finish) {
248
+ var range = start + '..' + finish;
249
+ this.assert(
250
+ this.obj >= start && this.obj <= finish
251
+ , function(){ return 'expected ' + i(this.obj) + ' to be within ' + range }
252
+ , function(){ return 'expected ' + i(this.obj) + ' to not be within ' + range });
253
+ return this;
254
+ };
255
+
256
+ /**
257
+ * Assert typeof / instance of
258
+ *
259
+ * @api public
260
+ */
261
+
262
+ Assertion.prototype.a =
263
+ Assertion.prototype.an = function (type) {
264
+ if ('string' == typeof type) {
265
+ // proper english in error msg
266
+ var n = /^[aeiou]/.test(type) ? 'n' : '';
267
+
268
+ // typeof with support for 'array'
269
+ this.assert(
270
+ 'array' == type ? isArray(this.obj) :
271
+ 'regexp' == type ? isRegExp(this.obj) :
272
+ 'object' == type
273
+ ? 'object' == typeof this.obj && null !== this.obj
274
+ : type == typeof this.obj
275
+ , function(){ return 'expected ' + i(this.obj) + ' to be a' + n + ' ' + type }
276
+ , function(){ return 'expected ' + i(this.obj) + ' not to be a' + n + ' ' + type });
277
+ } else {
278
+ // instanceof
279
+ var name = type.name || 'supplied constructor';
280
+ this.assert(
281
+ this.obj instanceof type
282
+ , function(){ return 'expected ' + i(this.obj) + ' to be an instance of ' + name }
283
+ , function(){ return 'expected ' + i(this.obj) + ' not to be an instance of ' + name });
284
+ }
285
+
286
+ return this;
287
+ };
288
+
289
+ /**
290
+ * Assert numeric value above _n_.
291
+ *
292
+ * @param {Number} n
293
+ * @api public
294
+ */
295
+
296
+ Assertion.prototype.greaterThan =
297
+ Assertion.prototype.above = function (n) {
298
+ this.assert(
299
+ this.obj > n
300
+ , function(){ return 'expected ' + i(this.obj) + ' to be above ' + n }
301
+ , function(){ return 'expected ' + i(this.obj) + ' to be below ' + n });
302
+ return this;
303
+ };
304
+
305
+ /**
306
+ * Assert numeric value below _n_.
307
+ *
308
+ * @param {Number} n
309
+ * @api public
310
+ */
311
+
312
+ Assertion.prototype.lessThan =
313
+ Assertion.prototype.below = function (n) {
314
+ this.assert(
315
+ this.obj < n
316
+ , function(){ return 'expected ' + i(this.obj) + ' to be below ' + n }
317
+ , function(){ return 'expected ' + i(this.obj) + ' to be above ' + n });
318
+ return this;
319
+ };
320
+
321
+ /**
322
+ * Assert string value matches _regexp_.
323
+ *
324
+ * @param {RegExp} regexp
325
+ * @api public
326
+ */
327
+
328
+ Assertion.prototype.match = function (regexp) {
329
+ this.assert(
330
+ regexp.exec(this.obj)
331
+ , function(){ return 'expected ' + i(this.obj) + ' to match ' + regexp }
332
+ , function(){ return 'expected ' + i(this.obj) + ' not to match ' + regexp });
333
+ return this;
334
+ };
335
+
336
+ /**
337
+ * Assert property "length" exists and has value of _n_.
338
+ *
339
+ * @param {Number} n
340
+ * @api public
341
+ */
342
+
343
+ Assertion.prototype.length = function (n) {
344
+ expect(this.obj).to.have.property('length');
345
+ var len = this.obj.length;
346
+ this.assert(
347
+ n == len
348
+ , function(){ return 'expected ' + i(this.obj) + ' to have a length of ' + n + ' but got ' + len }
349
+ , function(){ return 'expected ' + i(this.obj) + ' to not have a length of ' + len });
350
+ return this;
351
+ };
352
+
353
+ /**
354
+ * Assert property _name_ exists, with optional _val_.
355
+ *
356
+ * @param {String} name
357
+ * @param {Mixed} val
358
+ * @api public
359
+ */
360
+
361
+ Assertion.prototype.property = function (name, val) {
362
+ if (this.flags.own) {
363
+ this.assert(
364
+ Object.prototype.hasOwnProperty.call(this.obj, name)
365
+ , function(){ return 'expected ' + i(this.obj) + ' to have own property ' + i(name) }
366
+ , function(){ return 'expected ' + i(this.obj) + ' to not have own property ' + i(name) });
367
+ return this;
368
+ }
369
+
370
+ if (this.flags.not && undefined !== val) {
371
+ if (undefined === this.obj[name]) {
372
+ throw new Error(i(this.obj) + ' has no property ' + i(name));
373
+ }
374
+ } else {
375
+ var hasProp;
376
+ try {
377
+ hasProp = name in this.obj
378
+ } catch (e) {
379
+ hasProp = undefined !== this.obj[name]
380
+ }
381
+
382
+ this.assert(
383
+ hasProp
384
+ , function(){ return 'expected ' + i(this.obj) + ' to have a property ' + i(name) }
385
+ , function(){ return 'expected ' + i(this.obj) + ' to not have a property ' + i(name) });
386
+ }
387
+
388
+ if (undefined !== val) {
389
+ this.assert(
390
+ val === this.obj[name]
391
+ , function(){ return 'expected ' + i(this.obj) + ' to have a property ' + i(name)
392
+ + ' of ' + i(val) + ', but got ' + i(this.obj[name]) }
393
+ , function(){ return 'expected ' + i(this.obj) + ' to not have a property ' + i(name)
394
+ + ' of ' + i(val) });
395
+ }
396
+
397
+ this.obj = this.obj[name];
398
+ return this;
399
+ };
400
+
401
+ /**
402
+ * Assert that the array contains _obj_ or string contains _obj_.
403
+ *
404
+ * @param {Mixed} obj|string
405
+ * @api public
406
+ */
407
+
408
+ Assertion.prototype.string =
409
+ Assertion.prototype.contain = function (obj) {
410
+ if ('string' == typeof this.obj) {
411
+ this.assert(
412
+ ~this.obj.indexOf(obj)
413
+ , function(){ return 'expected ' + i(this.obj) + ' to contain ' + i(obj) }
414
+ , function(){ return 'expected ' + i(this.obj) + ' to not contain ' + i(obj) });
415
+ } else {
416
+ this.assert(
417
+ ~indexOf(this.obj, obj)
418
+ , function(){ return 'expected ' + i(this.obj) + ' to contain ' + i(obj) }
419
+ , function(){ return 'expected ' + i(this.obj) + ' to not contain ' + i(obj) });
420
+ }
421
+ return this;
422
+ };
423
+
424
+ /**
425
+ * Assert exact keys or inclusion of keys by using
426
+ * the `.own` modifier.
427
+ *
428
+ * @param {Array|String ...} keys
429
+ * @api public
430
+ */
431
+
432
+ Assertion.prototype.key =
433
+ Assertion.prototype.keys = function ($keys) {
434
+ var str
435
+ , ok = true;
436
+
437
+ $keys = isArray($keys)
438
+ ? $keys
439
+ : Array.prototype.slice.call(arguments);
440
+
441
+ if (!$keys.length) throw new Error('keys required');
442
+
443
+ var actual = keys(this.obj)
444
+ , len = $keys.length;
445
+
446
+ // Inclusion
447
+ ok = every($keys, function (key) {
448
+ return ~indexOf(actual, key);
449
+ });
450
+
451
+ // Strict
452
+ if (!this.flags.not && this.flags.only) {
453
+ ok = ok && $keys.length == actual.length;
454
+ }
455
+
456
+ // Key string
457
+ if (len > 1) {
458
+ $keys = map($keys, function (key) {
459
+ return i(key);
460
+ });
461
+ var last = $keys.pop();
462
+ str = $keys.join(', ') + ', and ' + last;
463
+ } else {
464
+ str = i($keys[0]);
465
+ }
466
+
467
+ // Form
468
+ str = (len > 1 ? 'keys ' : 'key ') + str;
469
+
470
+ // Have / include
471
+ str = (!this.flags.only ? 'include ' : 'only have ') + str;
472
+
473
+ // Assertion
474
+ this.assert(
475
+ ok
476
+ , function(){ return 'expected ' + i(this.obj) + ' to ' + str }
477
+ , function(){ return 'expected ' + i(this.obj) + ' to not ' + str });
478
+
479
+ return this;
480
+ };
481
+
482
+ /**
483
+ * Assert a failure.
484
+ *
485
+ * @param {String ...} custom message
486
+ * @api public
487
+ */
488
+ Assertion.prototype.fail = function (msg) {
489
+ var error = function() { return msg || "explicit failure"; }
490
+ this.assert(false, error, error);
491
+ return this;
492
+ };
493
+
494
+ /**
495
+ * Function bind implementation.
496
+ */
497
+
498
+ function bind (fn, scope) {
499
+ return function () {
500
+ return fn.apply(scope, arguments);
501
+ }
502
+ }
503
+
504
+ /**
505
+ * Array every compatibility
506
+ *
507
+ * @see bit.ly/5Fq1N2
508
+ * @api public
509
+ */
510
+
511
+ function every (arr, fn, thisObj) {
512
+ var scope = thisObj || global;
513
+ for (var i = 0, j = arr.length; i < j; ++i) {
514
+ if (!fn.call(scope, arr[i], i, arr)) {
515
+ return false;
516
+ }
517
+ }
518
+ return true;
519
+ }
520
+
521
+ /**
522
+ * Array indexOf compatibility.
523
+ *
524
+ * @see bit.ly/a5Dxa2
525
+ * @api public
526
+ */
527
+
528
+ function indexOf (arr, o, i) {
529
+ if (Array.prototype.indexOf) {
530
+ return Array.prototype.indexOf.call(arr, o, i);
531
+ }
532
+
533
+ if (arr.length === undefined) {
534
+ return -1;
535
+ }
536
+
537
+ for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0
538
+ ; i < j && arr[i] !== o; i++);
539
+
540
+ return j <= i ? -1 : i;
541
+ }
542
+
543
+ // https://gist.github.com/1044128/
544
+ var getOuterHTML = function(element) {
545
+ if ('outerHTML' in element) return element.outerHTML;
546
+ var ns = "http://www.w3.org/1999/xhtml";
547
+ var container = document.createElementNS(ns, '_');
548
+ var xmlSerializer = new XMLSerializer();
549
+ var html;
550
+ if (document.xmlVersion) {
551
+ return xmlSerializer.serializeToString(element);
552
+ } else {
553
+ container.appendChild(element.cloneNode(false));
554
+ html = container.innerHTML.replace('><', '>' + element.innerHTML + '<');
555
+ container.innerHTML = '';
556
+ return html;
557
+ }
558
+ };
559
+
560
+ // Returns true if object is a DOM element.
561
+ var isDOMElement = function (object) {
562
+ if (typeof HTMLElement === 'object') {
563
+ return object instanceof HTMLElement;
564
+ } else {
565
+ return object &&
566
+ typeof object === 'object' &&
567
+ object.nodeType === 1 &&
568
+ typeof object.nodeName === 'string';
569
+ }
570
+ };
571
+
572
+ /**
573
+ * Inspects an object.
574
+ *
575
+ * @see taken from node.js `util` module (copyright Joyent, MIT license)
576
+ * @api private
577
+ */
578
+
579
+ function i (obj, showHidden, depth) {
580
+ var seen = [];
581
+
582
+ function stylize (str) {
583
+ return str;
584
+ }
585
+
586
+ function format (value, recurseTimes) {
587
+ // Provide a hook for user-specified inspect functions.
588
+ // Check that value is an object with an inspect function on it
589
+ if (value && typeof value.inspect === 'function' &&
590
+ // Filter out the util module, it's inspect function is special
591
+ value !== exports &&
592
+ // Also filter out any prototype objects using the circular check.
593
+ !(value.constructor && value.constructor.prototype === value)) {
594
+ return value.inspect(recurseTimes);
595
+ }
596
+
597
+ // Primitive types cannot have properties
598
+ switch (typeof value) {
599
+ case 'undefined':
600
+ return stylize('undefined', 'undefined');
601
+
602
+ case 'string':
603
+ var simple = '\'' + json.stringify(value).replace(/^"|"$/g, '')
604
+ .replace(/'/g, "\\'")
605
+ .replace(/\\"/g, '"') + '\'';
606
+ return stylize(simple, 'string');
607
+
608
+ case 'number':
609
+ return stylize('' + value, 'number');
610
+
611
+ case 'boolean':
612
+ return stylize('' + value, 'boolean');
613
+ }
614
+ // For some reason typeof null is "object", so special case here.
615
+ if (value === null) {
616
+ return stylize('null', 'null');
617
+ }
618
+
619
+ if (isDOMElement(value)) {
620
+ return getOuterHTML(value);
621
+ }
622
+
623
+ // Look up the keys of the object.
624
+ var visible_keys = keys(value);
625
+ var $keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys;
626
+
627
+ // Functions without properties can be shortcutted.
628
+ if (typeof value === 'function' && $keys.length === 0) {
629
+ if (isRegExp(value)) {
630
+ return stylize('' + value, 'regexp');
631
+ } else {
632
+ var name = value.name ? ': ' + value.name : '';
633
+ return stylize('[Function' + name + ']', 'special');
634
+ }
635
+ }
636
+
637
+ // Dates without properties can be shortcutted
638
+ if (isDate(value) && $keys.length === 0) {
639
+ return stylize(value.toUTCString(), 'date');
640
+ }
641
+
642
+ // Error objects can be shortcutted
643
+ if (value instanceof Error) {
644
+ return stylize("["+value.toString()+"]", 'Error');
645
+ }
646
+
647
+ var base, type, braces;
648
+ // Determine the object type
649
+ if (isArray(value)) {
650
+ type = 'Array';
651
+ braces = ['[', ']'];
652
+ } else {
653
+ type = 'Object';
654
+ braces = ['{', '}'];
655
+ }
656
+
657
+ // Make functions say that they are functions
658
+ if (typeof value === 'function') {
659
+ var n = value.name ? ': ' + value.name : '';
660
+ base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']';
661
+ } else {
662
+ base = '';
663
+ }
664
+
665
+ // Make dates with properties first say the date
666
+ if (isDate(value)) {
667
+ base = ' ' + value.toUTCString();
668
+ }
669
+
670
+ if ($keys.length === 0) {
671
+ return braces[0] + base + braces[1];
672
+ }
673
+
674
+ if (recurseTimes < 0) {
675
+ if (isRegExp(value)) {
676
+ return stylize('' + value, 'regexp');
677
+ } else {
678
+ return stylize('[Object]', 'special');
679
+ }
680
+ }
681
+
682
+ seen.push(value);
683
+
684
+ var output = map($keys, function (key) {
685
+ var name, str;
686
+ if (value.__lookupGetter__) {
687
+ if (value.__lookupGetter__(key)) {
688
+ if (value.__lookupSetter__(key)) {
689
+ str = stylize('[Getter/Setter]', 'special');
690
+ } else {
691
+ str = stylize('[Getter]', 'special');
692
+ }
693
+ } else {
694
+ if (value.__lookupSetter__(key)) {
695
+ str = stylize('[Setter]', 'special');
696
+ }
697
+ }
698
+ }
699
+ if (indexOf(visible_keys, key) < 0) {
700
+ name = '[' + key + ']';
701
+ }
702
+ if (!str) {
703
+ if (indexOf(seen, value[key]) < 0) {
704
+ if (recurseTimes === null) {
705
+ str = format(value[key]);
706
+ } else {
707
+ str = format(value[key], recurseTimes - 1);
708
+ }
709
+ if (str.indexOf('\n') > -1) {
710
+ if (isArray(value)) {
711
+ str = map(str.split('\n'), function (line) {
712
+ return ' ' + line;
713
+ }).join('\n').substr(2);
714
+ } else {
715
+ str = '\n' + map(str.split('\n'), function (line) {
716
+ return ' ' + line;
717
+ }).join('\n');
718
+ }
719
+ }
720
+ } else {
721
+ str = stylize('[Circular]', 'special');
722
+ }
723
+ }
724
+ if (typeof name === 'undefined') {
725
+ if (type === 'Array' && key.match(/^\d+$/)) {
726
+ return str;
727
+ }
728
+ name = json.stringify('' + key);
729
+ if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
730
+ name = name.substr(1, name.length - 2);
731
+ name = stylize(name, 'name');
732
+ } else {
733
+ name = name.replace(/'/g, "\\'")
734
+ .replace(/\\"/g, '"')
735
+ .replace(/(^"|"$)/g, "'");
736
+ name = stylize(name, 'string');
737
+ }
738
+ }
739
+
740
+ return name + ': ' + str;
741
+ });
742
+
743
+ seen.pop();
744
+
745
+ var numLinesEst = 0;
746
+ var length = reduce(output, function (prev, cur) {
747
+ numLinesEst++;
748
+ if (indexOf(cur, '\n') >= 0) numLinesEst++;
749
+ return prev + cur.length + 1;
750
+ }, 0);
751
+
752
+ if (length > 50) {
753
+ output = braces[0] +
754
+ (base === '' ? '' : base + '\n ') +
755
+ ' ' +
756
+ output.join(',\n ') +
757
+ ' ' +
758
+ braces[1];
759
+
760
+ } else {
761
+ output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
762
+ }
763
+
764
+ return output;
765
+ }
766
+ return format(obj, (typeof depth === 'undefined' ? 2 : depth));
767
+ }
768
+
769
+ expect.stringify = i;
770
+
771
+ function isArray (ar) {
772
+ return Object.prototype.toString.call(ar) === '[object Array]';
773
+ }
774
+
775
+ function isRegExp(re) {
776
+ var s;
777
+ try {
778
+ s = '' + re;
779
+ } catch (e) {
780
+ return false;
781
+ }
782
+
783
+ return re instanceof RegExp || // easy case
784
+ // duck-type for context-switching evalcx case
785
+ typeof(re) === 'function' &&
786
+ re.constructor.name === 'RegExp' &&
787
+ re.compile &&
788
+ re.test &&
789
+ re.exec &&
790
+ s.match(/^\/.*\/[gim]{0,3}$/);
791
+ }
792
+
793
+ function isDate(d) {
794
+ return d instanceof Date;
795
+ }
796
+
797
+ function keys (obj) {
798
+ if (Object.keys) {
799
+ return Object.keys(obj);
800
+ }
801
+
802
+ var keys = [];
803
+
804
+ for (var i in obj) {
805
+ if (Object.prototype.hasOwnProperty.call(obj, i)) {
806
+ keys.push(i);
807
+ }
808
+ }
809
+
810
+ return keys;
811
+ }
812
+
813
+ function map (arr, mapper, that) {
814
+ if (Array.prototype.map) {
815
+ return Array.prototype.map.call(arr, mapper, that);
816
+ }
817
+
818
+ var other= new Array(arr.length);
819
+
820
+ for (var i= 0, n = arr.length; i<n; i++)
821
+ if (i in arr)
822
+ other[i] = mapper.call(that, arr[i], i, arr);
823
+
824
+ return other;
825
+ }
826
+
827
+ function reduce (arr, fun) {
828
+ if (Array.prototype.reduce) {
829
+ return Array.prototype.reduce.apply(
830
+ arr
831
+ , Array.prototype.slice.call(arguments, 1)
832
+ );
833
+ }
834
+
835
+ var len = +this.length;
836
+
837
+ if (typeof fun !== "function")
838
+ throw new TypeError();
839
+
840
+ // no value to return if no initial value and an empty array
841
+ if (len === 0 && arguments.length === 1)
842
+ throw new TypeError();
843
+
844
+ var i = 0;
845
+ if (arguments.length >= 2) {
846
+ var rv = arguments[1];
847
+ } else {
848
+ do {
849
+ if (i in this) {
850
+ rv = this[i++];
851
+ break;
852
+ }
853
+
854
+ // if array contains no values, no initial value to return
855
+ if (++i >= len)
856
+ throw new TypeError();
857
+ } while (true);
858
+ }
859
+
860
+ for (; i < len; i++) {
861
+ if (i in this)
862
+ rv = fun.call(null, rv, this[i], i, this);
863
+ }
864
+
865
+ return rv;
866
+ }
867
+
868
+ /**
869
+ * Asserts deep equality
870
+ *
871
+ * @see taken from node.js `assert` module (copyright Joyent, MIT license)
872
+ * @api private
873
+ */
874
+
875
+ expect.eql = function eql(actual, expected) {
876
+ // 7.1. All identical values are equivalent, as determined by ===.
877
+ if (actual === expected) {
878
+ return true;
879
+ } else if ('undefined' != typeof Buffer
880
+ && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
881
+ if (actual.length != expected.length) return false;
882
+
883
+ for (var i = 0; i < actual.length; i++) {
884
+ if (actual[i] !== expected[i]) return false;
885
+ }
886
+
887
+ return true;
888
+
889
+ // 7.2. If the expected value is a Date object, the actual value is
890
+ // equivalent if it is also a Date object that refers to the same time.
891
+ } else if (actual instanceof Date && expected instanceof Date) {
892
+ return actual.getTime() === expected.getTime();
893
+
894
+ // 7.3. Other pairs that do not both pass typeof value == "object",
895
+ // equivalence is determined by ==.
896
+ } else if (typeof actual != 'object' && typeof expected != 'object') {
897
+ return actual == expected;
898
+ // If both are regular expression use the special `regExpEquiv` method
899
+ // to determine equivalence.
900
+ } else if (isRegExp(actual) && isRegExp(expected)) {
901
+ return regExpEquiv(actual, expected);
902
+ // 7.4. For all other Object pairs, including Array objects, equivalence is
903
+ // determined by having the same number of owned properties (as verified
904
+ // with Object.prototype.hasOwnProperty.call), the same set of keys
905
+ // (although not necessarily the same order), equivalent values for every
906
+ // corresponding key, and an identical "prototype" property. Note: this
907
+ // accounts for both named and indexed properties on Arrays.
908
+ } else {
909
+ return objEquiv(actual, expected);
910
+ }
911
+ };
912
+
913
+ function isUndefinedOrNull (value) {
914
+ return value === null || value === undefined;
915
+ }
916
+
917
+ function isArguments (object) {
918
+ return Object.prototype.toString.call(object) == '[object Arguments]';
919
+ }
920
+
921
+ function regExpEquiv (a, b) {
922
+ return a.source === b.source && a.global === b.global &&
923
+ a.ignoreCase === b.ignoreCase && a.multiline === b.multiline;
924
+ }
925
+
926
+ function objEquiv (a, b) {
927
+ if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
928
+ return false;
929
+ // an identical "prototype" property.
930
+ if (a.prototype !== b.prototype) return false;
931
+ //~~~I've managed to break Object.keys through screwy arguments passing.
932
+ // Converting to array solves the problem.
933
+ if (isArguments(a)) {
934
+ if (!isArguments(b)) {
935
+ return false;
936
+ }
937
+ a = pSlice.call(a);
938
+ b = pSlice.call(b);
939
+ return expect.eql(a, b);
940
+ }
941
+ try{
942
+ var ka = keys(a),
943
+ kb = keys(b),
944
+ key, i;
945
+ } catch (e) {//happens when one is a string literal and the other isn't
946
+ return false;
947
+ }
948
+ // having the same number of owned properties (keys incorporates hasOwnProperty)
949
+ if (ka.length != kb.length)
950
+ return false;
951
+ //the same set of keys (although not necessarily the same order),
952
+ ka.sort();
953
+ kb.sort();
954
+ //~~~cheap key test
955
+ for (i = ka.length - 1; i >= 0; i--) {
956
+ if (ka[i] != kb[i])
957
+ return false;
958
+ }
959
+ //equivalent values for every corresponding key, and
960
+ //~~~possibly expensive deep test
961
+ for (i = ka.length - 1; i >= 0; i--) {
962
+ key = ka[i];
963
+ if (!expect.eql(a[key], b[key]))
964
+ return false;
965
+ }
966
+ return true;
967
+ }
968
+
969
+ var json = (function () {
970
+ "use strict";
971
+
972
+ if ('object' == typeof JSON && JSON.parse && JSON.stringify) {
973
+ return {
974
+ parse: nativeJSON.parse
975
+ , stringify: nativeJSON.stringify
976
+ }
977
+ }
978
+
979
+ var JSON = {};
980
+
981
+ function f(n) {
982
+ // Format integers to have at least two digits.
983
+ return n < 10 ? '0' + n : n;
984
+ }
985
+
986
+ function date(d, key) {
987
+ return isFinite(d.valueOf()) ?
988
+ d.getUTCFullYear() + '-' +
989
+ f(d.getUTCMonth() + 1) + '-' +
990
+ f(d.getUTCDate()) + 'T' +
991
+ f(d.getUTCHours()) + ':' +
992
+ f(d.getUTCMinutes()) + ':' +
993
+ f(d.getUTCSeconds()) + 'Z' : null;
994
+ }
995
+
996
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
997
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
998
+ gap,
999
+ indent,
1000
+ meta = { // table of character substitutions
1001
+ '\b': '\\b',
1002
+ '\t': '\\t',
1003
+ '\n': '\\n',
1004
+ '\f': '\\f',
1005
+ '\r': '\\r',
1006
+ '"' : '\\"',
1007
+ '\\': '\\\\'
1008
+ },
1009
+ rep;
1010
+
1011
+
1012
+ function quote(string) {
1013
+
1014
+ // If the string contains no control characters, no quote characters, and no
1015
+ // backslash characters, then we can safely slap some quotes around it.
1016
+ // Otherwise we must also replace the offending characters with safe escape
1017
+ // sequences.
1018
+
1019
+ escapable.lastIndex = 0;
1020
+ return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
1021
+ var c = meta[a];
1022
+ return typeof c === 'string' ? c :
1023
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
1024
+ }) + '"' : '"' + string + '"';
1025
+ }
1026
+
1027
+
1028
+ function str(key, holder) {
1029
+
1030
+ // Produce a string from holder[key].
1031
+
1032
+ var i, // The loop counter.
1033
+ k, // The member key.
1034
+ v, // The member value.
1035
+ length,
1036
+ mind = gap,
1037
+ partial,
1038
+ value = holder[key];
1039
+
1040
+ // If the value has a toJSON method, call it to obtain a replacement value.
1041
+
1042
+ if (value instanceof Date) {
1043
+ value = date(key);
1044
+ }
1045
+
1046
+ // If we were called with a replacer function, then call the replacer to
1047
+ // obtain a replacement value.
1048
+
1049
+ if (typeof rep === 'function') {
1050
+ value = rep.call(holder, key, value);
1051
+ }
1052
+
1053
+ // What happens next depends on the value's type.
1054
+
1055
+ switch (typeof value) {
1056
+ case 'string':
1057
+ return quote(value);
1058
+
1059
+ case 'number':
1060
+
1061
+ // JSON numbers must be finite. Encode non-finite numbers as null.
1062
+
1063
+ return isFinite(value) ? String(value) : 'null';
1064
+
1065
+ case 'boolean':
1066
+ case 'null':
1067
+
1068
+ // If the value is a boolean or null, convert it to a string. Note:
1069
+ // typeof null does not produce 'null'. The case is included here in
1070
+ // the remote chance that this gets fixed someday.
1071
+
1072
+ return String(value);
1073
+
1074
+ // If the type is 'object', we might be dealing with an object or an array or
1075
+ // null.
1076
+
1077
+ case 'object':
1078
+
1079
+ // Due to a specification blunder in ECMAScript, typeof null is 'object',
1080
+ // so watch out for that case.
1081
+
1082
+ if (!value) {
1083
+ return 'null';
1084
+ }
1085
+
1086
+ // Make an array to hold the partial results of stringifying this object value.
1087
+
1088
+ gap += indent;
1089
+ partial = [];
1090
+
1091
+ // Is the value an array?
1092
+
1093
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
1094
+
1095
+ // The value is an array. Stringify every element. Use null as a placeholder
1096
+ // for non-JSON values.
1097
+
1098
+ length = value.length;
1099
+ for (i = 0; i < length; i += 1) {
1100
+ partial[i] = str(i, value) || 'null';
1101
+ }
1102
+
1103
+ // Join all of the elements together, separated with commas, and wrap them in
1104
+ // brackets.
1105
+
1106
+ v = partial.length === 0 ? '[]' : gap ?
1107
+ '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
1108
+ '[' + partial.join(',') + ']';
1109
+ gap = mind;
1110
+ return v;
1111
+ }
1112
+
1113
+ // If the replacer is an array, use it to select the members to be stringified.
1114
+
1115
+ if (rep && typeof rep === 'object') {
1116
+ length = rep.length;
1117
+ for (i = 0; i < length; i += 1) {
1118
+ if (typeof rep[i] === 'string') {
1119
+ k = rep[i];
1120
+ v = str(k, value);
1121
+ if (v) {
1122
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
1123
+ }
1124
+ }
1125
+ }
1126
+ } else {
1127
+
1128
+ // Otherwise, iterate through all of the keys in the object.
1129
+
1130
+ for (k in value) {
1131
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
1132
+ v = str(k, value);
1133
+ if (v) {
1134
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
1135
+ }
1136
+ }
1137
+ }
1138
+ }
1139
+
1140
+ // Join all of the member texts together, separated with commas,
1141
+ // and wrap them in braces.
1142
+
1143
+ v = partial.length === 0 ? '{}' : gap ?
1144
+ '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
1145
+ '{' + partial.join(',') + '}';
1146
+ gap = mind;
1147
+ return v;
1148
+ }
1149
+ }
1150
+
1151
+ // If the JSON object does not yet have a stringify method, give it one.
1152
+
1153
+ JSON.stringify = function (value, replacer, space) {
1154
+
1155
+ // The stringify method takes a value and an optional replacer, and an optional
1156
+ // space parameter, and returns a JSON text. The replacer can be a function
1157
+ // that can replace values, or an array of strings that will select the keys.
1158
+ // A default replacer method can be provided. Use of the space parameter can
1159
+ // produce text that is more easily readable.
1160
+
1161
+ var i;
1162
+ gap = '';
1163
+ indent = '';
1164
+
1165
+ // If the space parameter is a number, make an indent string containing that
1166
+ // many spaces.
1167
+
1168
+ if (typeof space === 'number') {
1169
+ for (i = 0; i < space; i += 1) {
1170
+ indent += ' ';
1171
+ }
1172
+
1173
+ // If the space parameter is a string, it will be used as the indent string.
1174
+
1175
+ } else if (typeof space === 'string') {
1176
+ indent = space;
1177
+ }
1178
+
1179
+ // If there is a replacer, it must be a function or an array.
1180
+ // Otherwise, throw an error.
1181
+
1182
+ rep = replacer;
1183
+ if (replacer && typeof replacer !== 'function' &&
1184
+ (typeof replacer !== 'object' ||
1185
+ typeof replacer.length !== 'number')) {
1186
+ throw new Error('JSON.stringify');
1187
+ }
1188
+
1189
+ // Make a fake root object containing our value under the key of ''.
1190
+ // Return the result of stringifying the value.
1191
+
1192
+ return str('', {'': value});
1193
+ };
1194
+
1195
+ // If the JSON object does not yet have a parse method, give it one.
1196
+
1197
+ JSON.parse = function (text, reviver) {
1198
+ // The parse method takes a text and an optional reviver function, and returns
1199
+ // a JavaScript value if the text is a valid JSON text.
1200
+
1201
+ var j;
1202
+
1203
+ function walk(holder, key) {
1204
+
1205
+ // The walk method is used to recursively walk the resulting structure so
1206
+ // that modifications can be made.
1207
+
1208
+ var k, v, value = holder[key];
1209
+ if (value && typeof value === 'object') {
1210
+ for (k in value) {
1211
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
1212
+ v = walk(value, k);
1213
+ if (v !== undefined) {
1214
+ value[k] = v;
1215
+ } else {
1216
+ delete value[k];
1217
+ }
1218
+ }
1219
+ }
1220
+ }
1221
+ return reviver.call(holder, key, value);
1222
+ }
1223
+
1224
+
1225
+ // Parsing happens in four stages. In the first stage, we replace certain
1226
+ // Unicode characters with escape sequences. JavaScript handles many characters
1227
+ // incorrectly, either silently deleting them, or treating them as line endings.
1228
+
1229
+ text = String(text);
1230
+ cx.lastIndex = 0;
1231
+ if (cx.test(text)) {
1232
+ text = text.replace(cx, function (a) {
1233
+ return '\\u' +
1234
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
1235
+ });
1236
+ }
1237
+
1238
+ // In the second stage, we run the text against regular expressions that look
1239
+ // for non-JSON patterns. We are especially concerned with '()' and 'new'
1240
+ // because they can cause invocation, and '=' because it can cause mutation.
1241
+ // But just to be safe, we want to reject all unexpected forms.
1242
+
1243
+ // We split the second stage into 4 regexp operations in order to work around
1244
+ // crippling inefficiencies in IE's and Safari's regexp engines. First we
1245
+ // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
1246
+ // replace all simple value tokens with ']' characters. Third, we delete all
1247
+ // open brackets that follow a colon or comma or that begin the text. Finally,
1248
+ // we look to see that the remaining characters are only whitespace or ']' or
1249
+ // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
1250
+
1251
+ if (/^[\],:{}\s]*$/
1252
+ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
1253
+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
1254
+ .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
1255
+
1256
+ // In the third stage we use the eval function to compile the text into a
1257
+ // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
1258
+ // in JavaScript: it can begin a block or an object literal. We wrap the text
1259
+ // in parens to eliminate the ambiguity.
1260
+
1261
+ j = eval('(' + text + ')');
1262
+
1263
+ // In the optional fourth stage, we recursively walk the new structure, passing
1264
+ // each name/value pair to a reviver function for possible transformation.
1265
+
1266
+ return typeof reviver === 'function' ?
1267
+ walk({'': j}, '') : j;
1268
+ }
1269
+
1270
+ // If the text is not JSON parseable, then a SyntaxError is thrown.
1271
+
1272
+ throw new SyntaxError('JSON.parse');
1273
+ };
1274
+
1275
+ return JSON;
1276
+ })();
1277
+
1278
+ if ('undefined' != typeof window) {
1279
+ window.expect = module.exports;
1280
+ }
1281
+
1282
+ })(
1283
+ this
1284
+ , 'undefined' != typeof module ? module : {exports: {}}
1285
+ );