Localisation updates from https://translatewiki.net.
[mediawiki.git] / resources / lib / sinonjs / sinon.js
blobcf2f94efeb1338e89705312aeb2b2921d64a167a
1 /**
2  * Sinon.JS 1.17.7, 2017/02/15
3  *
4  * @author Christian Johansen (christian@cjohansen.no)
5  * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
6  *
7  * (The BSD License)
8  * 
9  * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
10  * All rights reserved.
11  * 
12  * Redistribution and use in source and binary forms, with or without modification,
13  * are permitted provided that the following conditions are met:
14  * 
15  *     * Redistributions of source code must retain the above copyright notice,
16  *       this list of conditions and the following disclaimer.
17  *     * Redistributions in binary form must reproduce the above copyright notice,
18  *       this list of conditions and the following disclaimer in the documentation
19  *       and/or other materials provided with the distribution.
20  *     * Neither the name of Christian Johansen nor the names of his contributors
21  *       may be used to endorse or promote products derived from this software
22  *       without specific prior written permission.
23  * 
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
36 (function (root, factory) {
37   'use strict';
38   if (typeof define === 'function' && define.amd) {
39     define('sinon', [], function () {
40       return (root.sinon = factory());
41     });
42   } else if (typeof exports === 'object') {
43     module.exports = factory();
44   } else {
45     root.sinon = factory();
46   }
47 }(this, function () {
48   'use strict';
49   var samsam, formatio, lolex;
50   (function () {
51                 function define(mod, deps, fn) {
52                   if (mod == "samsam") {
53                     samsam = deps();
54                   } else if (typeof deps === "function" && mod.length === 0) {
55                     lolex = deps();
56                   } else if (typeof fn === "function") {
57                     formatio = fn(samsam);
58                   }
59                 }
60     define.amd = {};
61 ((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
62  (typeof module === "object" &&
63       function (m) { module.exports = m(); }) || // Node
64  function (m) { this.samsam = m(); } // Browser globals
65 )(function () {
66     var o = Object.prototype;
67     var div = typeof document !== "undefined" && document.createElement("div");
69     function isNaN(value) {
70         // Unlike global isNaN, this avoids type coercion
71         // typeof check avoids IE host object issues, hat tip to
72         // lodash
73         var val = value; // JsLint thinks value !== value is "weird"
74         return typeof value === "number" && value !== val;
75     }
77     function getClass(value) {
78         // Returns the internal [[Class]] by calling Object.prototype.toString
79         // with the provided value as this. Return value is a string, naming the
80         // internal class, e.g. "Array"
81         return o.toString.call(value).split(/[ \]]/)[1];
82     }
84     /**
85      * @name samsam.isArguments
86      * @param Object object
87      *
88      * Returns ``true`` if ``object`` is an ``arguments`` object,
89      * ``false`` otherwise.
90      */
91     function isArguments(object) {
92         if (getClass(object) === 'Arguments') { return true; }
93         if (typeof object !== "object" || typeof object.length !== "number" ||
94                 getClass(object) === "Array") {
95             return false;
96         }
97         if (typeof object.callee == "function") { return true; }
98         try {
99             object[object.length] = 6;
100             delete object[object.length];
101         } catch (e) {
102             return true;
103         }
104         return false;
105     }
107     /**
108      * @name samsam.isElement
109      * @param Object object
110      *
111      * Returns ``true`` if ``object`` is a DOM element node. Unlike
112      * Underscore.js/lodash, this function will return ``false`` if ``object``
113      * is an *element-like* object, i.e. a regular object with a ``nodeType``
114      * property that holds the value ``1``.
115      */
116     function isElement(object) {
117         if (!object || object.nodeType !== 1 || !div) { return false; }
118         try {
119             object.appendChild(div);
120             object.removeChild(div);
121         } catch (e) {
122             return false;
123         }
124         return true;
125     }
127     /**
128      * @name samsam.keys
129      * @param Object object
130      *
131      * Return an array of own property names.
132      */
133     function keys(object) {
134         var ks = [], prop;
135         for (prop in object) {
136             if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
137         }
138         return ks;
139     }
141     /**
142      * @name samsam.isDate
143      * @param Object value
144      *
145      * Returns true if the object is a ``Date``, or *date-like*. Duck typing
146      * of date objects work by checking that the object has a ``getTime``
147      * function whose return value equals the return value from the object's
148      * ``valueOf``.
149      */
150     function isDate(value) {
151         return typeof value.getTime == "function" &&
152             value.getTime() == value.valueOf();
153     }
155     /**
156      * @name samsam.isNegZero
157      * @param Object value
158      *
159      * Returns ``true`` if ``value`` is ``-0``.
160      */
161     function isNegZero(value) {
162         return value === 0 && 1 / value === -Infinity;
163     }
165     /**
166      * @name samsam.equal
167      * @param Object obj1
168      * @param Object obj2
169      *
170      * Returns ``true`` if two objects are strictly equal. Compared to
171      * ``===`` there are two exceptions:
172      *
173      *   - NaN is considered equal to NaN
174      *   - -0 and +0 are not considered equal
175      */
176     function identical(obj1, obj2) {
177         if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
178             return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
179         }
180     }
182     function isSet(val) {
183         if (typeof Set !== 'undefined' && val instanceof Set) {
184             return true;
185         }
186     }
188     function isSubset(s1, s2, compare) {
189         var values1 = Array.from(s1);
190         var values2 = Array.from(s2);
192         for (var i = 0; i < values1.length; i++) {
193             var includes = false;
195             for (var j = 0; j < values2.length; j++) {
196                 if (compare(values2[j], values1[i])) {
197                     includes = true;
198                     break;
199                 }
200             }
202             if (!includes) {
203                 return false;
204             }
205         }
207         return true;
208     }
210     /**
211      * @name samsam.deepEqual
212      * @param Object obj1
213      * @param Object obj2
214      *
215      * Deep equal comparison. Two values are "deep equal" if:
216      *
217      *   - They are equal, according to samsam.identical
218      *   - They are both date objects representing the same time
219      *   - They are both arrays containing elements that are all deepEqual
220      *   - They are objects with the same set of properties, and each property
221      *     in ``obj1`` is deepEqual to the corresponding property in ``obj2``
222      *
223      * Supports cyclic objects.
224      */
225     function deepEqualCyclic(obj1, obj2) {
227         // used for cyclic comparison
228         // contain already visited objects
229         var objects1 = [],
230             objects2 = [],
231         // contain pathes (position in the object structure)
232         // of the already visited objects
233         // indexes same as in objects arrays
234             paths1 = [],
235             paths2 = [],
236         // contains combinations of already compared objects
237         // in the manner: { "$1['ref']$2['ref']": true }
238             compared = {};
240         /**
241          * used to check, if the value of a property is an object
242          * (cyclic logic is only needed for objects)
243          * only needed for cyclic logic
244          */
245         function isObject(value) {
247             if (typeof value === 'object' && value !== null &&
248                     !(value instanceof Boolean) &&
249                     !(value instanceof Date)    &&
250                     !(value instanceof Number)  &&
251                     !(value instanceof RegExp)  &&
252                     !(value instanceof String)) {
254                 return true;
255             }
257             return false;
258         }
260         /**
261          * returns the index of the given object in the
262          * given objects array, -1 if not contained
263          * only needed for cyclic logic
264          */
265         function getIndex(objects, obj) {
267             var i;
268             for (i = 0; i < objects.length; i++) {
269                 if (objects[i] === obj) {
270                     return i;
271                 }
272             }
274             return -1;
275         }
277         // does the recursion for the deep equal check
278         return (function deepEqual(obj1, obj2, path1, path2) {
279             var type1 = typeof obj1;
280             var type2 = typeof obj2;
282             // == null also matches undefined
283             if (obj1 === obj2 ||
284                     isNaN(obj1) || isNaN(obj2) ||
285                     obj1 == null || obj2 == null ||
286                     type1 !== "object" || type2 !== "object") {
288                 return identical(obj1, obj2);
289             }
291             // Elements are only equal if identical(expected, actual)
292             if (isElement(obj1) || isElement(obj2)) { return false; }
294             var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
295             if (isDate1 || isDate2) {
296                 if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
297                     return false;
298                 }
299             }
301             if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
302                 if (obj1.toString() !== obj2.toString()) { return false; }
303             }
305             var class1 = getClass(obj1);
306             var class2 = getClass(obj2);
307             var keys1 = keys(obj1);
308             var keys2 = keys(obj2);
310             if (isArguments(obj1) || isArguments(obj2)) {
311                 if (obj1.length !== obj2.length) { return false; }
312             } else {
313                 if (type1 !== type2 || class1 !== class2 ||
314                         keys1.length !== keys2.length) {
315                     return false;
316                 }
317             }
319             if (isSet(obj1) || isSet(obj2)) {
320                 if (!isSet(obj1) || !isSet(obj2) || obj1.size !== obj2.size) {
321                     return false;
322                 }
324                 return isSubset(obj1, obj2, deepEqual);
325             }
327             var key, i, l,
328                 // following vars are used for the cyclic logic
329                 value1, value2,
330                 isObject1, isObject2,
331                 index1, index2,
332                 newPath1, newPath2;
334             for (i = 0, l = keys1.length; i < l; i++) {
335                 key = keys1[i];
336                 if (!o.hasOwnProperty.call(obj2, key)) {
337                     return false;
338                 }
340                 // Start of the cyclic logic
342                 value1 = obj1[key];
343                 value2 = obj2[key];
345                 isObject1 = isObject(value1);
346                 isObject2 = isObject(value2);
348                 // determine, if the objects were already visited
349                 // (it's faster to check for isObject first, than to
350                 // get -1 from getIndex for non objects)
351                 index1 = isObject1 ? getIndex(objects1, value1) : -1;
352                 index2 = isObject2 ? getIndex(objects2, value2) : -1;
354                 // determine the new pathes of the objects
355                 // - for non cyclic objects the current path will be extended
356                 //   by current property name
357                 // - for cyclic objects the stored path is taken
358                 newPath1 = index1 !== -1
359                     ? paths1[index1]
360                     : path1 + '[' + JSON.stringify(key) + ']';
361                 newPath2 = index2 !== -1
362                     ? paths2[index2]
363                     : path2 + '[' + JSON.stringify(key) + ']';
365                 // stop recursion if current objects are already compared
366                 if (compared[newPath1 + newPath2]) {
367                     return true;
368                 }
370                 // remember the current objects and their pathes
371                 if (index1 === -1 && isObject1) {
372                     objects1.push(value1);
373                     paths1.push(newPath1);
374                 }
375                 if (index2 === -1 && isObject2) {
376                     objects2.push(value2);
377                     paths2.push(newPath2);
378                 }
380                 // remember that the current objects are already compared
381                 if (isObject1 && isObject2) {
382                     compared[newPath1 + newPath2] = true;
383                 }
385                 // End of cyclic logic
387                 // neither value1 nor value2 is a cycle
388                 // continue with next level
389                 if (!deepEqual(value1, value2, newPath1, newPath2)) {
390                     return false;
391                 }
392             }
394             return true;
396         }(obj1, obj2, '$1', '$2'));
397     }
399     function arrayContains(array, subset, compare) {
400         if (subset.length === 0) { return true; }
401         var i, l, j, k;
402         for (i = 0, l = array.length; i < l; ++i) {
403             if (compare(array[i], subset[0])) {
404                 for (j = 0, k = subset.length; j < k; ++j) {
405                     if ((i + j) >= l) { return false; }
406                     if (!compare(array[i + j], subset[j])) { return false; }
407                 }
408                 return true;
409             }
410         }
411         return false;
412     }
414     /**
415      * @name samsam.match
416      * @param Object object
417      * @param Object matcher
418      *
419      * Compare arbitrary value ``object`` with matcher.
420      */
421     function match(object, matcher) {
422         if (matcher && typeof matcher.test === "function") {
423             return matcher.test(object);
424         }
426         if (typeof matcher === "function") {
427             return matcher(object) === true;
428         }
430         if (typeof matcher === "string") {
431             matcher = matcher.toLowerCase();
432             var notNull = typeof object === "string" || !!object;
433             return notNull &&
434                 (String(object)).toLowerCase().indexOf(matcher) >= 0;
435         }
437         if (typeof matcher === "number") {
438             return matcher === object;
439         }
441         if (typeof matcher === "boolean") {
442             return matcher === object;
443         }
445         if (typeof(matcher) === "undefined") {
446             return typeof(object) === "undefined";
447         }
449         if (matcher === null) {
450             return object === null;
451         }
453         if (isSet(object)) {
454             return isSubset(matcher, object, match);
455         }
457         if (getClass(object) === "Array" && getClass(matcher) === "Array") {
458             return arrayContains(object, matcher, match);
459         }
461         if (matcher && typeof matcher === "object") {
462             if (matcher === object) {
463                 return true;
464             }
465             var prop;
466             for (prop in matcher) {
467                 var value = object[prop];
468                 if (typeof value === "undefined" &&
469                         typeof object.getAttribute === "function") {
470                     value = object.getAttribute(prop);
471                 }
472                 if (matcher[prop] === null || typeof matcher[prop] === 'undefined') {
473                     if (value !== matcher[prop]) {
474                         return false;
475                     }
476                 } else if (typeof  value === "undefined" || !match(value, matcher[prop])) {
477                     return false;
478                 }
479             }
480             return true;
481         }
483         throw new Error("Matcher was not a string, a number, a " +
484                         "function, a boolean or an object");
485     }
487     return {
488         isArguments: isArguments,
489         isElement: isElement,
490         isDate: isDate,
491         isNegZero: isNegZero,
492         identical: identical,
493         deepEqual: deepEqualCyclic,
494         match: match,
495         keys: keys
496     };
498 ((typeof define === "function" && define.amd && function (m) {
499     define("formatio", ["samsam"], m);
500 }) || (typeof module === "object" && function (m) {
501     module.exports = m(require("samsam"));
502 }) || function (m) { this.formatio = m(this.samsam); }
503 )(function (samsam) {
504     
505     var formatio = {
506         excludeConstructors: ["Object", /^.$/],
507         quoteStrings: true,
508         limitChildrenCount: 0
509     };
511     var hasOwn = Object.prototype.hasOwnProperty;
513     var specialObjects = [];
514     if (typeof global !== "undefined") {
515         specialObjects.push({ object: global, value: "[object global]" });
516     }
517     if (typeof document !== "undefined") {
518         specialObjects.push({
519             object: document,
520             value: "[object HTMLDocument]"
521         });
522     }
523     if (typeof window !== "undefined") {
524         specialObjects.push({ object: window, value: "[object Window]" });
525     }
527     function functionName(func) {
528         if (!func) { return ""; }
529         if (func.displayName) { return func.displayName; }
530         if (func.name) { return func.name; }
531         var matches = func.toString().match(/function\s+([^\(]+)/m);
532         return (matches && matches[1]) || "";
533     }
535     function constructorName(f, object) {
536         var name = functionName(object && object.constructor);
537         var excludes = f.excludeConstructors ||
538                 formatio.excludeConstructors || [];
540         var i, l;
541         for (i = 0, l = excludes.length; i < l; ++i) {
542             if (typeof excludes[i] === "string" && excludes[i] === name) {
543                 return "";
544             } else if (excludes[i].test && excludes[i].test(name)) {
545                 return "";
546             }
547         }
549         return name;
550     }
552     function isCircular(object, objects) {
553         if (typeof object !== "object") { return false; }
554         var i, l;
555         for (i = 0, l = objects.length; i < l; ++i) {
556             if (objects[i] === object) { return true; }
557         }
558         return false;
559     }
561     function ascii(f, object, processed, indent) {
562         if (typeof object === "string") {
563             var qs = f.quoteStrings;
564             var quote = typeof qs !== "boolean" || qs;
565             return processed || quote ? '"' + object + '"' : object;
566         }
568         if (typeof object === "function" && !(object instanceof RegExp)) {
569             return ascii.func(object);
570         }
572         processed = processed || [];
574         if (isCircular(object, processed)) { return "[Circular]"; }
576         if (Object.prototype.toString.call(object) === "[object Array]") {
577             return ascii.array.call(f, object, processed);
578         }
580         if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
581         if (samsam.isElement(object)) { return ascii.element(object); }
583         if (typeof object.toString === "function" &&
584                 object.toString !== Object.prototype.toString) {
585             return object.toString();
586         }
588         var i, l;
589         for (i = 0, l = specialObjects.length; i < l; i++) {
590             if (object === specialObjects[i].object) {
591                 return specialObjects[i].value;
592             }
593         }
595         return ascii.object.call(f, object, processed, indent);
596     }
598     ascii.func = function (func) {
599         return "function " + functionName(func) + "() {}";
600     };
602     ascii.array = function (array, processed) {
603         processed = processed || [];
604         processed.push(array);
605         var pieces = [];
606         var i, l;
607         l = (this.limitChildrenCount > 0) ? 
608             Math.min(this.limitChildrenCount, array.length) : array.length;
610         for (i = 0; i < l; ++i) {
611             pieces.push(ascii(this, array[i], processed));
612         }
614         if(l < array.length)
615             pieces.push("[... " + (array.length - l) + " more elements]");
617         return "[" + pieces.join(", ") + "]";
618     };
620     ascii.object = function (object, processed, indent) {
621         processed = processed || [];
622         processed.push(object);
623         indent = indent || 0;
624         var pieces = [], properties = samsam.keys(object).sort();
625         var length = 3;
626         var prop, str, obj, i, k, l;
627         l = (this.limitChildrenCount > 0) ? 
628             Math.min(this.limitChildrenCount, properties.length) : properties.length;
630         for (i = 0; i < l; ++i) {
631             prop = properties[i];
632             obj = object[prop];
634             if (isCircular(obj, processed)) {
635                 str = "[Circular]";
636             } else {
637                 str = ascii(this, obj, processed, indent + 2);
638             }
640             str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
641             length += str.length;
642             pieces.push(str);
643         }
645         var cons = constructorName(this, object);
646         var prefix = cons ? "[" + cons + "] " : "";
647         var is = "";
648         for (i = 0, k = indent; i < k; ++i) { is += " "; }
650         if(l < properties.length)
651             pieces.push("[... " + (properties.length - l) + " more elements]");
653         if (length + indent > 80) {
654             return prefix + "{\n  " + is + pieces.join(",\n  " + is) + "\n" +
655                 is + "}";
656         }
657         return prefix + "{ " + pieces.join(", ") + " }";
658     };
660     ascii.element = function (element) {
661         var tagName = element.tagName.toLowerCase();
662         var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
664         for (i = 0, l = attrs.length; i < l; ++i) {
665             attr = attrs.item(i);
666             attrName = attr.nodeName.toLowerCase().replace("html:", "");
667             val = attr.nodeValue;
668             if (attrName !== "contenteditable" || val !== "inherit") {
669                 if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
670             }
671         }
673         var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
674         var content = element.innerHTML;
676         if (content.length > 20) {
677             content = content.substr(0, 20) + "[...]";
678         }
680         var res = formatted + pairs.join(" ") + ">" + content +
681                 "</" + tagName + ">";
683         return res.replace(/ contentEditable="inherit"/, "");
684     };
686     function Formatio(options) {
687         for (var opt in options) {
688             this[opt] = options[opt];
689         }
690     }
692     Formatio.prototype = {
693         functionName: functionName,
695         configure: function (options) {
696             return new Formatio(options);
697         },
699         constructorName: function (object) {
700             return constructorName(this, object);
701         },
703         ascii: function (object, processed, indent) {
704             return ascii(this, object, processed, indent);
705         }
706     };
708     return Formatio.prototype;
710 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.lolex = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
711 (function (global){
712 (function (global) {
713     
714     var userAgent = global.navigator && global.navigator.userAgent;
715     var isRunningInIE = userAgent && userAgent.indexOf("MSIE ") > -1;
717     // Make properties writable in IE, as per
718     // http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
719     if (isRunningInIE) {
720         global.setTimeout = global.setTimeout;
721         global.clearTimeout = global.clearTimeout;
722         global.setInterval = global.setInterval;
723         global.clearInterval = global.clearInterval;
724         global.Date = global.Date;
725     }
727     // setImmediate is not a standard function
728     // avoid adding the prop to the window object if not present
729     if (global.setImmediate !== undefined) {
730         global.setImmediate = global.setImmediate;
731         global.clearImmediate = global.clearImmediate;
732     }
734     // node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
735     // browsers, a number.
736     // see https://github.com/cjohansen/Sinon.JS/pull/436
738     var NOOP = function () { return undefined; };
739     var timeoutResult = setTimeout(NOOP, 0);
740     var addTimerReturnsObject = typeof timeoutResult === "object";
741     var hrtimePresent = (global.process && typeof global.process.hrtime === "function");
742     clearTimeout(timeoutResult);
744     var NativeDate = Date;
745     var uniqueTimerId = 1;
747     /**
748      * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
749      * number of milliseconds. This is used to support human-readable strings passed
750      * to clock.tick()
751      */
752     function parseTime(str) {
753         if (!str) {
754             return 0;
755         }
757         var strings = str.split(":");
758         var l = strings.length, i = l;
759         var ms = 0, parsed;
761         if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
762             throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
763         }
765         while (i--) {
766             parsed = parseInt(strings[i], 10);
768             if (parsed >= 60) {
769                 throw new Error("Invalid time " + str);
770             }
772             ms += parsed * Math.pow(60, (l - i - 1));
773         }
775         return ms * 1000;
776     }
778     /**
779      * Floor function that also works for negative numbers
780      */
781     function fixedFloor(n) {
782         return (n >= 0 ? Math.floor(n) : Math.ceil(n));
783     }
785     /**
786      * % operator that also works for negative numbers
787      */
788     function fixedModulo(n, m) {
789         return ((n % m) + m) % m;
790     }
792     /**
793      * Used to grok the `now` parameter to createClock.
794      */
795     function getEpoch(epoch) {
796         if (!epoch) { return 0; }
797         if (typeof epoch.getTime === "function") { return epoch.getTime(); }
798         if (typeof epoch === "number") { return epoch; }
799         throw new TypeError("now should be milliseconds since UNIX epoch");
800     }
802     function inRange(from, to, timer) {
803         return timer && timer.callAt >= from && timer.callAt <= to;
804     }
806     function mirrorDateProperties(target, source) {
807         var prop;
808         for (prop in source) {
809             if (source.hasOwnProperty(prop)) {
810                 target[prop] = source[prop];
811             }
812         }
814         // set special now implementation
815         if (source.now) {
816             target.now = function now() {
817                 return target.clock.now;
818             };
819         } else {
820             delete target.now;
821         }
823         // set special toSource implementation
824         if (source.toSource) {
825             target.toSource = function toSource() {
826                 return source.toSource();
827             };
828         } else {
829             delete target.toSource;
830         }
832         // set special toString implementation
833         target.toString = function toString() {
834             return source.toString();
835         };
837         target.prototype = source.prototype;
838         target.parse = source.parse;
839         target.UTC = source.UTC;
840         target.prototype.toUTCString = source.prototype.toUTCString;
842         return target;
843     }
845     function createDate() {
846         function ClockDate(year, month, date, hour, minute, second, ms) {
847             // Defensive and verbose to avoid potential harm in passing
848             // explicit undefined when user does not pass argument
849             switch (arguments.length) {
850                 case 0:
851                     return new NativeDate(ClockDate.clock.now);
852                 case 1:
853                     return new NativeDate(year);
854                 case 2:
855                     return new NativeDate(year, month);
856                 case 3:
857                     return new NativeDate(year, month, date);
858                 case 4:
859                     return new NativeDate(year, month, date, hour);
860                 case 5:
861                     return new NativeDate(year, month, date, hour, minute);
862                 case 6:
863                     return new NativeDate(year, month, date, hour, minute, second);
864                 default:
865                     return new NativeDate(year, month, date, hour, minute, second, ms);
866             }
867         }
869         return mirrorDateProperties(ClockDate, NativeDate);
870     }
872     function addTimer(clock, timer) {
873         if (timer.func === undefined) {
874             throw new Error("Callback must be provided to timer calls");
875         }
877         if (!clock.timers) {
878             clock.timers = {};
879         }
881         timer.id = uniqueTimerId++;
882         timer.createdAt = clock.now;
883         timer.callAt = clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0));
885         clock.timers[timer.id] = timer;
887         if (addTimerReturnsObject) {
888             return {
889                 id: timer.id,
890                 ref: NOOP,
891                 unref: NOOP
892             };
893         }
895         return timer.id;
896     }
899     /* eslint consistent-return: "off" */
900     function compareTimers(a, b) {
901         // Sort first by absolute timing
902         if (a.callAt < b.callAt) {
903             return -1;
904         }
905         if (a.callAt > b.callAt) {
906             return 1;
907         }
909         // Sort next by immediate, immediate timers take precedence
910         if (a.immediate && !b.immediate) {
911             return -1;
912         }
913         if (!a.immediate && b.immediate) {
914             return 1;
915         }
917         // Sort next by creation time, earlier-created timers take precedence
918         if (a.createdAt < b.createdAt) {
919             return -1;
920         }
921         if (a.createdAt > b.createdAt) {
922             return 1;
923         }
925         // Sort next by id, lower-id timers take precedence
926         if (a.id < b.id) {
927             return -1;
928         }
929         if (a.id > b.id) {
930             return 1;
931         }
933         // As timer ids are unique, no fallback `0` is necessary
934     }
936     function firstTimerInRange(clock, from, to) {
937         var timers = clock.timers,
938             timer = null,
939             id,
940             isInRange;
942         for (id in timers) {
943             if (timers.hasOwnProperty(id)) {
944                 isInRange = inRange(from, to, timers[id]);
946                 if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
947                     timer = timers[id];
948                 }
949             }
950         }
952         return timer;
953     }
955     function firstTimer(clock) {
956         var timers = clock.timers,
957             timer = null,
958             id;
960         for (id in timers) {
961             if (timers.hasOwnProperty(id)) {
962                 if (!timer || compareTimers(timer, timers[id]) === 1) {
963                     timer = timers[id];
964                 }
965             }
966         }
968         return timer;
969     }
971     function lastTimer(clock) {
972         var timers = clock.timers,
973             timer = null,
974             id;
976         for (id in timers) {
977             if (timers.hasOwnProperty(id)) {
978                 if (!timer || compareTimers(timer, timers[id]) === -1) {
979                     timer = timers[id];
980                 }
981             }
982         }
984         return timer;
985     }
987     function callTimer(clock, timer) {
988         var exception;
990         if (typeof timer.interval === "number") {
991             clock.timers[timer.id].callAt += timer.interval;
992         } else {
993             delete clock.timers[timer.id];
994         }
996         try {
997             if (typeof timer.func === "function") {
998                 timer.func.apply(null, timer.args);
999             } else {
1000                 /* eslint no-eval: "off" */
1001                 eval(timer.func);
1002             }
1003         } catch (e) {
1004             exception = e;
1005         }
1007         if (!clock.timers[timer.id]) {
1008             if (exception) {
1009                 throw exception;
1010             }
1011             return;
1012         }
1014         if (exception) {
1015             throw exception;
1016         }
1017     }
1019     function timerType(timer) {
1020         if (timer.immediate) {
1021             return "Immediate";
1022         }
1023         if (timer.interval !== undefined) {
1024             return "Interval";
1025         }
1026         return "Timeout";
1027     }
1029     function clearTimer(clock, timerId, ttype) {
1030         if (!timerId) {
1031             // null appears to be allowed in most browsers, and appears to be
1032             // relied upon by some libraries, like Bootstrap carousel
1033             return;
1034         }
1036         if (!clock.timers) {
1037             clock.timers = [];
1038         }
1040         // in Node, timerId is an object with .ref()/.unref(), and
1041         // its .id field is the actual timer id.
1042         if (typeof timerId === "object") {
1043             timerId = timerId.id;
1044         }
1046         if (clock.timers.hasOwnProperty(timerId)) {
1047             // check that the ID matches a timer of the correct type
1048             var timer = clock.timers[timerId];
1049             if (timerType(timer) === ttype) {
1050                 delete clock.timers[timerId];
1051             } else {
1052                 throw new Error("Cannot clear timer: timer created with set" + timerType(timer)
1053                                 + "() but cleared with clear" + ttype + "()");
1054             }
1055         }
1056     }
1058     function uninstall(clock, target) {
1059         var method,
1060             i,
1061             l;
1062         var installedHrTime = "_hrtime";
1064         for (i = 0, l = clock.methods.length; i < l; i++) {
1065             method = clock.methods[i];
1066             if (method === "hrtime" && target.process) {
1067                 target.process.hrtime = clock[installedHrTime];
1068             } else {
1069                 if (target[method] && target[method].hadOwnProperty) {
1070                     target[method] = clock["_" + method];
1071                 } else {
1072                     try {
1073                         delete target[method];
1074                     } catch (ignore) { /* eslint empty-block: "off" */ }
1075                 }
1076             }
1077         }
1079         // Prevent multiple executions which will completely remove these props
1080         clock.methods = [];
1081     }
1083     function hijackMethod(target, method, clock) {
1084         var prop;
1086         clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
1087         clock["_" + method] = target[method];
1089         if (method === "Date") {
1090             var date = mirrorDateProperties(clock[method], target[method]);
1091             target[method] = date;
1092         } else {
1093             target[method] = function () {
1094                 return clock[method].apply(clock, arguments);
1095             };
1097             for (prop in clock[method]) {
1098                 if (clock[method].hasOwnProperty(prop)) {
1099                     target[method][prop] = clock[method][prop];
1100                 }
1101             }
1102         }
1104         target[method].clock = clock;
1105     }
1107     var timers = {
1108         setTimeout: setTimeout,
1109         clearTimeout: clearTimeout,
1110         setImmediate: global.setImmediate,
1111         clearImmediate: global.clearImmediate,
1112         setInterval: setInterval,
1113         clearInterval: clearInterval,
1114         Date: Date
1115     };
1117     if (hrtimePresent) {
1118         timers.hrtime = global.process.hrtime;
1119     }
1121     var keys = Object.keys || function (obj) {
1122         var ks = [],
1123             key;
1125         for (key in obj) {
1126             if (obj.hasOwnProperty(key)) {
1127                 ks.push(key);
1128             }
1129         }
1131         return ks;
1132     };
1134     exports.timers = timers;
1136     function createClock(now, loopLimit) {
1137         loopLimit = loopLimit || 1000;
1139         var clock = {
1140             now: getEpoch(now),
1141             hrNow: 0,
1142             timeouts: {},
1143             Date: createDate(),
1144             loopLimit: loopLimit
1145         };
1147         clock.Date.clock = clock;
1149         clock.setTimeout = function setTimeout(func, timeout) {
1150             return addTimer(clock, {
1151                 func: func,
1152                 args: Array.prototype.slice.call(arguments, 2),
1153                 delay: timeout
1154             });
1155         };
1157         clock.clearTimeout = function clearTimeout(timerId) {
1158             return clearTimer(clock, timerId, "Timeout");
1159         };
1161         clock.setInterval = function setInterval(func, timeout) {
1162             return addTimer(clock, {
1163                 func: func,
1164                 args: Array.prototype.slice.call(arguments, 2),
1165                 delay: timeout,
1166                 interval: timeout
1167             });
1168         };
1170         clock.clearInterval = function clearInterval(timerId) {
1171             return clearTimer(clock, timerId, "Interval");
1172         };
1174         clock.setImmediate = function setImmediate(func) {
1175             return addTimer(clock, {
1176                 func: func,
1177                 args: Array.prototype.slice.call(arguments, 1),
1178                 immediate: true
1179             });
1180         };
1182         clock.clearImmediate = function clearImmediate(timerId) {
1183             return clearTimer(clock, timerId, "Immediate");
1184         };
1186         clock.tick = function tick(ms) {
1187             ms = typeof ms === "number" ? ms : parseTime(ms);
1188             var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
1189             var timer = firstTimerInRange(clock, tickFrom, tickTo);
1190             var oldNow;
1192             clock.duringTick = true;
1194             function updateHrTime(newNow) {
1195                 clock.hrNow += (newNow - clock.now);
1196             }
1198             var firstException;
1199             while (timer && tickFrom <= tickTo) {
1200                 if (clock.timers[timer.id]) {
1201                     updateHrTime(timer.callAt);
1202                     tickFrom = timer.callAt;
1203                     clock.now = timer.callAt;
1204                     try {
1205                         oldNow = clock.now;
1206                         callTimer(clock, timer);
1207                         // compensate for any setSystemTime() call during timer callback
1208                         if (oldNow !== clock.now) {
1209                             tickFrom += clock.now - oldNow;
1210                             tickTo += clock.now - oldNow;
1211                             previous += clock.now - oldNow;
1212                         }
1213                     } catch (e) {
1214                         firstException = firstException || e;
1215                     }
1216                 }
1218                 timer = firstTimerInRange(clock, previous, tickTo);
1219                 previous = tickFrom;
1220             }
1222             clock.duringTick = false;
1223             updateHrTime(tickTo);
1224             clock.now = tickTo;
1226             if (firstException) {
1227                 throw firstException;
1228             }
1230             return clock.now;
1231         };
1233         clock.next = function next() {
1234             var timer = firstTimer(clock);
1235             if (!timer) {
1236                 return clock.now;
1237             }
1239             clock.duringTick = true;
1240             try {
1241                 clock.now = timer.callAt;
1242                 callTimer(clock, timer);
1243                 return clock.now;
1244             } finally {
1245                 clock.duringTick = false;
1246             }
1247         };
1249         clock.runAll = function runAll() {
1250             var numTimers, i;
1251             for (i = 0; i < clock.loopLimit; i++) {
1252                 if (!clock.timers) {
1253                     return clock.now;
1254                 }
1256                 numTimers = Object.keys(clock.timers).length;
1257                 if (numTimers === 0) {
1258                     return clock.now;
1259                 }
1261                 clock.next();
1262             }
1264             throw new Error("Aborting after running " + clock.loopLimit + "timers, assuming an infinite loop!");
1265         };
1267         clock.runToLast = function runToLast() {
1268             var timer = lastTimer(clock);
1269             if (!timer) {
1270                 return clock.now;
1271             }
1273             return clock.tick(timer.callAt);
1274         };
1276         clock.reset = function reset() {
1277             clock.timers = {};
1278         };
1280         clock.setSystemTime = function setSystemTime(now) {
1281             // determine time difference
1282             var newNow = getEpoch(now);
1283             var difference = newNow - clock.now;
1284             var id, timer;
1286             // update 'system clock'
1287             clock.now = newNow;
1289             // update timers and intervals to keep them stable
1290             for (id in clock.timers) {
1291                 if (clock.timers.hasOwnProperty(id)) {
1292                     timer = clock.timers[id];
1293                     timer.createdAt += difference;
1294                     timer.callAt += difference;
1295                 }
1296             }
1297         };
1299         if (hrtimePresent) {
1300             clock.hrtime = function (prev) {
1301                 if (Array.isArray(prev)) {
1302                     var oldSecs = (prev[0] + prev[1] / 1e9);
1303                     var newSecs = (clock.hrNow / 1000);
1304                     var difference = (newSecs - oldSecs);
1305                     var secs = fixedFloor(difference);
1306                     var nanosecs = fixedModulo(difference * 1e9, 1e9);
1307                     return [
1308                         secs,
1309                         nanosecs
1310                     ];
1311                 }
1312                 return [
1313                     fixedFloor(clock.hrNow / 1000),
1314                     fixedModulo(clock.hrNow * 1e6, 1e9)
1315                 ];
1316             };
1317         }
1319         return clock;
1320     }
1321     exports.createClock = createClock;
1323     exports.install = function install(target, now, toFake, loopLimit) {
1324         var i,
1325             l;
1327         if (typeof target === "number") {
1328             toFake = now;
1329             now = target;
1330             target = null;
1331         }
1333         if (!target) {
1334             target = global;
1335         }
1337         var clock = createClock(now, loopLimit);
1339         clock.uninstall = function () {
1340             uninstall(clock, target);
1341         };
1343         clock.methods = toFake || [];
1345         if (clock.methods.length === 0) {
1346             clock.methods = keys(timers);
1347         }
1349         for (i = 0, l = clock.methods.length; i < l; i++) {
1350             if (clock.methods[i] === "hrtime") {
1351                 if (target.process && typeof target.process.hrtime === "function") {
1352                     hijackMethod(target.process, clock.methods[i], clock);
1353                 }
1354             } else {
1355                 hijackMethod(target, clock.methods[i], clock);
1356             }
1357         }
1359         return clock;
1360     };
1362 }(global || this));
1364 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1365 },{}]},{},[1])(1)
1367   })();
1368   var define;
1370  * Sinon core utilities. For internal use only.
1372  * @author Christian Johansen (christian@cjohansen.no)
1373  * @license BSD
1375  * Copyright (c) 2010-2013 Christian Johansen
1376  */
1377 var sinon = (function () {
1378 "use strict";
1379  // eslint-disable-line no-unused-vars
1380     
1381     var sinonModule;
1382     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1383     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1385     function loadDependencies(require, exports, module) {
1386         sinonModule = module.exports = require("./sinon/util/core");
1387         require("./sinon/extend");
1388         require("./sinon/walk");
1389         require("./sinon/typeOf");
1390         require("./sinon/times_in_words");
1391         require("./sinon/spy");
1392         require("./sinon/call");
1393         require("./sinon/behavior");
1394         require("./sinon/stub");
1395         require("./sinon/mock");
1396         require("./sinon/collection");
1397         require("./sinon/assert");
1398         require("./sinon/sandbox");
1399         require("./sinon/test");
1400         require("./sinon/test_case");
1401         require("./sinon/match");
1402         require("./sinon/format");
1403         require("./sinon/log_error");
1404     }
1406     if (isAMD) {
1407         define(loadDependencies);
1408     } else if (isNode) {
1409         loadDependencies(require, module.exports, module);
1410         sinonModule = module.exports;
1411     } else {
1412         sinonModule = {};
1413     }
1415     return sinonModule;
1416 }());
1419  * @depend ../../sinon.js
1420  */
1422  * Sinon core utilities. For internal use only.
1424  * @author Christian Johansen (christian@cjohansen.no)
1425  * @license BSD
1427  * Copyright (c) 2010-2013 Christian Johansen
1428  */
1429 (function (sinonGlobal) {
1430     
1431     var div = typeof document !== "undefined" && document.createElement("div");
1432     var hasOwn = Object.prototype.hasOwnProperty;
1434     function isDOMNode(obj) {
1435         var success = false;
1437         try {
1438             obj.appendChild(div);
1439             success = div.parentNode === obj;
1440         } catch (e) {
1441             return false;
1442         } finally {
1443             try {
1444                 obj.removeChild(div);
1445             } catch (e) {
1446                 // Remove failed, not much we can do about that
1447             }
1448         }
1450         return success;
1451     }
1453     function isElement(obj) {
1454         return div && obj && obj.nodeType === 1 && isDOMNode(obj);
1455     }
1457     function isFunction(obj) {
1458         return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
1459     }
1461     function isReallyNaN(val) {
1462         return typeof val === "number" && isNaN(val);
1463     }
1465     function mirrorProperties(target, source) {
1466         for (var prop in source) {
1467             if (!hasOwn.call(target, prop)) {
1468                 target[prop] = source[prop];
1469             }
1470         }
1471     }
1473     function isRestorable(obj) {
1474         return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
1475     }
1477     // Cheap way to detect if we have ES5 support.
1478     var hasES5Support = "keys" in Object;
1480     function makeApi(sinon) {
1481         sinon.wrapMethod = function wrapMethod(object, property, method) {
1482             if (!object) {
1483                 throw new TypeError("Should wrap property of object");
1484             }
1486             if (typeof method !== "function" && typeof method !== "object") {
1487                 throw new TypeError("Method wrapper should be a function or a property descriptor");
1488             }
1490             function checkWrappedMethod(wrappedMethod) {
1491                 var error;
1493                 if (!isFunction(wrappedMethod)) {
1494                     error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
1495                                         property + " as function");
1496                 } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
1497                     error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
1498                 } else if (wrappedMethod.calledBefore) {
1499                     var verb = wrappedMethod.returns ? "stubbed" : "spied on";
1500                     error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
1501                 }
1503                 if (error) {
1504                     if (wrappedMethod && wrappedMethod.stackTrace) {
1505                         error.stack += "\n--------------\n" + wrappedMethod.stackTrace;
1506                     }
1507                     throw error;
1508                 }
1509             }
1511             var error, wrappedMethod, i;
1513             function simplePropertyAssignment() {
1514                 wrappedMethod = object[property];
1515                 checkWrappedMethod(wrappedMethod);
1516                 object[property] = method;
1517                 method.displayName = property;
1518             }
1520             // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
1521             // when using hasOwn.call on objects from other frames.
1522             var owned = (object.hasOwnProperty && object.hasOwnProperty === hasOwn) ?
1523                 object.hasOwnProperty(property) : hasOwn.call(object, property);
1525             if (hasES5Support) {
1526                 var methodDesc = (typeof method === "function") ? {value: method} : method;
1527                 var wrappedMethodDesc = sinon.getPropertyDescriptor(object, property);
1529                 if (!wrappedMethodDesc) {
1530                     error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
1531                                         property + " as function");
1532                 } else if (wrappedMethodDesc.restore && wrappedMethodDesc.restore.sinon) {
1533                     error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
1534                 }
1535                 if (error) {
1536                     if (wrappedMethodDesc && wrappedMethodDesc.stackTrace) {
1537                         error.stack += "\n--------------\n" + wrappedMethodDesc.stackTrace;
1538                     }
1539                     throw error;
1540                 }
1542                 var types = sinon.objectKeys(methodDesc);
1543                 for (i = 0; i < types.length; i++) {
1544                     wrappedMethod = wrappedMethodDesc[types[i]];
1545                     checkWrappedMethod(wrappedMethod);
1546                 }
1548                 mirrorProperties(methodDesc, wrappedMethodDesc);
1549                 for (i = 0; i < types.length; i++) {
1550                     mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]);
1551                 }
1552                 Object.defineProperty(object, property, methodDesc);
1554                 // catch failing assignment
1555                 // this is the converse of the check in `.restore` below
1556                 if ( typeof method === "function" && object[property] !== method ) {
1557                     // correct any wrongdoings caused by the defineProperty call above,
1558                     // such as adding new items (if object was a Storage object)
1559                     delete object[property];
1560                     simplePropertyAssignment();
1561                 }
1562             } else {
1563                 simplePropertyAssignment();
1564             }
1566             method.displayName = property;
1568             // Set up a stack trace which can be used later to find what line of
1569             // code the original method was created on.
1570             method.stackTrace = (new Error("Stack Trace for original")).stack;
1572             method.restore = function () {
1573                 // For prototype properties try to reset by delete first.
1574                 // If this fails (ex: localStorage on mobile safari) then force a reset
1575                 // via direct assignment.
1576                 if (!owned) {
1577                     // In some cases `delete` may throw an error
1578                     try {
1579                         delete object[property];
1580                     } catch (e) {} // eslint-disable-line no-empty
1581                     // For native code functions `delete` fails without throwing an error
1582                     // on Chrome < 43, PhantomJS, etc.
1583                 } else if (hasES5Support) {
1584                     Object.defineProperty(object, property, wrappedMethodDesc);
1585                 }
1587                 // this only supports ES5 getter/setter, for ES3.1 and lower
1588                 // __lookupSetter__ / __lookupGetter__ should be integrated
1589                 if (hasES5Support) {
1590                     var checkDesc = sinon.getPropertyDescriptor(object, property);
1591                     if (checkDesc.value === method) {
1592                         object[property] = wrappedMethod;
1593                     }
1595                 // Use strict equality comparison to check failures then force a reset
1596                 // via direct assignment.
1597                 } else if (object[property] === method) {
1598                     object[property] = wrappedMethod;
1599                 }
1600             };
1602             method.restore.sinon = true;
1604             if (!hasES5Support) {
1605                 mirrorProperties(method, wrappedMethod);
1606             }
1608             return method;
1609         };
1611         sinon.create = function create(proto) {
1612             var F = function () {};
1613             F.prototype = proto;
1614             return new F();
1615         };
1617         sinon.deepEqual = function deepEqual(a, b) {
1618             if (sinon.match && sinon.match.isMatcher(a)) {
1619                 return a.test(b);
1620             }
1622             if (typeof a !== "object" || typeof b !== "object") {
1623                 return isReallyNaN(a) && isReallyNaN(b) || a === b;
1624             }
1626             if (isElement(a) || isElement(b)) {
1627                 return a === b;
1628             }
1630             if (a === b) {
1631                 return true;
1632             }
1634             if ((a === null && b !== null) || (a !== null && b === null)) {
1635                 return false;
1636             }
1638             if (a instanceof RegExp && b instanceof RegExp) {
1639                 return (a.source === b.source) && (a.global === b.global) &&
1640                     (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
1641             }
1643             var aString = Object.prototype.toString.call(a);
1644             if (aString !== Object.prototype.toString.call(b)) {
1645                 return false;
1646             }
1648             if (aString === "[object Date]") {
1649                 return a.valueOf() === b.valueOf();
1650             }
1652             var prop;
1653             var aLength = 0;
1654             var bLength = 0;
1656             if (aString === "[object Array]" && a.length !== b.length) {
1657                 return false;
1658             }
1660             for (prop in a) {
1661                 if (hasOwn.call(a, prop)) {
1662                     aLength += 1;
1664                     if (!(prop in b)) {
1665                         return false;
1666                     }
1668                     if (!deepEqual(a[prop], b[prop])) {
1669                         return false;
1670                     }
1671                 }
1672             }
1674             for (prop in b) {
1675                 if (hasOwn.call(b, prop)) {
1676                     bLength += 1;
1677                 }
1678             }
1680             return aLength === bLength;
1681         };
1683         sinon.functionName = function functionName(func) {
1684             var name = func.displayName || func.name;
1686             // Use function decomposition as a last resort to get function
1687             // name. Does not rely on function decomposition to work - if it
1688             // doesn't debugging will be slightly less informative
1689             // (i.e. toString will say 'spy' rather than 'myFunc').
1690             if (!name) {
1691                 var matches = func.toString().match(/function ([^\s\(]+)/);
1692                 name = matches && matches[1];
1693             }
1695             return name;
1696         };
1698         sinon.functionToString = function toString() {
1699             if (this.getCall && this.callCount) {
1700                 var thisValue,
1701                     prop;
1702                 var i = this.callCount;
1704                 while (i--) {
1705                     thisValue = this.getCall(i).thisValue;
1707                     for (prop in thisValue) {
1708                         if (thisValue[prop] === this) {
1709                             return prop;
1710                         }
1711                     }
1712                 }
1713             }
1715             return this.displayName || "sinon fake";
1716         };
1718         sinon.objectKeys = function objectKeys(obj) {
1719             if (obj !== Object(obj)) {
1720                 throw new TypeError("sinon.objectKeys called on a non-object");
1721             }
1723             var keys = [];
1724             var key;
1725             for (key in obj) {
1726                 if (hasOwn.call(obj, key)) {
1727                     keys.push(key);
1728                 }
1729             }
1731             return keys;
1732         };
1734         sinon.getPropertyDescriptor = function getPropertyDescriptor(object, property) {
1735             var proto = object;
1736             var descriptor;
1738             while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
1739                 proto = Object.getPrototypeOf(proto);
1740             }
1741             return descriptor;
1742         };
1744         sinon.getConfig = function (custom) {
1745             var config = {};
1746             custom = custom || {};
1747             var defaults = sinon.defaultConfig;
1749             for (var prop in defaults) {
1750                 if (defaults.hasOwnProperty(prop)) {
1751                     config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
1752                 }
1753             }
1755             return config;
1756         };
1758         sinon.defaultConfig = {
1759             injectIntoThis: true,
1760             injectInto: null,
1761             properties: ["spy", "stub", "mock", "clock", "server", "requests"],
1762             useFakeTimers: true,
1763             useFakeServer: true
1764         };
1766         sinon.timesInWords = function timesInWords(count) {
1767             return count === 1 && "once" ||
1768                 count === 2 && "twice" ||
1769                 count === 3 && "thrice" ||
1770                 (count || 0) + " times";
1771         };
1773         sinon.calledInOrder = function (spies) {
1774             for (var i = 1, l = spies.length; i < l; i++) {
1775                 if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
1776                     return false;
1777                 }
1778             }
1780             return true;
1781         };
1783         sinon.orderByFirstCall = function (spies) {
1784             return spies.sort(function (a, b) {
1785                 // uuid, won't ever be equal
1786                 var aCall = a.getCall(0);
1787                 var bCall = b.getCall(0);
1788                 var aId = aCall && aCall.callId || -1;
1789                 var bId = bCall && bCall.callId || -1;
1791                 return aId < bId ? -1 : 1;
1792             });
1793         };
1795         sinon.createStubInstance = function (constructor) {
1796             if (typeof constructor !== "function") {
1797                 throw new TypeError("The constructor should be a function.");
1798             }
1799             return sinon.stub(sinon.create(constructor.prototype));
1800         };
1802         sinon.restore = function (object) {
1803             if (object !== null && typeof object === "object") {
1804                 for (var prop in object) {
1805                     if (isRestorable(object[prop])) {
1806                         object[prop].restore();
1807                     }
1808                 }
1809             } else if (isRestorable(object)) {
1810                 object.restore();
1811             }
1812         };
1814         return sinon;
1815     }
1817     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1818     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1820     function loadDependencies(require, exports) {
1821         makeApi(exports);
1822     }
1824     if (isAMD) {
1825         define(loadDependencies);
1826         return;
1827     }
1829     if (isNode) {
1830         loadDependencies(require, module.exports, module);
1831         return;
1832     }
1834     if (sinonGlobal) {
1835         makeApi(sinonGlobal);
1836     }
1838     typeof sinon === "object" && sinon // eslint-disable-line no-undef
1842  * @depend util/core.js
1843  */
1844 (function (sinonGlobal) {
1845     
1846     function makeApi(sinon) {
1848         // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
1849         var hasDontEnumBug = (function () {
1850             var obj = {
1851                 constructor: function () {
1852                     return "0";
1853                 },
1854                 toString: function () {
1855                     return "1";
1856                 },
1857                 valueOf: function () {
1858                     return "2";
1859                 },
1860                 toLocaleString: function () {
1861                     return "3";
1862                 },
1863                 prototype: function () {
1864                     return "4";
1865                 },
1866                 isPrototypeOf: function () {
1867                     return "5";
1868                 },
1869                 propertyIsEnumerable: function () {
1870                     return "6";
1871                 },
1872                 hasOwnProperty: function () {
1873                     return "7";
1874                 },
1875                 length: function () {
1876                     return "8";
1877                 },
1878                 unique: function () {
1879                     return "9";
1880                 }
1881             };
1883             var result = [];
1884             for (var prop in obj) {
1885                 if (obj.hasOwnProperty(prop)) {
1886                     result.push(obj[prop]());
1887                 }
1888             }
1889             return result.join("") !== "0123456789";
1890         })();
1892         /* Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will
1893          *         override properties in previous sources.
1894          *
1895          * target - The Object to extend
1896          * sources - Objects to copy properties from.
1897          *
1898          * Returns the extended target
1899          */
1900         function extend(target /*, sources */) {
1901             var sources = Array.prototype.slice.call(arguments, 1);
1902             var source, i, prop;
1904             for (i = 0; i < sources.length; i++) {
1905                 source = sources[i];
1907                 for (prop in source) {
1908                     if (source.hasOwnProperty(prop)) {
1909                         target[prop] = source[prop];
1910                     }
1911                 }
1913                 // Make sure we copy (own) toString method even when in JScript with DontEnum bug
1914                 // See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
1915                 if (hasDontEnumBug && source.hasOwnProperty("toString") && source.toString !== target.toString) {
1916                     target.toString = source.toString;
1917                 }
1918             }
1920             return target;
1921         }
1923         sinon.extend = extend;
1924         return sinon.extend;
1925     }
1927     function loadDependencies(require, exports, module) {
1928         var sinon = require("./util/core");
1929         module.exports = makeApi(sinon);
1930     }
1932     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1933     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1935     if (isAMD) {
1936         define(loadDependencies);
1937         return;
1938     }
1940     if (isNode) {
1941         loadDependencies(require, module.exports, module);
1942         return;
1943     }
1945     if (sinonGlobal) {
1946         makeApi(sinonGlobal);
1947     }
1949     typeof sinon === "object" && sinon // eslint-disable-line no-undef
1953  * @depend util/core.js
1954  */
1955 (function (sinonGlobal) {
1956     
1957     function makeApi(sinon) {
1959         function timesInWords(count) {
1960             switch (count) {
1961                 case 1:
1962                     return "once";
1963                 case 2:
1964                     return "twice";
1965                 case 3:
1966                     return "thrice";
1967                 default:
1968                     return (count || 0) + " times";
1969             }
1970         }
1972         sinon.timesInWords = timesInWords;
1973         return sinon.timesInWords;
1974     }
1976     function loadDependencies(require, exports, module) {
1977         var core = require("./util/core");
1978         module.exports = makeApi(core);
1979     }
1981     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1982     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1984     if (isAMD) {
1985         define(loadDependencies);
1986         return;
1987     }
1989     if (isNode) {
1990         loadDependencies(require, module.exports, module);
1991         return;
1992     }
1994     if (sinonGlobal) {
1995         makeApi(sinonGlobal);
1996     }
1998     typeof sinon === "object" && sinon // eslint-disable-line no-undef
2002  * @depend util/core.js
2003  */
2005  * Format functions
2007  * @author Christian Johansen (christian@cjohansen.no)
2008  * @license BSD
2010  * Copyright (c) 2010-2014 Christian Johansen
2011  */
2012 (function (sinonGlobal) {
2013     
2014     function makeApi(sinon) {
2015         function typeOf(value) {
2016             if (value === null) {
2017                 return "null";
2018             } else if (value === undefined) {
2019                 return "undefined";
2020             }
2021             var string = Object.prototype.toString.call(value);
2022             return string.substring(8, string.length - 1).toLowerCase();
2023         }
2025         sinon.typeOf = typeOf;
2026         return sinon.typeOf;
2027     }
2029     function loadDependencies(require, exports, module) {
2030         var core = require("./util/core");
2031         module.exports = makeApi(core);
2032     }
2034     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
2035     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2037     if (isAMD) {
2038         define(loadDependencies);
2039         return;
2040     }
2042     if (isNode) {
2043         loadDependencies(require, module.exports, module);
2044         return;
2045     }
2047     if (sinonGlobal) {
2048         makeApi(sinonGlobal);
2049     }
2051     typeof sinon === "object" && sinon // eslint-disable-line no-undef
2055  * @depend util/core.js
2056  * @depend typeOf.js
2057  */
2058 /*jslint eqeqeq: false, onevar: false, plusplus: false*/
2059 /*global module, require, sinon*/
2061  * Match functions
2063  * @author Maximilian Antoni (mail@maxantoni.de)
2064  * @license BSD
2066  * Copyright (c) 2012 Maximilian Antoni
2067  */
2068 (function (sinonGlobal) {
2069     
2070     function makeApi(sinon) {
2071         function assertType(value, type, name) {
2072             var actual = sinon.typeOf(value);
2073             if (actual !== type) {
2074                 throw new TypeError("Expected type of " + name + " to be " +
2075                     type + ", but was " + actual);
2076             }
2077         }
2079         var matcher = {
2080             toString: function () {
2081                 return this.message;
2082             }
2083         };
2085         function isMatcher(object) {
2086             return matcher.isPrototypeOf(object);
2087         }
2089         function matchObject(expectation, actual) {
2090             if (actual === null || actual === undefined) {
2091                 return false;
2092             }
2093             for (var key in expectation) {
2094                 if (expectation.hasOwnProperty(key)) {
2095                     var exp = expectation[key];
2096                     var act = actual[key];
2097                     if (isMatcher(exp)) {
2098                         if (!exp.test(act)) {
2099                             return false;
2100                         }
2101                     } else if (sinon.typeOf(exp) === "object") {
2102                         if (!matchObject(exp, act)) {
2103                             return false;
2104                         }
2105                     } else if (!sinon.deepEqual(exp, act)) {
2106                         return false;
2107                     }
2108                 }
2109             }
2110             return true;
2111         }
2113         function match(expectation, message) {
2114             var m = sinon.create(matcher);
2115             var type = sinon.typeOf(expectation);
2116             switch (type) {
2117             case "object":
2118                 if (typeof expectation.test === "function") {
2119                     m.test = function (actual) {
2120                         return expectation.test(actual) === true;
2121                     };
2122                     m.message = "match(" + sinon.functionName(expectation.test) + ")";
2123                     return m;
2124                 }
2125                 var str = [];
2126                 for (var key in expectation) {
2127                     if (expectation.hasOwnProperty(key)) {
2128                         str.push(key + ": " + expectation[key]);
2129                     }
2130                 }
2131                 m.test = function (actual) {
2132                     return matchObject(expectation, actual);
2133                 };
2134                 m.message = "match(" + str.join(", ") + ")";
2135                 break;
2136             case "number":
2137                 m.test = function (actual) {
2138                     // we need type coercion here
2139                     return expectation == actual; // eslint-disable-line eqeqeq
2140                 };
2141                 break;
2142             case "string":
2143                 m.test = function (actual) {
2144                     if (typeof actual !== "string") {
2145                         return false;
2146                     }
2147                     return actual.indexOf(expectation) !== -1;
2148                 };
2149                 m.message = "match(\"" + expectation + "\")";
2150                 break;
2151             case "regexp":
2152                 m.test = function (actual) {
2153                     if (typeof actual !== "string") {
2154                         return false;
2155                     }
2156                     return expectation.test(actual);
2157                 };
2158                 break;
2159             case "function":
2160                 m.test = expectation;
2161                 if (message) {
2162                     m.message = message;
2163                 } else {
2164                     m.message = "match(" + sinon.functionName(expectation) + ")";
2165                 }
2166                 break;
2167             default:
2168                 m.test = function (actual) {
2169                     return sinon.deepEqual(expectation, actual);
2170                 };
2171             }
2172             if (!m.message) {
2173                 m.message = "match(" + expectation + ")";
2174             }
2175             return m;
2176         }
2178         matcher.or = function (m2) {
2179             if (!arguments.length) {
2180                 throw new TypeError("Matcher expected");
2181             } else if (!isMatcher(m2)) {
2182                 m2 = match(m2);
2183             }
2184             var m1 = this;
2185             var or = sinon.create(matcher);
2186             or.test = function (actual) {
2187                 return m1.test(actual) || m2.test(actual);
2188             };
2189             or.message = m1.message + ".or(" + m2.message + ")";
2190             return or;
2191         };
2193         matcher.and = function (m2) {
2194             if (!arguments.length) {
2195                 throw new TypeError("Matcher expected");
2196             } else if (!isMatcher(m2)) {
2197                 m2 = match(m2);
2198             }
2199             var m1 = this;
2200             var and = sinon.create(matcher);
2201             and.test = function (actual) {
2202                 return m1.test(actual) && m2.test(actual);
2203             };
2204             and.message = m1.message + ".and(" + m2.message + ")";
2205             return and;
2206         };
2208         match.isMatcher = isMatcher;
2210         match.any = match(function () {
2211             return true;
2212         }, "any");
2214         match.defined = match(function (actual) {
2215             return actual !== null && actual !== undefined;
2216         }, "defined");
2218         match.truthy = match(function (actual) {
2219             return !!actual;
2220         }, "truthy");
2222         match.falsy = match(function (actual) {
2223             return !actual;
2224         }, "falsy");
2226         match.same = function (expectation) {
2227             return match(function (actual) {
2228                 return expectation === actual;
2229             }, "same(" + expectation + ")");
2230         };
2232         match.typeOf = function (type) {
2233             assertType(type, "string", "type");
2234             return match(function (actual) {
2235                 return sinon.typeOf(actual) === type;
2236             }, "typeOf(\"" + type + "\")");
2237         };
2239         match.instanceOf = function (type) {
2240             assertType(type, "function", "type");
2241             return match(function (actual) {
2242                 return actual instanceof type;
2243             }, "instanceOf(" + sinon.functionName(type) + ")");
2244         };
2246         function createPropertyMatcher(propertyTest, messagePrefix) {
2247             return function (property, value) {
2248                 assertType(property, "string", "property");
2249                 var onlyProperty = arguments.length === 1;
2250                 var message = messagePrefix + "(\"" + property + "\"";
2251                 if (!onlyProperty) {
2252                     message += ", " + value;
2253                 }
2254                 message += ")";
2255                 return match(function (actual) {
2256                     if (actual === undefined || actual === null ||
2257                             !propertyTest(actual, property)) {
2258                         return false;
2259                     }
2260                     return onlyProperty || sinon.deepEqual(value, actual[property]);
2261                 }, message);
2262             };
2263         }
2265         match.has = createPropertyMatcher(function (actual, property) {
2266             if (typeof actual === "object") {
2267                 return property in actual;
2268             }
2269             return actual[property] !== undefined;
2270         }, "has");
2272         match.hasOwn = createPropertyMatcher(function (actual, property) {
2273             return actual.hasOwnProperty(property);
2274         }, "hasOwn");
2276         match.bool = match.typeOf("boolean");
2277         match.number = match.typeOf("number");
2278         match.string = match.typeOf("string");
2279         match.object = match.typeOf("object");
2280         match.func = match.typeOf("function");
2281         match.array = match.typeOf("array");
2282         match.regexp = match.typeOf("regexp");
2283         match.date = match.typeOf("date");
2285         sinon.match = match;
2286         return match;
2287     }
2289     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
2290     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2292     function loadDependencies(require, exports, module) {
2293         var sinon = require("./util/core");
2294         require("./typeOf");
2295         module.exports = makeApi(sinon);
2296     }
2298     if (isAMD) {
2299         define(loadDependencies);
2300         return;
2301     }
2303     if (isNode) {
2304         loadDependencies(require, module.exports, module);
2305         return;
2306     }
2308     if (sinonGlobal) {
2309         makeApi(sinonGlobal);
2310     }
2312     typeof sinon === "object" && sinon // eslint-disable-line no-undef
2316  * @depend util/core.js
2317  */
2319  * Format functions
2321  * @author Christian Johansen (christian@cjohansen.no)
2322  * @license BSD
2324  * Copyright (c) 2010-2014 Christian Johansen
2325  */
2326 (function (sinonGlobal, formatio) {
2327     
2328     function makeApi(sinon) {
2329         function valueFormatter(value) {
2330             return "" + value;
2331         }
2333         function getFormatioFormatter() {
2334             var formatter = formatio.configure({
2335                     quoteStrings: false,
2336                     limitChildrenCount: 250
2337                 });
2339             function format() {
2340                 return formatter.ascii.apply(formatter, arguments);
2341             }
2343             return format;
2344         }
2346         function getNodeFormatter() {
2347             try {
2348                 var util = require("util");
2349             } catch (e) {
2350                 /* Node, but no util module - would be very old, but better safe than sorry */
2351             }
2353             function format(v) {
2354                 var isObjectWithNativeToString = typeof v === "object" && v.toString === Object.prototype.toString;
2355                 return isObjectWithNativeToString ? util.inspect(v) : v;
2356             }
2358             return util ? format : valueFormatter;
2359         }
2361         var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
2362         var formatter;
2364         if (isNode) {
2365             try {
2366                 formatio = require("formatio");
2367             }
2368             catch (e) {} // eslint-disable-line no-empty
2369         }
2371         if (formatio) {
2372             formatter = getFormatioFormatter();
2373         } else if (isNode) {
2374             formatter = getNodeFormatter();
2375         } else {
2376             formatter = valueFormatter;
2377         }
2379         sinon.format = formatter;
2380         return sinon.format;
2381     }
2383     function loadDependencies(require, exports, module) {
2384         var sinon = require("./util/core");
2385         module.exports = makeApi(sinon);
2386     }
2388     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
2389     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2391     if (isAMD) {
2392         define(loadDependencies);
2393         return;
2394     }
2396     if (isNode) {
2397         loadDependencies(require, module.exports, module);
2398         return;
2399     }
2401     if (sinonGlobal) {
2402         makeApi(sinonGlobal);
2403     }
2405     typeof sinon === "object" && sinon, // eslint-disable-line no-undef
2406     typeof formatio === "object" && formatio // eslint-disable-line no-undef
2410   * @depend util/core.js
2411   * @depend match.js
2412   * @depend format.js
2413   */
2415   * Spy calls
2416   *
2417   * @author Christian Johansen (christian@cjohansen.no)
2418   * @author Maximilian Antoni (mail@maxantoni.de)
2419   * @license BSD
2420   *
2421   * Copyright (c) 2010-2013 Christian Johansen
2422   * Copyright (c) 2013 Maximilian Antoni
2423   */
2424 (function (sinonGlobal) {
2425     
2426     var slice = Array.prototype.slice;
2428     function makeApi(sinon) {
2429         function throwYieldError(proxy, text, args) {
2430             var msg = sinon.functionName(proxy) + text;
2431             if (args.length) {
2432                 msg += " Received [" + slice.call(args).join(", ") + "]";
2433             }
2434             throw new Error(msg);
2435         }
2437         var callProto = {
2438             calledOn: function calledOn(thisValue) {
2439                 if (sinon.match && sinon.match.isMatcher(thisValue)) {
2440                     return thisValue.test(this.thisValue);
2441                 }
2442                 return this.thisValue === thisValue;
2443             },
2445             calledWith: function calledWith() {
2446                 var l = arguments.length;
2447                 if (l > this.args.length) {
2448                     return false;
2449                 }
2450                 for (var i = 0; i < l; i += 1) {
2451                     if (!sinon.deepEqual(arguments[i], this.args[i])) {
2452                         return false;
2453                     }
2454                 }
2456                 return true;
2457             },
2459             calledWithMatch: function calledWithMatch() {
2460                 var l = arguments.length;
2461                 if (l > this.args.length) {
2462                     return false;
2463                 }
2464                 for (var i = 0; i < l; i += 1) {
2465                     var actual = this.args[i];
2466                     var expectation = arguments[i];
2467                     if (!sinon.match || !sinon.match(expectation).test(actual)) {
2468                         return false;
2469                     }
2470                 }
2471                 return true;
2472             },
2474             calledWithExactly: function calledWithExactly() {
2475                 return arguments.length === this.args.length &&
2476                     this.calledWith.apply(this, arguments);
2477             },
2479             notCalledWith: function notCalledWith() {
2480                 return !this.calledWith.apply(this, arguments);
2481             },
2483             notCalledWithMatch: function notCalledWithMatch() {
2484                 return !this.calledWithMatch.apply(this, arguments);
2485             },
2487             returned: function returned(value) {
2488                 return sinon.deepEqual(value, this.returnValue);
2489             },
2491             threw: function threw(error) {
2492                 if (typeof error === "undefined" || !this.exception) {
2493                     return !!this.exception;
2494                 }
2496                 return this.exception === error || this.exception.name === error;
2497             },
2499             calledWithNew: function calledWithNew() {
2500                 return this.proxy.prototype && this.thisValue instanceof this.proxy;
2501             },
2503             calledBefore: function (other) {
2504                 return this.callId < other.callId;
2505             },
2507             calledAfter: function (other) {
2508                 return this.callId > other.callId;
2509             },
2511             callArg: function (pos) {
2512                 this.args[pos]();
2513             },
2515             callArgOn: function (pos, thisValue) {
2516                 this.args[pos].apply(thisValue);
2517             },
2519             callArgWith: function (pos) {
2520                 this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
2521             },
2523             callArgOnWith: function (pos, thisValue) {
2524                 var args = slice.call(arguments, 2);
2525                 this.args[pos].apply(thisValue, args);
2526             },
2528             "yield": function () {
2529                 this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
2530             },
2532             yieldOn: function (thisValue) {
2533                 var args = this.args;
2534                 for (var i = 0, l = args.length; i < l; ++i) {
2535                     if (typeof args[i] === "function") {
2536                         args[i].apply(thisValue, slice.call(arguments, 1));
2537                         return;
2538                     }
2539                 }
2540                 throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
2541             },
2543             yieldTo: function (prop) {
2544                 this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
2545             },
2547             yieldToOn: function (prop, thisValue) {
2548                 var args = this.args;
2549                 for (var i = 0, l = args.length; i < l; ++i) {
2550                     if (args[i] && typeof args[i][prop] === "function") {
2551                         args[i][prop].apply(thisValue, slice.call(arguments, 2));
2552                         return;
2553                     }
2554                 }
2555                 throwYieldError(this.proxy, " cannot yield to '" + prop +
2556                     "' since no callback was passed.", args);
2557             },
2559             getStackFrames: function () {
2560                 // Omit the error message and the two top stack frames in sinon itself:
2561                 return this.stack && this.stack.split("\n").slice(3);
2562             },
2564             toString: function () {
2565                 var callStr = this.proxy ? this.proxy.toString() + "(" : "";
2566                 var args = [];
2568                 if (!this.args) {
2569                     return ":(";
2570                 }
2572                 for (var i = 0, l = this.args.length; i < l; ++i) {
2573                     args.push(sinon.format(this.args[i]));
2574                 }
2576                 callStr = callStr + args.join(", ") + ")";
2578                 if (typeof this.returnValue !== "undefined") {
2579                     callStr += " => " + sinon.format(this.returnValue);
2580                 }
2582                 if (this.exception) {
2583                     callStr += " !" + this.exception.name;
2585                     if (this.exception.message) {
2586                         callStr += "(" + this.exception.message + ")";
2587                     }
2588                 }
2589                 if (this.stack) {
2590                     callStr += this.getStackFrames()[0].replace(/^\s*(?:at\s+|@)?/, " at ");
2592                 }
2594                 return callStr;
2595             }
2596         };
2598         callProto.invokeCallback = callProto.yield;
2600         function createSpyCall(spy, thisValue, args, returnValue, exception, id, stack) {
2601             if (typeof id !== "number") {
2602                 throw new TypeError("Call id is not a number");
2603             }
2604             var proxyCall = sinon.create(callProto);
2605             proxyCall.proxy = spy;
2606             proxyCall.thisValue = thisValue;
2607             proxyCall.args = args;
2608             proxyCall.returnValue = returnValue;
2609             proxyCall.exception = exception;
2610             proxyCall.callId = id;
2611             proxyCall.stack = stack;
2613             return proxyCall;
2614         }
2615         createSpyCall.toString = callProto.toString; // used by mocks
2617         sinon.spyCall = createSpyCall;
2618         return createSpyCall;
2619     }
2621     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
2622     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2624     function loadDependencies(require, exports, module) {
2625         var sinon = require("./util/core");
2626         require("./match");
2627         require("./format");
2628         module.exports = makeApi(sinon);
2629     }
2631     if (isAMD) {
2632         define(loadDependencies);
2633         return;
2634     }
2636     if (isNode) {
2637         loadDependencies(require, module.exports, module);
2638         return;
2639     }
2641     if (sinonGlobal) {
2642         makeApi(sinonGlobal);
2643     }
2645     typeof sinon === "object" && sinon // eslint-disable-line no-undef
2649   * @depend times_in_words.js
2650   * @depend util/core.js
2651   * @depend extend.js
2652   * @depend call.js
2653   * @depend format.js
2654   */
2656   * Spy functions
2657   *
2658   * @author Christian Johansen (christian@cjohansen.no)
2659   * @license BSD
2660   *
2661   * Copyright (c) 2010-2013 Christian Johansen
2662   */
2663 (function (sinonGlobal) {
2664     
2665     function makeApi(sinon) {
2666         var push = Array.prototype.push;
2667         var slice = Array.prototype.slice;
2668         var callId = 0;
2670         function spy(object, property, types) {
2671             if (!property && typeof object === "function") {
2672                 return spy.create(object);
2673             }
2675             if (!object && !property) {
2676                 return spy.create(function () { });
2677             }
2679             if (types) {
2680                 // A new descriptor is needed here because we can only wrap functions
2681                 // By passing the original descriptor we would end up trying to spy non-function properties
2682                 var descriptor = {};
2683                 var methodDesc = sinon.getPropertyDescriptor(object, property);
2685                 for (var i = 0; i < types.length; i++) {
2686                     descriptor[types[i]] = spy.create(methodDesc[types[i]]);
2687                 }
2688                 return sinon.wrapMethod(object, property, descriptor);
2689             }
2691             return sinon.wrapMethod(object, property, spy.create(object[property]));
2692         }
2694         function matchingFake(fakes, args, strict) {
2695             if (!fakes) {
2696                 return undefined;
2697             }
2699             for (var i = 0, l = fakes.length; i < l; i++) {
2700                 if (fakes[i].matches(args, strict)) {
2701                     return fakes[i];
2702                 }
2703             }
2704         }
2706         function incrementCallCount() {
2707             this.called = true;
2708             this.callCount += 1;
2709             this.notCalled = false;
2710             this.calledOnce = this.callCount === 1;
2711             this.calledTwice = this.callCount === 2;
2712             this.calledThrice = this.callCount === 3;
2713         }
2715         function createCallProperties() {
2716             this.firstCall = this.getCall(0);
2717             this.secondCall = this.getCall(1);
2718             this.thirdCall = this.getCall(2);
2719             this.lastCall = this.getCall(this.callCount - 1);
2720         }
2722         var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
2723         function createProxy(func, proxyLength) {
2724             // Retain the function length:
2725             var p;
2726             if (proxyLength) {
2727                 eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) + // eslint-disable-line no-eval
2728                     ") { return p.invoke(func, this, slice.call(arguments)); });");
2729             } else {
2730                 p = function proxy() {
2731                     return p.invoke(func, this, slice.call(arguments));
2732                 };
2733             }
2734             p.isSinonProxy = true;
2735             return p;
2736         }
2738         var uuid = 0;
2740         // Public API
2741         var spyApi = {
2742             reset: function () {
2743                 if (this.invoking) {
2744                     var err = new Error("Cannot reset Sinon function while invoking it. " +
2745                                         "Move the call to .reset outside of the callback.");
2746                     err.name = "InvalidResetException";
2747                     throw err;
2748                 }
2750                 this.called = false;
2751                 this.notCalled = true;
2752                 this.calledOnce = false;
2753                 this.calledTwice = false;
2754                 this.calledThrice = false;
2755                 this.callCount = 0;
2756                 this.firstCall = null;
2757                 this.secondCall = null;
2758                 this.thirdCall = null;
2759                 this.lastCall = null;
2760                 this.args = [];
2761                 this.returnValues = [];
2762                 this.thisValues = [];
2763                 this.exceptions = [];
2764                 this.callIds = [];
2765                 this.stacks = [];
2766                 if (this.fakes) {
2767                     for (var i = 0; i < this.fakes.length; i++) {
2768                         this.fakes[i].reset();
2769                     }
2770                 }
2772                 return this;
2773             },
2775             create: function create(func, spyLength) {
2776                 var name;
2778                 if (typeof func !== "function") {
2779                     func = function () { };
2780                 } else {
2781                     name = sinon.functionName(func);
2782                 }
2784                 if (!spyLength) {
2785                     spyLength = func.length;
2786                 }
2788                 var proxy = createProxy(func, spyLength);
2790                 sinon.extend(proxy, spy);
2791                 delete proxy.create;
2792                 sinon.extend(proxy, func);
2794                 proxy.reset();
2795                 proxy.prototype = func.prototype;
2796                 proxy.displayName = name || "spy";
2797                 proxy.toString = sinon.functionToString;
2798                 proxy.instantiateFake = sinon.spy.create;
2799                 proxy.id = "spy#" + uuid++;
2801                 return proxy;
2802             },
2804             invoke: function invoke(func, thisValue, args) {
2805                 var matching = matchingFake(this.fakes, args);
2806                 var exception, returnValue;
2808                 incrementCallCount.call(this);
2809                 push.call(this.thisValues, thisValue);
2810                 push.call(this.args, args);
2811                 push.call(this.callIds, callId++);
2813                 // Make call properties available from within the spied function:
2814                 createCallProperties.call(this);
2816                 try {
2817                     this.invoking = true;
2819                     if (matching) {
2820                         returnValue = matching.invoke(func, thisValue, args);
2821                     } else {
2822                         returnValue = (this.func || func).apply(thisValue, args);
2823                     }
2825                     var thisCall = this.getCall(this.callCount - 1);
2826                     if (thisCall.calledWithNew() && typeof returnValue !== "object") {
2827                         returnValue = thisValue;
2828                     }
2829                 } catch (e) {
2830                     exception = e;
2831                 } finally {
2832                     delete this.invoking;
2833                 }
2835                 push.call(this.exceptions, exception);
2836                 push.call(this.returnValues, returnValue);
2837                 push.call(this.stacks, new Error().stack);
2839                 // Make return value and exception available in the calls:
2840                 createCallProperties.call(this);
2842                 if (exception !== undefined) {
2843                     throw exception;
2844                 }
2846                 return returnValue;
2847             },
2849             named: function named(name) {
2850                 this.displayName = name;
2851                 return this;
2852             },
2854             getCall: function getCall(i) {
2855                 if (i < 0 || i >= this.callCount) {
2856                     return null;
2857                 }
2859                 return sinon.spyCall(this, this.thisValues[i], this.args[i],
2860                                         this.returnValues[i], this.exceptions[i],
2861                                         this.callIds[i], this.stacks[i]);
2862             },
2864             getCalls: function () {
2865                 var calls = [];
2866                 var i;
2868                 for (i = 0; i < this.callCount; i++) {
2869                     calls.push(this.getCall(i));
2870                 }
2872                 return calls;
2873             },
2875             calledBefore: function calledBefore(spyFn) {
2876                 if (!this.called) {
2877                     return false;
2878                 }
2880                 if (!spyFn.called) {
2881                     return true;
2882                 }
2884                 return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
2885             },
2887             calledAfter: function calledAfter(spyFn) {
2888                 if (!this.called || !spyFn.called) {
2889                     return false;
2890                 }
2892                 return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
2893             },
2895             withArgs: function () {
2896                 var args = slice.call(arguments);
2898                 if (this.fakes) {
2899                     var match = matchingFake(this.fakes, args, true);
2901                     if (match) {
2902                         return match;
2903                     }
2904                 } else {
2905                     this.fakes = [];
2906                 }
2908                 var original = this;
2909                 var fake = this.instantiateFake();
2910                 fake.matchingAguments = args;
2911                 fake.parent = this;
2912                 push.call(this.fakes, fake);
2914                 fake.withArgs = function () {
2915                     return original.withArgs.apply(original, arguments);
2916                 };
2918                 for (var i = 0; i < this.args.length; i++) {
2919                     if (fake.matches(this.args[i])) {
2920                         incrementCallCount.call(fake);
2921                         push.call(fake.thisValues, this.thisValues[i]);
2922                         push.call(fake.args, this.args[i]);
2923                         push.call(fake.returnValues, this.returnValues[i]);
2924                         push.call(fake.exceptions, this.exceptions[i]);
2925                         push.call(fake.callIds, this.callIds[i]);
2926                     }
2927                 }
2928                 createCallProperties.call(fake);
2930                 return fake;
2931             },
2933             matches: function (args, strict) {
2934                 var margs = this.matchingAguments;
2936                 if (margs.length <= args.length &&
2937                     sinon.deepEqual(margs, args.slice(0, margs.length))) {
2938                     return !strict || margs.length === args.length;
2939                 }
2940             },
2942             printf: function (format) {
2943                 var spyInstance = this;
2944                 var args = slice.call(arguments, 1);
2945                 var formatter;
2947                 return (format || "").replace(/%(.)/g, function (match, specifyer) {
2948                     formatter = spyApi.formatters[specifyer];
2950                     if (typeof formatter === "function") {
2951                         return formatter.call(null, spyInstance, args);
2952                     } else if (!isNaN(parseInt(specifyer, 10))) {
2953                         return sinon.format(args[specifyer - 1]);
2954                     }
2956                     return "%" + specifyer;
2957                 });
2958             }
2959         };
2961         function delegateToCalls(method, matchAny, actual, notCalled) {
2962             spyApi[method] = function () {
2963                 if (!this.called) {
2964                     if (notCalled) {
2965                         return notCalled.apply(this, arguments);
2966                     }
2967                     return false;
2968                 }
2970                 var currentCall;
2971                 var matches = 0;
2973                 for (var i = 0, l = this.callCount; i < l; i += 1) {
2974                     currentCall = this.getCall(i);
2976                     if (currentCall[actual || method].apply(currentCall, arguments)) {
2977                         matches += 1;
2979                         if (matchAny) {
2980                             return true;
2981                         }
2982                     }
2983                 }
2985                 return matches === this.callCount;
2986             };
2987         }
2989         delegateToCalls("calledOn", true);
2990         delegateToCalls("alwaysCalledOn", false, "calledOn");
2991         delegateToCalls("calledWith", true);
2992         delegateToCalls("calledWithMatch", true);
2993         delegateToCalls("alwaysCalledWith", false, "calledWith");
2994         delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
2995         delegateToCalls("calledWithExactly", true);
2996         delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
2997         delegateToCalls("neverCalledWith", false, "notCalledWith", function () {
2998             return true;
2999         });
3000         delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch", function () {
3001             return true;
3002         });
3003         delegateToCalls("threw", true);
3004         delegateToCalls("alwaysThrew", false, "threw");
3005         delegateToCalls("returned", true);
3006         delegateToCalls("alwaysReturned", false, "returned");
3007         delegateToCalls("calledWithNew", true);
3008         delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
3009         delegateToCalls("callArg", false, "callArgWith", function () {
3010             throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
3011         });
3012         spyApi.callArgWith = spyApi.callArg;
3013         delegateToCalls("callArgOn", false, "callArgOnWith", function () {
3014             throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
3015         });
3016         spyApi.callArgOnWith = spyApi.callArgOn;
3017         delegateToCalls("yield", false, "yield", function () {
3018             throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
3019         });
3020         // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
3021         spyApi.invokeCallback = spyApi.yield;
3022         delegateToCalls("yieldOn", false, "yieldOn", function () {
3023             throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
3024         });
3025         delegateToCalls("yieldTo", false, "yieldTo", function (property) {
3026             throw new Error(this.toString() + " cannot yield to '" + property +
3027                 "' since it was not yet invoked.");
3028         });
3029         delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
3030             throw new Error(this.toString() + " cannot yield to '" + property +
3031                 "' since it was not yet invoked.");
3032         });
3034         spyApi.formatters = {
3035             c: function (spyInstance) {
3036                 return sinon.timesInWords(spyInstance.callCount);
3037             },
3039             n: function (spyInstance) {
3040                 return spyInstance.toString();
3041             },
3043             C: function (spyInstance) {
3044                 var calls = [];
3046                 for (var i = 0, l = spyInstance.callCount; i < l; ++i) {
3047                     var stringifiedCall = "    " + spyInstance.getCall(i).toString();
3048                     if (/\n/.test(calls[i - 1])) {
3049                         stringifiedCall = "\n" + stringifiedCall;
3050                     }
3051                     push.call(calls, stringifiedCall);
3052                 }
3054                 return calls.length > 0 ? "\n" + calls.join("\n") : "";
3055             },
3057             t: function (spyInstance) {
3058                 var objects = [];
3060                 for (var i = 0, l = spyInstance.callCount; i < l; ++i) {
3061                     push.call(objects, sinon.format(spyInstance.thisValues[i]));
3062                 }
3064                 return objects.join(", ");
3065             },
3067             "*": function (spyInstance, args) {
3068                 var formatted = [];
3070                 for (var i = 0, l = args.length; i < l; ++i) {
3071                     push.call(formatted, sinon.format(args[i]));
3072                 }
3074                 return formatted.join(", ");
3075             }
3076         };
3078         sinon.extend(spy, spyApi);
3080         spy.spyCall = sinon.spyCall;
3081         sinon.spy = spy;
3083         return spy;
3084     }
3086     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
3087     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3089     function loadDependencies(require, exports, module) {
3090         var core = require("./util/core");
3091         require("./call");
3092         require("./extend");
3093         require("./times_in_words");
3094         require("./format");
3095         module.exports = makeApi(core);
3096     }
3098     if (isAMD) {
3099         define(loadDependencies);
3100         return;
3101     }
3103     if (isNode) {
3104         loadDependencies(require, module.exports, module);
3105         return;
3106     }
3108     if (sinonGlobal) {
3109         makeApi(sinonGlobal);
3110     }
3112     typeof sinon === "object" && sinon // eslint-disable-line no-undef
3116  * @depend util/core.js
3117  * @depend extend.js
3118  */
3120  * Stub behavior
3122  * @author Christian Johansen (christian@cjohansen.no)
3123  * @author Tim Fischbach (mail@timfischbach.de)
3124  * @license BSD
3126  * Copyright (c) 2010-2013 Christian Johansen
3127  */
3128 (function (sinonGlobal) {
3129     
3130     var slice = Array.prototype.slice;
3131     var join = Array.prototype.join;
3132     var useLeftMostCallback = -1;
3133     var useRightMostCallback = -2;
3135     var nextTick = (function () {
3136         if (typeof process === "object" && typeof process.nextTick === "function") {
3137             return process.nextTick;
3138         }
3140         if (typeof setImmediate === "function") {
3141             return setImmediate;
3142         }
3144         return function (callback) {
3145             setTimeout(callback, 0);
3146         };
3147     })();
3149     function throwsException(error, message) {
3150         if (typeof error === "string") {
3151             this.exception = new Error(message || "");
3152             this.exception.name = error;
3153         } else if (!error) {
3154             this.exception = new Error("Error");
3155         } else {
3156             this.exception = error;
3157         }
3159         return this;
3160     }
3162     function getCallback(behavior, args) {
3163         var callArgAt = behavior.callArgAt;
3165         if (callArgAt >= 0) {
3166             return args[callArgAt];
3167         }
3169         var argumentList;
3171         if (callArgAt === useLeftMostCallback) {
3172             argumentList = args;
3173         }
3175         if (callArgAt === useRightMostCallback) {
3176             argumentList = slice.call(args).reverse();
3177         }
3179         var callArgProp = behavior.callArgProp;
3181         for (var i = 0, l = argumentList.length; i < l; ++i) {
3182             if (!callArgProp && typeof argumentList[i] === "function") {
3183                 return argumentList[i];
3184             }
3186             if (callArgProp && argumentList[i] &&
3187                 typeof argumentList[i][callArgProp] === "function") {
3188                 return argumentList[i][callArgProp];
3189             }
3190         }
3192         return null;
3193     }
3195     function makeApi(sinon) {
3196         function getCallbackError(behavior, func, args) {
3197             if (behavior.callArgAt < 0) {
3198                 var msg;
3200                 if (behavior.callArgProp) {
3201                     msg = sinon.functionName(behavior.stub) +
3202                         " expected to yield to '" + behavior.callArgProp +
3203                         "', but no object with such a property was passed.";
3204                 } else {
3205                     msg = sinon.functionName(behavior.stub) +
3206                         " expected to yield, but no callback was passed.";
3207                 }
3209                 if (args.length > 0) {
3210                     msg += " Received [" + join.call(args, ", ") + "]";
3211                 }
3213                 return msg;
3214             }
3216             return "argument at index " + behavior.callArgAt + " is not a function: " + func;
3217         }
3219         function callCallback(behavior, args) {
3220             if (typeof behavior.callArgAt === "number") {
3221                 var func = getCallback(behavior, args);
3223                 if (typeof func !== "function") {
3224                     throw new TypeError(getCallbackError(behavior, func, args));
3225                 }
3227                 if (behavior.callbackAsync) {
3228                     nextTick(function () {
3229                         func.apply(behavior.callbackContext, behavior.callbackArguments);
3230                     });
3231                 } else {
3232                     func.apply(behavior.callbackContext, behavior.callbackArguments);
3233                 }
3234             }
3235         }
3237         var proto = {
3238             create: function create(stub) {
3239                 var behavior = sinon.extend({}, sinon.behavior);
3240                 delete behavior.create;
3241                 behavior.stub = stub;
3243                 return behavior;
3244             },
3246             isPresent: function isPresent() {
3247                 return (typeof this.callArgAt === "number" ||
3248                         this.exception ||
3249                         typeof this.returnArgAt === "number" ||
3250                         this.returnThis ||
3251                         this.returnValueDefined);
3252             },
3254             invoke: function invoke(context, args) {
3255                 callCallback(this, args);
3257                 if (this.exception) {
3258                     throw this.exception;
3259                 } else if (typeof this.returnArgAt === "number") {
3260                     return args[this.returnArgAt];
3261                 } else if (this.returnThis) {
3262                     return context;
3263                 }
3265                 return this.returnValue;
3266             },
3268             onCall: function onCall(index) {
3269                 return this.stub.onCall(index);
3270             },
3272             onFirstCall: function onFirstCall() {
3273                 return this.stub.onFirstCall();
3274             },
3276             onSecondCall: function onSecondCall() {
3277                 return this.stub.onSecondCall();
3278             },
3280             onThirdCall: function onThirdCall() {
3281                 return this.stub.onThirdCall();
3282             },
3284             withArgs: function withArgs(/* arguments */) {
3285                 throw new Error(
3286                     "Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" " +
3287                     "is not supported. Use \"stub.withArgs(...).onCall(...)\" " +
3288                     "to define sequential behavior for calls with certain arguments."
3289                 );
3290             },
3292             callsArg: function callsArg(pos) {
3293                 if (typeof pos !== "number") {
3294                     throw new TypeError("argument index is not number");
3295                 }
3297                 this.callArgAt = pos;
3298                 this.callbackArguments = [];
3299                 this.callbackContext = undefined;
3300                 this.callArgProp = undefined;
3301                 this.callbackAsync = false;
3303                 return this;
3304             },
3306             callsArgOn: function callsArgOn(pos, context) {
3307                 if (typeof pos !== "number") {
3308                     throw new TypeError("argument index is not number");
3309                 }
3310                 if (typeof context !== "object") {
3311                     throw new TypeError("argument context is not an object");
3312                 }
3314                 this.callArgAt = pos;
3315                 this.callbackArguments = [];
3316                 this.callbackContext = context;
3317                 this.callArgProp = undefined;
3318                 this.callbackAsync = false;
3320                 return this;
3321             },
3323             callsArgWith: function callsArgWith(pos) {
3324                 if (typeof pos !== "number") {
3325                     throw new TypeError("argument index is not number");
3326                 }
3328                 this.callArgAt = pos;
3329                 this.callbackArguments = slice.call(arguments, 1);
3330                 this.callbackContext = undefined;
3331                 this.callArgProp = undefined;
3332                 this.callbackAsync = false;
3334                 return this;
3335             },
3337             callsArgOnWith: function callsArgWith(pos, context) {
3338                 if (typeof pos !== "number") {
3339                     throw new TypeError("argument index is not number");
3340                 }
3341                 if (typeof context !== "object") {
3342                     throw new TypeError("argument context is not an object");
3343                 }
3345                 this.callArgAt = pos;
3346                 this.callbackArguments = slice.call(arguments, 2);
3347                 this.callbackContext = context;
3348                 this.callArgProp = undefined;
3349                 this.callbackAsync = false;
3351                 return this;
3352             },
3354             yields: function () {
3355                 this.callArgAt = useLeftMostCallback;
3356                 this.callbackArguments = slice.call(arguments, 0);
3357                 this.callbackContext = undefined;
3358                 this.callArgProp = undefined;
3359                 this.callbackAsync = false;
3361                 return this;
3362             },
3364             yieldsRight: function () {
3365                 this.callArgAt = useRightMostCallback;
3366                 this.callbackArguments = slice.call(arguments, 0);
3367                 this.callbackContext = undefined;
3368                 this.callArgProp = undefined;
3369                 this.callbackAsync = false;
3371                 return this;
3372             },
3374             yieldsOn: function (context) {
3375                 if (typeof context !== "object") {
3376                     throw new TypeError("argument context is not an object");
3377                 }
3379                 this.callArgAt = useLeftMostCallback;
3380                 this.callbackArguments = slice.call(arguments, 1);
3381                 this.callbackContext = context;
3382                 this.callArgProp = undefined;
3383                 this.callbackAsync = false;
3385                 return this;
3386             },
3388             yieldsTo: function (prop) {
3389                 this.callArgAt = useLeftMostCallback;
3390                 this.callbackArguments = slice.call(arguments, 1);
3391                 this.callbackContext = undefined;
3392                 this.callArgProp = prop;
3393                 this.callbackAsync = false;
3395                 return this;
3396             },
3398             yieldsToOn: function (prop, context) {
3399                 if (typeof context !== "object") {
3400                     throw new TypeError("argument context is not an object");
3401                 }
3403                 this.callArgAt = useLeftMostCallback;
3404                 this.callbackArguments = slice.call(arguments, 2);
3405                 this.callbackContext = context;
3406                 this.callArgProp = prop;
3407                 this.callbackAsync = false;
3409                 return this;
3410             },
3412             throws: throwsException,
3413             throwsException: throwsException,
3415             returns: function returns(value) {
3416                 this.returnValue = value;
3417                 this.returnValueDefined = true;
3418                 this.exception = undefined;
3420                 return this;
3421             },
3423             returnsArg: function returnsArg(pos) {
3424                 if (typeof pos !== "number") {
3425                     throw new TypeError("argument index is not number");
3426                 }
3428                 this.returnArgAt = pos;
3430                 return this;
3431             },
3433             returnsThis: function returnsThis() {
3434                 this.returnThis = true;
3436                 return this;
3437             }
3438         };
3440         function createAsyncVersion(syncFnName) {
3441             return function () {
3442                 var result = this[syncFnName].apply(this, arguments);
3443                 this.callbackAsync = true;
3444                 return result;
3445             };
3446         }
3448         // create asynchronous versions of callsArg* and yields* methods
3449         for (var method in proto) {
3450             // need to avoid creating anotherasync versions of the newly added async methods
3451             if (proto.hasOwnProperty(method) && method.match(/^(callsArg|yields)/) && !method.match(/Async/)) {
3452                 proto[method + "Async"] = createAsyncVersion(method);
3453             }
3454         }
3456         sinon.behavior = proto;
3457         return proto;
3458     }
3460     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
3461     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3463     function loadDependencies(require, exports, module) {
3464         var sinon = require("./util/core");
3465         require("./extend");
3466         module.exports = makeApi(sinon);
3467     }
3469     if (isAMD) {
3470         define(loadDependencies);
3471         return;
3472     }
3474     if (isNode) {
3475         loadDependencies(require, module.exports, module);
3476         return;
3477     }
3479     if (sinonGlobal) {
3480         makeApi(sinonGlobal);
3481     }
3483     typeof sinon === "object" && sinon // eslint-disable-line no-undef
3487  * @depend util/core.js
3488  */
3489 (function (sinonGlobal) {
3490     
3491     function makeApi(sinon) {
3492         function walkInternal(obj, iterator, context, originalObj, seen) {
3493             var proto, prop;
3495             if (typeof Object.getOwnPropertyNames !== "function") {
3496                 // We explicitly want to enumerate through all of the prototype's properties
3497                 // in this case, therefore we deliberately leave out an own property check.
3498                 /* eslint-disable guard-for-in */
3499                 for (prop in obj) {
3500                     iterator.call(context, obj[prop], prop, obj);
3501                 }
3502                 /* eslint-enable guard-for-in */
3504                 return;
3505             }
3507             Object.getOwnPropertyNames(obj).forEach(function (k) {
3508                 if (seen[k] !== true) {
3509                     seen[k] = true;
3510                     var target = typeof Object.getOwnPropertyDescriptor(obj, k).get === "function" ?
3511                         originalObj : obj;
3512                     iterator.call(context, target[k], k, target);
3513                 }
3514             });
3516             proto = Object.getPrototypeOf(obj);
3517             if (proto) {
3518                 walkInternal(proto, iterator, context, originalObj, seen);
3519             }
3520         }
3522         /* Public: walks the prototype chain of an object and iterates over every own property
3523          * name encountered. The iterator is called in the same fashion that Array.prototype.forEach
3524          * works, where it is passed the value, key, and own object as the 1st, 2nd, and 3rd positional
3525          * argument, respectively. In cases where Object.getOwnPropertyNames is not available, walk will
3526          * default to using a simple for..in loop.
3527          *
3528          * obj - The object to walk the prototype chain for.
3529          * iterator - The function to be called on each pass of the walk.
3530          * context - (Optional) When given, the iterator will be called with this object as the receiver.
3531          */
3532         function walk(obj, iterator, context) {
3533             return walkInternal(obj, iterator, context, obj, {});
3534         }
3536         sinon.walk = walk;
3537         return sinon.walk;
3538     }
3540     function loadDependencies(require, exports, module) {
3541         var sinon = require("./util/core");
3542         module.exports = makeApi(sinon);
3543     }
3545     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
3546     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3548     if (isAMD) {
3549         define(loadDependencies);
3550         return;
3551     }
3553     if (isNode) {
3554         loadDependencies(require, module.exports, module);
3555         return;
3556     }
3558     if (sinonGlobal) {
3559         makeApi(sinonGlobal);
3560     }
3562     typeof sinon === "object" && sinon // eslint-disable-line no-undef
3566  * @depend util/core.js
3567  * @depend extend.js
3568  * @depend spy.js
3569  * @depend behavior.js
3570  * @depend walk.js
3571  */
3573  * Stub functions
3575  * @author Christian Johansen (christian@cjohansen.no)
3576  * @license BSD
3578  * Copyright (c) 2010-2013 Christian Johansen
3579  */
3580 (function (sinonGlobal) {
3581     
3582     function makeApi(sinon) {
3583         function stub(object, property, func) {
3584             if (!!func && typeof func !== "function" && typeof func !== "object") {
3585                 throw new TypeError("Custom stub should be a function or a property descriptor");
3586             }
3588             var wrapper;
3590             if (func) {
3591                 if (typeof func === "function") {
3592                     wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
3593                 } else {
3594                     wrapper = func;
3595                     if (sinon.spy && sinon.spy.create) {
3596                         var types = sinon.objectKeys(wrapper);
3597                         for (var i = 0; i < types.length; i++) {
3598                             wrapper[types[i]] = sinon.spy.create(wrapper[types[i]]);
3599                         }
3600                     }
3601                 }
3602             } else {
3603                 var stubLength = 0;
3604                 if (typeof object === "object" && typeof object[property] === "function") {
3605                     stubLength = object[property].length;
3606                 }
3607                 wrapper = stub.create(stubLength);
3608             }
3610             if (!object && typeof property === "undefined") {
3611                 return sinon.stub.create();
3612             }
3614             if (typeof property === "undefined" && typeof object === "object") {
3615                 sinon.walk(object || {}, function (value, prop, propOwner) {
3616                     // we don't want to stub things like toString(), valueOf(), etc. so we only stub if the object
3617                     // is not Object.prototype
3618                     if (
3619                         propOwner !== Object.prototype &&
3620                         prop !== "constructor" &&
3621                         typeof sinon.getPropertyDescriptor(propOwner, prop).value === "function"
3622                     ) {
3623                         stub(object, prop);
3624                     }
3625                 });
3627                 return object;
3628             }
3630             return sinon.wrapMethod(object, property, wrapper);
3631         }
3634         /*eslint-disable no-use-before-define*/
3635         function getParentBehaviour(stubInstance) {
3636             return (stubInstance.parent && getCurrentBehavior(stubInstance.parent));
3637         }
3639         function getDefaultBehavior(stubInstance) {
3640             return stubInstance.defaultBehavior ||
3641                     getParentBehaviour(stubInstance) ||
3642                     sinon.behavior.create(stubInstance);
3643         }
3645         function getCurrentBehavior(stubInstance) {
3646             var behavior = stubInstance.behaviors[stubInstance.callCount - 1];
3647             return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stubInstance);
3648         }
3649         /*eslint-enable no-use-before-define*/
3651         var uuid = 0;
3653         var proto = {
3654             create: function create(stubLength) {
3655                 var functionStub = function () {
3656                     return getCurrentBehavior(functionStub).invoke(this, arguments);
3657                 };
3659                 functionStub.id = "stub#" + uuid++;
3660                 var orig = functionStub;
3661                 functionStub = sinon.spy.create(functionStub, stubLength);
3662                 functionStub.func = orig;
3664                 sinon.extend(functionStub, stub);
3665                 functionStub.instantiateFake = sinon.stub.create;
3666                 functionStub.displayName = "stub";
3667                 functionStub.toString = sinon.functionToString;
3669                 functionStub.defaultBehavior = null;
3670                 functionStub.behaviors = [];
3672                 return functionStub;
3673             },
3675             resetBehavior: function () {
3676                 var i;
3678                 this.defaultBehavior = null;
3679                 this.behaviors = [];
3681                 delete this.returnValue;
3682                 delete this.returnArgAt;
3683                 this.returnThis = false;
3685                 if (this.fakes) {
3686                     for (i = 0; i < this.fakes.length; i++) {
3687                         this.fakes[i].resetBehavior();
3688                     }
3689                 }
3690             },
3692             onCall: function onCall(index) {
3693                 if (!this.behaviors[index]) {
3694                     this.behaviors[index] = sinon.behavior.create(this);
3695                 }
3697                 return this.behaviors[index];
3698             },
3700             onFirstCall: function onFirstCall() {
3701                 return this.onCall(0);
3702             },
3704             onSecondCall: function onSecondCall() {
3705                 return this.onCall(1);
3706             },
3708             onThirdCall: function onThirdCall() {
3709                 return this.onCall(2);
3710             }
3711         };
3713         function createBehavior(behaviorMethod) {
3714             return function () {
3715                 this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
3716                 this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
3717                 return this;
3718             };
3719         }
3721         for (var method in sinon.behavior) {
3722             if (sinon.behavior.hasOwnProperty(method) &&
3723                 !proto.hasOwnProperty(method) &&
3724                 method !== "create" &&
3725                 method !== "withArgs" &&
3726                 method !== "invoke") {
3727                 proto[method] = createBehavior(method);
3728             }
3729         }
3731         sinon.extend(stub, proto);
3732         sinon.stub = stub;
3734         return stub;
3735     }
3737     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
3738     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3740     function loadDependencies(require, exports, module) {
3741         var core = require("./util/core");
3742         require("./behavior");
3743         require("./spy");
3744         require("./extend");
3745         module.exports = makeApi(core);
3746     }
3748     if (isAMD) {
3749         define(loadDependencies);
3750         return;
3751     }
3753     if (isNode) {
3754         loadDependencies(require, module.exports, module);
3755         return;
3756     }
3758     if (sinonGlobal) {
3759         makeApi(sinonGlobal);
3760     }
3762     typeof sinon === "object" && sinon // eslint-disable-line no-undef
3766  * @depend times_in_words.js
3767  * @depend util/core.js
3768  * @depend call.js
3769  * @depend extend.js
3770  * @depend match.js
3771  * @depend spy.js
3772  * @depend stub.js
3773  * @depend format.js
3774  */
3776  * Mock functions.
3778  * @author Christian Johansen (christian@cjohansen.no)
3779  * @license BSD
3781  * Copyright (c) 2010-2013 Christian Johansen
3782  */
3783 (function (sinonGlobal) {
3784     
3785     function makeApi(sinon) {
3786         var push = [].push;
3787         var match = sinon.match;
3789         function mock(object) {
3790             // if (typeof console !== undefined && console.warn) {
3791             //     console.warn("mock will be removed from Sinon.JS v2.0");
3792             // }
3794             if (!object) {
3795                 return sinon.expectation.create("Anonymous mock");
3796             }
3798             return mock.create(object);
3799         }
3801         function each(collection, callback) {
3802             if (!collection) {
3803                 return;
3804             }
3806             for (var i = 0, l = collection.length; i < l; i += 1) {
3807                 callback(collection[i]);
3808             }
3809         }
3811         function arrayEquals(arr1, arr2, compareLength) {
3812             if (compareLength && (arr1.length !== arr2.length)) {
3813                 return false;
3814             }
3816             for (var i = 0, l = arr1.length; i < l; i++) {
3817                 if (!sinon.deepEqual(arr1[i], arr2[i])) {
3818                     return false;
3819                 }
3820             }
3821             return true;
3822         }
3824         sinon.extend(mock, {
3825             create: function create(object) {
3826                 if (!object) {
3827                     throw new TypeError("object is null");
3828                 }
3830                 var mockObject = sinon.extend({}, mock);
3831                 mockObject.object = object;
3832                 delete mockObject.create;
3834                 return mockObject;
3835             },
3837             expects: function expects(method) {
3838                 if (!method) {
3839                     throw new TypeError("method is falsy");
3840                 }
3842                 if (!this.expectations) {
3843                     this.expectations = {};
3844                     this.proxies = [];
3845                 }
3847                 if (!this.expectations[method]) {
3848                     this.expectations[method] = [];
3849                     var mockObject = this;
3851                     sinon.wrapMethod(this.object, method, function () {
3852                         return mockObject.invokeMethod(method, this, arguments);
3853                     });
3855                     push.call(this.proxies, method);
3856                 }
3858                 var expectation = sinon.expectation.create(method);
3859                 push.call(this.expectations[method], expectation);
3861                 return expectation;
3862             },
3864             restore: function restore() {
3865                 var object = this.object;
3867                 each(this.proxies, function (proxy) {
3868                     if (typeof object[proxy].restore === "function") {
3869                         object[proxy].restore();
3870                     }
3871                 });
3872             },
3874             verify: function verify() {
3875                 var expectations = this.expectations || {};
3876                 var messages = [];
3877                 var met = [];
3879                 each(this.proxies, function (proxy) {
3880                     each(expectations[proxy], function (expectation) {
3881                         if (!expectation.met()) {
3882                             push.call(messages, expectation.toString());
3883                         } else {
3884                             push.call(met, expectation.toString());
3885                         }
3886                     });
3887                 });
3889                 this.restore();
3891                 if (messages.length > 0) {
3892                     sinon.expectation.fail(messages.concat(met).join("\n"));
3893                 } else if (met.length > 0) {
3894                     sinon.expectation.pass(messages.concat(met).join("\n"));
3895                 }
3897                 return true;
3898             },
3900             invokeMethod: function invokeMethod(method, thisValue, args) {
3901                 var expectations = this.expectations && this.expectations[method] ? this.expectations[method] : [];
3902                 var expectationsWithMatchingArgs = [];
3903                 var currentArgs = args || [];
3904                 var i, available;
3906                 for (i = 0; i < expectations.length; i += 1) {
3907                     var expectedArgs = expectations[i].expectedArguments || [];
3908                     if (arrayEquals(expectedArgs, currentArgs, expectations[i].expectsExactArgCount)) {
3909                         expectationsWithMatchingArgs.push(expectations[i]);
3910                     }
3911                 }
3913                 for (i = 0; i < expectationsWithMatchingArgs.length; i += 1) {
3914                     if (!expectationsWithMatchingArgs[i].met() &&
3915                         expectationsWithMatchingArgs[i].allowsCall(thisValue, args)) {
3916                         return expectationsWithMatchingArgs[i].apply(thisValue, args);
3917                     }
3918                 }
3920                 var messages = [];
3921                 var exhausted = 0;
3923                 for (i = 0; i < expectationsWithMatchingArgs.length; i += 1) {
3924                     if (expectationsWithMatchingArgs[i].allowsCall(thisValue, args)) {
3925                         available = available || expectationsWithMatchingArgs[i];
3926                     } else {
3927                         exhausted += 1;
3928                     }
3929                 }
3931                 if (available && exhausted === 0) {
3932                     return available.apply(thisValue, args);
3933                 }
3935                 for (i = 0; i < expectations.length; i += 1) {
3936                     push.call(messages, "    " + expectations[i].toString());
3937                 }
3939                 messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
3940                     proxy: method,
3941                     args: args
3942                 }));
3944                 sinon.expectation.fail(messages.join("\n"));
3945             }
3946         });
3948         var times = sinon.timesInWords;
3949         var slice = Array.prototype.slice;
3951         function callCountInWords(callCount) {
3952             if (callCount === 0) {
3953                 return "never called";
3954             }
3956             return "called " + times(callCount);
3957         }
3959         function expectedCallCountInWords(expectation) {
3960             var min = expectation.minCalls;
3961             var max = expectation.maxCalls;
3963             if (typeof min === "number" && typeof max === "number") {
3964                 var str = times(min);
3966                 if (min !== max) {
3967                     str = "at least " + str + " and at most " + times(max);
3968                 }
3970                 return str;
3971             }
3973             if (typeof min === "number") {
3974                 return "at least " + times(min);
3975             }
3977             return "at most " + times(max);
3978         }
3980         function receivedMinCalls(expectation) {
3981             var hasMinLimit = typeof expectation.minCalls === "number";
3982             return !hasMinLimit || expectation.callCount >= expectation.minCalls;
3983         }
3985         function receivedMaxCalls(expectation) {
3986             if (typeof expectation.maxCalls !== "number") {
3987                 return false;
3988             }
3990             return expectation.callCount === expectation.maxCalls;
3991         }
3993         function verifyMatcher(possibleMatcher, arg) {
3994             var isMatcher = match && match.isMatcher(possibleMatcher);
3996             return isMatcher && possibleMatcher.test(arg) || true;
3997         }
3999         sinon.expectation = {
4000             minCalls: 1,
4001             maxCalls: 1,
4003             create: function create(methodName) {
4004                 var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
4005                 delete expectation.create;
4006                 expectation.method = methodName;
4008                 return expectation;
4009             },
4011             invoke: function invoke(func, thisValue, args) {
4012                 this.verifyCallAllowed(thisValue, args);
4014                 return sinon.spy.invoke.apply(this, arguments);
4015             },
4017             atLeast: function atLeast(num) {
4018                 if (typeof num !== "number") {
4019                     throw new TypeError("'" + num + "' is not number");
4020                 }
4022                 if (!this.limitsSet) {
4023                     this.maxCalls = null;
4024                     this.limitsSet = true;
4025                 }
4027                 this.minCalls = num;
4029                 return this;
4030             },
4032             atMost: function atMost(num) {
4033                 if (typeof num !== "number") {
4034                     throw new TypeError("'" + num + "' is not number");
4035                 }
4037                 if (!this.limitsSet) {
4038                     this.minCalls = null;
4039                     this.limitsSet = true;
4040                 }
4042                 this.maxCalls = num;
4044                 return this;
4045             },
4047             never: function never() {
4048                 return this.exactly(0);
4049             },
4051             once: function once() {
4052                 return this.exactly(1);
4053             },
4055             twice: function twice() {
4056                 return this.exactly(2);
4057             },
4059             thrice: function thrice() {
4060                 return this.exactly(3);
4061             },
4063             exactly: function exactly(num) {
4064                 if (typeof num !== "number") {
4065                     throw new TypeError("'" + num + "' is not a number");
4066                 }
4068                 this.atLeast(num);
4069                 return this.atMost(num);
4070             },
4072             met: function met() {
4073                 return !this.failed && receivedMinCalls(this);
4074             },
4076             verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
4077                 if (receivedMaxCalls(this)) {
4078                     this.failed = true;
4079                     sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
4080                 }
4082                 if ("expectedThis" in this && this.expectedThis !== thisValue) {
4083                     sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
4084                         this.expectedThis);
4085                 }
4087                 if (!("expectedArguments" in this)) {
4088                     return;
4089                 }
4091                 if (!args) {
4092                     sinon.expectation.fail(this.method + " received no arguments, expected " +
4093                         sinon.format(this.expectedArguments));
4094                 }
4096                 if (args.length < this.expectedArguments.length) {
4097                     sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
4098                         "), expected " + sinon.format(this.expectedArguments));
4099                 }
4101                 if (this.expectsExactArgCount &&
4102                     args.length !== this.expectedArguments.length) {
4103                     sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
4104                         "), expected " + sinon.format(this.expectedArguments));
4105                 }
4107                 for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
4109                     if (!verifyMatcher(this.expectedArguments[i], args[i])) {
4110                         sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
4111                             ", didn't match " + this.expectedArguments.toString());
4112                     }
4114                     if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
4115                         sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
4116                             ", expected " + sinon.format(this.expectedArguments));
4117                     }
4118                 }
4119             },
4121             allowsCall: function allowsCall(thisValue, args) {
4122                 if (this.met() && receivedMaxCalls(this)) {
4123                     return false;
4124                 }
4126                 if ("expectedThis" in this && this.expectedThis !== thisValue) {
4127                     return false;
4128                 }
4130                 if (!("expectedArguments" in this)) {
4131                     return true;
4132                 }
4134                 args = args || [];
4136                 if (args.length < this.expectedArguments.length) {
4137                     return false;
4138                 }
4140                 if (this.expectsExactArgCount &&
4141                     args.length !== this.expectedArguments.length) {
4142                     return false;
4143                 }
4145                 for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
4146                     if (!verifyMatcher(this.expectedArguments[i], args[i])) {
4147                         return false;
4148                     }
4150                     if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
4151                         return false;
4152                     }
4153                 }
4155                 return true;
4156             },
4158             withArgs: function withArgs() {
4159                 this.expectedArguments = slice.call(arguments);
4160                 return this;
4161             },
4163             withExactArgs: function withExactArgs() {
4164                 this.withArgs.apply(this, arguments);
4165                 this.expectsExactArgCount = true;
4166                 return this;
4167             },
4169             on: function on(thisValue) {
4170                 this.expectedThis = thisValue;
4171                 return this;
4172             },
4174             toString: function () {
4175                 var args = (this.expectedArguments || []).slice();
4177                 if (!this.expectsExactArgCount) {
4178                     push.call(args, "[...]");
4179                 }
4181                 var callStr = sinon.spyCall.toString.call({
4182                     proxy: this.method || "anonymous mock expectation",
4183                     args: args
4184                 });
4186                 var message = callStr.replace(", [...", "[, ...") + " " +
4187                     expectedCallCountInWords(this);
4189                 if (this.met()) {
4190                     return "Expectation met: " + message;
4191                 }
4193                 return "Expected " + message + " (" +
4194                     callCountInWords(this.callCount) + ")";
4195             },
4197             verify: function verify() {
4198                 if (!this.met()) {
4199                     sinon.expectation.fail(this.toString());
4200                 } else {
4201                     sinon.expectation.pass(this.toString());
4202                 }
4204                 return true;
4205             },
4207             pass: function pass(message) {
4208                 sinon.assert.pass(message);
4209             },
4211             fail: function fail(message) {
4212                 var exception = new Error(message);
4213                 exception.name = "ExpectationError";
4215                 throw exception;
4216             }
4217         };
4219         sinon.mock = mock;
4220         return mock;
4221     }
4223     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4224     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4226     function loadDependencies(require, exports, module) {
4227         var sinon = require("./util/core");
4228         require("./times_in_words");
4229         require("./call");
4230         require("./extend");
4231         require("./match");
4232         require("./spy");
4233         require("./stub");
4234         require("./format");
4236         module.exports = makeApi(sinon);
4237     }
4239     if (isAMD) {
4240         define(loadDependencies);
4241         return;
4242     }
4244     if (isNode) {
4245         loadDependencies(require, module.exports, module);
4246         return;
4247     }
4249     if (sinonGlobal) {
4250         makeApi(sinonGlobal);
4251     }
4253     typeof sinon === "object" && sinon // eslint-disable-line no-undef
4257  * @depend util/core.js
4258  * @depend spy.js
4259  * @depend stub.js
4260  * @depend mock.js
4261  */
4263  * Collections of stubs, spies and mocks.
4265  * @author Christian Johansen (christian@cjohansen.no)
4266  * @license BSD
4268  * Copyright (c) 2010-2013 Christian Johansen
4269  */
4270 (function (sinonGlobal) {
4271     
4272     var push = [].push;
4273     var hasOwnProperty = Object.prototype.hasOwnProperty;
4275     function getFakes(fakeCollection) {
4276         if (!fakeCollection.fakes) {
4277             fakeCollection.fakes = [];
4278         }
4280         return fakeCollection.fakes;
4281     }
4283     function each(fakeCollection, method) {
4284         var fakes = getFakes(fakeCollection);
4286         for (var i = 0, l = fakes.length; i < l; i += 1) {
4287             if (typeof fakes[i][method] === "function") {
4288                 fakes[i][method]();
4289             }
4290         }
4291     }
4293     function compact(fakeCollection) {
4294         var fakes = getFakes(fakeCollection);
4295         var i = 0;
4296         while (i < fakes.length) {
4297             fakes.splice(i, 1);
4298         }
4299     }
4301     function makeApi(sinon) {
4302         var collection = {
4303             verify: function resolve() {
4304                 each(this, "verify");
4305             },
4307             restore: function restore() {
4308                 each(this, "restore");
4309                 compact(this);
4310             },
4312             reset: function restore() {
4313                 each(this, "reset");
4314             },
4316             verifyAndRestore: function verifyAndRestore() {
4317                 var exception;
4319                 try {
4320                     this.verify();
4321                 } catch (e) {
4322                     exception = e;
4323                 }
4325                 this.restore();
4327                 if (exception) {
4328                     throw exception;
4329                 }
4330             },
4332             add: function add(fake) {
4333                 push.call(getFakes(this), fake);
4334                 return fake;
4335             },
4337             spy: function spy() {
4338                 return this.add(sinon.spy.apply(sinon, arguments));
4339             },
4341             stub: function stub(object, property, value) {
4342                 if (property) {
4343                     var original = object[property];
4345                     if (typeof original !== "function") {
4346                         if (!hasOwnProperty.call(object, property)) {
4347                             throw new TypeError("Cannot stub non-existent own property " + property);
4348                         }
4350                         object[property] = value;
4352                         return this.add({
4353                             restore: function () {
4354                                 object[property] = original;
4355                             }
4356                         });
4357                     }
4358                 }
4359                 if (!property && !!object && typeof object === "object") {
4360                     var stubbedObj = sinon.stub.apply(sinon, arguments);
4362                     for (var prop in stubbedObj) {
4363                         if (typeof stubbedObj[prop] === "function") {
4364                             this.add(stubbedObj[prop]);
4365                         }
4366                     }
4368                     return stubbedObj;
4369                 }
4371                 return this.add(sinon.stub.apply(sinon, arguments));
4372             },
4374             mock: function mock() {
4375                 return this.add(sinon.mock.apply(sinon, arguments));
4376             },
4378             inject: function inject(obj) {
4379                 var col = this;
4381                 obj.spy = function () {
4382                     return col.spy.apply(col, arguments);
4383                 };
4385                 obj.stub = function () {
4386                     return col.stub.apply(col, arguments);
4387                 };
4389                 obj.mock = function () {
4390                     return col.mock.apply(col, arguments);
4391                 };
4393                 return obj;
4394             }
4395         };
4397         sinon.collection = collection;
4398         return collection;
4399     }
4401     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4402     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4404     function loadDependencies(require, exports, module) {
4405         var sinon = require("./util/core");
4406         require("./mock");
4407         require("./spy");
4408         require("./stub");
4409         module.exports = makeApi(sinon);
4410     }
4412     if (isAMD) {
4413         define(loadDependencies);
4414         return;
4415     }
4417     if (isNode) {
4418         loadDependencies(require, module.exports, module);
4419         return;
4420     }
4422     if (sinonGlobal) {
4423         makeApi(sinonGlobal);
4424     }
4426     typeof sinon === "object" && sinon // eslint-disable-line no-undef
4430  * Fake timer API
4431  * setTimeout
4432  * setInterval
4433  * clearTimeout
4434  * clearInterval
4435  * tick
4436  * reset
4437  * Date
4439  * Inspired by jsUnitMockTimeOut from JsUnit
4441  * @author Christian Johansen (christian@cjohansen.no)
4442  * @license BSD
4444  * Copyright (c) 2010-2013 Christian Johansen
4445  */
4446 (function () {
4447     
4448     function makeApi(s, lol) {
4449         /*global lolex */
4450         var llx = typeof lolex !== "undefined" ? lolex : lol;
4452         s.useFakeTimers = function () {
4453             var now;
4454             var methods = Array.prototype.slice.call(arguments);
4456             if (typeof methods[0] === "string") {
4457                 now = 0;
4458             } else {
4459                 now = methods.shift();
4460             }
4462             var clock = llx.install(now || 0, methods);
4463             clock.restore = clock.uninstall;
4464             return clock;
4465         };
4467         s.clock = {
4468             create: function (now) {
4469                 return llx.createClock(now);
4470             }
4471         };
4473         s.timers = {
4474             setTimeout: setTimeout,
4475             clearTimeout: clearTimeout,
4476             setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
4477             clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate : undefined),
4478             setInterval: setInterval,
4479             clearInterval: clearInterval,
4480             Date: Date
4481         };
4482     }
4484     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4485     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4487     function loadDependencies(require, epxorts, module, lolex) {
4488         var core = require("./core");
4489         makeApi(core, lolex);
4490         module.exports = core;
4491     }
4493     if (isAMD) {
4494         define(loadDependencies);
4495     } else if (isNode) {
4496         loadDependencies(require, module.exports, module, require("lolex"));
4497     } else {
4498         makeApi(sinon); // eslint-disable-line no-undef
4499     }
4500 }());
4503  * Minimal Event interface implementation
4505  * Original implementation by Sven Fuchs: https://gist.github.com/995028
4506  * Modifications and tests by Christian Johansen.
4508  * @author Sven Fuchs (svenfuchs@artweb-design.de)
4509  * @author Christian Johansen (christian@cjohansen.no)
4510  * @license BSD
4512  * Copyright (c) 2011 Sven Fuchs, Christian Johansen
4513  */
4514 if (typeof sinon === "undefined") {
4515     this.sinon = {};
4518 (function () {
4519     
4520     var push = [].push;
4522     function makeApi(sinon) {
4523         sinon.Event = function Event(type, bubbles, cancelable, target) {
4524             this.initEvent(type, bubbles, cancelable, target);
4525         };
4527         sinon.Event.prototype = {
4528             initEvent: function (type, bubbles, cancelable, target) {
4529                 this.type = type;
4530                 this.bubbles = bubbles;
4531                 this.cancelable = cancelable;
4532                 this.target = target;
4533             },
4535             stopPropagation: function () {},
4537             preventDefault: function () {
4538                 this.defaultPrevented = true;
4539             }
4540         };
4542         sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
4543             this.initEvent(type, false, false, target);
4544             this.loaded = typeof progressEventRaw.loaded === "number" ? progressEventRaw.loaded : null;
4545             this.total = typeof progressEventRaw.total === "number" ? progressEventRaw.total : null;
4546             this.lengthComputable = !!progressEventRaw.total;
4547         };
4549         sinon.ProgressEvent.prototype = new sinon.Event();
4551         sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent;
4553         sinon.CustomEvent = function CustomEvent(type, customData, target) {
4554             this.initEvent(type, false, false, target);
4555             this.detail = customData.detail || null;
4556         };
4558         sinon.CustomEvent.prototype = new sinon.Event();
4560         sinon.CustomEvent.prototype.constructor = sinon.CustomEvent;
4562         sinon.EventTarget = {
4563             addEventListener: function addEventListener(event, listener) {
4564                 this.eventListeners = this.eventListeners || {};
4565                 this.eventListeners[event] = this.eventListeners[event] || [];
4566                 push.call(this.eventListeners[event], listener);
4567             },
4569             removeEventListener: function removeEventListener(event, listener) {
4570                 var listeners = this.eventListeners && this.eventListeners[event] || [];
4572                 for (var i = 0, l = listeners.length; i < l; ++i) {
4573                     if (listeners[i] === listener) {
4574                         return listeners.splice(i, 1);
4575                     }
4576                 }
4577             },
4579             dispatchEvent: function dispatchEvent(event) {
4580                 var type = event.type;
4581                 var listeners = this.eventListeners && this.eventListeners[type] || [];
4583                 for (var i = 0; i < listeners.length; i++) {
4584                     if (typeof listeners[i] === "function") {
4585                         listeners[i].call(this, event);
4586                     } else {
4587                         listeners[i].handleEvent(event);
4588                     }
4589                 }
4591                 return !!event.defaultPrevented;
4592             }
4593         };
4594     }
4596     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4597     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4599     function loadDependencies(require) {
4600         var sinon = require("./core");
4601         makeApi(sinon);
4602     }
4604     if (isAMD) {
4605         define(loadDependencies);
4606     } else if (isNode) {
4607         loadDependencies(require);
4608     } else {
4609         makeApi(sinon); // eslint-disable-line no-undef
4610     }
4611 }());
4614  * @depend util/core.js
4615  */
4617  * Logs errors
4619  * @author Christian Johansen (christian@cjohansen.no)
4620  * @license BSD
4622  * Copyright (c) 2010-2014 Christian Johansen
4623  */
4624 (function (sinonGlobal) {
4625     
4626     // cache a reference to setTimeout, so that our reference won't be stubbed out
4627     // when using fake timers and errors will still get logged
4628     // https://github.com/cjohansen/Sinon.JS/issues/381
4629     var realSetTimeout = setTimeout;
4631     function makeApi(sinon) {
4633         function log() {}
4635         function logError(label, err) {
4636             var msg = label + " threw exception: ";
4638             function throwLoggedError() {
4639                 err.message = msg + err.message;
4640                 throw err;
4641             }
4643             sinon.log(msg + "[" + err.name + "] " + err.message);
4645             if (err.stack) {
4646                 sinon.log(err.stack);
4647             }
4649             if (logError.useImmediateExceptions) {
4650                 throwLoggedError();
4651             } else {
4652                 logError.setTimeout(throwLoggedError, 0);
4653             }
4654         }
4656         // When set to true, any errors logged will be thrown immediately;
4657         // If set to false, the errors will be thrown in separate execution frame.
4658         logError.useImmediateExceptions = false;
4660         // wrap realSetTimeout with something we can stub in tests
4661         logError.setTimeout = function (func, timeout) {
4662             realSetTimeout(func, timeout);
4663         };
4665         var exports = {};
4666         exports.log = sinon.log = log;
4667         exports.logError = sinon.logError = logError;
4669         return exports;
4670     }
4672     function loadDependencies(require, exports, module) {
4673         var sinon = require("./util/core");
4674         module.exports = makeApi(sinon);
4675     }
4677     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4678     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4680     if (isAMD) {
4681         define(loadDependencies);
4682         return;
4683     }
4685     if (isNode) {
4686         loadDependencies(require, module.exports, module);
4687         return;
4688     }
4690     if (sinonGlobal) {
4691         makeApi(sinonGlobal);
4692     }
4694     typeof sinon === "object" && sinon // eslint-disable-line no-undef
4698  * @depend core.js
4699  * @depend ../extend.js
4700  * @depend event.js
4701  * @depend ../log_error.js
4702  */
4704  * Fake XDomainRequest object
4705  */
4708  * Returns the global to prevent assigning values to 'this' when this is undefined.
4709  * This can occur when files are interpreted by node in strict mode.
4710  * @private
4711  */
4712 function getGlobal() {
4713     
4714     return typeof window !== "undefined" ? window : global;
4717 if (typeof sinon === "undefined") {
4718     if (typeof this === "undefined") {
4719         getGlobal().sinon = {};
4720     } else {
4721         this.sinon = {};
4722     }
4725 // wrapper for global
4726 (function (global) {
4727     
4728     var xdr = { XDomainRequest: global.XDomainRequest };
4729     xdr.GlobalXDomainRequest = global.XDomainRequest;
4730     xdr.supportsXDR = typeof xdr.GlobalXDomainRequest !== "undefined";
4731     xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false;
4733     function makeApi(sinon) {
4734         sinon.xdr = xdr;
4736         function FakeXDomainRequest() {
4737             this.readyState = FakeXDomainRequest.UNSENT;
4738             this.requestBody = null;
4739             this.requestHeaders = {};
4740             this.status = 0;
4741             this.timeout = null;
4743             if (typeof FakeXDomainRequest.onCreate === "function") {
4744                 FakeXDomainRequest.onCreate(this);
4745             }
4746         }
4748         function verifyState(x) {
4749             if (x.readyState !== FakeXDomainRequest.OPENED) {
4750                 throw new Error("INVALID_STATE_ERR");
4751             }
4753             if (x.sendFlag) {
4754                 throw new Error("INVALID_STATE_ERR");
4755             }
4756         }
4758         function verifyRequestSent(x) {
4759             if (x.readyState === FakeXDomainRequest.UNSENT) {
4760                 throw new Error("Request not sent");
4761             }
4762             if (x.readyState === FakeXDomainRequest.DONE) {
4763                 throw new Error("Request done");
4764             }
4765         }
4767         function verifyResponseBodyType(body) {
4768             if (typeof body !== "string") {
4769                 var error = new Error("Attempted to respond to fake XDomainRequest with " +
4770                                     body + ", which is not a string.");
4771                 error.name = "InvalidBodyException";
4772                 throw error;
4773             }
4774         }
4776         sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
4777             open: function open(method, url) {
4778                 this.method = method;
4779                 this.url = url;
4781                 this.responseText = null;
4782                 this.sendFlag = false;
4784                 this.readyStateChange(FakeXDomainRequest.OPENED);
4785             },
4787             readyStateChange: function readyStateChange(state) {
4788                 this.readyState = state;
4789                 var eventName = "";
4790                 switch (this.readyState) {
4791                 case FakeXDomainRequest.UNSENT:
4792                     break;
4793                 case FakeXDomainRequest.OPENED:
4794                     break;
4795                 case FakeXDomainRequest.LOADING:
4796                     if (this.sendFlag) {
4797                         //raise the progress event
4798                         eventName = "onprogress";
4799                     }
4800                     break;
4801                 case FakeXDomainRequest.DONE:
4802                     if (this.isTimeout) {
4803                         eventName = "ontimeout";
4804                     } else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
4805                         eventName = "onerror";
4806                     } else {
4807                         eventName = "onload";
4808                     }
4809                     break;
4810                 }
4812                 // raising event (if defined)
4813                 if (eventName) {
4814                     if (typeof this[eventName] === "function") {
4815                         try {
4816                             this[eventName]();
4817                         } catch (e) {
4818                             sinon.logError("Fake XHR " + eventName + " handler", e);
4819                         }
4820                     }
4821                 }
4822             },
4824             send: function send(data) {
4825                 verifyState(this);
4827                 if (!/^(get|head)$/i.test(this.method)) {
4828                     this.requestBody = data;
4829                 }
4830                 this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
4832                 this.errorFlag = false;
4833                 this.sendFlag = true;
4834                 this.readyStateChange(FakeXDomainRequest.OPENED);
4836                 if (typeof this.onSend === "function") {
4837                     this.onSend(this);
4838                 }
4839             },
4841             abort: function abort() {
4842                 this.aborted = true;
4843                 this.responseText = null;
4844                 this.errorFlag = true;
4846                 if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
4847                     this.readyStateChange(sinon.FakeXDomainRequest.DONE);
4848                     this.sendFlag = false;
4849                 }
4850             },
4852             setResponseBody: function setResponseBody(body) {
4853                 verifyRequestSent(this);
4854                 verifyResponseBodyType(body);
4856                 var chunkSize = this.chunkSize || 10;
4857                 var index = 0;
4858                 this.responseText = "";
4860                 do {
4861                     this.readyStateChange(FakeXDomainRequest.LOADING);
4862                     this.responseText += body.substring(index, index + chunkSize);
4863                     index += chunkSize;
4864                 } while (index < body.length);
4866                 this.readyStateChange(FakeXDomainRequest.DONE);
4867             },
4869             respond: function respond(status, contentType, body) {
4870                 // content-type ignored, since XDomainRequest does not carry this
4871                 // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
4872                 // test integration across browsers
4873                 this.status = typeof status === "number" ? status : 200;
4874                 this.setResponseBody(body || "");
4875             },
4877             simulatetimeout: function simulatetimeout() {
4878                 this.status = 0;
4879                 this.isTimeout = true;
4880                 // Access to this should actually throw an error
4881                 this.responseText = undefined;
4882                 this.readyStateChange(FakeXDomainRequest.DONE);
4883             }
4884         });
4886         sinon.extend(FakeXDomainRequest, {
4887             UNSENT: 0,
4888             OPENED: 1,
4889             LOADING: 3,
4890             DONE: 4
4891         });
4893         sinon.useFakeXDomainRequest = function useFakeXDomainRequest() {
4894             sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
4895                 if (xdr.supportsXDR) {
4896                     global.XDomainRequest = xdr.GlobalXDomainRequest;
4897                 }
4899                 delete sinon.FakeXDomainRequest.restore;
4901                 if (keepOnCreate !== true) {
4902                     delete sinon.FakeXDomainRequest.onCreate;
4903                 }
4904             };
4905             if (xdr.supportsXDR) {
4906                 global.XDomainRequest = sinon.FakeXDomainRequest;
4907             }
4908             return sinon.FakeXDomainRequest;
4909         };
4911         sinon.FakeXDomainRequest = FakeXDomainRequest;
4912     }
4914     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4915     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4917     function loadDependencies(require, exports, module) {
4918         var sinon = require("./core");
4919         require("../extend");
4920         require("./event");
4921         require("../log_error");
4922         makeApi(sinon);
4923         module.exports = sinon;
4924     }
4926     if (isAMD) {
4927         define(loadDependencies);
4928     } else if (isNode) {
4929         loadDependencies(require, module.exports, module);
4930     } else {
4931         makeApi(sinon); // eslint-disable-line no-undef
4932     }
4933 })(typeof global !== "undefined" ? global : self);
4936  * @depend core.js
4937  * @depend ../extend.js
4938  * @depend event.js
4939  * @depend ../log_error.js
4940  */
4942  * Fake XMLHttpRequest object
4944  * @author Christian Johansen (christian@cjohansen.no)
4945  * @license BSD
4947  * Copyright (c) 2010-2013 Christian Johansen
4948  */
4949 (function (sinonGlobal, global) {
4950     
4951     function getWorkingXHR(globalScope) {
4952         var supportsXHR = typeof globalScope.XMLHttpRequest !== "undefined";
4953         if (supportsXHR) {
4954             return globalScope.XMLHttpRequest;
4955         }
4957         var supportsActiveX = typeof globalScope.ActiveXObject !== "undefined";
4958         if (supportsActiveX) {
4959             return function () {
4960                 return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0");
4961             };
4962         }
4964         return false;
4965     }
4967     var supportsProgress = typeof ProgressEvent !== "undefined";
4968     var supportsCustomEvent = typeof CustomEvent !== "undefined";
4969     var supportsFormData = typeof FormData !== "undefined";
4970     var supportsArrayBuffer = typeof ArrayBuffer !== "undefined";
4971     var supportsBlob = (function () {
4972         try {
4973             return !!new Blob();
4974         } catch (e) {
4975             return false;
4976         }
4977     })();
4978     var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest };
4979     sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
4980     sinonXhr.GlobalActiveXObject = global.ActiveXObject;
4981     sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject !== "undefined";
4982     sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest !== "undefined";
4983     sinonXhr.workingXHR = getWorkingXHR(global);
4984     sinonXhr.supportsCORS = sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest());
4986     var unsafeHeaders = {
4987         "Accept-Charset": true,
4988         "Accept-Encoding": true,
4989         Connection: true,
4990         "Content-Length": true,
4991         Cookie: true,
4992         Cookie2: true,
4993         "Content-Transfer-Encoding": true,
4994         Date: true,
4995         Expect: true,
4996         Host: true,
4997         "Keep-Alive": true,
4998         Referer: true,
4999         TE: true,
5000         Trailer: true,
5001         "Transfer-Encoding": true,
5002         Upgrade: true,
5003         "User-Agent": true,
5004         Via: true
5005     };
5007     // An upload object is created for each
5008     // FakeXMLHttpRequest and allows upload
5009     // events to be simulated using uploadProgress
5010     // and uploadError.
5011     function UploadProgress() {
5012         this.eventListeners = {
5013             abort: [],
5014             error: [],
5015             load: [],
5016             loadend: [],
5017             progress: []
5018         };
5019     }
5021     UploadProgress.prototype.addEventListener = function addEventListener(event, listener) {
5022         this.eventListeners[event].push(listener);
5023     };
5025     UploadProgress.prototype.removeEventListener = function removeEventListener(event, listener) {
5026         var listeners = this.eventListeners[event] || [];
5028         for (var i = 0, l = listeners.length; i < l; ++i) {
5029             if (listeners[i] === listener) {
5030                 return listeners.splice(i, 1);
5031             }
5032         }
5033     };
5035     UploadProgress.prototype.dispatchEvent = function dispatchEvent(event) {
5036         var listeners = this.eventListeners[event.type] || [];
5038         for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
5039             listener(event);
5040         }
5041     };
5043     // Note that for FakeXMLHttpRequest to work pre ES5
5044     // we lose some of the alignment with the spec.
5045     // To ensure as close a match as possible,
5046     // set responseType before calling open, send or respond;
5047     function FakeXMLHttpRequest() {
5048         this.readyState = FakeXMLHttpRequest.UNSENT;
5049         this.requestHeaders = {};
5050         this.requestBody = null;
5051         this.status = 0;
5052         this.statusText = "";
5053         this.upload = new UploadProgress();
5054         this.responseType = "";
5055         this.response = "";
5056         if (sinonXhr.supportsCORS) {
5057             this.withCredentials = false;
5058         }
5060         var xhr = this;
5061         var events = ["loadstart", "load", "abort", "error", "loadend"];
5063         function addEventListener(eventName) {
5064             xhr.addEventListener(eventName, function (event) {
5065                 var listener = xhr["on" + eventName];
5067                 if (listener && typeof listener === "function") {
5068                     listener.call(this, event);
5069                 }
5070             });
5071         }
5073         for (var i = events.length - 1; i >= 0; i--) {
5074             addEventListener(events[i]);
5075         }
5077         if (typeof FakeXMLHttpRequest.onCreate === "function") {
5078             FakeXMLHttpRequest.onCreate(this);
5079         }
5080     }
5082     function verifyState(xhr) {
5083         if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
5084             throw new Error("INVALID_STATE_ERR");
5085         }
5087         if (xhr.sendFlag) {
5088             throw new Error("INVALID_STATE_ERR");
5089         }
5090     }
5092     function getHeader(headers, header) {
5093         header = header.toLowerCase();
5095         for (var h in headers) {
5096             if (h.toLowerCase() === header) {
5097                 return h;
5098             }
5099         }
5101         return null;
5102     }
5104     // filtering to enable a white-list version of Sinon FakeXhr,
5105     // where whitelisted requests are passed through to real XHR
5106     function each(collection, callback) {
5107         if (!collection) {
5108             return;
5109         }
5111         for (var i = 0, l = collection.length; i < l; i += 1) {
5112             callback(collection[i]);
5113         }
5114     }
5115     function some(collection, callback) {
5116         for (var index = 0; index < collection.length; index++) {
5117             if (callback(collection[index]) === true) {
5118                 return true;
5119             }
5120         }
5121         return false;
5122     }
5123     // largest arity in XHR is 5 - XHR#open
5124     var apply = function (obj, method, args) {
5125         switch (args.length) {
5126         case 0: return obj[method]();
5127         case 1: return obj[method](args[0]);
5128         case 2: return obj[method](args[0], args[1]);
5129         case 3: return obj[method](args[0], args[1], args[2]);
5130         case 4: return obj[method](args[0], args[1], args[2], args[3]);
5131         case 5: return obj[method](args[0], args[1], args[2], args[3], args[4]);
5132         }
5133     };
5135     FakeXMLHttpRequest.filters = [];
5136     FakeXMLHttpRequest.addFilter = function addFilter(fn) {
5137         this.filters.push(fn);
5138     };
5139     var IE6Re = /MSIE 6/;
5140     FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) {
5141         var xhr = new sinonXhr.workingXHR(); // eslint-disable-line new-cap
5143         each([
5144             "open",
5145             "setRequestHeader",
5146             "send",
5147             "abort",
5148             "getResponseHeader",
5149             "getAllResponseHeaders",
5150             "addEventListener",
5151             "overrideMimeType",
5152             "removeEventListener"
5153         ], function (method) {
5154             fakeXhr[method] = function () {
5155                 return apply(xhr, method, arguments);
5156             };
5157         });
5159         var copyAttrs = function (args) {
5160             each(args, function (attr) {
5161                 try {
5162                     fakeXhr[attr] = xhr[attr];
5163                 } catch (e) {
5164                     if (!IE6Re.test(navigator.userAgent)) {
5165                         throw e;
5166                     }
5167                 }
5168             });
5169         };
5171         var stateChange = function stateChange() {
5172             fakeXhr.readyState = xhr.readyState;
5173             if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
5174                 copyAttrs(["status", "statusText"]);
5175             }
5176             if (xhr.readyState >= FakeXMLHttpRequest.LOADING) {
5177                 copyAttrs(["responseText", "response"]);
5178             }
5179             if (xhr.readyState === FakeXMLHttpRequest.DONE) {
5180                 copyAttrs(["responseXML"]);
5181             }
5182             if (fakeXhr.onreadystatechange) {
5183                 fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
5184             }
5185         };
5187         if (xhr.addEventListener) {
5188             for (var event in fakeXhr.eventListeners) {
5189                 if (fakeXhr.eventListeners.hasOwnProperty(event)) {
5191                     /*eslint-disable no-loop-func*/
5192                     each(fakeXhr.eventListeners[event], function (handler) {
5193                         xhr.addEventListener(event, handler);
5194                     });
5195                     /*eslint-enable no-loop-func*/
5196                 }
5197             }
5198             xhr.addEventListener("readystatechange", stateChange);
5199         } else {
5200             xhr.onreadystatechange = stateChange;
5201         }
5202         apply(xhr, "open", xhrArgs);
5203     };
5204     FakeXMLHttpRequest.useFilters = false;
5206     function verifyRequestOpened(xhr) {
5207         if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
5208             throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
5209         }
5210     }
5212     function verifyRequestSent(xhr) {
5213         if (xhr.readyState === FakeXMLHttpRequest.DONE) {
5214             throw new Error("Request done");
5215         }
5216     }
5218     function verifyHeadersReceived(xhr) {
5219         if (xhr.async && xhr.readyState !== FakeXMLHttpRequest.HEADERS_RECEIVED) {
5220             throw new Error("No headers received");
5221         }
5222     }
5224     function verifyResponseBodyType(body) {
5225         if (typeof body !== "string") {
5226             var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
5227                                  body + ", which is not a string.");
5228             error.name = "InvalidBodyException";
5229             throw error;
5230         }
5231     }
5233     function convertToArrayBuffer(body) {
5234         var buffer = new ArrayBuffer(body.length);
5235         var view = new Uint8Array(buffer);
5236         for (var i = 0; i < body.length; i++) {
5237             var charCode = body.charCodeAt(i);
5238             if (charCode >= 256) {
5239                 throw new TypeError("arraybuffer or blob responseTypes require binary string, " +
5240                                     "invalid character " + body[i] + " found.");
5241             }
5242             view[i] = charCode;
5243         }
5244         return buffer;
5245     }
5247     function isXmlContentType(contentType) {
5248         return !contentType || /(text\/xml)|(application\/xml)|(\+xml)/.test(contentType);
5249     }
5251     function convertResponseBody(responseType, contentType, body) {
5252         if (responseType === "" || responseType === "text") {
5253             return body;
5254         } else if (supportsArrayBuffer && responseType === "arraybuffer") {
5255             return convertToArrayBuffer(body);
5256         } else if (responseType === "json") {
5257             try {
5258                 return JSON.parse(body);
5259             } catch (e) {
5260                 // Return parsing failure as null
5261                 return null;
5262             }
5263         } else if (supportsBlob && responseType === "blob") {
5264             var blobOptions = {};
5265             if (contentType) {
5266                 blobOptions.type = contentType;
5267             }
5268             return new Blob([convertToArrayBuffer(body)], blobOptions);
5269         } else if (responseType === "document") {
5270             if (isXmlContentType(contentType)) {
5271                 return FakeXMLHttpRequest.parseXML(body);
5272             }
5273             return null;
5274         }
5275         throw new Error("Invalid responseType " + responseType);
5276     }
5278     function clearResponse(xhr) {
5279         if (xhr.responseType === "" || xhr.responseType === "text") {
5280             xhr.response = xhr.responseText = "";
5281         } else {
5282             xhr.response = xhr.responseText = null;
5283         }
5284         xhr.responseXML = null;
5285     }
5287     FakeXMLHttpRequest.parseXML = function parseXML(text) {
5288         // Treat empty string as parsing failure
5289         if (text !== "") {
5290             try {
5291                 if (typeof DOMParser !== "undefined") {
5292                     var parser = new DOMParser();
5293                     return parser.parseFromString(text, "text/xml");
5294                 }
5295                 var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
5296                 xmlDoc.async = "false";
5297                 xmlDoc.loadXML(text);
5298                 return xmlDoc;
5299             } catch (e) {
5300                 // Unable to parse XML - no biggie
5301             }
5302         }
5304         return null;
5305     };
5307     FakeXMLHttpRequest.statusCodes = {
5308         100: "Continue",
5309         101: "Switching Protocols",
5310         200: "OK",
5311         201: "Created",
5312         202: "Accepted",
5313         203: "Non-Authoritative Information",
5314         204: "No Content",
5315         205: "Reset Content",
5316         206: "Partial Content",
5317         207: "Multi-Status",
5318         300: "Multiple Choice",
5319         301: "Moved Permanently",
5320         302: "Found",
5321         303: "See Other",
5322         304: "Not Modified",
5323         305: "Use Proxy",
5324         307: "Temporary Redirect",
5325         400: "Bad Request",
5326         401: "Unauthorized",
5327         402: "Payment Required",
5328         403: "Forbidden",
5329         404: "Not Found",
5330         405: "Method Not Allowed",
5331         406: "Not Acceptable",
5332         407: "Proxy Authentication Required",
5333         408: "Request Timeout",
5334         409: "Conflict",
5335         410: "Gone",
5336         411: "Length Required",
5337         412: "Precondition Failed",
5338         413: "Request Entity Too Large",
5339         414: "Request-URI Too Long",
5340         415: "Unsupported Media Type",
5341         416: "Requested Range Not Satisfiable",
5342         417: "Expectation Failed",
5343         422: "Unprocessable Entity",
5344         500: "Internal Server Error",
5345         501: "Not Implemented",
5346         502: "Bad Gateway",
5347         503: "Service Unavailable",
5348         504: "Gateway Timeout",
5349         505: "HTTP Version Not Supported"
5350     };
5352     function makeApi(sinon) {
5353         sinon.xhr = sinonXhr;
5355         sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
5356             async: true,
5358             open: function open(method, url, async, username, password) {
5359                 this.method = method;
5360                 this.url = url;
5361                 this.async = typeof async === "boolean" ? async : true;
5362                 this.username = username;
5363                 this.password = password;
5364                 clearResponse(this);
5365                 this.requestHeaders = {};
5366                 this.sendFlag = false;
5368                 if (FakeXMLHttpRequest.useFilters === true) {
5369                     var xhrArgs = arguments;
5370                     var defake = some(FakeXMLHttpRequest.filters, function (filter) {
5371                         return filter.apply(this, xhrArgs);
5372                     });
5373                     if (defake) {
5374                         return FakeXMLHttpRequest.defake(this, arguments);
5375                     }
5376                 }
5377                 this.readyStateChange(FakeXMLHttpRequest.OPENED);
5378             },
5380             readyStateChange: function readyStateChange(state) {
5381                 this.readyState = state;
5383                 var readyStateChangeEvent = new sinon.Event("readystatechange", false, false, this);
5384                 var event, progress;
5386                 if (typeof this.onreadystatechange === "function") {
5387                     try {
5388                         this.onreadystatechange(readyStateChangeEvent);
5389                     } catch (e) {
5390                         sinon.logError("Fake XHR onreadystatechange handler", e);
5391                     }
5392                 }
5394                 if (this.readyState === FakeXMLHttpRequest.DONE) {
5395                     // ensure loaded and total are numbers
5396                     progress = {
5397                       loaded: this.progress || 0,
5398                       total: this.progress || 0
5399                     };
5401                     if (this.status === 0) {
5402                         event = this.aborted ? "abort" : "error";
5403                     }
5404                     else {
5405                         event = "load";
5406                     }
5408                     if (supportsProgress) {
5409                         this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progress, this));
5410                         this.upload.dispatchEvent(new sinon.ProgressEvent(event, progress, this));
5411                         this.upload.dispatchEvent(new sinon.ProgressEvent("loadend", progress, this));
5412                     }
5414                     this.dispatchEvent(new sinon.ProgressEvent("progress", progress, this));
5415                     this.dispatchEvent(new sinon.ProgressEvent(event, progress, this));
5416                     this.dispatchEvent(new sinon.ProgressEvent("loadend", progress, this));
5417                 }
5419                 this.dispatchEvent(readyStateChangeEvent);
5420             },
5422             setRequestHeader: function setRequestHeader(header, value) {
5423                 verifyState(this);
5425                 if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
5426                     throw new Error("Refused to set unsafe header \"" + header + "\"");
5427                 }
5429                 if (this.requestHeaders[header]) {
5430                     this.requestHeaders[header] += "," + value;
5431                 } else {
5432                     this.requestHeaders[header] = value;
5433                 }
5434             },
5436             // Helps testing
5437             setResponseHeaders: function setResponseHeaders(headers) {
5438                 verifyRequestOpened(this);
5439                 this.responseHeaders = {};
5441                 for (var header in headers) {
5442                     if (headers.hasOwnProperty(header)) {
5443                         this.responseHeaders[header] = headers[header];
5444                     }
5445                 }
5447                 if (this.async) {
5448                     this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
5449                 } else {
5450                     this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
5451                 }
5452             },
5454             // Currently treats ALL data as a DOMString (i.e. no Document)
5455             send: function send(data) {
5456                 verifyState(this);
5458                 if (!/^(get|head)$/i.test(this.method)) {
5459                     var contentType = getHeader(this.requestHeaders, "Content-Type");
5460                     if (this.requestHeaders[contentType]) {
5461                         var value = this.requestHeaders[contentType].split(";");
5462                         this.requestHeaders[contentType] = value[0] + ";charset=utf-8";
5463                     } else if (supportsFormData && !(data instanceof FormData)) {
5464                         this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
5465                     }
5467                     this.requestBody = data;
5468                 }
5470                 this.errorFlag = false;
5471                 this.sendFlag = this.async;
5472                 clearResponse(this);
5473                 this.readyStateChange(FakeXMLHttpRequest.OPENED);
5475                 if (typeof this.onSend === "function") {
5476                     this.onSend(this);
5477                 }
5479                 this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
5480             },
5482             abort: function abort() {
5483                 this.aborted = true;
5484                 clearResponse(this);
5485                 this.errorFlag = true;
5486                 this.requestHeaders = {};
5487                 this.responseHeaders = {};
5489                 if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) {
5490                     this.readyStateChange(FakeXMLHttpRequest.DONE);
5491                     this.sendFlag = false;
5492                 }
5494                 this.readyState = FakeXMLHttpRequest.UNSENT;
5495             },
5497             error: function error() {
5498                 clearResponse(this);
5499                 this.errorFlag = true;
5500                 this.requestHeaders = {};
5501                 this.responseHeaders = {};
5503                 this.readyStateChange(FakeXMLHttpRequest.DONE);
5504             },
5506             getResponseHeader: function getResponseHeader(header) {
5507                 if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
5508                     return null;
5509                 }
5511                 if (/^Set-Cookie2?$/i.test(header)) {
5512                     return null;
5513                 }
5515                 header = getHeader(this.responseHeaders, header);
5517                 return this.responseHeaders[header] || null;
5518             },
5520             getAllResponseHeaders: function getAllResponseHeaders() {
5521                 if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
5522                     return "";
5523                 }
5525                 var headers = "";
5527                 for (var header in this.responseHeaders) {
5528                     if (this.responseHeaders.hasOwnProperty(header) &&
5529                         !/^Set-Cookie2?$/i.test(header)) {
5530                         headers += header + ": " + this.responseHeaders[header] + "\r\n";
5531                     }
5532                 }
5534                 return headers;
5535             },
5537             setResponseBody: function setResponseBody(body) {
5538                 verifyRequestSent(this);
5539                 verifyHeadersReceived(this);
5540                 verifyResponseBodyType(body);
5541                 var contentType = this.getResponseHeader("Content-Type");
5543                 var isTextResponse = this.responseType === "" || this.responseType === "text";
5544                 clearResponse(this);
5545                 if (this.async) {
5546                     var chunkSize = this.chunkSize || 10;
5547                     var index = 0;
5549                     do {
5550                         this.readyStateChange(FakeXMLHttpRequest.LOADING);
5552                         if (isTextResponse) {
5553                             this.responseText = this.response += body.substring(index, index + chunkSize);
5554                         }
5555                         index += chunkSize;
5556                     } while (index < body.length);
5557                 }
5559                 this.response = convertResponseBody(this.responseType, contentType, body);
5560                 if (isTextResponse) {
5561                     this.responseText = this.response;
5562                 }
5564                 if (this.responseType === "document") {
5565                     this.responseXML = this.response;
5566                 } else if (this.responseType === "" && isXmlContentType(contentType)) {
5567                     this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
5568                 }
5569                 this.progress = body.length;
5570                 this.readyStateChange(FakeXMLHttpRequest.DONE);
5571             },
5573             respond: function respond(status, headers, body) {
5574                 this.status = typeof status === "number" ? status : 200;
5575                 this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
5576                 this.setResponseHeaders(headers || {});
5577                 this.setResponseBody(body || "");
5578             },
5580             uploadProgress: function uploadProgress(progressEventRaw) {
5581                 if (supportsProgress) {
5582                     this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
5583                 }
5584             },
5586             downloadProgress: function downloadProgress(progressEventRaw) {
5587                 if (supportsProgress) {
5588                     this.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
5589                 }
5590             },
5592             uploadError: function uploadError(error) {
5593                 if (supportsCustomEvent) {
5594                     this.upload.dispatchEvent(new sinon.CustomEvent("error", {detail: error}));
5595                 }
5596             }
5597         });
5599         sinon.extend(FakeXMLHttpRequest, {
5600             UNSENT: 0,
5601             OPENED: 1,
5602             HEADERS_RECEIVED: 2,
5603             LOADING: 3,
5604             DONE: 4
5605         });
5607         sinon.useFakeXMLHttpRequest = function () {
5608             FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
5609                 if (sinonXhr.supportsXHR) {
5610                     global.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest;
5611                 }
5613                 if (sinonXhr.supportsActiveX) {
5614                     global.ActiveXObject = sinonXhr.GlobalActiveXObject;
5615                 }
5617                 delete FakeXMLHttpRequest.restore;
5619                 if (keepOnCreate !== true) {
5620                     delete FakeXMLHttpRequest.onCreate;
5621                 }
5622             };
5623             if (sinonXhr.supportsXHR) {
5624                 global.XMLHttpRequest = FakeXMLHttpRequest;
5625             }
5627             if (sinonXhr.supportsActiveX) {
5628                 global.ActiveXObject = function ActiveXObject(objId) {
5629                     if (objId === "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
5631                         return new FakeXMLHttpRequest();
5632                     }
5634                     return new sinonXhr.GlobalActiveXObject(objId);
5635                 };
5636             }
5638             return FakeXMLHttpRequest;
5639         };
5641         sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
5642     }
5644     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
5645     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5647     function loadDependencies(require, exports, module) {
5648         var sinon = require("./core");
5649         require("../extend");
5650         require("./event");
5651         require("../log_error");
5652         makeApi(sinon);
5653         module.exports = sinon;
5654     }
5656     if (isAMD) {
5657         define(loadDependencies);
5658         return;
5659     }
5661     if (isNode) {
5662         loadDependencies(require, module.exports, module);
5663         return;
5664     }
5666     if (sinonGlobal) {
5667         makeApi(sinonGlobal);
5668     }
5670     typeof sinon === "object" && sinon, // eslint-disable-line no-undef
5671     typeof global !== "undefined" ? global : self
5675  * @depend fake_xdomain_request.js
5676  * @depend fake_xml_http_request.js
5677  * @depend ../format.js
5678  * @depend ../log_error.js
5679  */
5681  * The Sinon "server" mimics a web server that receives requests from
5682  * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
5683  * both synchronously and asynchronously. To respond synchronuously, canned
5684  * answers have to be provided upfront.
5686  * @author Christian Johansen (christian@cjohansen.no)
5687  * @license BSD
5689  * Copyright (c) 2010-2013 Christian Johansen
5690  */
5691 (function () {
5692     
5693     var push = [].push;
5695     function responseArray(handler) {
5696         var response = handler;
5698         if (Object.prototype.toString.call(handler) !== "[object Array]") {
5699             response = [200, {}, handler];
5700         }
5702         if (typeof response[2] !== "string") {
5703             throw new TypeError("Fake server response body should be string, but was " +
5704                                 typeof response[2]);
5705         }
5707         return response;
5708     }
5710     var wloc = typeof window !== "undefined" ? window.location : {};
5711     var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
5713     function matchOne(response, reqMethod, reqUrl) {
5714         var rmeth = response.method;
5715         var matchMethod = !rmeth || rmeth.toLowerCase() === reqMethod.toLowerCase();
5716         var url = response.url;
5717         var matchUrl = !url || url === reqUrl || (typeof url.test === "function" && url.test(reqUrl));
5719         return matchMethod && matchUrl;
5720     }
5722     function match(response, request) {
5723         var requestUrl = request.url;
5725         if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
5726             requestUrl = requestUrl.replace(rCurrLoc, "");
5727         }
5729         if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
5730             if (typeof response.response === "function") {
5731                 var ru = response.url;
5732                 var args = [request].concat(ru && typeof ru.exec === "function" ? ru.exec(requestUrl).slice(1) : []);
5733                 return response.response.apply(response, args);
5734             }
5736             return true;
5737         }
5739         return false;
5740     }
5742     function makeApi(sinon) {
5743         sinon.fakeServer = {
5744             create: function (config) {
5745                 var server = sinon.create(this);
5746                 server.configure(config);
5747                 if (!sinon.xhr.supportsCORS) {
5748                     this.xhr = sinon.useFakeXDomainRequest();
5749                 } else {
5750                     this.xhr = sinon.useFakeXMLHttpRequest();
5751                 }
5752                 server.requests = [];
5754                 this.xhr.onCreate = function (xhrObj) {
5755                     server.addRequest(xhrObj);
5756                 };
5758                 return server;
5759             },
5760             configure: function (config) {
5761                 var whitelist = {
5762                     "autoRespond": true,
5763                     "autoRespondAfter": true,
5764                     "respondImmediately": true,
5765                     "fakeHTTPMethods": true
5766                 };
5767                 var setting;
5769                 config = config || {};
5770                 for (setting in config) {
5771                     if (whitelist.hasOwnProperty(setting) && config.hasOwnProperty(setting)) {
5772                         this[setting] = config[setting];
5773                     }
5774                 }
5775             },
5776             addRequest: function addRequest(xhrObj) {
5777                 var server = this;
5778                 push.call(this.requests, xhrObj);
5780                 xhrObj.onSend = function () {
5781                     server.handleRequest(this);
5783                     if (server.respondImmediately) {
5784                         server.respond();
5785                     } else if (server.autoRespond && !server.responding) {
5786                         setTimeout(function () {
5787                             server.responding = false;
5788                             server.respond();
5789                         }, server.autoRespondAfter || 10);
5791                         server.responding = true;
5792                     }
5793                 };
5794             },
5796             getHTTPMethod: function getHTTPMethod(request) {
5797                 if (this.fakeHTTPMethods && /post/i.test(request.method)) {
5798                     var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
5799                     return matches ? matches[1] : request.method;
5800                 }
5802                 return request.method;
5803             },
5805             handleRequest: function handleRequest(xhr) {
5806                 if (xhr.async) {
5807                     if (!this.queue) {
5808                         this.queue = [];
5809                     }
5811                     push.call(this.queue, xhr);
5812                 } else {
5813                     this.processRequest(xhr);
5814                 }
5815             },
5817             log: function log(response, request) {
5818                 var str;
5820                 str = "Request:\n" + sinon.format(request) + "\n\n";
5821                 str += "Response:\n" + sinon.format(response) + "\n\n";
5823                 sinon.log(str);
5824             },
5826             respondWith: function respondWith(method, url, body) {
5827                 if (arguments.length === 1 && typeof method !== "function") {
5828                     this.response = responseArray(method);
5829                     return;
5830                 }
5832                 if (!this.responses) {
5833                     this.responses = [];
5834                 }
5836                 if (arguments.length === 1) {
5837                     body = method;
5838                     url = method = null;
5839                 }
5841                 if (arguments.length === 2) {
5842                     body = url;
5843                     url = method;
5844                     method = null;
5845                 }
5847                 push.call(this.responses, {
5848                     method: method,
5849                     url: url,
5850                     response: typeof body === "function" ? body : responseArray(body)
5851                 });
5852             },
5854             respond: function respond() {
5855                 if (arguments.length > 0) {
5856                     this.respondWith.apply(this, arguments);
5857                 }
5859                 var queue = this.queue || [];
5860                 var requests = queue.splice(0, queue.length);
5862                 for (var i = 0; i < requests.length; i++) {
5863                     this.processRequest(requests[i]);
5864                 }
5865             },
5867             processRequest: function processRequest(request) {
5868                 try {
5869                     if (request.aborted) {
5870                         return;
5871                     }
5873                     var response = this.response || [404, {}, ""];
5875                     if (this.responses) {
5876                         for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
5877                             if (match.call(this, this.responses[i], request)) {
5878                                 response = this.responses[i].response;
5879                                 break;
5880                             }
5881                         }
5882                     }
5884                     if (request.readyState !== 4) {
5885                         this.log(response, request);
5887                         request.respond(response[0], response[1], response[2]);
5888                     }
5889                 } catch (e) {
5890                     sinon.logError("Fake server request processing", e);
5891                 }
5892             },
5894             restore: function restore() {
5895                 return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
5896             }
5897         };
5898     }
5900     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
5901     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5903     function loadDependencies(require, exports, module) {
5904         var sinon = require("./core");
5905         require("./fake_xdomain_request");
5906         require("./fake_xml_http_request");
5907         require("../format");
5908         makeApi(sinon);
5909         module.exports = sinon;
5910     }
5912     if (isAMD) {
5913         define(loadDependencies);
5914     } else if (isNode) {
5915         loadDependencies(require, module.exports, module);
5916     } else {
5917         makeApi(sinon); // eslint-disable-line no-undef
5918     }
5919 }());
5922  * @depend fake_server.js
5923  * @depend fake_timers.js
5924  */
5926  * Add-on for sinon.fakeServer that automatically handles a fake timer along with
5927  * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
5928  * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
5929  * it polls the object for completion with setInterval. Dispite the direct
5930  * motivation, there is nothing jQuery-specific in this file, so it can be used
5931  * in any environment where the ajax implementation depends on setInterval or
5932  * setTimeout.
5934  * @author Christian Johansen (christian@cjohansen.no)
5935  * @license BSD
5937  * Copyright (c) 2010-2013 Christian Johansen
5938  */
5939 (function () {
5940     
5941     function makeApi(sinon) {
5942         function Server() {}
5943         Server.prototype = sinon.fakeServer;
5945         sinon.fakeServerWithClock = new Server();
5947         sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
5948             if (xhr.async) {
5949                 if (typeof setTimeout.clock === "object") {
5950                     this.clock = setTimeout.clock;
5951                 } else {
5952                     this.clock = sinon.useFakeTimers();
5953                     this.resetClock = true;
5954                 }
5956                 if (!this.longestTimeout) {
5957                     var clockSetTimeout = this.clock.setTimeout;
5958                     var clockSetInterval = this.clock.setInterval;
5959                     var server = this;
5961                     this.clock.setTimeout = function (fn, timeout) {
5962                         server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
5964                         return clockSetTimeout.apply(this, arguments);
5965                     };
5967                     this.clock.setInterval = function (fn, timeout) {
5968                         server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
5970                         return clockSetInterval.apply(this, arguments);
5971                     };
5972                 }
5973             }
5975             return sinon.fakeServer.addRequest.call(this, xhr);
5976         };
5978         sinon.fakeServerWithClock.respond = function respond() {
5979             var returnVal = sinon.fakeServer.respond.apply(this, arguments);
5981             if (this.clock) {
5982                 this.clock.tick(this.longestTimeout || 0);
5983                 this.longestTimeout = 0;
5985                 if (this.resetClock) {
5986                     this.clock.restore();
5987                     this.resetClock = false;
5988                 }
5989             }
5991             return returnVal;
5992         };
5994         sinon.fakeServerWithClock.restore = function restore() {
5995             if (this.clock) {
5996                 this.clock.restore();
5997             }
5999             return sinon.fakeServer.restore.apply(this, arguments);
6000         };
6001     }
6003     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
6004     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
6006     function loadDependencies(require) {
6007         var sinon = require("./core");
6008         require("./fake_server");
6009         require("./fake_timers");
6010         makeApi(sinon);
6011     }
6013     if (isAMD) {
6014         define(loadDependencies);
6015     } else if (isNode) {
6016         loadDependencies(require);
6017     } else {
6018         makeApi(sinon); // eslint-disable-line no-undef
6019     }
6020 }());
6023  * @depend util/core.js
6024  * @depend extend.js
6025  * @depend collection.js
6026  * @depend util/fake_timers.js
6027  * @depend util/fake_server_with_clock.js
6028  */
6030  * Manages fake collections as well as fake utilities such as Sinon's
6031  * timers and fake XHR implementation in one convenient object.
6033  * @author Christian Johansen (christian@cjohansen.no)
6034  * @license BSD
6036  * Copyright (c) 2010-2013 Christian Johansen
6037  */
6038 (function (sinonGlobal) {
6039     
6040     function makeApi(sinon) {
6041         var push = [].push;
6043         function exposeValue(sandbox, config, key, value) {
6044             if (!value) {
6045                 return;
6046             }
6048             if (config.injectInto && !(key in config.injectInto)) {
6049                 config.injectInto[key] = value;
6050                 sandbox.injectedKeys.push(key);
6051             } else {
6052                 push.call(sandbox.args, value);
6053             }
6054         }
6056         function prepareSandboxFromConfig(config) {
6057             var sandbox = sinon.create(sinon.sandbox);
6059             if (config.useFakeServer) {
6060                 if (typeof config.useFakeServer === "object") {
6061                     sandbox.serverPrototype = config.useFakeServer;
6062                 }
6064                 sandbox.useFakeServer();
6065             }
6067             if (config.useFakeTimers) {
6068                 if (typeof config.useFakeTimers === "object") {
6069                     sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
6070                 } else {
6071                     sandbox.useFakeTimers();
6072                 }
6073             }
6075             return sandbox;
6076         }
6078         sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
6079             useFakeTimers: function useFakeTimers() {
6080                 this.clock = sinon.useFakeTimers.apply(sinon, arguments);
6082                 return this.add(this.clock);
6083             },
6085             serverPrototype: sinon.fakeServer,
6087             useFakeServer: function useFakeServer() {
6088                 var proto = this.serverPrototype || sinon.fakeServer;
6090                 if (!proto || !proto.create) {
6091                     return null;
6092                 }
6094                 this.server = proto.create();
6095                 return this.add(this.server);
6096             },
6098             inject: function (obj) {
6099                 sinon.collection.inject.call(this, obj);
6101                 if (this.clock) {
6102                     obj.clock = this.clock;
6103                 }
6105                 if (this.server) {
6106                     obj.server = this.server;
6107                     obj.requests = this.server.requests;
6108                 }
6110                 obj.match = sinon.match;
6112                 return obj;
6113             },
6115             restore: function () {
6116                 if (arguments.length) {
6117                     throw new Error("sandbox.restore() does not take any parameters. Perhaps you meant stub.restore()");
6118                 }
6120                 sinon.collection.restore.apply(this, arguments);
6121                 this.restoreContext();
6122             },
6124             restoreContext: function () {
6125                 if (this.injectedKeys) {
6126                     for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
6127                         delete this.injectInto[this.injectedKeys[i]];
6128                     }
6129                     this.injectedKeys = [];
6130                 }
6131             },
6133             create: function (config) {
6134                 if (!config) {
6135                     return sinon.create(sinon.sandbox);
6136                 }
6138                 var sandbox = prepareSandboxFromConfig(config);
6139                 sandbox.args = sandbox.args || [];
6140                 sandbox.injectedKeys = [];
6141                 sandbox.injectInto = config.injectInto;
6142                 var prop,
6143                     value;
6144                 var exposed = sandbox.inject({});
6146                 if (config.properties) {
6147                     for (var i = 0, l = config.properties.length; i < l; i++) {
6148                         prop = config.properties[i];
6149                         value = exposed[prop] || prop === "sandbox" && sandbox;
6150                         exposeValue(sandbox, config, prop, value);
6151                     }
6152                 } else {
6153                     exposeValue(sandbox, config, "sandbox", value);
6154                 }
6156                 return sandbox;
6157             },
6159             match: sinon.match
6160         });
6162         sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
6164         return sinon.sandbox;
6165     }
6167     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
6168     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
6170     function loadDependencies(require, exports, module) {
6171         var sinon = require("./util/core");
6172         require("./extend");
6173         require("./util/fake_server_with_clock");
6174         require("./util/fake_timers");
6175         require("./collection");
6176         module.exports = makeApi(sinon);
6177     }
6179     if (isAMD) {
6180         define(loadDependencies);
6181         return;
6182     }
6184     if (isNode) {
6185         loadDependencies(require, module.exports, module);
6186         return;
6187     }
6189     if (sinonGlobal) {
6190         makeApi(sinonGlobal);
6191     }
6193     typeof sinon === "object" && sinon // eslint-disable-line no-undef
6197  * @depend util/core.js
6198  * @depend sandbox.js
6199  */
6201  * Test function, sandboxes fakes
6203  * @author Christian Johansen (christian@cjohansen.no)
6204  * @license BSD
6206  * Copyright (c) 2010-2013 Christian Johansen
6207  */
6208 (function (sinonGlobal) {
6209     
6210     function makeApi(sinon) {
6211         var slice = Array.prototype.slice;
6213         function test(callback) {
6214             var type = typeof callback;
6216             if (type !== "function") {
6217                 throw new TypeError("sinon.test needs to wrap a test function, got " + type);
6218             }
6220             function sinonSandboxedTest() {
6221                 var config = sinon.getConfig(sinon.config);
6222                 config.injectInto = config.injectIntoThis && this || config.injectInto;
6223                 var sandbox = sinon.sandbox.create(config);
6224                 var args = slice.call(arguments);
6225                 var oldDone = args.length && args[args.length - 1];
6226                 var exception, result;
6228                 if (typeof oldDone === "function") {
6229                     args[args.length - 1] = function sinonDone(res) {
6230                         if (res) {
6231                             sandbox.restore();
6232                         } else {
6233                             sandbox.verifyAndRestore();
6234                         }
6235                         oldDone(res);
6236                     };
6237                 }
6239                 try {
6240                     result = callback.apply(this, args.concat(sandbox.args));
6241                 } catch (e) {
6242                     exception = e;
6243                 }
6245                 if (typeof exception !== "undefined") {
6246                     sandbox.restore();
6247                     throw exception;
6248                 } else if (typeof oldDone !== "function") {
6249                     sandbox.verifyAndRestore();
6250                 }
6252                 return result;
6253             }
6255             if (callback.length) {
6256                 return function sinonAsyncSandboxedTest(done) { // eslint-disable-line no-unused-vars
6257                     return sinonSandboxedTest.apply(this, arguments);
6258                 };
6259             }
6261             return sinonSandboxedTest;
6262         }
6264         test.config = {
6265             injectIntoThis: true,
6266             injectInto: null,
6267             properties: ["spy", "stub", "mock", "clock", "server", "requests"],
6268             useFakeTimers: true,
6269             useFakeServer: true
6270         };
6272         sinon.test = test;
6273         return test;
6274     }
6276     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
6277     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
6279     function loadDependencies(require, exports, module) {
6280         var core = require("./util/core");
6281         require("./sandbox");
6282         module.exports = makeApi(core);
6283     }
6285     if (isAMD) {
6286         define(loadDependencies);
6287     } else if (isNode) {
6288         loadDependencies(require, module.exports, module);
6289     } else if (sinonGlobal) {
6290         makeApi(sinonGlobal);
6291     }
6292 }(typeof sinon === "object" && sinon || null)); // eslint-disable-line no-undef
6295  * @depend util/core.js
6296  * @depend test.js
6297  */
6299  * Test case, sandboxes all test functions
6301  * @author Christian Johansen (christian@cjohansen.no)
6302  * @license BSD
6304  * Copyright (c) 2010-2013 Christian Johansen
6305  */
6306 (function (sinonGlobal) {
6307     
6308     function createTest(property, setUp, tearDown) {
6309         return function () {
6310             if (setUp) {
6311                 setUp.apply(this, arguments);
6312             }
6314             var exception, result;
6316             try {
6317                 result = property.apply(this, arguments);
6318             } catch (e) {
6319                 exception = e;
6320             }
6322             if (tearDown) {
6323                 tearDown.apply(this, arguments);
6324             }
6326             if (exception) {
6327                 throw exception;
6328             }
6330             return result;
6331         };
6332     }
6334     function makeApi(sinon) {
6335         function testCase(tests, prefix) {
6336             if (!tests || typeof tests !== "object") {
6337                 throw new TypeError("sinon.testCase needs an object with test functions");
6338             }
6340             prefix = prefix || "test";
6341             var rPrefix = new RegExp("^" + prefix);
6342             var methods = {};
6343             var setUp = tests.setUp;
6344             var tearDown = tests.tearDown;
6345             var testName,
6346                 property,
6347                 method;
6349             for (testName in tests) {
6350                 if (tests.hasOwnProperty(testName) && !/^(setUp|tearDown)$/.test(testName)) {
6351                     property = tests[testName];
6353                     if (typeof property === "function" && rPrefix.test(testName)) {
6354                         method = property;
6356                         if (setUp || tearDown) {
6357                             method = createTest(property, setUp, tearDown);
6358                         }
6360                         methods[testName] = sinon.test(method);
6361                     } else {
6362                         methods[testName] = tests[testName];
6363                     }
6364                 }
6365             }
6367             return methods;
6368         }
6370         sinon.testCase = testCase;
6371         return testCase;
6372     }
6374     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
6375     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
6377     function loadDependencies(require, exports, module) {
6378         var core = require("./util/core");
6379         require("./test");
6380         module.exports = makeApi(core);
6381     }
6383     if (isAMD) {
6384         define(loadDependencies);
6385         return;
6386     }
6388     if (isNode) {
6389         loadDependencies(require, module.exports, module);
6390         return;
6391     }
6393     if (sinonGlobal) {
6394         makeApi(sinonGlobal);
6395     }
6397     typeof sinon === "object" && sinon // eslint-disable-line no-undef
6401  * @depend times_in_words.js
6402  * @depend util/core.js
6403  * @depend match.js
6404  * @depend format.js
6405  */
6407  * Assertions matching the test spy retrieval interface.
6409  * @author Christian Johansen (christian@cjohansen.no)
6410  * @license BSD
6412  * Copyright (c) 2010-2013 Christian Johansen
6413  */
6414 (function (sinonGlobal, global) {
6415     
6416     var slice = Array.prototype.slice;
6418     function makeApi(sinon) {
6419         var assert;
6421         function verifyIsStub() {
6422             var method;
6424             for (var i = 0, l = arguments.length; i < l; ++i) {
6425                 method = arguments[i];
6427                 if (!method) {
6428                     assert.fail("fake is not a spy");
6429                 }
6431                 if (method.proxy && method.proxy.isSinonProxy) {
6432                     verifyIsStub(method.proxy);
6433                 } else {
6434                     if (typeof method !== "function") {
6435                         assert.fail(method + " is not a function");
6436                     }
6438                     if (typeof method.getCall !== "function") {
6439                         assert.fail(method + " is not stubbed");
6440                     }
6441                 }
6443             }
6444         }
6446         function verifyIsValidAssertion(assertionMethod, assertionArgs) {
6447             switch (assertionMethod) {
6448                 case "notCalled":
6449                 case "called":
6450                 case "calledOnce":
6451                 case "calledTwice":
6452                 case "calledThrice":
6453                     if (assertionArgs.length !== 0) {
6454                         assert.fail(assertionMethod +
6455                                     " takes 1 argument but was called with " +
6456                                     (assertionArgs.length + 1) + " arguments");
6457                     }
6458                     break;
6459                 default:
6460                     break;
6461             }
6462         }
6464         function failAssertion(object, msg) {
6465             object = object || global;
6466             var failMethod = object.fail || assert.fail;
6467             failMethod.call(object, msg);
6468         }
6470         function mirrorPropAsAssertion(name, method, message) {
6471             if (arguments.length === 2) {
6472                 message = method;
6473                 method = name;
6474             }
6476             assert[name] = function (fake) {
6477                 verifyIsStub(fake);
6479                 var args = slice.call(arguments, 1);
6480                 verifyIsValidAssertion(name, args);
6482                 var failed = false;
6484                 if (typeof method === "function") {
6485                     failed = !method(fake);
6486                 } else {
6487                     failed = typeof fake[method] === "function" ?
6488                         !fake[method].apply(fake, args) : !fake[method];
6489                 }
6491                 if (failed) {
6492                     failAssertion(this, (fake.printf || fake.proxy.printf).apply(fake, [message].concat(args)));
6493                 } else {
6494                     assert.pass(name);
6495                 }
6496             };
6497         }
6499         function exposedName(prefix, prop) {
6500             return !prefix || /^fail/.test(prop) ? prop :
6501                 prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
6502         }
6504         assert = {
6505             failException: "AssertError",
6507             fail: function fail(message) {
6508                 var error = new Error(message);
6509                 error.name = this.failException || assert.failException;
6511                 throw error;
6512             },
6514             pass: function pass() {},
6516             callOrder: function assertCallOrder() {
6517                 verifyIsStub.apply(null, arguments);
6518                 var expected = "";
6519                 var actual = "";
6521                 if (!sinon.calledInOrder(arguments)) {
6522                     try {
6523                         expected = [].join.call(arguments, ", ");
6524                         var calls = slice.call(arguments);
6525                         var i = calls.length;
6526                         while (i) {
6527                             if (!calls[--i].called) {
6528                                 calls.splice(i, 1);
6529                             }
6530                         }
6531                         actual = sinon.orderByFirstCall(calls).join(", ");
6532                     } catch (e) {
6533                         // If this fails, we'll just fall back to the blank string
6534                     }
6536                     failAssertion(this, "expected " + expected + " to be " +
6537                                 "called in order but were called as " + actual);
6538                 } else {
6539                     assert.pass("callOrder");
6540                 }
6541             },
6543             callCount: function assertCallCount(method, count) {
6544                 verifyIsStub(method);
6546                 if (method.callCount !== count) {
6547                     var msg = "expected %n to be called " + sinon.timesInWords(count) +
6548                         " but was called %c%C";
6549                     failAssertion(this, method.printf(msg));
6550                 } else {
6551                     assert.pass("callCount");
6552                 }
6553             },
6555             expose: function expose(target, options) {
6556                 if (!target) {
6557                     throw new TypeError("target is null or undefined");
6558                 }
6560                 var o = options || {};
6561                 var prefix = typeof o.prefix === "undefined" && "assert" || o.prefix;
6562                 var includeFail = typeof o.includeFail === "undefined" || !!o.includeFail;
6564                 for (var method in this) {
6565                     if (method !== "expose" && (includeFail || !/^(fail)/.test(method))) {
6566                         target[exposedName(prefix, method)] = this[method];
6567                     }
6568                 }
6570                 return target;
6571             },
6573             match: function match(actual, expectation) {
6574                 var matcher = sinon.match(expectation);
6575                 if (matcher.test(actual)) {
6576                     assert.pass("match");
6577                 } else {
6578                     var formatted = [
6579                         "expected value to match",
6580                         "    expected = " + sinon.format(expectation),
6581                         "    actual = " + sinon.format(actual)
6582                     ];
6584                     failAssertion(this, formatted.join("\n"));
6585                 }
6586             }
6587         };
6589         mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
6590         mirrorPropAsAssertion("notCalled", function (spy) {
6591             return !spy.called;
6592         }, "expected %n to not have been called but was called %c%C");
6593         mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
6594         mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
6595         mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
6596         mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
6597         mirrorPropAsAssertion(
6598             "alwaysCalledOn",
6599             "expected %n to always be called with %1 as this but was called with %t"
6600         );
6601         mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
6602         mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
6603         mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
6604         mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
6605         mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
6606         mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
6607         mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
6608         mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
6609         mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
6610         mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
6611         mirrorPropAsAssertion("threw", "%n did not throw exception%C");
6612         mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
6614         sinon.assert = assert;
6615         return assert;
6616     }
6618     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
6619     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
6621     function loadDependencies(require, exports, module) {
6622         var sinon = require("./util/core");
6623         require("./match");
6624         require("./format");
6625         module.exports = makeApi(sinon);
6626     }
6628     if (isAMD) {
6629         define(loadDependencies);
6630         return;
6631     }
6633     if (isNode) {
6634         loadDependencies(require, module.exports, module);
6635         return;
6636     }
6638     if (sinonGlobal) {
6639         makeApi(sinonGlobal);
6640     }
6642     typeof sinon === "object" && sinon, // eslint-disable-line no-undef
6643     typeof global !== "undefined" ? global : self
6646   return sinon;
6647 }));