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