Merge "Fix positioning of jQuery.tipsy tooltip arrows"
[mediawiki.git] / resources / lib / sinonjs / sinon-1.15.4.js
blob20bc9e208d7179d88f4f24cbabdba3077e1f0187
1 /**
2  * Sinon.JS 1.15.4, 2015/06/27
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     }
183     /**
184      * @name samsam.deepEqual
185      * @param Object obj1
186      * @param Object obj2
187      *
188      * Deep equal comparison. Two values are "deep equal" if:
189      *
190      *   - They are equal, according to samsam.identical
191      *   - They are both date objects representing the same time
192      *   - They are both arrays containing elements that are all deepEqual
193      *   - They are objects with the same set of properties, and each property
194      *     in ``obj1`` is deepEqual to the corresponding property in ``obj2``
195      *
196      * Supports cyclic objects.
197      */
198     function deepEqualCyclic(obj1, obj2) {
200         // used for cyclic comparison
201         // contain already visited objects
202         var objects1 = [],
203             objects2 = [],
204         // contain pathes (position in the object structure)
205         // of the already visited objects
206         // indexes same as in objects arrays
207             paths1 = [],
208             paths2 = [],
209         // contains combinations of already compared objects
210         // in the manner: { "$1['ref']$2['ref']": true }
211             compared = {};
213         /**
214          * used to check, if the value of a property is an object
215          * (cyclic logic is only needed for objects)
216          * only needed for cyclic logic
217          */
218         function isObject(value) {
220             if (typeof value === 'object' && value !== null &&
221                     !(value instanceof Boolean) &&
222                     !(value instanceof Date)    &&
223                     !(value instanceof Number)  &&
224                     !(value instanceof RegExp)  &&
225                     !(value instanceof String)) {
227                 return true;
228             }
230             return false;
231         }
233         /**
234          * returns the index of the given object in the
235          * given objects array, -1 if not contained
236          * only needed for cyclic logic
237          */
238         function getIndex(objects, obj) {
240             var i;
241             for (i = 0; i < objects.length; i++) {
242                 if (objects[i] === obj) {
243                     return i;
244                 }
245             }
247             return -1;
248         }
250         // does the recursion for the deep equal check
251         return (function deepEqual(obj1, obj2, path1, path2) {
252             var type1 = typeof obj1;
253             var type2 = typeof obj2;
255             // == null also matches undefined
256             if (obj1 === obj2 ||
257                     isNaN(obj1) || isNaN(obj2) ||
258                     obj1 == null || obj2 == null ||
259                     type1 !== "object" || type2 !== "object") {
261                 return identical(obj1, obj2);
262             }
264             // Elements are only equal if identical(expected, actual)
265             if (isElement(obj1) || isElement(obj2)) { return false; }
267             var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
268             if (isDate1 || isDate2) {
269                 if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
270                     return false;
271                 }
272             }
274             if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
275                 if (obj1.toString() !== obj2.toString()) { return false; }
276             }
278             var class1 = getClass(obj1);
279             var class2 = getClass(obj2);
280             var keys1 = keys(obj1);
281             var keys2 = keys(obj2);
283             if (isArguments(obj1) || isArguments(obj2)) {
284                 if (obj1.length !== obj2.length) { return false; }
285             } else {
286                 if (type1 !== type2 || class1 !== class2 ||
287                         keys1.length !== keys2.length) {
288                     return false;
289                 }
290             }
292             var key, i, l,
293                 // following vars are used for the cyclic logic
294                 value1, value2,
295                 isObject1, isObject2,
296                 index1, index2,
297                 newPath1, newPath2;
299             for (i = 0, l = keys1.length; i < l; i++) {
300                 key = keys1[i];
301                 if (!o.hasOwnProperty.call(obj2, key)) {
302                     return false;
303                 }
305                 // Start of the cyclic logic
307                 value1 = obj1[key];
308                 value2 = obj2[key];
310                 isObject1 = isObject(value1);
311                 isObject2 = isObject(value2);
313                 // determine, if the objects were already visited
314                 // (it's faster to check for isObject first, than to
315                 // get -1 from getIndex for non objects)
316                 index1 = isObject1 ? getIndex(objects1, value1) : -1;
317                 index2 = isObject2 ? getIndex(objects2, value2) : -1;
319                 // determine the new pathes of the objects
320                 // - for non cyclic objects the current path will be extended
321                 //   by current property name
322                 // - for cyclic objects the stored path is taken
323                 newPath1 = index1 !== -1
324                     ? paths1[index1]
325                     : path1 + '[' + JSON.stringify(key) + ']';
326                 newPath2 = index2 !== -1
327                     ? paths2[index2]
328                     : path2 + '[' + JSON.stringify(key) + ']';
330                 // stop recursion if current objects are already compared
331                 if (compared[newPath1 + newPath2]) {
332                     return true;
333                 }
335                 // remember the current objects and their pathes
336                 if (index1 === -1 && isObject1) {
337                     objects1.push(value1);
338                     paths1.push(newPath1);
339                 }
340                 if (index2 === -1 && isObject2) {
341                     objects2.push(value2);
342                     paths2.push(newPath2);
343                 }
345                 // remember that the current objects are already compared
346                 if (isObject1 && isObject2) {
347                     compared[newPath1 + newPath2] = true;
348                 }
350                 // End of cyclic logic
352                 // neither value1 nor value2 is a cycle
353                 // continue with next level
354                 if (!deepEqual(value1, value2, newPath1, newPath2)) {
355                     return false;
356                 }
357             }
359             return true;
361         }(obj1, obj2, '$1', '$2'));
362     }
364     var match;
366     function arrayContains(array, subset) {
367         if (subset.length === 0) { return true; }
368         var i, l, j, k;
369         for (i = 0, l = array.length; i < l; ++i) {
370             if (match(array[i], subset[0])) {
371                 for (j = 0, k = subset.length; j < k; ++j) {
372                     if (!match(array[i + j], subset[j])) { return false; }
373                 }
374                 return true;
375             }
376         }
377         return false;
378     }
380     /**
381      * @name samsam.match
382      * @param Object object
383      * @param Object matcher
384      *
385      * Compare arbitrary value ``object`` with matcher.
386      */
387     match = function match(object, matcher) {
388         if (matcher && typeof matcher.test === "function") {
389             return matcher.test(object);
390         }
392         if (typeof matcher === "function") {
393             return matcher(object) === true;
394         }
396         if (typeof matcher === "string") {
397             matcher = matcher.toLowerCase();
398             var notNull = typeof object === "string" || !!object;
399             return notNull &&
400                 (String(object)).toLowerCase().indexOf(matcher) >= 0;
401         }
403         if (typeof matcher === "number") {
404             return matcher === object;
405         }
407         if (typeof matcher === "boolean") {
408             return matcher === object;
409         }
411         if (typeof(matcher) === "undefined") {
412             return typeof(object) === "undefined";
413         }
415         if (matcher === null) {
416             return object === null;
417         }
419         if (getClass(object) === "Array" && getClass(matcher) === "Array") {
420             return arrayContains(object, matcher);
421         }
423         if (matcher && typeof matcher === "object") {
424             if (matcher === object) {
425                 return true;
426             }
427             var prop;
428             for (prop in matcher) {
429                 var value = object[prop];
430                 if (typeof value === "undefined" &&
431                         typeof object.getAttribute === "function") {
432                     value = object.getAttribute(prop);
433                 }
434                 if (matcher[prop] === null || typeof matcher[prop] === 'undefined') {
435                     if (value !== matcher[prop]) {
436                         return false;
437                     }
438                 } else if (typeof  value === "undefined" || !match(value, matcher[prop])) {
439                     return false;
440                 }
441             }
442             return true;
443         }
445         throw new Error("Matcher was not a string, a number, a " +
446                         "function, a boolean or an object");
447     };
449     return {
450         isArguments: isArguments,
451         isElement: isElement,
452         isDate: isDate,
453         isNegZero: isNegZero,
454         identical: identical,
455         deepEqual: deepEqualCyclic,
456         match: match,
457         keys: keys
458     };
460 ((typeof define === "function" && define.amd && function (m) {
461     define("formatio", ["samsam"], m);
462 }) || (typeof module === "object" && function (m) {
463     module.exports = m(require("samsam"));
464 }) || function (m) { this.formatio = m(this.samsam); }
465 )(function (samsam) {
466     
467     var formatio = {
468         excludeConstructors: ["Object", /^.$/],
469         quoteStrings: true,
470         limitChildrenCount: 0
471     };
473     var hasOwn = Object.prototype.hasOwnProperty;
475     var specialObjects = [];
476     if (typeof global !== "undefined") {
477         specialObjects.push({ object: global, value: "[object global]" });
478     }
479     if (typeof document !== "undefined") {
480         specialObjects.push({
481             object: document,
482             value: "[object HTMLDocument]"
483         });
484     }
485     if (typeof window !== "undefined") {
486         specialObjects.push({ object: window, value: "[object Window]" });
487     }
489     function functionName(func) {
490         if (!func) { return ""; }
491         if (func.displayName) { return func.displayName; }
492         if (func.name) { return func.name; }
493         var matches = func.toString().match(/function\s+([^\(]+)/m);
494         return (matches && matches[1]) || "";
495     }
497     function constructorName(f, object) {
498         var name = functionName(object && object.constructor);
499         var excludes = f.excludeConstructors ||
500                 formatio.excludeConstructors || [];
502         var i, l;
503         for (i = 0, l = excludes.length; i < l; ++i) {
504             if (typeof excludes[i] === "string" && excludes[i] === name) {
505                 return "";
506             } else if (excludes[i].test && excludes[i].test(name)) {
507                 return "";
508             }
509         }
511         return name;
512     }
514     function isCircular(object, objects) {
515         if (typeof object !== "object") { return false; }
516         var i, l;
517         for (i = 0, l = objects.length; i < l; ++i) {
518             if (objects[i] === object) { return true; }
519         }
520         return false;
521     }
523     function ascii(f, object, processed, indent) {
524         if (typeof object === "string") {
525             var qs = f.quoteStrings;
526             var quote = typeof qs !== "boolean" || qs;
527             return processed || quote ? '"' + object + '"' : object;
528         }
530         if (typeof object === "function" && !(object instanceof RegExp)) {
531             return ascii.func(object);
532         }
534         processed = processed || [];
536         if (isCircular(object, processed)) { return "[Circular]"; }
538         if (Object.prototype.toString.call(object) === "[object Array]") {
539             return ascii.array.call(f, object, processed);
540         }
542         if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
543         if (samsam.isElement(object)) { return ascii.element(object); }
545         if (typeof object.toString === "function" &&
546                 object.toString !== Object.prototype.toString) {
547             return object.toString();
548         }
550         var i, l;
551         for (i = 0, l = specialObjects.length; i < l; i++) {
552             if (object === specialObjects[i].object) {
553                 return specialObjects[i].value;
554             }
555         }
557         return ascii.object.call(f, object, processed, indent);
558     }
560     ascii.func = function (func) {
561         return "function " + functionName(func) + "() {}";
562     };
564     ascii.array = function (array, processed) {
565         processed = processed || [];
566         processed.push(array);
567         var pieces = [];
568         var i, l;
569         l = (this.limitChildrenCount > 0) ? 
570             Math.min(this.limitChildrenCount, array.length) : array.length;
572         for (i = 0; i < l; ++i) {
573             pieces.push(ascii(this, array[i], processed));
574         }
576         if(l < array.length)
577             pieces.push("[... " + (array.length - l) + " more elements]");
579         return "[" + pieces.join(", ") + "]";
580     };
582     ascii.object = function (object, processed, indent) {
583         processed = processed || [];
584         processed.push(object);
585         indent = indent || 0;
586         var pieces = [], properties = samsam.keys(object).sort();
587         var length = 3;
588         var prop, str, obj, i, k, l;
589         l = (this.limitChildrenCount > 0) ? 
590             Math.min(this.limitChildrenCount, properties.length) : properties.length;
592         for (i = 0; i < l; ++i) {
593             prop = properties[i];
594             obj = object[prop];
596             if (isCircular(obj, processed)) {
597                 str = "[Circular]";
598             } else {
599                 str = ascii(this, obj, processed, indent + 2);
600             }
602             str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
603             length += str.length;
604             pieces.push(str);
605         }
607         var cons = constructorName(this, object);
608         var prefix = cons ? "[" + cons + "] " : "";
609         var is = "";
610         for (i = 0, k = indent; i < k; ++i) { is += " "; }
612         if(l < properties.length)
613             pieces.push("[... " + (properties.length - l) + " more elements]");
615         if (length + indent > 80) {
616             return prefix + "{\n  " + is + pieces.join(",\n  " + is) + "\n" +
617                 is + "}";
618         }
619         return prefix + "{ " + pieces.join(", ") + " }";
620     };
622     ascii.element = function (element) {
623         var tagName = element.tagName.toLowerCase();
624         var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
626         for (i = 0, l = attrs.length; i < l; ++i) {
627             attr = attrs.item(i);
628             attrName = attr.nodeName.toLowerCase().replace("html:", "");
629             val = attr.nodeValue;
630             if (attrName !== "contenteditable" || val !== "inherit") {
631                 if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
632             }
633         }
635         var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
636         var content = element.innerHTML;
638         if (content.length > 20) {
639             content = content.substr(0, 20) + "[...]";
640         }
642         var res = formatted + pairs.join(" ") + ">" + content +
643                 "</" + tagName + ">";
645         return res.replace(/ contentEditable="inherit"/, "");
646     };
648     function Formatio(options) {
649         for (var opt in options) {
650             this[opt] = options[opt];
651         }
652     }
654     Formatio.prototype = {
655         functionName: functionName,
657         configure: function (options) {
658             return new Formatio(options);
659         },
661         constructorName: function (object) {
662             return constructorName(this, object);
663         },
665         ascii: function (object, processed, indent) {
666             return ascii(this, object, processed, indent);
667         }
668     };
670     return Formatio.prototype;
672 !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.lolex=e()}}(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){
673 (function (global){
674 /*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
675 /*global global*/
677  * @author Christian Johansen (christian@cjohansen.no) and contributors
678  * @license BSD
680  * Copyright (c) 2010-2014 Christian Johansen
681  */
683 // node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
684 // browsers, a number.
685 // see https://github.com/cjohansen/Sinon.JS/pull/436
686 var timeoutResult = setTimeout(function() {}, 0);
687 var addTimerReturnsObject = typeof timeoutResult === "object";
688 clearTimeout(timeoutResult);
690 var NativeDate = Date;
691 var id = 1;
694  * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
695  * number of milliseconds. This is used to support human-readable strings passed
696  * to clock.tick()
697  */
698 function parseTime(str) {
699     if (!str) {
700         return 0;
701     }
703     var strings = str.split(":");
704     var l = strings.length, i = l;
705     var ms = 0, parsed;
707     if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
708         throw new Error("tick only understands numbers and 'h:m:s'");
709     }
711     while (i--) {
712         parsed = parseInt(strings[i], 10);
714         if (parsed >= 60) {
715             throw new Error("Invalid time " + str);
716         }
718         ms += parsed * Math.pow(60, (l - i - 1));
719     }
721     return ms * 1000;
725  * Used to grok the `now` parameter to createClock.
726  */
727 function getEpoch(epoch) {
728     if (!epoch) { return 0; }
729     if (typeof epoch.getTime === "function") { return epoch.getTime(); }
730     if (typeof epoch === "number") { return epoch; }
731     throw new TypeError("now should be milliseconds since UNIX epoch");
734 function inRange(from, to, timer) {
735     return timer && timer.callAt >= from && timer.callAt <= to;
738 function mirrorDateProperties(target, source) {
739     if (source.now) {
740         target.now = function now() {
741             return target.clock.now;
742         };
743     } else {
744         delete target.now;
745     }
747     if (source.toSource) {
748         target.toSource = function toSource() {
749             return source.toSource();
750         };
751     } else {
752         delete target.toSource;
753     }
755     target.toString = function toString() {
756         return source.toString();
757     };
759     target.prototype = source.prototype;
760     target.parse = source.parse;
761     target.UTC = source.UTC;
762     target.prototype.toUTCString = source.prototype.toUTCString;
764     for (var prop in source) {
765         if (source.hasOwnProperty(prop)) {
766             target[prop] = source[prop];
767         }
768     }
770     return target;
773 function createDate() {
774     function ClockDate(year, month, date, hour, minute, second, ms) {
775         // Defensive and verbose to avoid potential harm in passing
776         // explicit undefined when user does not pass argument
777         switch (arguments.length) {
778         case 0:
779             return new NativeDate(ClockDate.clock.now);
780         case 1:
781             return new NativeDate(year);
782         case 2:
783             return new NativeDate(year, month);
784         case 3:
785             return new NativeDate(year, month, date);
786         case 4:
787             return new NativeDate(year, month, date, hour);
788         case 5:
789             return new NativeDate(year, month, date, hour, minute);
790         case 6:
791             return new NativeDate(year, month, date, hour, minute, second);
792         default:
793             return new NativeDate(year, month, date, hour, minute, second, ms);
794         }
795     }
797     return mirrorDateProperties(ClockDate, NativeDate);
800 function addTimer(clock, timer) {
801     if (typeof timer.func === "undefined") {
802         throw new Error("Callback must be provided to timer calls");
803     }
805     if (!clock.timers) {
806         clock.timers = {};
807     }
809     timer.id = id++;
810     timer.createdAt = clock.now;
811     timer.callAt = clock.now + (timer.delay || 0);
813     clock.timers[timer.id] = timer;
815     if (addTimerReturnsObject) {
816         return {
817             id: timer.id,
818             ref: function() {},
819             unref: function() {}
820         };
821     }
822     else {
823         return timer.id;
824     }
827 function firstTimerInRange(clock, from, to) {
828     var timers = clock.timers, timer = null;
830     for (var id in timers) {
831         if (!inRange(from, to, timers[id])) {
832             continue;
833         }
835         if (!timer || ~compareTimers(timer, timers[id])) {
836             timer = timers[id];
837         }
838     }
840     return timer;
843 function compareTimers(a, b) {
844     // Sort first by absolute timing
845     if (a.callAt < b.callAt) {
846         return -1;
847     }
848     if (a.callAt > b.callAt) {
849         return 1;
850     }
852     // Sort next by immediate, immediate timers take precedence
853     if (a.immediate && !b.immediate) {
854         return -1;
855     }
856     if (!a.immediate && b.immediate) {
857         return 1;
858     }
860     // Sort next by creation time, earlier-created timers take precedence
861     if (a.createdAt < b.createdAt) {
862         return -1;
863     }
864     if (a.createdAt > b.createdAt) {
865         return 1;
866     }
868     // Sort next by id, lower-id timers take precedence
869     if (a.id < b.id) {
870         return -1;
871     }
872     if (a.id > b.id) {
873         return 1;
874     }
876     // As timer ids are unique, no fallback `0` is necessary
879 function callTimer(clock, timer) {
880     if (typeof timer.interval == "number") {
881         clock.timers[timer.id].callAt += timer.interval;
882     } else {
883         delete clock.timers[timer.id];
884     }
886     try {
887         if (typeof timer.func == "function") {
888             timer.func.apply(null, timer.args);
889         } else {
890             eval(timer.func);
891         }
892     } catch (e) {
893         var exception = e;
894     }
896     if (!clock.timers[timer.id]) {
897         if (exception) {
898             throw exception;
899         }
900         return;
901     }
903     if (exception) {
904         throw exception;
905     }
908 function uninstall(clock, target) {
909     var method;
911     for (var i = 0, l = clock.methods.length; i < l; i++) {
912         method = clock.methods[i];
914         if (target[method].hadOwnProperty) {
915             target[method] = clock["_" + method];
916         } else {
917             try {
918                 delete target[method];
919             } catch (e) {}
920         }
921     }
923     // Prevent multiple executions which will completely remove these props
924     clock.methods = [];
927 function hijackMethod(target, method, clock) {
928     clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
929     clock["_" + method] = target[method];
931     if (method == "Date") {
932         var date = mirrorDateProperties(clock[method], target[method]);
933         target[method] = date;
934     } else {
935         target[method] = function () {
936             return clock[method].apply(clock, arguments);
937         };
939         for (var prop in clock[method]) {
940             if (clock[method].hasOwnProperty(prop)) {
941                 target[method][prop] = clock[method][prop];
942             }
943         }
944     }
946     target[method].clock = clock;
949 var timers = {
950     setTimeout: setTimeout,
951     clearTimeout: clearTimeout,
952     setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
953     clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
954     setInterval: setInterval,
955     clearInterval: clearInterval,
956     Date: Date
959 var keys = Object.keys || function (obj) {
960     var ks = [];
961     for (var key in obj) {
962         ks.push(key);
963     }
964     return ks;
967 exports.timers = timers;
969 var createClock = exports.createClock = function (now) {
970     var clock = {
971         now: getEpoch(now),
972         timeouts: {},
973         Date: createDate()
974     };
976     clock.Date.clock = clock;
978     clock.setTimeout = function setTimeout(func, timeout) {
979         return addTimer(clock, {
980             func: func,
981             args: Array.prototype.slice.call(arguments, 2),
982             delay: timeout
983         });
984     };
986     clock.clearTimeout = function clearTimeout(timerId) {
987         if (!timerId) {
988             // null appears to be allowed in most browsers, and appears to be
989             // relied upon by some libraries, like Bootstrap carousel
990             return;
991         }
992         if (!clock.timers) {
993             clock.timers = [];
994         }
995         // in Node, timerId is an object with .ref()/.unref(), and
996         // its .id field is the actual timer id.
997         if (typeof timerId === "object") {
998             timerId = timerId.id
999         }
1000         if (timerId in clock.timers) {
1001             delete clock.timers[timerId];
1002         }
1003     };
1005     clock.setInterval = function setInterval(func, timeout) {
1006         return addTimer(clock, {
1007             func: func,
1008             args: Array.prototype.slice.call(arguments, 2),
1009             delay: timeout,
1010             interval: timeout
1011         });
1012     };
1014     clock.clearInterval = function clearInterval(timerId) {
1015         clock.clearTimeout(timerId);
1016     };
1018     clock.setImmediate = function setImmediate(func) {
1019         return addTimer(clock, {
1020             func: func,
1021             args: Array.prototype.slice.call(arguments, 1),
1022             immediate: true
1023         });
1024     };
1026     clock.clearImmediate = function clearImmediate(timerId) {
1027         clock.clearTimeout(timerId);
1028     };
1030     clock.tick = function tick(ms) {
1031         ms = typeof ms == "number" ? ms : parseTime(ms);
1032         var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
1033         var timer = firstTimerInRange(clock, tickFrom, tickTo);
1035         var firstException;
1036         while (timer && tickFrom <= tickTo) {
1037             if (clock.timers[timer.id]) {
1038                 tickFrom = clock.now = timer.callAt;
1039                 try {
1040                     callTimer(clock, timer);
1041                 } catch (e) {
1042                     firstException = firstException || e;
1043                 }
1044             }
1046             timer = firstTimerInRange(clock, previous, tickTo);
1047             previous = tickFrom;
1048         }
1050         clock.now = tickTo;
1052         if (firstException) {
1053             throw firstException;
1054         }
1056         return clock.now;
1057     };
1059     clock.reset = function reset() {
1060         clock.timers = {};
1061     };
1063     return clock;
1066 exports.install = function install(target, now, toFake) {
1067     if (typeof target === "number") {
1068         toFake = now;
1069         now = target;
1070         target = null;
1071     }
1073     if (!target) {
1074         target = global;
1075     }
1077     var clock = createClock(now);
1079     clock.uninstall = function () {
1080         uninstall(clock, target);
1081     };
1083     clock.methods = toFake || [];
1085     if (clock.methods.length === 0) {
1086         clock.methods = keys(timers);
1087     }
1089     for (var i = 0, l = clock.methods.length; i < l; i++) {
1090         hijackMethod(target, clock.methods[i], clock);
1091     }
1093     return clock;
1096 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1097 },{}]},{},[1])(1)
1099   })();
1100   var define;
1102  * Sinon core utilities. For internal use only.
1104  * @author Christian Johansen (christian@cjohansen.no)
1105  * @license BSD
1107  * Copyright (c) 2010-2013 Christian Johansen
1108  */
1110 var sinon = (function () {
1111 "use strict";
1113     var sinon;
1114     var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1115     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1117     function loadDependencies(require, exports, module) {
1118         sinon = module.exports = require("./sinon/util/core");
1119         require("./sinon/extend");
1120         require("./sinon/typeOf");
1121         require("./sinon/times_in_words");
1122         require("./sinon/spy");
1123         require("./sinon/call");
1124         require("./sinon/behavior");
1125         require("./sinon/stub");
1126         require("./sinon/mock");
1127         require("./sinon/collection");
1128         require("./sinon/assert");
1129         require("./sinon/sandbox");
1130         require("./sinon/test");
1131         require("./sinon/test_case");
1132         require("./sinon/match");
1133         require("./sinon/format");
1134         require("./sinon/log_error");
1135     }
1137     if (isAMD) {
1138         define(loadDependencies);
1139     } else if (isNode) {
1140         loadDependencies(require, module.exports, module);
1141         sinon = module.exports;
1142     } else {
1143         sinon = {};
1144     }
1146     return sinon;
1147 }());
1150  * @depend ../../sinon.js
1151  */
1153  * Sinon core utilities. For internal use only.
1155  * @author Christian Johansen (christian@cjohansen.no)
1156  * @license BSD
1158  * Copyright (c) 2010-2013 Christian Johansen
1159  */
1161 (function (sinon) {
1162     var div = typeof document != "undefined" && document.createElement("div");
1163     var hasOwn = Object.prototype.hasOwnProperty;
1165     function isDOMNode(obj) {
1166         var success = false;
1168         try {
1169             obj.appendChild(div);
1170             success = div.parentNode == obj;
1171         } catch (e) {
1172             return false;
1173         } finally {
1174             try {
1175                 obj.removeChild(div);
1176             } catch (e) {
1177                 // Remove failed, not much we can do about that
1178             }
1179         }
1181         return success;
1182     }
1184     function isElement(obj) {
1185         return div && obj && obj.nodeType === 1 && isDOMNode(obj);
1186     }
1188     function isFunction(obj) {
1189         return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
1190     }
1192     function isReallyNaN(val) {
1193         return typeof val === "number" && isNaN(val);
1194     }
1196     function mirrorProperties(target, source) {
1197         for (var prop in source) {
1198             if (!hasOwn.call(target, prop)) {
1199                 target[prop] = source[prop];
1200             }
1201         }
1202     }
1204     function isRestorable(obj) {
1205         return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
1206     }
1208     // Cheap way to detect if we have ES5 support.
1209     var hasES5Support = "keys" in Object;
1211     function makeApi(sinon) {
1212         sinon.wrapMethod = function wrapMethod(object, property, method) {
1213             if (!object) {
1214                 throw new TypeError("Should wrap property of object");
1215             }
1217             if (typeof method != "function" && typeof method != "object") {
1218                 throw new TypeError("Method wrapper should be a function or a property descriptor");
1219             }
1221             function checkWrappedMethod(wrappedMethod) {
1222                 if (!isFunction(wrappedMethod)) {
1223                     error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
1224                                         property + " as function");
1225                 } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
1226                     error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
1227                 } else if (wrappedMethod.calledBefore) {
1228                     var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
1229                     error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
1230                 }
1232                 if (error) {
1233                     if (wrappedMethod && wrappedMethod.stackTrace) {
1234                         error.stack += "\n--------------\n" + wrappedMethod.stackTrace;
1235                     }
1236                     throw error;
1237                 }
1238             }
1240             var error, wrappedMethod;
1242             // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
1243             // when using hasOwn.call on objects from other frames.
1244             var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
1246             if (hasES5Support) {
1247                 var methodDesc = (typeof method == "function") ? {value: method} : method,
1248                     wrappedMethodDesc = sinon.getPropertyDescriptor(object, property),
1249                     i;
1251                 if (!wrappedMethodDesc) {
1252                     error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
1253                                         property + " as function");
1254                 } else if (wrappedMethodDesc.restore && wrappedMethodDesc.restore.sinon) {
1255                     error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
1256                 }
1257                 if (error) {
1258                     if (wrappedMethodDesc && wrappedMethodDesc.stackTrace) {
1259                         error.stack += "\n--------------\n" + wrappedMethodDesc.stackTrace;
1260                     }
1261                     throw error;
1262                 }
1264                 var types = sinon.objectKeys(methodDesc);
1265                 for (i = 0; i < types.length; i++) {
1266                     wrappedMethod = wrappedMethodDesc[types[i]];
1267                     checkWrappedMethod(wrappedMethod);
1268                 }
1270                 mirrorProperties(methodDesc, wrappedMethodDesc);
1271                 for (i = 0; i < types.length; i++) {
1272                     mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]);
1273                 }
1274                 Object.defineProperty(object, property, methodDesc);
1275             } else {
1276                 wrappedMethod = object[property];
1277                 checkWrappedMethod(wrappedMethod);
1278                 object[property] = method;
1279                 method.displayName = property;
1280             }
1282             method.displayName = property;
1284             // Set up a stack trace which can be used later to find what line of
1285             // code the original method was created on.
1286             method.stackTrace = (new Error("Stack Trace for original")).stack;
1288             method.restore = function () {
1289                 // For prototype properties try to reset by delete first.
1290                 // If this fails (ex: localStorage on mobile safari) then force a reset
1291                 // via direct assignment.
1292                 if (!owned) {
1293                     // In some cases `delete` may throw an error
1294                     try {
1295                         delete object[property];
1296                     } catch (e) {}
1297                     // For native code functions `delete` fails without throwing an error
1298                     // on Chrome < 43, PhantomJS, etc.
1299                 } else if (hasES5Support) {
1300                     Object.defineProperty(object, property, wrappedMethodDesc);
1301                 }
1303                 // Use strict equality comparison to check failures then force a reset
1304                 // via direct assignment.
1305                 if (object[property] === method) {
1306                     object[property] = wrappedMethod;
1307                 }
1308             };
1310             method.restore.sinon = true;
1312             if (!hasES5Support) {
1313                 mirrorProperties(method, wrappedMethod);
1314             }
1316             return method;
1317         };
1319         sinon.create = function create(proto) {
1320             var F = function () {};
1321             F.prototype = proto;
1322             return new F();
1323         };
1325         sinon.deepEqual = function deepEqual(a, b) {
1326             if (sinon.match && sinon.match.isMatcher(a)) {
1327                 return a.test(b);
1328             }
1330             if (typeof a != "object" || typeof b != "object") {
1331                 if (isReallyNaN(a) && isReallyNaN(b)) {
1332                     return true;
1333                 } else {
1334                     return a === b;
1335                 }
1336             }
1338             if (isElement(a) || isElement(b)) {
1339                 return a === b;
1340             }
1342             if (a === b) {
1343                 return true;
1344             }
1346             if ((a === null && b !== null) || (a !== null && b === null)) {
1347                 return false;
1348             }
1350             if (a instanceof RegExp && b instanceof RegExp) {
1351                 return (a.source === b.source) && (a.global === b.global) &&
1352                     (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
1353             }
1355             var aString = Object.prototype.toString.call(a);
1356             if (aString != Object.prototype.toString.call(b)) {
1357                 return false;
1358             }
1360             if (aString == "[object Date]") {
1361                 return a.valueOf() === b.valueOf();
1362             }
1364             var prop, aLength = 0, bLength = 0;
1366             if (aString == "[object Array]" && a.length !== b.length) {
1367                 return false;
1368             }
1370             for (prop in a) {
1371                 aLength += 1;
1373                 if (!(prop in b)) {
1374                     return false;
1375                 }
1377                 if (!deepEqual(a[prop], b[prop])) {
1378                     return false;
1379                 }
1380             }
1382             for (prop in b) {
1383                 bLength += 1;
1384             }
1386             return aLength == bLength;
1387         };
1389         sinon.functionName = function functionName(func) {
1390             var name = func.displayName || func.name;
1392             // Use function decomposition as a last resort to get function
1393             // name. Does not rely on function decomposition to work - if it
1394             // doesn't debugging will be slightly less informative
1395             // (i.e. toString will say 'spy' rather than 'myFunc').
1396             if (!name) {
1397                 var matches = func.toString().match(/function ([^\s\(]+)/);
1398                 name = matches && matches[1];
1399             }
1401             return name;
1402         };
1404         sinon.functionToString = function toString() {
1405             if (this.getCall && this.callCount) {
1406                 var thisValue, prop, i = this.callCount;
1408                 while (i--) {
1409                     thisValue = this.getCall(i).thisValue;
1411                     for (prop in thisValue) {
1412                         if (thisValue[prop] === this) {
1413                             return prop;
1414                         }
1415                     }
1416                 }
1417             }
1419             return this.displayName || "sinon fake";
1420         };
1422         sinon.objectKeys = function objectKeys(obj) {
1423             if (obj !== Object(obj)) {
1424                 throw new TypeError("sinon.objectKeys called on a non-object");
1425             }
1427             var keys = [];
1428             var key;
1429             for (key in obj) {
1430                 if (hasOwn.call(obj, key)) {
1431                     keys.push(key);
1432                 }
1433             }
1435             return keys;
1436         };
1438         sinon.getPropertyDescriptor = function getPropertyDescriptor(object, property) {
1439             var proto = object, descriptor;
1440             while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
1441                 proto = Object.getPrototypeOf(proto);
1442             }
1443             return descriptor;
1444         }
1446         sinon.getConfig = function (custom) {
1447             var config = {};
1448             custom = custom || {};
1449             var defaults = sinon.defaultConfig;
1451             for (var prop in defaults) {
1452                 if (defaults.hasOwnProperty(prop)) {
1453                     config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
1454                 }
1455             }
1457             return config;
1458         };
1460         sinon.defaultConfig = {
1461             injectIntoThis: true,
1462             injectInto: null,
1463             properties: ["spy", "stub", "mock", "clock", "server", "requests"],
1464             useFakeTimers: true,
1465             useFakeServer: true
1466         };
1468         sinon.timesInWords = function timesInWords(count) {
1469             return count == 1 && "once" ||
1470                 count == 2 && "twice" ||
1471                 count == 3 && "thrice" ||
1472                 (count || 0) + " times";
1473         };
1475         sinon.calledInOrder = function (spies) {
1476             for (var i = 1, l = spies.length; i < l; i++) {
1477                 if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
1478                     return false;
1479                 }
1480             }
1482             return true;
1483         };
1485         sinon.orderByFirstCall = function (spies) {
1486             return spies.sort(function (a, b) {
1487                 // uuid, won't ever be equal
1488                 var aCall = a.getCall(0);
1489                 var bCall = b.getCall(0);
1490                 var aId = aCall && aCall.callId || -1;
1491                 var bId = bCall && bCall.callId || -1;
1493                 return aId < bId ? -1 : 1;
1494             });
1495         };
1497         sinon.createStubInstance = function (constructor) {
1498             if (typeof constructor !== "function") {
1499                 throw new TypeError("The constructor should be a function.");
1500             }
1501             return sinon.stub(sinon.create(constructor.prototype));
1502         };
1504         sinon.restore = function (object) {
1505             if (object !== null && typeof object === "object") {
1506                 for (var prop in object) {
1507                     if (isRestorable(object[prop])) {
1508                         object[prop].restore();
1509                     }
1510                 }
1511             } else if (isRestorable(object)) {
1512                 object.restore();
1513             }
1514         };
1516         return sinon;
1517     }
1519     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
1520     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1522     function loadDependencies(require, exports) {
1523         makeApi(exports);
1524     }
1526     if (isAMD) {
1527         define(loadDependencies);
1528     } else if (isNode) {
1529         loadDependencies(require, module.exports);
1530     } else if (!sinon) {
1531         return;
1532     } else {
1533         makeApi(sinon);
1534     }
1535 }(typeof sinon == "object" && sinon || null));
1538  * @depend util/core.js
1539  */
1541 (function (sinon) {
1542     function makeApi(sinon) {
1544         // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
1545         var hasDontEnumBug = (function () {
1546             var obj = {
1547                 constructor: function () {
1548                     return "0";
1549                 },
1550                 toString: function () {
1551                     return "1";
1552                 },
1553                 valueOf: function () {
1554                     return "2";
1555                 },
1556                 toLocaleString: function () {
1557                     return "3";
1558                 },
1559                 prototype: function () {
1560                     return "4";
1561                 },
1562                 isPrototypeOf: function () {
1563                     return "5";
1564                 },
1565                 propertyIsEnumerable: function () {
1566                     return "6";
1567                 },
1568                 hasOwnProperty: function () {
1569                     return "7";
1570                 },
1571                 length: function () {
1572                     return "8";
1573                 },
1574                 unique: function () {
1575                     return "9"
1576                 }
1577             };
1579             var result = [];
1580             for (var prop in obj) {
1581                 result.push(obj[prop]());
1582             }
1583             return result.join("") !== "0123456789";
1584         })();
1586         /* Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will
1587          *         override properties in previous sources.
1588          *
1589          * target - The Object to extend
1590          * sources - Objects to copy properties from.
1591          *
1592          * Returns the extended target
1593          */
1594         function extend(target /*, sources */) {
1595             var sources = Array.prototype.slice.call(arguments, 1),
1596                 source, i, prop;
1598             for (i = 0; i < sources.length; i++) {
1599                 source = sources[i];
1601                 for (prop in source) {
1602                     if (source.hasOwnProperty(prop)) {
1603                         target[prop] = source[prop];
1604                     }
1605                 }
1607                 // Make sure we copy (own) toString method even when in JScript with DontEnum bug
1608                 // See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
1609                 if (hasDontEnumBug && source.hasOwnProperty("toString") && source.toString !== target.toString) {
1610                     target.toString = source.toString;
1611                 }
1612             }
1614             return target;
1615         };
1617         sinon.extend = extend;
1618         return sinon.extend;
1619     }
1621     function loadDependencies(require, exports, module) {
1622         var sinon = require("./util/core");
1623         module.exports = makeApi(sinon);
1624     }
1626     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
1627     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1629     if (isAMD) {
1630         define(loadDependencies);
1631     } else if (isNode) {
1632         loadDependencies(require, module.exports, module);
1633     } else if (!sinon) {
1634         return;
1635     } else {
1636         makeApi(sinon);
1637     }
1638 }(typeof sinon == "object" && sinon || null));
1641  * @depend util/core.js
1642  */
1644 (function (sinon) {
1645     function makeApi(sinon) {
1647         function timesInWords(count) {
1648             switch (count) {
1649                 case 1:
1650                     return "once";
1651                 case 2:
1652                     return "twice";
1653                 case 3:
1654                     return "thrice";
1655                 default:
1656                     return (count || 0) + " times";
1657             }
1658         }
1660         sinon.timesInWords = timesInWords;
1661         return sinon.timesInWords;
1662     }
1664     function loadDependencies(require, exports, module) {
1665         var sinon = require("./util/core");
1666         module.exports = makeApi(sinon);
1667     }
1669     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
1670     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1672     if (isAMD) {
1673         define(loadDependencies);
1674     } else if (isNode) {
1675         loadDependencies(require, module.exports, module);
1676     } else if (!sinon) {
1677         return;
1678     } else {
1679         makeApi(sinon);
1680     }
1681 }(typeof sinon == "object" && sinon || null));
1684  * @depend util/core.js
1685  */
1687  * Format functions
1689  * @author Christian Johansen (christian@cjohansen.no)
1690  * @license BSD
1692  * Copyright (c) 2010-2014 Christian Johansen
1693  */
1695 (function (sinon, formatio) {
1696     function makeApi(sinon) {
1697         function typeOf(value) {
1698             if (value === null) {
1699                 return "null";
1700             } else if (value === undefined) {
1701                 return "undefined";
1702             }
1703             var string = Object.prototype.toString.call(value);
1704             return string.substring(8, string.length - 1).toLowerCase();
1705         };
1707         sinon.typeOf = typeOf;
1708         return sinon.typeOf;
1709     }
1711     function loadDependencies(require, exports, module) {
1712         var sinon = require("./util/core");
1713         module.exports = makeApi(sinon);
1714     }
1716     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
1717     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1719     if (isAMD) {
1720         define(loadDependencies);
1721     } else if (isNode) {
1722         loadDependencies(require, module.exports, module);
1723     } else if (!sinon) {
1724         return;
1725     } else {
1726         makeApi(sinon);
1727     }
1729     (typeof sinon == "object" && sinon || null),
1730     (typeof formatio == "object" && formatio)
1734  * @depend util/core.js
1735  * @depend typeOf.js
1736  */
1737 /*jslint eqeqeq: false, onevar: false, plusplus: false*/
1738 /*global module, require, sinon*/
1740  * Match functions
1742  * @author Maximilian Antoni (mail@maxantoni.de)
1743  * @license BSD
1745  * Copyright (c) 2012 Maximilian Antoni
1746  */
1748 (function (sinon) {
1749     function makeApi(sinon) {
1750         function assertType(value, type, name) {
1751             var actual = sinon.typeOf(value);
1752             if (actual !== type) {
1753                 throw new TypeError("Expected type of " + name + " to be " +
1754                     type + ", but was " + actual);
1755             }
1756         }
1758         var matcher = {
1759             toString: function () {
1760                 return this.message;
1761             }
1762         };
1764         function isMatcher(object) {
1765             return matcher.isPrototypeOf(object);
1766         }
1768         function matchObject(expectation, actual) {
1769             if (actual === null || actual === undefined) {
1770                 return false;
1771             }
1772             for (var key in expectation) {
1773                 if (expectation.hasOwnProperty(key)) {
1774                     var exp = expectation[key];
1775                     var act = actual[key];
1776                     if (match.isMatcher(exp)) {
1777                         if (!exp.test(act)) {
1778                             return false;
1779                         }
1780                     } else if (sinon.typeOf(exp) === "object") {
1781                         if (!matchObject(exp, act)) {
1782                             return false;
1783                         }
1784                     } else if (!sinon.deepEqual(exp, act)) {
1785                         return false;
1786                     }
1787                 }
1788             }
1789             return true;
1790         }
1792         matcher.or = function (m2) {
1793             if (!arguments.length) {
1794                 throw new TypeError("Matcher expected");
1795             } else if (!isMatcher(m2)) {
1796                 m2 = match(m2);
1797             }
1798             var m1 = this;
1799             var or = sinon.create(matcher);
1800             or.test = function (actual) {
1801                 return m1.test(actual) || m2.test(actual);
1802             };
1803             or.message = m1.message + ".or(" + m2.message + ")";
1804             return or;
1805         };
1807         matcher.and = function (m2) {
1808             if (!arguments.length) {
1809                 throw new TypeError("Matcher expected");
1810             } else if (!isMatcher(m2)) {
1811                 m2 = match(m2);
1812             }
1813             var m1 = this;
1814             var and = sinon.create(matcher);
1815             and.test = function (actual) {
1816                 return m1.test(actual) && m2.test(actual);
1817             };
1818             and.message = m1.message + ".and(" + m2.message + ")";
1819             return and;
1820         };
1822         var match = function (expectation, message) {
1823             var m = sinon.create(matcher);
1824             var type = sinon.typeOf(expectation);
1825             switch (type) {
1826             case "object":
1827                 if (typeof expectation.test === "function") {
1828                     m.test = function (actual) {
1829                         return expectation.test(actual) === true;
1830                     };
1831                     m.message = "match(" + sinon.functionName(expectation.test) + ")";
1832                     return m;
1833                 }
1834                 var str = [];
1835                 for (var key in expectation) {
1836                     if (expectation.hasOwnProperty(key)) {
1837                         str.push(key + ": " + expectation[key]);
1838                     }
1839                 }
1840                 m.test = function (actual) {
1841                     return matchObject(expectation, actual);
1842                 };
1843                 m.message = "match(" + str.join(", ") + ")";
1844                 break;
1845             case "number":
1846                 m.test = function (actual) {
1847                     return expectation == actual;
1848                 };
1849                 break;
1850             case "string":
1851                 m.test = function (actual) {
1852                     if (typeof actual !== "string") {
1853                         return false;
1854                     }
1855                     return actual.indexOf(expectation) !== -1;
1856                 };
1857                 m.message = "match(\"" + expectation + "\")";
1858                 break;
1859             case "regexp":
1860                 m.test = function (actual) {
1861                     if (typeof actual !== "string") {
1862                         return false;
1863                     }
1864                     return expectation.test(actual);
1865                 };
1866                 break;
1867             case "function":
1868                 m.test = expectation;
1869                 if (message) {
1870                     m.message = message;
1871                 } else {
1872                     m.message = "match(" + sinon.functionName(expectation) + ")";
1873                 }
1874                 break;
1875             default:
1876                 m.test = function (actual) {
1877                     return sinon.deepEqual(expectation, actual);
1878                 };
1879             }
1880             if (!m.message) {
1881                 m.message = "match(" + expectation + ")";
1882             }
1883             return m;
1884         };
1886         match.isMatcher = isMatcher;
1888         match.any = match(function () {
1889             return true;
1890         }, "any");
1892         match.defined = match(function (actual) {
1893             return actual !== null && actual !== undefined;
1894         }, "defined");
1896         match.truthy = match(function (actual) {
1897             return !!actual;
1898         }, "truthy");
1900         match.falsy = match(function (actual) {
1901             return !actual;
1902         }, "falsy");
1904         match.same = function (expectation) {
1905             return match(function (actual) {
1906                 return expectation === actual;
1907             }, "same(" + expectation + ")");
1908         };
1910         match.typeOf = function (type) {
1911             assertType(type, "string", "type");
1912             return match(function (actual) {
1913                 return sinon.typeOf(actual) === type;
1914             }, "typeOf(\"" + type + "\")");
1915         };
1917         match.instanceOf = function (type) {
1918             assertType(type, "function", "type");
1919             return match(function (actual) {
1920                 return actual instanceof type;
1921             }, "instanceOf(" + sinon.functionName(type) + ")");
1922         };
1924         function createPropertyMatcher(propertyTest, messagePrefix) {
1925             return function (property, value) {
1926                 assertType(property, "string", "property");
1927                 var onlyProperty = arguments.length === 1;
1928                 var message = messagePrefix + "(\"" + property + "\"";
1929                 if (!onlyProperty) {
1930                     message += ", " + value;
1931                 }
1932                 message += ")";
1933                 return match(function (actual) {
1934                     if (actual === undefined || actual === null ||
1935                             !propertyTest(actual, property)) {
1936                         return false;
1937                     }
1938                     return onlyProperty || sinon.deepEqual(value, actual[property]);
1939                 }, message);
1940             };
1941         }
1943         match.has = createPropertyMatcher(function (actual, property) {
1944             if (typeof actual === "object") {
1945                 return property in actual;
1946             }
1947             return actual[property] !== undefined;
1948         }, "has");
1950         match.hasOwn = createPropertyMatcher(function (actual, property) {
1951             return actual.hasOwnProperty(property);
1952         }, "hasOwn");
1954         match.bool = match.typeOf("boolean");
1955         match.number = match.typeOf("number");
1956         match.string = match.typeOf("string");
1957         match.object = match.typeOf("object");
1958         match.func = match.typeOf("function");
1959         match.array = match.typeOf("array");
1960         match.regexp = match.typeOf("regexp");
1961         match.date = match.typeOf("date");
1963         sinon.match = match;
1964         return match;
1965     }
1967     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
1968     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1970     function loadDependencies(require, exports, module) {
1971         var sinon = require("./util/core");
1972         require("./typeOf");
1973         module.exports = makeApi(sinon);
1974     }
1976     if (isAMD) {
1977         define(loadDependencies);
1978     } else if (isNode) {
1979         loadDependencies(require, module.exports, module);
1980     } else if (!sinon) {
1981         return;
1982     } else {
1983         makeApi(sinon);
1984     }
1985 }(typeof sinon == "object" && sinon || null));
1988  * @depend util/core.js
1989  */
1991  * Format functions
1993  * @author Christian Johansen (christian@cjohansen.no)
1994  * @license BSD
1996  * Copyright (c) 2010-2014 Christian Johansen
1997  */
1999 (function (sinon, formatio) {
2000     function makeApi(sinon) {
2001         function valueFormatter(value) {
2002             return "" + value;
2003         }
2005         function getFormatioFormatter() {
2006             var formatter = formatio.configure({
2007                     quoteStrings: false,
2008                     limitChildrenCount: 250
2009                 });
2011             function format() {
2012                 return formatter.ascii.apply(formatter, arguments);
2013             };
2015             return format;
2016         }
2018         function getNodeFormatter(value) {
2019             function format(value) {
2020                 return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
2021             };
2023             try {
2024                 var util = require("util");
2025             } catch (e) {
2026                 /* Node, but no util module - would be very old, but better safe than sorry */
2027             }
2029             return util ? format : valueFormatter;
2030         }
2032         var isNode = typeof module !== "undefined" && module.exports && typeof require == "function",
2033             formatter;
2035         if (isNode) {
2036             try {
2037                 formatio = require("formatio");
2038             } catch (e) {}
2039         }
2041         if (formatio) {
2042             formatter = getFormatioFormatter()
2043         } else if (isNode) {
2044             formatter = getNodeFormatter();
2045         } else {
2046             formatter = valueFormatter;
2047         }
2049         sinon.format = formatter;
2050         return sinon.format;
2051     }
2053     function loadDependencies(require, exports, module) {
2054         var sinon = require("./util/core");
2055         module.exports = makeApi(sinon);
2056     }
2058     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
2059     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2061     if (isAMD) {
2062         define(loadDependencies);
2063     } else if (isNode) {
2064         loadDependencies(require, module.exports, module);
2065     } else if (!sinon) {
2066         return;
2067     } else {
2068         makeApi(sinon);
2069     }
2071     (typeof sinon == "object" && sinon || null),
2072     (typeof formatio == "object" && formatio)
2076   * @depend util/core.js
2077   * @depend match.js
2078   * @depend format.js
2079   */
2081   * Spy calls
2082   *
2083   * @author Christian Johansen (christian@cjohansen.no)
2084   * @author Maximilian Antoni (mail@maxantoni.de)
2085   * @license BSD
2086   *
2087   * Copyright (c) 2010-2013 Christian Johansen
2088   * Copyright (c) 2013 Maximilian Antoni
2089   */
2091 (function (sinon) {
2092     function makeApi(sinon) {
2093         function throwYieldError(proxy, text, args) {
2094             var msg = sinon.functionName(proxy) + text;
2095             if (args.length) {
2096                 msg += " Received [" + slice.call(args).join(", ") + "]";
2097             }
2098             throw new Error(msg);
2099         }
2101         var slice = Array.prototype.slice;
2103         var callProto = {
2104             calledOn: function calledOn(thisValue) {
2105                 if (sinon.match && sinon.match.isMatcher(thisValue)) {
2106                     return thisValue.test(this.thisValue);
2107                 }
2108                 return this.thisValue === thisValue;
2109             },
2111             calledWith: function calledWith() {
2112                 var l = arguments.length;
2113                 if (l > this.args.length) {
2114                     return false;
2115                 }
2116                 for (var i = 0; i < l; i += 1) {
2117                     if (!sinon.deepEqual(arguments[i], this.args[i])) {
2118                         return false;
2119                     }
2120                 }
2122                 return true;
2123             },
2125             calledWithMatch: function calledWithMatch() {
2126                 var l = arguments.length;
2127                 if (l > this.args.length) {
2128                     return false;
2129                 }
2130                 for (var i = 0; i < l; i += 1) {
2131                     var actual = this.args[i];
2132                     var expectation = arguments[i];
2133                     if (!sinon.match || !sinon.match(expectation).test(actual)) {
2134                         return false;
2135                     }
2136                 }
2137                 return true;
2138             },
2140             calledWithExactly: function calledWithExactly() {
2141                 return arguments.length == this.args.length &&
2142                     this.calledWith.apply(this, arguments);
2143             },
2145             notCalledWith: function notCalledWith() {
2146                 return !this.calledWith.apply(this, arguments);
2147             },
2149             notCalledWithMatch: function notCalledWithMatch() {
2150                 return !this.calledWithMatch.apply(this, arguments);
2151             },
2153             returned: function returned(value) {
2154                 return sinon.deepEqual(value, this.returnValue);
2155             },
2157             threw: function threw(error) {
2158                 if (typeof error === "undefined" || !this.exception) {
2159                     return !!this.exception;
2160                 }
2162                 return this.exception === error || this.exception.name === error;
2163             },
2165             calledWithNew: function calledWithNew() {
2166                 return this.proxy.prototype && this.thisValue instanceof this.proxy;
2167             },
2169             calledBefore: function (other) {
2170                 return this.callId < other.callId;
2171             },
2173             calledAfter: function (other) {
2174                 return this.callId > other.callId;
2175             },
2177             callArg: function (pos) {
2178                 this.args[pos]();
2179             },
2181             callArgOn: function (pos, thisValue) {
2182                 this.args[pos].apply(thisValue);
2183             },
2185             callArgWith: function (pos) {
2186                 this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
2187             },
2189             callArgOnWith: function (pos, thisValue) {
2190                 var args = slice.call(arguments, 2);
2191                 this.args[pos].apply(thisValue, args);
2192             },
2194             yield: function () {
2195                 this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
2196             },
2198             yieldOn: function (thisValue) {
2199                 var args = this.args;
2200                 for (var i = 0, l = args.length; i < l; ++i) {
2201                     if (typeof args[i] === "function") {
2202                         args[i].apply(thisValue, slice.call(arguments, 1));
2203                         return;
2204                     }
2205                 }
2206                 throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
2207             },
2209             yieldTo: function (prop) {
2210                 this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
2211             },
2213             yieldToOn: function (prop, thisValue) {
2214                 var args = this.args;
2215                 for (var i = 0, l = args.length; i < l; ++i) {
2216                     if (args[i] && typeof args[i][prop] === "function") {
2217                         args[i][prop].apply(thisValue, slice.call(arguments, 2));
2218                         return;
2219                     }
2220                 }
2221                 throwYieldError(this.proxy, " cannot yield to '" + prop +
2222                     "' since no callback was passed.", args);
2223             },
2225             toString: function () {
2226                 var callStr = this.proxy.toString() + "(";
2227                 var args = [];
2229                 for (var i = 0, l = this.args.length; i < l; ++i) {
2230                     args.push(sinon.format(this.args[i]));
2231                 }
2233                 callStr = callStr + args.join(", ") + ")";
2235                 if (typeof this.returnValue != "undefined") {
2236                     callStr += " => " + sinon.format(this.returnValue);
2237                 }
2239                 if (this.exception) {
2240                     callStr += " !" + this.exception.name;
2242                     if (this.exception.message) {
2243                         callStr += "(" + this.exception.message + ")";
2244                     }
2245                 }
2247                 return callStr;
2248             }
2249         };
2251         callProto.invokeCallback = callProto.yield;
2253         function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
2254             if (typeof id !== "number") {
2255                 throw new TypeError("Call id is not a number");
2256             }
2257             var proxyCall = sinon.create(callProto);
2258             proxyCall.proxy = spy;
2259             proxyCall.thisValue = thisValue;
2260             proxyCall.args = args;
2261             proxyCall.returnValue = returnValue;
2262             proxyCall.exception = exception;
2263             proxyCall.callId = id;
2265             return proxyCall;
2266         }
2267         createSpyCall.toString = callProto.toString; // used by mocks
2269         sinon.spyCall = createSpyCall;
2270         return createSpyCall;
2271     }
2273     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
2274     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2276     function loadDependencies(require, exports, module) {
2277         var sinon = require("./util/core");
2278         require("./match");
2279         require("./format");
2280         module.exports = makeApi(sinon);
2281     }
2283     if (isAMD) {
2284         define(loadDependencies);
2285     } else if (isNode) {
2286         loadDependencies(require, module.exports, module);
2287     } else if (!sinon) {
2288         return;
2289     } else {
2290         makeApi(sinon);
2291     }
2292 }(typeof sinon == "object" && sinon || null));
2295   * @depend times_in_words.js
2296   * @depend util/core.js
2297   * @depend extend.js
2298   * @depend call.js
2299   * @depend format.js
2300   */
2302   * Spy functions
2303   *
2304   * @author Christian Johansen (christian@cjohansen.no)
2305   * @license BSD
2306   *
2307   * Copyright (c) 2010-2013 Christian Johansen
2308   */
2310 (function (sinon) {
2312     function makeApi(sinon) {
2313         var push = Array.prototype.push;
2314         var slice = Array.prototype.slice;
2315         var callId = 0;
2317         function spy(object, property, types) {
2318             if (!property && typeof object == "function") {
2319                 return spy.create(object);
2320             }
2322             if (!object && !property) {
2323                 return spy.create(function () { });
2324             }
2326             if (types) {
2327                 var methodDesc = sinon.getPropertyDescriptor(object, property);
2328                 for (var i = 0; i < types.length; i++) {
2329                     methodDesc[types[i]] = spy.create(methodDesc[types[i]]);
2330                 }
2331                 return sinon.wrapMethod(object, property, methodDesc);
2332             } else {
2333                 var method = object[property];
2334                 return sinon.wrapMethod(object, property, spy.create(method));
2335             }
2336         }
2338         function matchingFake(fakes, args, strict) {
2339             if (!fakes) {
2340                 return;
2341             }
2343             for (var i = 0, l = fakes.length; i < l; i++) {
2344                 if (fakes[i].matches(args, strict)) {
2345                     return fakes[i];
2346                 }
2347             }
2348         }
2350         function incrementCallCount() {
2351             this.called = true;
2352             this.callCount += 1;
2353             this.notCalled = false;
2354             this.calledOnce = this.callCount == 1;
2355             this.calledTwice = this.callCount == 2;
2356             this.calledThrice = this.callCount == 3;
2357         }
2359         function createCallProperties() {
2360             this.firstCall = this.getCall(0);
2361             this.secondCall = this.getCall(1);
2362             this.thirdCall = this.getCall(2);
2363             this.lastCall = this.getCall(this.callCount - 1);
2364         }
2366         var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
2367         function createProxy(func, proxyLength) {
2368             // Retain the function length:
2369             var p;
2370             if (proxyLength) {
2371                 eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) +
2372                     ") { return p.invoke(func, this, slice.call(arguments)); });");
2373             } else {
2374                 p = function proxy() {
2375                     return p.invoke(func, this, slice.call(arguments));
2376                 };
2377             }
2378             p.isSinonProxy = true;
2379             return p;
2380         }
2382         var uuid = 0;
2384         // Public API
2385         var spyApi = {
2386             reset: function () {
2387                 if (this.invoking) {
2388                     var err = new Error("Cannot reset Sinon function while invoking it. " +
2389                                         "Move the call to .reset outside of the callback.");
2390                     err.name = "InvalidResetException";
2391                     throw err;
2392                 }
2394                 this.called = false;
2395                 this.notCalled = true;
2396                 this.calledOnce = false;
2397                 this.calledTwice = false;
2398                 this.calledThrice = false;
2399                 this.callCount = 0;
2400                 this.firstCall = null;
2401                 this.secondCall = null;
2402                 this.thirdCall = null;
2403                 this.lastCall = null;
2404                 this.args = [];
2405                 this.returnValues = [];
2406                 this.thisValues = [];
2407                 this.exceptions = [];
2408                 this.callIds = [];
2409                 if (this.fakes) {
2410                     for (var i = 0; i < this.fakes.length; i++) {
2411                         this.fakes[i].reset();
2412                     }
2413                 }
2415                 return this;
2416             },
2418             create: function create(func, spyLength) {
2419                 var name;
2421                 if (typeof func != "function") {
2422                     func = function () { };
2423                 } else {
2424                     name = sinon.functionName(func);
2425                 }
2427                 if (!spyLength) {
2428                     spyLength = func.length;
2429                 }
2431                 var proxy = createProxy(func, spyLength);
2433                 sinon.extend(proxy, spy);
2434                 delete proxy.create;
2435                 sinon.extend(proxy, func);
2437                 proxy.reset();
2438                 proxy.prototype = func.prototype;
2439                 proxy.displayName = name || "spy";
2440                 proxy.toString = sinon.functionToString;
2441                 proxy.instantiateFake = sinon.spy.create;
2442                 proxy.id = "spy#" + uuid++;
2444                 return proxy;
2445             },
2447             invoke: function invoke(func, thisValue, args) {
2448                 var matching = matchingFake(this.fakes, args);
2449                 var exception, returnValue;
2451                 incrementCallCount.call(this);
2452                 push.call(this.thisValues, thisValue);
2453                 push.call(this.args, args);
2454                 push.call(this.callIds, callId++);
2456                 // Make call properties available from within the spied function:
2457                 createCallProperties.call(this);
2459                 try {
2460                     this.invoking = true;
2462                     if (matching) {
2463                         returnValue = matching.invoke(func, thisValue, args);
2464                     } else {
2465                         returnValue = (this.func || func).apply(thisValue, args);
2466                     }
2468                     var thisCall = this.getCall(this.callCount - 1);
2469                     if (thisCall.calledWithNew() && typeof returnValue !== "object") {
2470                         returnValue = thisValue;
2471                     }
2472                 } catch (e) {
2473                     exception = e;
2474                 } finally {
2475                     delete this.invoking;
2476                 }
2478                 push.call(this.exceptions, exception);
2479                 push.call(this.returnValues, returnValue);
2481                 // Make return value and exception available in the calls:
2482                 createCallProperties.call(this);
2484                 if (exception !== undefined) {
2485                     throw exception;
2486                 }
2488                 return returnValue;
2489             },
2491             named: function named(name) {
2492                 this.displayName = name;
2493                 return this;
2494             },
2496             getCall: function getCall(i) {
2497                 if (i < 0 || i >= this.callCount) {
2498                     return null;
2499                 }
2501                 return sinon.spyCall(this, this.thisValues[i], this.args[i],
2502                                         this.returnValues[i], this.exceptions[i],
2503                                         this.callIds[i]);
2504             },
2506             getCalls: function () {
2507                 var calls = [];
2508                 var i;
2510                 for (i = 0; i < this.callCount; i++) {
2511                     calls.push(this.getCall(i));
2512                 }
2514                 return calls;
2515             },
2517             calledBefore: function calledBefore(spyFn) {
2518                 if (!this.called) {
2519                     return false;
2520                 }
2522                 if (!spyFn.called) {
2523                     return true;
2524                 }
2526                 return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
2527             },
2529             calledAfter: function calledAfter(spyFn) {
2530                 if (!this.called || !spyFn.called) {
2531                     return false;
2532                 }
2534                 return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
2535             },
2537             withArgs: function () {
2538                 var args = slice.call(arguments);
2540                 if (this.fakes) {
2541                     var match = matchingFake(this.fakes, args, true);
2543                     if (match) {
2544                         return match;
2545                     }
2546                 } else {
2547                     this.fakes = [];
2548                 }
2550                 var original = this;
2551                 var fake = this.instantiateFake();
2552                 fake.matchingAguments = args;
2553                 fake.parent = this;
2554                 push.call(this.fakes, fake);
2556                 fake.withArgs = function () {
2557                     return original.withArgs.apply(original, arguments);
2558                 };
2560                 for (var i = 0; i < this.args.length; i++) {
2561                     if (fake.matches(this.args[i])) {
2562                         incrementCallCount.call(fake);
2563                         push.call(fake.thisValues, this.thisValues[i]);
2564                         push.call(fake.args, this.args[i]);
2565                         push.call(fake.returnValues, this.returnValues[i]);
2566                         push.call(fake.exceptions, this.exceptions[i]);
2567                         push.call(fake.callIds, this.callIds[i]);
2568                     }
2569                 }
2570                 createCallProperties.call(fake);
2572                 return fake;
2573             },
2575             matches: function (args, strict) {
2576                 var margs = this.matchingAguments;
2578                 if (margs.length <= args.length &&
2579                     sinon.deepEqual(margs, args.slice(0, margs.length))) {
2580                     return !strict || margs.length == args.length;
2581                 }
2582             },
2584             printf: function (format) {
2585                 var spy = this;
2586                 var args = slice.call(arguments, 1);
2587                 var formatter;
2589                 return (format || "").replace(/%(.)/g, function (match, specifyer) {
2590                     formatter = spyApi.formatters[specifyer];
2592                     if (typeof formatter == "function") {
2593                         return formatter.call(null, spy, args);
2594                     } else if (!isNaN(parseInt(specifyer, 10))) {
2595                         return sinon.format(args[specifyer - 1]);
2596                     }
2598                     return "%" + specifyer;
2599                 });
2600             }
2601         };
2603         function delegateToCalls(method, matchAny, actual, notCalled) {
2604             spyApi[method] = function () {
2605                 if (!this.called) {
2606                     if (notCalled) {
2607                         return notCalled.apply(this, arguments);
2608                     }
2609                     return false;
2610                 }
2612                 var currentCall;
2613                 var matches = 0;
2615                 for (var i = 0, l = this.callCount; i < l; i += 1) {
2616                     currentCall = this.getCall(i);
2618                     if (currentCall[actual || method].apply(currentCall, arguments)) {
2619                         matches += 1;
2621                         if (matchAny) {
2622                             return true;
2623                         }
2624                     }
2625                 }
2627                 return matches === this.callCount;
2628             };
2629         }
2631         delegateToCalls("calledOn", true);
2632         delegateToCalls("alwaysCalledOn", false, "calledOn");
2633         delegateToCalls("calledWith", true);
2634         delegateToCalls("calledWithMatch", true);
2635         delegateToCalls("alwaysCalledWith", false, "calledWith");
2636         delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
2637         delegateToCalls("calledWithExactly", true);
2638         delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
2639         delegateToCalls("neverCalledWith", false, "notCalledWith", function () {
2640             return true;
2641         });
2642         delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch", function () {
2643             return true;
2644         });
2645         delegateToCalls("threw", true);
2646         delegateToCalls("alwaysThrew", false, "threw");
2647         delegateToCalls("returned", true);
2648         delegateToCalls("alwaysReturned", false, "returned");
2649         delegateToCalls("calledWithNew", true);
2650         delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
2651         delegateToCalls("callArg", false, "callArgWith", function () {
2652             throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
2653         });
2654         spyApi.callArgWith = spyApi.callArg;
2655         delegateToCalls("callArgOn", false, "callArgOnWith", function () {
2656             throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
2657         });
2658         spyApi.callArgOnWith = spyApi.callArgOn;
2659         delegateToCalls("yield", false, "yield", function () {
2660             throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
2661         });
2662         // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
2663         spyApi.invokeCallback = spyApi.yield;
2664         delegateToCalls("yieldOn", false, "yieldOn", function () {
2665             throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
2666         });
2667         delegateToCalls("yieldTo", false, "yieldTo", function (property) {
2668             throw new Error(this.toString() + " cannot yield to '" + property +
2669                 "' since it was not yet invoked.");
2670         });
2671         delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
2672             throw new Error(this.toString() + " cannot yield to '" + property +
2673                 "' since it was not yet invoked.");
2674         });
2676         spyApi.formatters = {
2677             c: function (spy) {
2678                 return sinon.timesInWords(spy.callCount);
2679             },
2681             n: function (spy) {
2682                 return spy.toString();
2683             },
2685             C: function (spy) {
2686                 var calls = [];
2688                 for (var i = 0, l = spy.callCount; i < l; ++i) {
2689                     var stringifiedCall = "    " + spy.getCall(i).toString();
2690                     if (/\n/.test(calls[i - 1])) {
2691                         stringifiedCall = "\n" + stringifiedCall;
2692                     }
2693                     push.call(calls, stringifiedCall);
2694                 }
2696                 return calls.length > 0 ? "\n" + calls.join("\n") : "";
2697             },
2699             t: function (spy) {
2700                 var objects = [];
2702                 for (var i = 0, l = spy.callCount; i < l; ++i) {
2703                     push.call(objects, sinon.format(spy.thisValues[i]));
2704                 }
2706                 return objects.join(", ");
2707             },
2709             "*": function (spy, args) {
2710                 var formatted = [];
2712                 for (var i = 0, l = args.length; i < l; ++i) {
2713                     push.call(formatted, sinon.format(args[i]));
2714                 }
2716                 return formatted.join(", ");
2717             }
2718         };
2720         sinon.extend(spy, spyApi);
2722         spy.spyCall = sinon.spyCall;
2723         sinon.spy = spy;
2725         return spy;
2726     }
2728     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
2729     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2731     function loadDependencies(require, exports, module) {
2732         var sinon = require("./util/core");
2733         require("./call");
2734         require("./extend");
2735         require("./times_in_words");
2736         require("./format");
2737         module.exports = makeApi(sinon);
2738     }
2740     if (isAMD) {
2741         define(loadDependencies);
2742     } else if (isNode) {
2743         loadDependencies(require, module.exports, module);
2744     } else if (!sinon) {
2745         return;
2746     } else {
2747         makeApi(sinon);
2748     }
2749 }(typeof sinon == "object" && sinon || null));
2752  * @depend util/core.js
2753  * @depend extend.js
2754  */
2756  * Stub behavior
2758  * @author Christian Johansen (christian@cjohansen.no)
2759  * @author Tim Fischbach (mail@timfischbach.de)
2760  * @license BSD
2762  * Copyright (c) 2010-2013 Christian Johansen
2763  */
2765 (function (sinon) {
2766     var slice = Array.prototype.slice;
2767     var join = Array.prototype.join;
2768     var useLeftMostCallback = -1;
2769     var useRightMostCallback = -2;
2771     var nextTick = (function () {
2772         if (typeof process === "object" && typeof process.nextTick === "function") {
2773             return process.nextTick;
2774         } else if (typeof setImmediate === "function") {
2775             return setImmediate;
2776         } else {
2777             return function (callback) {
2778                 setTimeout(callback, 0);
2779             };
2780         }
2781     })();
2783     function throwsException(error, message) {
2784         if (typeof error == "string") {
2785             this.exception = new Error(message || "");
2786             this.exception.name = error;
2787         } else if (!error) {
2788             this.exception = new Error("Error");
2789         } else {
2790             this.exception = error;
2791         }
2793         return this;
2794     }
2796     function getCallback(behavior, args) {
2797         var callArgAt = behavior.callArgAt;
2799         if (callArgAt >= 0) {
2800             return args[callArgAt];
2801         }
2803         var argumentList;
2805         if (callArgAt === useLeftMostCallback) {
2806             argumentList = args;
2807         }
2809         if (callArgAt === useRightMostCallback) {
2810             argumentList = slice.call(args).reverse();
2811         }
2813         var callArgProp = behavior.callArgProp;
2815         for (var i = 0, l = argumentList.length; i < l; ++i) {
2816             if (!callArgProp && typeof argumentList[i] == "function") {
2817                 return argumentList[i];
2818             }
2820             if (callArgProp && argumentList[i] &&
2821                 typeof argumentList[i][callArgProp] == "function") {
2822                 return argumentList[i][callArgProp];
2823             }
2824         }
2826         return null;
2827     }
2829     function makeApi(sinon) {
2830         function getCallbackError(behavior, func, args) {
2831             if (behavior.callArgAt < 0) {
2832                 var msg;
2834                 if (behavior.callArgProp) {
2835                     msg = sinon.functionName(behavior.stub) +
2836                         " expected to yield to '" + behavior.callArgProp +
2837                         "', but no object with such a property was passed.";
2838                 } else {
2839                     msg = sinon.functionName(behavior.stub) +
2840                         " expected to yield, but no callback was passed.";
2841                 }
2843                 if (args.length > 0) {
2844                     msg += " Received [" + join.call(args, ", ") + "]";
2845                 }
2847                 return msg;
2848             }
2850             return "argument at index " + behavior.callArgAt + " is not a function: " + func;
2851         }
2853         function callCallback(behavior, args) {
2854             if (typeof behavior.callArgAt == "number") {
2855                 var func = getCallback(behavior, args);
2857                 if (typeof func != "function") {
2858                     throw new TypeError(getCallbackError(behavior, func, args));
2859                 }
2861                 if (behavior.callbackAsync) {
2862                     nextTick(function () {
2863                         func.apply(behavior.callbackContext, behavior.callbackArguments);
2864                     });
2865                 } else {
2866                     func.apply(behavior.callbackContext, behavior.callbackArguments);
2867                 }
2868             }
2869         }
2871         var proto = {
2872             create: function create(stub) {
2873                 var behavior = sinon.extend({}, sinon.behavior);
2874                 delete behavior.create;
2875                 behavior.stub = stub;
2877                 return behavior;
2878             },
2880             isPresent: function isPresent() {
2881                 return (typeof this.callArgAt == "number" ||
2882                         this.exception ||
2883                         typeof this.returnArgAt == "number" ||
2884                         this.returnThis ||
2885                         this.returnValueDefined);
2886             },
2888             invoke: function invoke(context, args) {
2889                 callCallback(this, args);
2891                 if (this.exception) {
2892                     throw this.exception;
2893                 } else if (typeof this.returnArgAt == "number") {
2894                     return args[this.returnArgAt];
2895                 } else if (this.returnThis) {
2896                     return context;
2897                 }
2899                 return this.returnValue;
2900             },
2902             onCall: function onCall(index) {
2903                 return this.stub.onCall(index);
2904             },
2906             onFirstCall: function onFirstCall() {
2907                 return this.stub.onFirstCall();
2908             },
2910             onSecondCall: function onSecondCall() {
2911                 return this.stub.onSecondCall();
2912             },
2914             onThirdCall: function onThirdCall() {
2915                 return this.stub.onThirdCall();
2916             },
2918             withArgs: function withArgs(/* arguments */) {
2919                 throw new Error("Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" is not supported. " +
2920                                 "Use \"stub.withArgs(...).onCall(...)\" to define sequential behavior for calls with certain arguments.");
2921             },
2923             callsArg: function callsArg(pos) {
2924                 if (typeof pos != "number") {
2925                     throw new TypeError("argument index is not number");
2926                 }
2928                 this.callArgAt = pos;
2929                 this.callbackArguments = [];
2930                 this.callbackContext = undefined;
2931                 this.callArgProp = undefined;
2932                 this.callbackAsync = false;
2934                 return this;
2935             },
2937             callsArgOn: function callsArgOn(pos, context) {
2938                 if (typeof pos != "number") {
2939                     throw new TypeError("argument index is not number");
2940                 }
2941                 if (typeof context != "object") {
2942                     throw new TypeError("argument context is not an object");
2943                 }
2945                 this.callArgAt = pos;
2946                 this.callbackArguments = [];
2947                 this.callbackContext = context;
2948                 this.callArgProp = undefined;
2949                 this.callbackAsync = false;
2951                 return this;
2952             },
2954             callsArgWith: function callsArgWith(pos) {
2955                 if (typeof pos != "number") {
2956                     throw new TypeError("argument index is not number");
2957                 }
2959                 this.callArgAt = pos;
2960                 this.callbackArguments = slice.call(arguments, 1);
2961                 this.callbackContext = undefined;
2962                 this.callArgProp = undefined;
2963                 this.callbackAsync = false;
2965                 return this;
2966             },
2968             callsArgOnWith: function callsArgWith(pos, context) {
2969                 if (typeof pos != "number") {
2970                     throw new TypeError("argument index is not number");
2971                 }
2972                 if (typeof context != "object") {
2973                     throw new TypeError("argument context is not an object");
2974                 }
2976                 this.callArgAt = pos;
2977                 this.callbackArguments = slice.call(arguments, 2);
2978                 this.callbackContext = context;
2979                 this.callArgProp = undefined;
2980                 this.callbackAsync = false;
2982                 return this;
2983             },
2985             yields: function () {
2986                 this.callArgAt = useLeftMostCallback;
2987                 this.callbackArguments = slice.call(arguments, 0);
2988                 this.callbackContext = undefined;
2989                 this.callArgProp = undefined;
2990                 this.callbackAsync = false;
2992                 return this;
2993             },
2995             yieldsRight: function () {
2996                 this.callArgAt = useRightMostCallback;
2997                 this.callbackArguments = slice.call(arguments, 0);
2998                 this.callbackContext = undefined;
2999                 this.callArgProp = undefined;
3000                 this.callbackAsync = false;
3002                 return this;
3003             },
3005             yieldsOn: function (context) {
3006                 if (typeof context != "object") {
3007                     throw new TypeError("argument context is not an object");
3008                 }
3010                 this.callArgAt = useLeftMostCallback;
3011                 this.callbackArguments = slice.call(arguments, 1);
3012                 this.callbackContext = context;
3013                 this.callArgProp = undefined;
3014                 this.callbackAsync = false;
3016                 return this;
3017             },
3019             yieldsTo: function (prop) {
3020                 this.callArgAt = useLeftMostCallback;
3021                 this.callbackArguments = slice.call(arguments, 1);
3022                 this.callbackContext = undefined;
3023                 this.callArgProp = prop;
3024                 this.callbackAsync = false;
3026                 return this;
3027             },
3029             yieldsToOn: function (prop, context) {
3030                 if (typeof context != "object") {
3031                     throw new TypeError("argument context is not an object");
3032                 }
3034                 this.callArgAt = useLeftMostCallback;
3035                 this.callbackArguments = slice.call(arguments, 2);
3036                 this.callbackContext = context;
3037                 this.callArgProp = prop;
3038                 this.callbackAsync = false;
3040                 return this;
3041             },
3043             throws: throwsException,
3044             throwsException: throwsException,
3046             returns: function returns(value) {
3047                 this.returnValue = value;
3048                 this.returnValueDefined = true;
3050                 return this;
3051             },
3053             returnsArg: function returnsArg(pos) {
3054                 if (typeof pos != "number") {
3055                     throw new TypeError("argument index is not number");
3056                 }
3058                 this.returnArgAt = pos;
3060                 return this;
3061             },
3063             returnsThis: function returnsThis() {
3064                 this.returnThis = true;
3066                 return this;
3067             }
3068         };
3070         // create asynchronous versions of callsArg* and yields* methods
3071         for (var method in proto) {
3072             // need to avoid creating anotherasync versions of the newly added async methods
3073             if (proto.hasOwnProperty(method) &&
3074                 method.match(/^(callsArg|yields)/) &&
3075                 !method.match(/Async/)) {
3076                 proto[method + "Async"] = (function (syncFnName) {
3077                     return function () {
3078                         var result = this[syncFnName].apply(this, arguments);
3079                         this.callbackAsync = true;
3080                         return result;
3081                     };
3082                 })(method);
3083             }
3084         }
3086         sinon.behavior = proto;
3087         return proto;
3088     }
3090     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
3091     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3093     function loadDependencies(require, exports, module) {
3094         var sinon = require("./util/core");
3095         require("./extend");
3096         module.exports = makeApi(sinon);
3097     }
3099     if (isAMD) {
3100         define(loadDependencies);
3101     } else if (isNode) {
3102         loadDependencies(require, module.exports, module);
3103     } else if (!sinon) {
3104         return;
3105     } else {
3106         makeApi(sinon);
3107     }
3108 }(typeof sinon == "object" && sinon || null));
3111  * @depend util/core.js
3112  * @depend extend.js
3113  * @depend spy.js
3114  * @depend behavior.js
3115  */
3117  * Stub functions
3119  * @author Christian Johansen (christian@cjohansen.no)
3120  * @license BSD
3122  * Copyright (c) 2010-2013 Christian Johansen
3123  */
3125 (function (sinon) {
3126     function makeApi(sinon) {
3127         function stub(object, property, func) {
3128             if (!!func && typeof func != "function" && typeof func != "object") {
3129                 throw new TypeError("Custom stub should be a function or a property descriptor");
3130             }
3132             var wrapper;
3134             if (func) {
3135                 if (typeof func == "function") {
3136                     wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
3137                 } else {
3138                     wrapper = func;
3139                     if (sinon.spy && sinon.spy.create) {
3140                         var types = sinon.objectKeys(wrapper);
3141                         for (var i = 0; i < types.length; i++) {
3142                             wrapper[types[i]] = sinon.spy.create(wrapper[types[i]]);
3143                         }
3144                     }
3145                 }
3146             } else {
3147                 var stubLength = 0;
3148                 if (typeof object == "object" && typeof object[property] == "function") {
3149                     stubLength = object[property].length;
3150                 }
3151                 wrapper = stub.create(stubLength);
3152             }
3154             if (!object && typeof property === "undefined") {
3155                 return sinon.stub.create();
3156             }
3158             if (typeof property === "undefined" && typeof object == "object") {
3159                 for (var prop in object) {
3160                     if (typeof sinon.getPropertyDescriptor(object, prop).value === "function") {
3161                         stub(object, prop);
3162                     }
3163                 }
3165                 return object;
3166             }
3168             return sinon.wrapMethod(object, property, wrapper);
3169         }
3171         function getDefaultBehavior(stub) {
3172             return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
3173         }
3175         function getParentBehaviour(stub) {
3176             return (stub.parent && getCurrentBehavior(stub.parent));
3177         }
3179         function getCurrentBehavior(stub) {
3180             var behavior = stub.behaviors[stub.callCount - 1];
3181             return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
3182         }
3184         var uuid = 0;
3186         var proto = {
3187             create: function create(stubLength) {
3188                 var functionStub = function () {
3189                     return getCurrentBehavior(functionStub).invoke(this, arguments);
3190                 };
3192                 functionStub.id = "stub#" + uuid++;
3193                 var orig = functionStub;
3194                 functionStub = sinon.spy.create(functionStub, stubLength);
3195                 functionStub.func = orig;
3197                 sinon.extend(functionStub, stub);
3198                 functionStub.instantiateFake = sinon.stub.create;
3199                 functionStub.displayName = "stub";
3200                 functionStub.toString = sinon.functionToString;
3202                 functionStub.defaultBehavior = null;
3203                 functionStub.behaviors = [];
3205                 return functionStub;
3206             },
3208             resetBehavior: function () {
3209                 var i;
3211                 this.defaultBehavior = null;
3212                 this.behaviors = [];
3214                 delete this.returnValue;
3215                 delete this.returnArgAt;
3216                 this.returnThis = false;
3218                 if (this.fakes) {
3219                     for (i = 0; i < this.fakes.length; i++) {
3220                         this.fakes[i].resetBehavior();
3221                     }
3222                 }
3223             },
3225             onCall: function onCall(index) {
3226                 if (!this.behaviors[index]) {
3227                     this.behaviors[index] = sinon.behavior.create(this);
3228                 }
3230                 return this.behaviors[index];
3231             },
3233             onFirstCall: function onFirstCall() {
3234                 return this.onCall(0);
3235             },
3237             onSecondCall: function onSecondCall() {
3238                 return this.onCall(1);
3239             },
3241             onThirdCall: function onThirdCall() {
3242                 return this.onCall(2);
3243             }
3244         };
3246         for (var method in sinon.behavior) {
3247             if (sinon.behavior.hasOwnProperty(method) &&
3248                 !proto.hasOwnProperty(method) &&
3249                 method != "create" &&
3250                 method != "withArgs" &&
3251                 method != "invoke") {
3252                 proto[method] = (function (behaviorMethod) {
3253                     return function () {
3254                         this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
3255                         this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
3256                         return this;
3257                     };
3258                 }(method));
3259             }
3260         }
3262         sinon.extend(stub, proto);
3263         sinon.stub = stub;
3265         return stub;
3266     }
3268     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
3269     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3271     function loadDependencies(require, exports, module) {
3272         var sinon = require("./util/core");
3273         require("./behavior");
3274         require("./spy");
3275         require("./extend");
3276         module.exports = makeApi(sinon);
3277     }
3279     if (isAMD) {
3280         define(loadDependencies);
3281     } else if (isNode) {
3282         loadDependencies(require, module.exports, module);
3283     } else if (!sinon) {
3284         return;
3285     } else {
3286         makeApi(sinon);
3287     }
3288 }(typeof sinon == "object" && sinon || null));
3291  * @depend times_in_words.js
3292  * @depend util/core.js
3293  * @depend call.js
3294  * @depend extend.js
3295  * @depend match.js
3296  * @depend spy.js
3297  * @depend stub.js
3298  * @depend format.js
3299  */
3301  * Mock functions.
3303  * @author Christian Johansen (christian@cjohansen.no)
3304  * @license BSD
3306  * Copyright (c) 2010-2013 Christian Johansen
3307  */
3309 (function (sinon) {
3310     function makeApi(sinon) {
3311         var push = [].push;
3312         var match = sinon.match;
3314         function mock(object) {
3315             // if (typeof console !== undefined && console.warn) {
3316             //     console.warn("mock will be removed from Sinon.JS v2.0");
3317             // }
3319             if (!object) {
3320                 return sinon.expectation.create("Anonymous mock");
3321             }
3323             return mock.create(object);
3324         }
3326         function each(collection, callback) {
3327             if (!collection) {
3328                 return;
3329             }
3331             for (var i = 0, l = collection.length; i < l; i += 1) {
3332                 callback(collection[i]);
3333             }
3334         }
3336         sinon.extend(mock, {
3337             create: function create(object) {
3338                 if (!object) {
3339                     throw new TypeError("object is null");
3340                 }
3342                 var mockObject = sinon.extend({}, mock);
3343                 mockObject.object = object;
3344                 delete mockObject.create;
3346                 return mockObject;
3347             },
3349             expects: function expects(method) {
3350                 if (!method) {
3351                     throw new TypeError("method is falsy");
3352                 }
3354                 if (!this.expectations) {
3355                     this.expectations = {};
3356                     this.proxies = [];
3357                 }
3359                 if (!this.expectations[method]) {
3360                     this.expectations[method] = [];
3361                     var mockObject = this;
3363                     sinon.wrapMethod(this.object, method, function () {
3364                         return mockObject.invokeMethod(method, this, arguments);
3365                     });
3367                     push.call(this.proxies, method);
3368                 }
3370                 var expectation = sinon.expectation.create(method);
3371                 push.call(this.expectations[method], expectation);
3373                 return expectation;
3374             },
3376             restore: function restore() {
3377                 var object = this.object;
3379                 each(this.proxies, function (proxy) {
3380                     if (typeof object[proxy].restore == "function") {
3381                         object[proxy].restore();
3382                     }
3383                 });
3384             },
3386             verify: function verify() {
3387                 var expectations = this.expectations || {};
3388                 var messages = [], met = [];
3390                 each(this.proxies, function (proxy) {
3391                     each(expectations[proxy], function (expectation) {
3392                         if (!expectation.met()) {
3393                             push.call(messages, expectation.toString());
3394                         } else {
3395                             push.call(met, expectation.toString());
3396                         }
3397                     });
3398                 });
3400                 this.restore();
3402                 if (messages.length > 0) {
3403                     sinon.expectation.fail(messages.concat(met).join("\n"));
3404                 } else if (met.length > 0) {
3405                     sinon.expectation.pass(messages.concat(met).join("\n"));
3406                 }
3408                 return true;
3409             },
3411             invokeMethod: function invokeMethod(method, thisValue, args) {
3412                 var expectations = this.expectations && this.expectations[method];
3413                 var length = expectations && expectations.length || 0, i;
3415                 for (i = 0; i < length; i += 1) {
3416                     if (!expectations[i].met() &&
3417                         expectations[i].allowsCall(thisValue, args)) {
3418                         return expectations[i].apply(thisValue, args);
3419                     }
3420                 }
3422                 var messages = [], available, exhausted = 0;
3424                 for (i = 0; i < length; i += 1) {
3425                     if (expectations[i].allowsCall(thisValue, args)) {
3426                         available = available || expectations[i];
3427                     } else {
3428                         exhausted += 1;
3429                     }
3430                     push.call(messages, "    " + expectations[i].toString());
3431                 }
3433                 if (exhausted === 0) {
3434                     return available.apply(thisValue, args);
3435                 }
3437                 messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
3438                     proxy: method,
3439                     args: args
3440                 }));
3442                 sinon.expectation.fail(messages.join("\n"));
3443             }
3444         });
3446         var times = sinon.timesInWords;
3447         var slice = Array.prototype.slice;
3449         function callCountInWords(callCount) {
3450             if (callCount == 0) {
3451                 return "never called";
3452             } else {
3453                 return "called " + times(callCount);
3454             }
3455         }
3457         function expectedCallCountInWords(expectation) {
3458             var min = expectation.minCalls;
3459             var max = expectation.maxCalls;
3461             if (typeof min == "number" && typeof max == "number") {
3462                 var str = times(min);
3464                 if (min != max) {
3465                     str = "at least " + str + " and at most " + times(max);
3466                 }
3468                 return str;
3469             }
3471             if (typeof min == "number") {
3472                 return "at least " + times(min);
3473             }
3475             return "at most " + times(max);
3476         }
3478         function receivedMinCalls(expectation) {
3479             var hasMinLimit = typeof expectation.minCalls == "number";
3480             return !hasMinLimit || expectation.callCount >= expectation.minCalls;
3481         }
3483         function receivedMaxCalls(expectation) {
3484             if (typeof expectation.maxCalls != "number") {
3485                 return false;
3486             }
3488             return expectation.callCount == expectation.maxCalls;
3489         }
3491         function verifyMatcher(possibleMatcher, arg) {
3492             if (match && match.isMatcher(possibleMatcher)) {
3493                 return possibleMatcher.test(arg);
3494             } else {
3495                 return true;
3496             }
3497         }
3499         sinon.expectation = {
3500             minCalls: 1,
3501             maxCalls: 1,
3503             create: function create(methodName) {
3504                 var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
3505                 delete expectation.create;
3506                 expectation.method = methodName;
3508                 return expectation;
3509             },
3511             invoke: function invoke(func, thisValue, args) {
3512                 this.verifyCallAllowed(thisValue, args);
3514                 return sinon.spy.invoke.apply(this, arguments);
3515             },
3517             atLeast: function atLeast(num) {
3518                 if (typeof num != "number") {
3519                     throw new TypeError("'" + num + "' is not number");
3520                 }
3522                 if (!this.limitsSet) {
3523                     this.maxCalls = null;
3524                     this.limitsSet = true;
3525                 }
3527                 this.minCalls = num;
3529                 return this;
3530             },
3532             atMost: function atMost(num) {
3533                 if (typeof num != "number") {
3534                     throw new TypeError("'" + num + "' is not number");
3535                 }
3537                 if (!this.limitsSet) {
3538                     this.minCalls = null;
3539                     this.limitsSet = true;
3540                 }
3542                 this.maxCalls = num;
3544                 return this;
3545             },
3547             never: function never() {
3548                 return this.exactly(0);
3549             },
3551             once: function once() {
3552                 return this.exactly(1);
3553             },
3555             twice: function twice() {
3556                 return this.exactly(2);
3557             },
3559             thrice: function thrice() {
3560                 return this.exactly(3);
3561             },
3563             exactly: function exactly(num) {
3564                 if (typeof num != "number") {
3565                     throw new TypeError("'" + num + "' is not a number");
3566                 }
3568                 this.atLeast(num);
3569                 return this.atMost(num);
3570             },
3572             met: function met() {
3573                 return !this.failed && receivedMinCalls(this);
3574             },
3576             verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
3577                 if (receivedMaxCalls(this)) {
3578                     this.failed = true;
3579                     sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
3580                 }
3582                 if ("expectedThis" in this && this.expectedThis !== thisValue) {
3583                     sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
3584                         this.expectedThis);
3585                 }
3587                 if (!("expectedArguments" in this)) {
3588                     return;
3589                 }
3591                 if (!args) {
3592                     sinon.expectation.fail(this.method + " received no arguments, expected " +
3593                         sinon.format(this.expectedArguments));
3594                 }
3596                 if (args.length < this.expectedArguments.length) {
3597                     sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
3598                         "), expected " + sinon.format(this.expectedArguments));
3599                 }
3601                 if (this.expectsExactArgCount &&
3602                     args.length != this.expectedArguments.length) {
3603                     sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
3604                         "), expected " + sinon.format(this.expectedArguments));
3605                 }
3607                 for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
3609                     if (!verifyMatcher(this.expectedArguments[i], args[i])) {
3610                         sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
3611                             ", didn't match " + this.expectedArguments.toString());
3612                     }
3614                     if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
3615                         sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
3616                             ", expected " + sinon.format(this.expectedArguments));
3617                     }
3618                 }
3619             },
3621             allowsCall: function allowsCall(thisValue, args) {
3622                 if (this.met() && receivedMaxCalls(this)) {
3623                     return false;
3624                 }
3626                 if ("expectedThis" in this && this.expectedThis !== thisValue) {
3627                     return false;
3628                 }
3630                 if (!("expectedArguments" in this)) {
3631                     return true;
3632                 }
3634                 args = args || [];
3636                 if (args.length < this.expectedArguments.length) {
3637                     return false;
3638                 }
3640                 if (this.expectsExactArgCount &&
3641                     args.length != this.expectedArguments.length) {
3642                     return false;
3643                 }
3645                 for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
3646                     if (!verifyMatcher(this.expectedArguments[i], args[i])) {
3647                         return false;
3648                     }
3650                     if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
3651                         return false;
3652                     }
3653                 }
3655                 return true;
3656             },
3658             withArgs: function withArgs() {
3659                 this.expectedArguments = slice.call(arguments);
3660                 return this;
3661             },
3663             withExactArgs: function withExactArgs() {
3664                 this.withArgs.apply(this, arguments);
3665                 this.expectsExactArgCount = true;
3666                 return this;
3667             },
3669             on: function on(thisValue) {
3670                 this.expectedThis = thisValue;
3671                 return this;
3672             },
3674             toString: function () {
3675                 var args = (this.expectedArguments || []).slice();
3677                 if (!this.expectsExactArgCount) {
3678                     push.call(args, "[...]");
3679                 }
3681                 var callStr = sinon.spyCall.toString.call({
3682                     proxy: this.method || "anonymous mock expectation",
3683                     args: args
3684                 });
3686                 var message = callStr.replace(", [...", "[, ...") + " " +
3687                     expectedCallCountInWords(this);
3689                 if (this.met()) {
3690                     return "Expectation met: " + message;
3691                 }
3693                 return "Expected " + message + " (" +
3694                     callCountInWords(this.callCount) + ")";
3695             },
3697             verify: function verify() {
3698                 if (!this.met()) {
3699                     sinon.expectation.fail(this.toString());
3700                 } else {
3701                     sinon.expectation.pass(this.toString());
3702                 }
3704                 return true;
3705             },
3707             pass: function pass(message) {
3708                 sinon.assert.pass(message);
3709             },
3711             fail: function fail(message) {
3712                 var exception = new Error(message);
3713                 exception.name = "ExpectationError";
3715                 throw exception;
3716             }
3717         };
3719         sinon.mock = mock;
3720         return mock;
3721     }
3723     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
3724     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3726     function loadDependencies(require, exports, module) {
3727         var sinon = require("./util/core");
3728         require("./times_in_words");
3729         require("./call");
3730         require("./extend");
3731         require("./match");
3732         require("./spy");
3733         require("./stub");
3734         require("./format");
3736         module.exports = makeApi(sinon);
3737     }
3739     if (isAMD) {
3740         define(loadDependencies);
3741     } else if (isNode) {
3742         loadDependencies(require, module.exports, module);
3743     } else if (!sinon) {
3744         return;
3745     } else {
3746         makeApi(sinon);
3747     }
3748 }(typeof sinon == "object" && sinon || null));
3751  * @depend util/core.js
3752  * @depend spy.js
3753  * @depend stub.js
3754  * @depend mock.js
3755  */
3757  * Collections of stubs, spies and mocks.
3759  * @author Christian Johansen (christian@cjohansen.no)
3760  * @license BSD
3762  * Copyright (c) 2010-2013 Christian Johansen
3763  */
3765 (function (sinon) {
3766     var push = [].push;
3767     var hasOwnProperty = Object.prototype.hasOwnProperty;
3769     function getFakes(fakeCollection) {
3770         if (!fakeCollection.fakes) {
3771             fakeCollection.fakes = [];
3772         }
3774         return fakeCollection.fakes;
3775     }
3777     function each(fakeCollection, method) {
3778         var fakes = getFakes(fakeCollection);
3780         for (var i = 0, l = fakes.length; i < l; i += 1) {
3781             if (typeof fakes[i][method] == "function") {
3782                 fakes[i][method]();
3783             }
3784         }
3785     }
3787     function compact(fakeCollection) {
3788         var fakes = getFakes(fakeCollection);
3789         var i = 0;
3790         while (i < fakes.length) {
3791             fakes.splice(i, 1);
3792         }
3793     }
3795     function makeApi(sinon) {
3796         var collection = {
3797             verify: function resolve() {
3798                 each(this, "verify");
3799             },
3801             restore: function restore() {
3802                 each(this, "restore");
3803                 compact(this);
3804             },
3806             reset: function restore() {
3807                 each(this, "reset");
3808             },
3810             verifyAndRestore: function verifyAndRestore() {
3811                 var exception;
3813                 try {
3814                     this.verify();
3815                 } catch (e) {
3816                     exception = e;
3817                 }
3819                 this.restore();
3821                 if (exception) {
3822                     throw exception;
3823                 }
3824             },
3826             add: function add(fake) {
3827                 push.call(getFakes(this), fake);
3828                 return fake;
3829             },
3831             spy: function spy() {
3832                 return this.add(sinon.spy.apply(sinon, arguments));
3833             },
3835             stub: function stub(object, property, value) {
3836                 if (property) {
3837                     var original = object[property];
3839                     if (typeof original != "function") {
3840                         if (!hasOwnProperty.call(object, property)) {
3841                             throw new TypeError("Cannot stub non-existent own property " + property);
3842                         }
3844                         object[property] = value;
3846                         return this.add({
3847                             restore: function () {
3848                                 object[property] = original;
3849                             }
3850                         });
3851                     }
3852                 }
3853                 if (!property && !!object && typeof object == "object") {
3854                     var stubbedObj = sinon.stub.apply(sinon, arguments);
3856                     for (var prop in stubbedObj) {
3857                         if (typeof stubbedObj[prop] === "function") {
3858                             this.add(stubbedObj[prop]);
3859                         }
3860                     }
3862                     return stubbedObj;
3863                 }
3865                 return this.add(sinon.stub.apply(sinon, arguments));
3866             },
3868             mock: function mock() {
3869                 return this.add(sinon.mock.apply(sinon, arguments));
3870             },
3872             inject: function inject(obj) {
3873                 var col = this;
3875                 obj.spy = function () {
3876                     return col.spy.apply(col, arguments);
3877                 };
3879                 obj.stub = function () {
3880                     return col.stub.apply(col, arguments);
3881                 };
3883                 obj.mock = function () {
3884                     return col.mock.apply(col, arguments);
3885                 };
3887                 return obj;
3888             }
3889         };
3891         sinon.collection = collection;
3892         return collection;
3893     }
3895     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
3896     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3898     function loadDependencies(require, exports, module) {
3899         var sinon = require("./util/core");
3900         require("./mock");
3901         require("./spy");
3902         require("./stub");
3903         module.exports = makeApi(sinon);
3904     }
3906     if (isAMD) {
3907         define(loadDependencies);
3908     } else if (isNode) {
3909         loadDependencies(require, module.exports, module);
3910     } else if (!sinon) {
3911         return;
3912     } else {
3913         makeApi(sinon);
3914     }
3915 }(typeof sinon == "object" && sinon || null));
3917 /*global lolex */
3920  * Fake timer API
3921  * setTimeout
3922  * setInterval
3923  * clearTimeout
3924  * clearInterval
3925  * tick
3926  * reset
3927  * Date
3929  * Inspired by jsUnitMockTimeOut from JsUnit
3931  * @author Christian Johansen (christian@cjohansen.no)
3932  * @license BSD
3934  * Copyright (c) 2010-2013 Christian Johansen
3935  */
3937 if (typeof sinon == "undefined") {
3938     var sinon = {};
3941 (function (global) {
3942     function makeApi(sinon, lol) {
3943         var llx = typeof lolex !== "undefined" ? lolex : lol;
3945         sinon.useFakeTimers = function () {
3946             var now, methods = Array.prototype.slice.call(arguments);
3948             if (typeof methods[0] === "string") {
3949                 now = 0;
3950             } else {
3951                 now = methods.shift();
3952             }
3954             var clock = llx.install(now || 0, methods);
3955             clock.restore = clock.uninstall;
3956             return clock;
3957         };
3959         sinon.clock = {
3960             create: function (now) {
3961                 return llx.createClock(now);
3962             }
3963         };
3965         sinon.timers = {
3966             setTimeout: setTimeout,
3967             clearTimeout: clearTimeout,
3968             setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
3969             clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate : undefined),
3970             setInterval: setInterval,
3971             clearInterval: clearInterval,
3972             Date: Date
3973         };
3974     }
3976     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
3977     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3979     function loadDependencies(require, epxorts, module, lolex) {
3980         var sinon = require("./core");
3981         makeApi(sinon, lolex);
3982         module.exports = sinon;
3983     }
3985     if (isAMD) {
3986         define(loadDependencies);
3987     } else if (isNode) {
3988         loadDependencies(require, module.exports, module, require("lolex"));
3989     } else {
3990         makeApi(sinon);
3991     }
3992 }(typeof global != "undefined" && typeof global !== "function" ? global : this));
3995  * Minimal Event interface implementation
3997  * Original implementation by Sven Fuchs: https://gist.github.com/995028
3998  * Modifications and tests by Christian Johansen.
4000  * @author Sven Fuchs (svenfuchs@artweb-design.de)
4001  * @author Christian Johansen (christian@cjohansen.no)
4002  * @license BSD
4004  * Copyright (c) 2011 Sven Fuchs, Christian Johansen
4005  */
4007 if (typeof sinon == "undefined") {
4008     this.sinon = {};
4011 (function () {
4012     var push = [].push;
4014     function makeApi(sinon) {
4015         sinon.Event = function Event(type, bubbles, cancelable, target) {
4016             this.initEvent(type, bubbles, cancelable, target);
4017         };
4019         sinon.Event.prototype = {
4020             initEvent: function (type, bubbles, cancelable, target) {
4021                 this.type = type;
4022                 this.bubbles = bubbles;
4023                 this.cancelable = cancelable;
4024                 this.target = target;
4025             },
4027             stopPropagation: function () {},
4029             preventDefault: function () {
4030                 this.defaultPrevented = true;
4031             }
4032         };
4034         sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
4035             this.initEvent(type, false, false, target);
4036             this.loaded = progressEventRaw.loaded || null;
4037             this.total = progressEventRaw.total || null;
4038             this.lengthComputable = !!progressEventRaw.total;
4039         };
4041         sinon.ProgressEvent.prototype = new sinon.Event();
4043         sinon.ProgressEvent.prototype.constructor =  sinon.ProgressEvent;
4045         sinon.CustomEvent = function CustomEvent(type, customData, target) {
4046             this.initEvent(type, false, false, target);
4047             this.detail = customData.detail || null;
4048         };
4050         sinon.CustomEvent.prototype = new sinon.Event();
4052         sinon.CustomEvent.prototype.constructor =  sinon.CustomEvent;
4054         sinon.EventTarget = {
4055             addEventListener: function addEventListener(event, listener) {
4056                 this.eventListeners = this.eventListeners || {};
4057                 this.eventListeners[event] = this.eventListeners[event] || [];
4058                 push.call(this.eventListeners[event], listener);
4059             },
4061             removeEventListener: function removeEventListener(event, listener) {
4062                 var listeners = this.eventListeners && this.eventListeners[event] || [];
4064                 for (var i = 0, l = listeners.length; i < l; ++i) {
4065                     if (listeners[i] == listener) {
4066                         return listeners.splice(i, 1);
4067                     }
4068                 }
4069             },
4071             dispatchEvent: function dispatchEvent(event) {
4072                 var type = event.type;
4073                 var listeners = this.eventListeners && this.eventListeners[type] || [];
4075                 for (var i = 0; i < listeners.length; i++) {
4076                     if (typeof listeners[i] == "function") {
4077                         listeners[i].call(this, event);
4078                     } else {
4079                         listeners[i].handleEvent(event);
4080                     }
4081                 }
4083                 return !!event.defaultPrevented;
4084             }
4085         };
4086     }
4088     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
4089     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4091     function loadDependencies(require) {
4092         var sinon = require("./core");
4093         makeApi(sinon);
4094     }
4096     if (isAMD) {
4097         define(loadDependencies);
4098     } else if (isNode) {
4099         loadDependencies(require);
4100     } else {
4101         makeApi(sinon);
4102     }
4103 }());
4106  * @depend util/core.js
4107  */
4109  * Logs errors
4111  * @author Christian Johansen (christian@cjohansen.no)
4112  * @license BSD
4114  * Copyright (c) 2010-2014 Christian Johansen
4115  */
4117 (function (sinon) {
4118     // cache a reference to setTimeout, so that our reference won't be stubbed out
4119     // when using fake timers and errors will still get logged
4120     // https://github.com/cjohansen/Sinon.JS/issues/381
4121     var realSetTimeout = setTimeout;
4123     function makeApi(sinon) {
4125         function log() {}
4127         function logError(label, err) {
4128             var msg = label + " threw exception: ";
4130             sinon.log(msg + "[" + err.name + "] " + err.message);
4132             if (err.stack) {
4133                 sinon.log(err.stack);
4134             }
4136             logError.setTimeout(function () {
4137                 err.message = msg + err.message;
4138                 throw err;
4139             }, 0);
4140         };
4142         // wrap realSetTimeout with something we can stub in tests
4143         logError.setTimeout = function (func, timeout) {
4144             realSetTimeout(func, timeout);
4145         }
4147         var exports = {};
4148         exports.log = sinon.log = log;
4149         exports.logError = sinon.logError = logError;
4151         return exports;
4152     }
4154     function loadDependencies(require, exports, module) {
4155         var sinon = require("./util/core");
4156         module.exports = makeApi(sinon);
4157     }
4159     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
4160     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4162     if (isAMD) {
4163         define(loadDependencies);
4164     } else if (isNode) {
4165         loadDependencies(require, module.exports, module);
4166     } else if (!sinon) {
4167         return;
4168     } else {
4169         makeApi(sinon);
4170     }
4171 }(typeof sinon == "object" && sinon || null));
4174  * @depend core.js
4175  * @depend ../extend.js
4176  * @depend event.js
4177  * @depend ../log_error.js
4178  */
4180  * Fake XDomainRequest object
4181  */
4183 if (typeof sinon == "undefined") {
4184     this.sinon = {};
4187 // wrapper for global
4188 (function (global) {
4189     var xdr = { XDomainRequest: global.XDomainRequest };
4190     xdr.GlobalXDomainRequest = global.XDomainRequest;
4191     xdr.supportsXDR = typeof xdr.GlobalXDomainRequest != "undefined";
4192     xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest :  false;
4194     function makeApi(sinon) {
4195         sinon.xdr = xdr;
4197         function FakeXDomainRequest() {
4198             this.readyState = FakeXDomainRequest.UNSENT;
4199             this.requestBody = null;
4200             this.requestHeaders = {};
4201             this.status = 0;
4202             this.timeout = null;
4204             if (typeof FakeXDomainRequest.onCreate == "function") {
4205                 FakeXDomainRequest.onCreate(this);
4206             }
4207         }
4209         function verifyState(xdr) {
4210             if (xdr.readyState !== FakeXDomainRequest.OPENED) {
4211                 throw new Error("INVALID_STATE_ERR");
4212             }
4214             if (xdr.sendFlag) {
4215                 throw new Error("INVALID_STATE_ERR");
4216             }
4217         }
4219         function verifyRequestSent(xdr) {
4220             if (xdr.readyState == FakeXDomainRequest.UNSENT) {
4221                 throw new Error("Request not sent");
4222             }
4223             if (xdr.readyState == FakeXDomainRequest.DONE) {
4224                 throw new Error("Request done");
4225             }
4226         }
4228         function verifyResponseBodyType(body) {
4229             if (typeof body != "string") {
4230                 var error = new Error("Attempted to respond to fake XDomainRequest with " +
4231                                     body + ", which is not a string.");
4232                 error.name = "InvalidBodyException";
4233                 throw error;
4234             }
4235         }
4237         sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
4238             open: function open(method, url) {
4239                 this.method = method;
4240                 this.url = url;
4242                 this.responseText = null;
4243                 this.sendFlag = false;
4245                 this.readyStateChange(FakeXDomainRequest.OPENED);
4246             },
4248             readyStateChange: function readyStateChange(state) {
4249                 this.readyState = state;
4250                 var eventName = "";
4251                 switch (this.readyState) {
4252                 case FakeXDomainRequest.UNSENT:
4253                     break;
4254                 case FakeXDomainRequest.OPENED:
4255                     break;
4256                 case FakeXDomainRequest.LOADING:
4257                     if (this.sendFlag) {
4258                         //raise the progress event
4259                         eventName = "onprogress";
4260                     }
4261                     break;
4262                 case FakeXDomainRequest.DONE:
4263                     if (this.isTimeout) {
4264                         eventName = "ontimeout"
4265                     } else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
4266                         eventName = "onerror";
4267                     } else {
4268                         eventName = "onload"
4269                     }
4270                     break;
4271                 }
4273                 // raising event (if defined)
4274                 if (eventName) {
4275                     if (typeof this[eventName] == "function") {
4276                         try {
4277                             this[eventName]();
4278                         } catch (e) {
4279                             sinon.logError("Fake XHR " + eventName + " handler", e);
4280                         }
4281                     }
4282                 }
4283             },
4285             send: function send(data) {
4286                 verifyState(this);
4288                 if (!/^(get|head)$/i.test(this.method)) {
4289                     this.requestBody = data;
4290                 }
4291                 this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
4293                 this.errorFlag = false;
4294                 this.sendFlag = true;
4295                 this.readyStateChange(FakeXDomainRequest.OPENED);
4297                 if (typeof this.onSend == "function") {
4298                     this.onSend(this);
4299                 }
4300             },
4302             abort: function abort() {
4303                 this.aborted = true;
4304                 this.responseText = null;
4305                 this.errorFlag = true;
4307                 if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
4308                     this.readyStateChange(sinon.FakeXDomainRequest.DONE);
4309                     this.sendFlag = false;
4310                 }
4311             },
4313             setResponseBody: function setResponseBody(body) {
4314                 verifyRequestSent(this);
4315                 verifyResponseBodyType(body);
4317                 var chunkSize = this.chunkSize || 10;
4318                 var index = 0;
4319                 this.responseText = "";
4321                 do {
4322                     this.readyStateChange(FakeXDomainRequest.LOADING);
4323                     this.responseText += body.substring(index, index + chunkSize);
4324                     index += chunkSize;
4325                 } while (index < body.length);
4327                 this.readyStateChange(FakeXDomainRequest.DONE);
4328             },
4330             respond: function respond(status, contentType, body) {
4331                 // content-type ignored, since XDomainRequest does not carry this
4332                 // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
4333                 // test integration across browsers
4334                 this.status = typeof status == "number" ? status : 200;
4335                 this.setResponseBody(body || "");
4336             },
4338             simulatetimeout: function simulatetimeout() {
4339                 this.status = 0;
4340                 this.isTimeout = true;
4341                 // Access to this should actually throw an error
4342                 this.responseText = undefined;
4343                 this.readyStateChange(FakeXDomainRequest.DONE);
4344             }
4345         });
4347         sinon.extend(FakeXDomainRequest, {
4348             UNSENT: 0,
4349             OPENED: 1,
4350             LOADING: 3,
4351             DONE: 4
4352         });
4354         sinon.useFakeXDomainRequest = function useFakeXDomainRequest() {
4355             sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
4356                 if (xdr.supportsXDR) {
4357                     global.XDomainRequest = xdr.GlobalXDomainRequest;
4358                 }
4360                 delete sinon.FakeXDomainRequest.restore;
4362                 if (keepOnCreate !== true) {
4363                     delete sinon.FakeXDomainRequest.onCreate;
4364                 }
4365             };
4366             if (xdr.supportsXDR) {
4367                 global.XDomainRequest = sinon.FakeXDomainRequest;
4368             }
4369             return sinon.FakeXDomainRequest;
4370         };
4372         sinon.FakeXDomainRequest = FakeXDomainRequest;
4373     }
4375     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
4376     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4378     function loadDependencies(require, exports, module) {
4379         var sinon = require("./core");
4380         require("../extend");
4381         require("./event");
4382         require("../log_error");
4383         makeApi(sinon);
4384         module.exports = sinon;
4385     }
4387     if (isAMD) {
4388         define(loadDependencies);
4389     } else if (isNode) {
4390         loadDependencies(require, module.exports, module);
4391     } else {
4392         makeApi(sinon);
4393     }
4394 })(typeof global !== "undefined" ? global : self);
4397  * @depend core.js
4398  * @depend ../extend.js
4399  * @depend event.js
4400  * @depend ../log_error.js
4401  */
4403  * Fake XMLHttpRequest object
4405  * @author Christian Johansen (christian@cjohansen.no)
4406  * @license BSD
4408  * Copyright (c) 2010-2013 Christian Johansen
4409  */
4411 (function (global) {
4413     var supportsProgress = typeof ProgressEvent !== "undefined";
4414     var supportsCustomEvent = typeof CustomEvent !== "undefined";
4415     var supportsFormData = typeof FormData !== "undefined";
4416     var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest };
4417     sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
4418     sinonXhr.GlobalActiveXObject = global.ActiveXObject;
4419     sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject != "undefined";
4420     sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest != "undefined";
4421     sinonXhr.workingXHR = sinonXhr.supportsXHR ? sinonXhr.GlobalXMLHttpRequest : sinonXhr.supportsActiveX
4422                                      ? function () {
4423                                         return new sinonXhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0")
4424                                     } : false;
4425     sinonXhr.supportsCORS = sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest());
4427     /*jsl:ignore*/
4428     var unsafeHeaders = {
4429         "Accept-Charset": true,
4430         "Accept-Encoding": true,
4431         Connection: true,
4432         "Content-Length": true,
4433         Cookie: true,
4434         Cookie2: true,
4435         "Content-Transfer-Encoding": true,
4436         Date: true,
4437         Expect: true,
4438         Host: true,
4439         "Keep-Alive": true,
4440         Referer: true,
4441         TE: true,
4442         Trailer: true,
4443         "Transfer-Encoding": true,
4444         Upgrade: true,
4445         "User-Agent": true,
4446         Via: true
4447     };
4448     /*jsl:end*/
4450     // Note that for FakeXMLHttpRequest to work pre ES5
4451     // we lose some of the alignment with the spec.
4452     // To ensure as close a match as possible,
4453     // set responseType before calling open, send or respond;
4454     function FakeXMLHttpRequest() {
4455         this.readyState = FakeXMLHttpRequest.UNSENT;
4456         this.requestHeaders = {};
4457         this.requestBody = null;
4458         this.status = 0;
4459         this.statusText = "";
4460         this.upload = new UploadProgress();
4461         this.responseType = "";
4462         this.response = "";
4463         if (sinonXhr.supportsCORS) {
4464             this.withCredentials = false;
4465         }
4467         var xhr = this;
4468         var events = ["loadstart", "load", "abort", "loadend"];
4470         function addEventListener(eventName) {
4471             xhr.addEventListener(eventName, function (event) {
4472                 var listener = xhr["on" + eventName];
4474                 if (listener && typeof listener == "function") {
4475                     listener.call(this, event);
4476                 }
4477             });
4478         }
4480         for (var i = events.length - 1; i >= 0; i--) {
4481             addEventListener(events[i]);
4482         }
4484         if (typeof FakeXMLHttpRequest.onCreate == "function") {
4485             FakeXMLHttpRequest.onCreate(this);
4486         }
4487     }
4489     // An upload object is created for each
4490     // FakeXMLHttpRequest and allows upload
4491     // events to be simulated using uploadProgress
4492     // and uploadError.
4493     function UploadProgress() {
4494         this.eventListeners = {
4495             progress: [],
4496             load: [],
4497             abort: [],
4498             error: []
4499         }
4500     }
4502     UploadProgress.prototype.addEventListener = function addEventListener(event, listener) {
4503         this.eventListeners[event].push(listener);
4504     };
4506     UploadProgress.prototype.removeEventListener = function removeEventListener(event, listener) {
4507         var listeners = this.eventListeners[event] || [];
4509         for (var i = 0, l = listeners.length; i < l; ++i) {
4510             if (listeners[i] == listener) {
4511                 return listeners.splice(i, 1);
4512             }
4513         }
4514     };
4516     UploadProgress.prototype.dispatchEvent = function dispatchEvent(event) {
4517         var listeners = this.eventListeners[event.type] || [];
4519         for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
4520             listener(event);
4521         }
4522     };
4524     function verifyState(xhr) {
4525         if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
4526             throw new Error("INVALID_STATE_ERR");
4527         }
4529         if (xhr.sendFlag) {
4530             throw new Error("INVALID_STATE_ERR");
4531         }
4532     }
4534     function getHeader(headers, header) {
4535         header = header.toLowerCase();
4537         for (var h in headers) {
4538             if (h.toLowerCase() == header) {
4539                 return h;
4540             }
4541         }
4543         return null;
4544     }
4546     // filtering to enable a white-list version of Sinon FakeXhr,
4547     // where whitelisted requests are passed through to real XHR
4548     function each(collection, callback) {
4549         if (!collection) {
4550             return;
4551         }
4553         for (var i = 0, l = collection.length; i < l; i += 1) {
4554             callback(collection[i]);
4555         }
4556     }
4557     function some(collection, callback) {
4558         for (var index = 0; index < collection.length; index++) {
4559             if (callback(collection[index]) === true) {
4560                 return true;
4561             }
4562         }
4563         return false;
4564     }
4565     // largest arity in XHR is 5 - XHR#open
4566     var apply = function (obj, method, args) {
4567         switch (args.length) {
4568         case 0: return obj[method]();
4569         case 1: return obj[method](args[0]);
4570         case 2: return obj[method](args[0], args[1]);
4571         case 3: return obj[method](args[0], args[1], args[2]);
4572         case 4: return obj[method](args[0], args[1], args[2], args[3]);
4573         case 5: return obj[method](args[0], args[1], args[2], args[3], args[4]);
4574         }
4575     };
4577     FakeXMLHttpRequest.filters = [];
4578     FakeXMLHttpRequest.addFilter = function addFilter(fn) {
4579         this.filters.push(fn)
4580     };
4581     var IE6Re = /MSIE 6/;
4582     FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) {
4583         var xhr = new sinonXhr.workingXHR();
4584         each([
4585             "open",
4586             "setRequestHeader",
4587             "send",
4588             "abort",
4589             "getResponseHeader",
4590             "getAllResponseHeaders",
4591             "addEventListener",
4592             "overrideMimeType",
4593             "removeEventListener"
4594         ], function (method) {
4595             fakeXhr[method] = function () {
4596                 return apply(xhr, method, arguments);
4597             };
4598         });
4600         var copyAttrs = function (args) {
4601             each(args, function (attr) {
4602                 try {
4603                     fakeXhr[attr] = xhr[attr]
4604                 } catch (e) {
4605                     if (!IE6Re.test(navigator.userAgent)) {
4606                         throw e;
4607                     }
4608                 }
4609             });
4610         };
4612         var stateChange = function stateChange() {
4613             fakeXhr.readyState = xhr.readyState;
4614             if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
4615                 copyAttrs(["status", "statusText"]);
4616             }
4617             if (xhr.readyState >= FakeXMLHttpRequest.LOADING) {
4618                 copyAttrs(["responseText", "response"]);
4619             }
4620             if (xhr.readyState === FakeXMLHttpRequest.DONE) {
4621                 copyAttrs(["responseXML"]);
4622             }
4623             if (fakeXhr.onreadystatechange) {
4624                 fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
4625             }
4626         };
4628         if (xhr.addEventListener) {
4629             for (var event in fakeXhr.eventListeners) {
4630                 if (fakeXhr.eventListeners.hasOwnProperty(event)) {
4631                     each(fakeXhr.eventListeners[event], function (handler) {
4632                         xhr.addEventListener(event, handler);
4633                     });
4634                 }
4635             }
4636             xhr.addEventListener("readystatechange", stateChange);
4637         } else {
4638             xhr.onreadystatechange = stateChange;
4639         }
4640         apply(xhr, "open", xhrArgs);
4641     };
4642     FakeXMLHttpRequest.useFilters = false;
4644     function verifyRequestOpened(xhr) {
4645         if (xhr.readyState != FakeXMLHttpRequest.OPENED) {
4646             throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
4647         }
4648     }
4650     function verifyRequestSent(xhr) {
4651         if (xhr.readyState == FakeXMLHttpRequest.DONE) {
4652             throw new Error("Request done");
4653         }
4654     }
4656     function verifyHeadersReceived(xhr) {
4657         if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
4658             throw new Error("No headers received");
4659         }
4660     }
4662     function verifyResponseBodyType(body) {
4663         if (typeof body != "string") {
4664             var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
4665                                  body + ", which is not a string.");
4666             error.name = "InvalidBodyException";
4667             throw error;
4668         }
4669     }
4671     FakeXMLHttpRequest.parseXML = function parseXML(text) {
4672         var xmlDoc;
4674         if (typeof DOMParser != "undefined") {
4675             var parser = new DOMParser();
4676             xmlDoc = parser.parseFromString(text, "text/xml");
4677         } else {
4678             xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
4679             xmlDoc.async = "false";
4680             xmlDoc.loadXML(text);
4681         }
4683         return xmlDoc;
4684     };
4686     FakeXMLHttpRequest.statusCodes = {
4687         100: "Continue",
4688         101: "Switching Protocols",
4689         200: "OK",
4690         201: "Created",
4691         202: "Accepted",
4692         203: "Non-Authoritative Information",
4693         204: "No Content",
4694         205: "Reset Content",
4695         206: "Partial Content",
4696         207: "Multi-Status",
4697         300: "Multiple Choice",
4698         301: "Moved Permanently",
4699         302: "Found",
4700         303: "See Other",
4701         304: "Not Modified",
4702         305: "Use Proxy",
4703         307: "Temporary Redirect",
4704         400: "Bad Request",
4705         401: "Unauthorized",
4706         402: "Payment Required",
4707         403: "Forbidden",
4708         404: "Not Found",
4709         405: "Method Not Allowed",
4710         406: "Not Acceptable",
4711         407: "Proxy Authentication Required",
4712         408: "Request Timeout",
4713         409: "Conflict",
4714         410: "Gone",
4715         411: "Length Required",
4716         412: "Precondition Failed",
4717         413: "Request Entity Too Large",
4718         414: "Request-URI Too Long",
4719         415: "Unsupported Media Type",
4720         416: "Requested Range Not Satisfiable",
4721         417: "Expectation Failed",
4722         422: "Unprocessable Entity",
4723         500: "Internal Server Error",
4724         501: "Not Implemented",
4725         502: "Bad Gateway",
4726         503: "Service Unavailable",
4727         504: "Gateway Timeout",
4728         505: "HTTP Version Not Supported"
4729     };
4731     function makeApi(sinon) {
4732         sinon.xhr = sinonXhr;
4734         sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
4735             async: true,
4737             open: function open(method, url, async, username, password) {
4738                 this.method = method;
4739                 this.url = url;
4740                 this.async = typeof async == "boolean" ? async : true;
4741                 this.username = username;
4742                 this.password = password;
4743                 this.responseText = null;
4744                 this.response = this.responseType === "json" ? null : "";
4745                 this.responseXML = null;
4746                 this.requestHeaders = {};
4747                 this.sendFlag = false;
4749                 if (FakeXMLHttpRequest.useFilters === true) {
4750                     var xhrArgs = arguments;
4751                     var defake = some(FakeXMLHttpRequest.filters, function (filter) {
4752                         return filter.apply(this, xhrArgs)
4753                     });
4754                     if (defake) {
4755                         return FakeXMLHttpRequest.defake(this, arguments);
4756                     }
4757                 }
4758                 this.readyStateChange(FakeXMLHttpRequest.OPENED);
4759             },
4761             readyStateChange: function readyStateChange(state) {
4762                 this.readyState = state;
4764                 if (typeof this.onreadystatechange == "function") {
4765                     try {
4766                         this.onreadystatechange();
4767                     } catch (e) {
4768                         sinon.logError("Fake XHR onreadystatechange handler", e);
4769                     }
4770                 }
4772                 switch (this.readyState) {
4773                     case FakeXMLHttpRequest.DONE:
4774                         if (supportsProgress) {
4775                             this.upload.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
4776                             this.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
4777                         }
4778                         this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
4779                         this.dispatchEvent(new sinon.Event("load", false, false, this));
4780                         this.dispatchEvent(new sinon.Event("loadend", false, false, this));
4781                         break;
4782                 }
4784                 this.dispatchEvent(new sinon.Event("readystatechange"));
4785             },
4787             setRequestHeader: function setRequestHeader(header, value) {
4788                 verifyState(this);
4790                 if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
4791                     throw new Error("Refused to set unsafe header \"" + header + "\"");
4792                 }
4794                 if (this.requestHeaders[header]) {
4795                     this.requestHeaders[header] += "," + value;
4796                 } else {
4797                     this.requestHeaders[header] = value;
4798                 }
4799             },
4801             // Helps testing
4802             setResponseHeaders: function setResponseHeaders(headers) {
4803                 verifyRequestOpened(this);
4804                 this.responseHeaders = {};
4806                 for (var header in headers) {
4807                     if (headers.hasOwnProperty(header)) {
4808                         this.responseHeaders[header] = headers[header];
4809                     }
4810                 }
4812                 if (this.async) {
4813                     this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
4814                 } else {
4815                     this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
4816                 }
4817             },
4819             // Currently treats ALL data as a DOMString (i.e. no Document)
4820             send: function send(data) {
4821                 verifyState(this);
4823                 if (!/^(get|head)$/i.test(this.method)) {
4824                     var contentType = getHeader(this.requestHeaders, "Content-Type");
4825                     if (this.requestHeaders[contentType]) {
4826                         var value = this.requestHeaders[contentType].split(";");
4827                         this.requestHeaders[contentType] = value[0] + ";charset=utf-8";
4828                     } else if (supportsFormData && !(data instanceof FormData)) {
4829                         this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
4830                     }
4832                     this.requestBody = data;
4833                 }
4835                 this.errorFlag = false;
4836                 this.sendFlag = this.async;
4837                 this.response = this.responseType === "json" ? null : "";
4838                 this.readyStateChange(FakeXMLHttpRequest.OPENED);
4840                 if (typeof this.onSend == "function") {
4841                     this.onSend(this);
4842                 }
4844                 this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
4845             },
4847             abort: function abort() {
4848                 this.aborted = true;
4849                 this.responseText = null;
4850                 this.response = this.responseType === "json" ? null : "";
4851                 this.errorFlag = true;
4852                 this.requestHeaders = {};
4853                 this.responseHeaders = {};
4855                 if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) {
4856                     this.readyStateChange(FakeXMLHttpRequest.DONE);
4857                     this.sendFlag = false;
4858                 }
4860                 this.readyState = FakeXMLHttpRequest.UNSENT;
4862                 this.dispatchEvent(new sinon.Event("abort", false, false, this));
4864                 this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
4866                 if (typeof this.onerror === "function") {
4867                     this.onerror();
4868                 }
4869             },
4871             getResponseHeader: function getResponseHeader(header) {
4872                 if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
4873                     return null;
4874                 }
4876                 if (/^Set-Cookie2?$/i.test(header)) {
4877                     return null;
4878                 }
4880                 header = getHeader(this.responseHeaders, header);
4882                 return this.responseHeaders[header] || null;
4883             },
4885             getAllResponseHeaders: function getAllResponseHeaders() {
4886                 if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
4887                     return "";
4888                 }
4890                 var headers = "";
4892                 for (var header in this.responseHeaders) {
4893                     if (this.responseHeaders.hasOwnProperty(header) &&
4894                         !/^Set-Cookie2?$/i.test(header)) {
4895                         headers += header + ": " + this.responseHeaders[header] + "\r\n";
4896                     }
4897                 }
4899                 return headers;
4900             },
4902             setResponseBody: function setResponseBody(body) {
4903                 verifyRequestSent(this);
4904                 verifyHeadersReceived(this);
4905                 verifyResponseBodyType(body);
4907                 var chunkSize = this.chunkSize || 10;
4908                 var index = 0;
4909                 this.responseText = "";
4911                 do {
4912                     if (this.async) {
4913                         this.readyStateChange(FakeXMLHttpRequest.LOADING);
4914                     }
4916                     this.responseText += body.substring(index, index + chunkSize);
4917                     index += chunkSize;
4918                 } while (index < body.length);
4920                 var type = this.getResponseHeader("Content-Type");
4922                 if (this.responseText &&
4923                     (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
4924                     try {
4925                         this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
4926                     } catch (e) {
4927                         // Unable to parse XML - no biggie
4928                     }
4929                 }
4931                 this.response = this.responseType === "json" ? JSON.parse(this.responseText) : this.responseText;
4932                 this.readyStateChange(FakeXMLHttpRequest.DONE);
4933             },
4935             respond: function respond(status, headers, body) {
4936                 this.status = typeof status == "number" ? status : 200;
4937                 this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
4938                 this.setResponseHeaders(headers || {});
4939                 this.setResponseBody(body || "");
4940             },
4942             uploadProgress: function uploadProgress(progressEventRaw) {
4943                 if (supportsProgress) {
4944                     this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
4945                 }
4946             },
4948             downloadProgress: function downloadProgress(progressEventRaw) {
4949                 if (supportsProgress) {
4950                     this.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
4951                 }
4952             },
4954             uploadError: function uploadError(error) {
4955                 if (supportsCustomEvent) {
4956                     this.upload.dispatchEvent(new sinon.CustomEvent("error", {detail: error}));
4957                 }
4958             }
4959         });
4961         sinon.extend(FakeXMLHttpRequest, {
4962             UNSENT: 0,
4963             OPENED: 1,
4964             HEADERS_RECEIVED: 2,
4965             LOADING: 3,
4966             DONE: 4
4967         });
4969         sinon.useFakeXMLHttpRequest = function () {
4970             FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
4971                 if (sinonXhr.supportsXHR) {
4972                     global.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest;
4973                 }
4975                 if (sinonXhr.supportsActiveX) {
4976                     global.ActiveXObject = sinonXhr.GlobalActiveXObject;
4977                 }
4979                 delete FakeXMLHttpRequest.restore;
4981                 if (keepOnCreate !== true) {
4982                     delete FakeXMLHttpRequest.onCreate;
4983                 }
4984             };
4985             if (sinonXhr.supportsXHR) {
4986                 global.XMLHttpRequest = FakeXMLHttpRequest;
4987             }
4989             if (sinonXhr.supportsActiveX) {
4990                 global.ActiveXObject = function ActiveXObject(objId) {
4991                     if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
4993                         return new FakeXMLHttpRequest();
4994                     }
4996                     return new sinonXhr.GlobalActiveXObject(objId);
4997                 };
4998             }
5000             return FakeXMLHttpRequest;
5001         };
5003         sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
5004     }
5006     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5007     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5009     function loadDependencies(require, exports, module) {
5010         var sinon = require("./core");
5011         require("../extend");
5012         require("./event");
5013         require("../log_error");
5014         makeApi(sinon);
5015         module.exports = sinon;
5016     }
5018     if (isAMD) {
5019         define(loadDependencies);
5020     } else if (isNode) {
5021         loadDependencies(require, module.exports, module);
5022     } else if (typeof sinon === "undefined") {
5023         return;
5024     } else {
5025         makeApi(sinon);
5026     }
5028 })(typeof global !== "undefined" ? global : self);
5031  * @depend fake_xdomain_request.js
5032  * @depend fake_xml_http_request.js
5033  * @depend ../format.js
5034  * @depend ../log_error.js
5035  */
5037  * The Sinon "server" mimics a web server that receives requests from
5038  * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
5039  * both synchronously and asynchronously. To respond synchronuously, canned
5040  * answers have to be provided upfront.
5042  * @author Christian Johansen (christian@cjohansen.no)
5043  * @license BSD
5045  * Copyright (c) 2010-2013 Christian Johansen
5046  */
5048 if (typeof sinon == "undefined") {
5049     var sinon = {};
5052 (function () {
5053     var push = [].push;
5054     function F() {}
5056     function create(proto) {
5057         F.prototype = proto;
5058         return new F();
5059     }
5061     function responseArray(handler) {
5062         var response = handler;
5064         if (Object.prototype.toString.call(handler) != "[object Array]") {
5065             response = [200, {}, handler];
5066         }
5068         if (typeof response[2] != "string") {
5069             throw new TypeError("Fake server response body should be string, but was " +
5070                                 typeof response[2]);
5071         }
5073         return response;
5074     }
5076     var wloc = typeof window !== "undefined" ? window.location : {};
5077     var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
5079     function matchOne(response, reqMethod, reqUrl) {
5080         var rmeth = response.method;
5081         var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
5082         var url = response.url;
5083         var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
5085         return matchMethod && matchUrl;
5086     }
5088     function match(response, request) {
5089         var requestUrl = request.url;
5091         if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
5092             requestUrl = requestUrl.replace(rCurrLoc, "");
5093         }
5095         if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
5096             if (typeof response.response == "function") {
5097                 var ru = response.url;
5098                 var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
5099                 return response.response.apply(response, args);
5100             }
5102             return true;
5103         }
5105         return false;
5106     }
5108     function makeApi(sinon) {
5109         sinon.fakeServer = {
5110             create: function () {
5111                 var server = create(this);
5112                 if (!sinon.xhr.supportsCORS) {
5113                     this.xhr = sinon.useFakeXDomainRequest();
5114                 } else {
5115                     this.xhr = sinon.useFakeXMLHttpRequest();
5116                 }
5117                 server.requests = [];
5119                 this.xhr.onCreate = function (xhrObj) {
5120                     server.addRequest(xhrObj);
5121                 };
5123                 return server;
5124             },
5126             addRequest: function addRequest(xhrObj) {
5127                 var server = this;
5128                 push.call(this.requests, xhrObj);
5130                 xhrObj.onSend = function () {
5131                     server.handleRequest(this);
5133                     if (server.respondImmediately) {
5134                         server.respond();
5135                     } else if (server.autoRespond && !server.responding) {
5136                         setTimeout(function () {
5137                             server.responding = false;
5138                             server.respond();
5139                         }, server.autoRespondAfter || 10);
5141                         server.responding = true;
5142                     }
5143                 };
5144             },
5146             getHTTPMethod: function getHTTPMethod(request) {
5147                 if (this.fakeHTTPMethods && /post/i.test(request.method)) {
5148                     var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
5149                     return !!matches ? matches[1] : request.method;
5150                 }
5152                 return request.method;
5153             },
5155             handleRequest: function handleRequest(xhr) {
5156                 if (xhr.async) {
5157                     if (!this.queue) {
5158                         this.queue = [];
5159                     }
5161                     push.call(this.queue, xhr);
5162                 } else {
5163                     this.processRequest(xhr);
5164                 }
5165             },
5167             log: function log(response, request) {
5168                 var str;
5170                 str =  "Request:\n"  + sinon.format(request)  + "\n\n";
5171                 str += "Response:\n" + sinon.format(response) + "\n\n";
5173                 sinon.log(str);
5174             },
5176             respondWith: function respondWith(method, url, body) {
5177                 if (arguments.length == 1 && typeof method != "function") {
5178                     this.response = responseArray(method);
5179                     return;
5180                 }
5182                 if (!this.responses) {
5183                     this.responses = [];
5184                 }
5186                 if (arguments.length == 1) {
5187                     body = method;
5188                     url = method = null;
5189                 }
5191                 if (arguments.length == 2) {
5192                     body = url;
5193                     url = method;
5194                     method = null;
5195                 }
5197                 push.call(this.responses, {
5198                     method: method,
5199                     url: url,
5200                     response: typeof body == "function" ? body : responseArray(body)
5201                 });
5202             },
5204             respond: function respond() {
5205                 if (arguments.length > 0) {
5206                     this.respondWith.apply(this, arguments);
5207                 }
5209                 var queue = this.queue || [];
5210                 var requests = queue.splice(0, queue.length);
5211                 var request;
5213                 while (request = requests.shift()) {
5214                     this.processRequest(request);
5215                 }
5216             },
5218             processRequest: function processRequest(request) {
5219                 try {
5220                     if (request.aborted) {
5221                         return;
5222                     }
5224                     var response = this.response || [404, {}, ""];
5226                     if (this.responses) {
5227                         for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
5228                             if (match.call(this, this.responses[i], request)) {
5229                                 response = this.responses[i].response;
5230                                 break;
5231                             }
5232                         }
5233                     }
5235                     if (request.readyState != 4) {
5236                         this.log(response, request);
5238                         request.respond(response[0], response[1], response[2]);
5239                     }
5240                 } catch (e) {
5241                     sinon.logError("Fake server request processing", e);
5242                 }
5243             },
5245             restore: function restore() {
5246                 return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
5247             }
5248         };
5249     }
5251     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5252     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5254     function loadDependencies(require, exports, module) {
5255         var sinon = require("./core");
5256         require("./fake_xdomain_request");
5257         require("./fake_xml_http_request");
5258         require("../format");
5259         makeApi(sinon);
5260         module.exports = sinon;
5261     }
5263     if (isAMD) {
5264         define(loadDependencies);
5265     } else if (isNode) {
5266         loadDependencies(require, module.exports, module);
5267     } else {
5268         makeApi(sinon);
5269     }
5270 }());
5273  * @depend fake_server.js
5274  * @depend fake_timers.js
5275  */
5277  * Add-on for sinon.fakeServer that automatically handles a fake timer along with
5278  * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
5279  * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
5280  * it polls the object for completion with setInterval. Dispite the direct
5281  * motivation, there is nothing jQuery-specific in this file, so it can be used
5282  * in any environment where the ajax implementation depends on setInterval or
5283  * setTimeout.
5285  * @author Christian Johansen (christian@cjohansen.no)
5286  * @license BSD
5288  * Copyright (c) 2010-2013 Christian Johansen
5289  */
5291 (function () {
5292     function makeApi(sinon) {
5293         function Server() {}
5294         Server.prototype = sinon.fakeServer;
5296         sinon.fakeServerWithClock = new Server();
5298         sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
5299             if (xhr.async) {
5300                 if (typeof setTimeout.clock == "object") {
5301                     this.clock = setTimeout.clock;
5302                 } else {
5303                     this.clock = sinon.useFakeTimers();
5304                     this.resetClock = true;
5305                 }
5307                 if (!this.longestTimeout) {
5308                     var clockSetTimeout = this.clock.setTimeout;
5309                     var clockSetInterval = this.clock.setInterval;
5310                     var server = this;
5312                     this.clock.setTimeout = function (fn, timeout) {
5313                         server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
5315                         return clockSetTimeout.apply(this, arguments);
5316                     };
5318                     this.clock.setInterval = function (fn, timeout) {
5319                         server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
5321                         return clockSetInterval.apply(this, arguments);
5322                     };
5323                 }
5324             }
5326             return sinon.fakeServer.addRequest.call(this, xhr);
5327         };
5329         sinon.fakeServerWithClock.respond = function respond() {
5330             var returnVal = sinon.fakeServer.respond.apply(this, arguments);
5332             if (this.clock) {
5333                 this.clock.tick(this.longestTimeout || 0);
5334                 this.longestTimeout = 0;
5336                 if (this.resetClock) {
5337                     this.clock.restore();
5338                     this.resetClock = false;
5339                 }
5340             }
5342             return returnVal;
5343         };
5345         sinon.fakeServerWithClock.restore = function restore() {
5346             if (this.clock) {
5347                 this.clock.restore();
5348             }
5350             return sinon.fakeServer.restore.apply(this, arguments);
5351         };
5352     }
5354     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5355     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5357     function loadDependencies(require) {
5358         var sinon = require("./core");
5359         require("./fake_server");
5360         require("./fake_timers");
5361         makeApi(sinon);
5362     }
5364     if (isAMD) {
5365         define(loadDependencies);
5366     } else if (isNode) {
5367         loadDependencies(require);
5368     } else {
5369         makeApi(sinon);
5370     }
5371 }());
5374  * @depend util/core.js
5375  * @depend extend.js
5376  * @depend collection.js
5377  * @depend util/fake_timers.js
5378  * @depend util/fake_server_with_clock.js
5379  */
5381  * Manages fake collections as well as fake utilities such as Sinon's
5382  * timers and fake XHR implementation in one convenient object.
5384  * @author Christian Johansen (christian@cjohansen.no)
5385  * @license BSD
5387  * Copyright (c) 2010-2013 Christian Johansen
5388  */
5390 (function () {
5391     function makeApi(sinon) {
5392         var push = [].push;
5394         function exposeValue(sandbox, config, key, value) {
5395             if (!value) {
5396                 return;
5397             }
5399             if (config.injectInto && !(key in config.injectInto)) {
5400                 config.injectInto[key] = value;
5401                 sandbox.injectedKeys.push(key);
5402             } else {
5403                 push.call(sandbox.args, value);
5404             }
5405         }
5407         function prepareSandboxFromConfig(config) {
5408             var sandbox = sinon.create(sinon.sandbox);
5410             if (config.useFakeServer) {
5411                 if (typeof config.useFakeServer == "object") {
5412                     sandbox.serverPrototype = config.useFakeServer;
5413                 }
5415                 sandbox.useFakeServer();
5416             }
5418             if (config.useFakeTimers) {
5419                 if (typeof config.useFakeTimers == "object") {
5420                     sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
5421                 } else {
5422                     sandbox.useFakeTimers();
5423                 }
5424             }
5426             return sandbox;
5427         }
5429         sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
5430             useFakeTimers: function useFakeTimers() {
5431                 this.clock = sinon.useFakeTimers.apply(sinon, arguments);
5433                 return this.add(this.clock);
5434             },
5436             serverPrototype: sinon.fakeServer,
5438             useFakeServer: function useFakeServer() {
5439                 var proto = this.serverPrototype || sinon.fakeServer;
5441                 if (!proto || !proto.create) {
5442                     return null;
5443                 }
5445                 this.server = proto.create();
5446                 return this.add(this.server);
5447             },
5449             inject: function (obj) {
5450                 sinon.collection.inject.call(this, obj);
5452                 if (this.clock) {
5453                     obj.clock = this.clock;
5454                 }
5456                 if (this.server) {
5457                     obj.server = this.server;
5458                     obj.requests = this.server.requests;
5459                 }
5461                 obj.match = sinon.match;
5463                 return obj;
5464             },
5466             restore: function () {
5467                 sinon.collection.restore.apply(this, arguments);
5468                 this.restoreContext();
5469             },
5471             restoreContext: function () {
5472                 if (this.injectedKeys) {
5473                     for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
5474                         delete this.injectInto[this.injectedKeys[i]];
5475                     }
5476                     this.injectedKeys = [];
5477                 }
5478             },
5480             create: function (config) {
5481                 if (!config) {
5482                     return sinon.create(sinon.sandbox);
5483                 }
5485                 var sandbox = prepareSandboxFromConfig(config);
5486                 sandbox.args = sandbox.args || [];
5487                 sandbox.injectedKeys = [];
5488                 sandbox.injectInto = config.injectInto;
5489                 var prop, value, exposed = sandbox.inject({});
5491                 if (config.properties) {
5492                     for (var i = 0, l = config.properties.length; i < l; i++) {
5493                         prop = config.properties[i];
5494                         value = exposed[prop] || prop == "sandbox" && sandbox;
5495                         exposeValue(sandbox, config, prop, value);
5496                     }
5497                 } else {
5498                     exposeValue(sandbox, config, "sandbox", value);
5499                 }
5501                 return sandbox;
5502             },
5504             match: sinon.match
5505         });
5507         sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
5509         return sinon.sandbox;
5510     }
5512     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5513     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5515     function loadDependencies(require, exports, module) {
5516         var sinon = require("./util/core");
5517         require("./extend");
5518         require("./util/fake_server_with_clock");
5519         require("./util/fake_timers");
5520         require("./collection");
5521         module.exports = makeApi(sinon);
5522     }
5524     if (isAMD) {
5525         define(loadDependencies);
5526     } else if (isNode) {
5527         loadDependencies(require, module.exports, module);
5528     } else if (!sinon) {
5529         return;
5530     } else {
5531         makeApi(sinon);
5532     }
5533 }());
5536  * @depend util/core.js
5537  * @depend sandbox.js
5538  */
5540  * Test function, sandboxes fakes
5542  * @author Christian Johansen (christian@cjohansen.no)
5543  * @license BSD
5545  * Copyright (c) 2010-2013 Christian Johansen
5546  */
5548 (function (sinon) {
5549     function makeApi(sinon) {
5550         var slice = Array.prototype.slice;
5552         function test(callback) {
5553             var type = typeof callback;
5555             if (type != "function") {
5556                 throw new TypeError("sinon.test needs to wrap a test function, got " + type);
5557             }
5559             function sinonSandboxedTest() {
5560                 var config = sinon.getConfig(sinon.config);
5561                 config.injectInto = config.injectIntoThis && this || config.injectInto;
5562                 var sandbox = sinon.sandbox.create(config);
5563                 var args = slice.call(arguments);
5564                 var oldDone = args.length && args[args.length - 1];
5565                 var exception, result;
5567                 if (typeof oldDone == "function") {
5568                     args[args.length - 1] = function sinonDone(result) {
5569                         if (result) {
5570                             sandbox.restore();
5571                             throw exception;
5572                         } else {
5573                             sandbox.verifyAndRestore();
5574                         }
5575                         oldDone(result);
5576                     };
5577                 }
5579                 try {
5580                     result = callback.apply(this, args.concat(sandbox.args));
5581                 } catch (e) {
5582                     exception = e;
5583                 }
5585                 if (typeof oldDone != "function") {
5586                     if (typeof exception !== "undefined") {
5587                         sandbox.restore();
5588                         throw exception;
5589                     } else {
5590                         sandbox.verifyAndRestore();
5591                     }
5592                 }
5594                 return result;
5595             }
5597             if (callback.length) {
5598                 return function sinonAsyncSandboxedTest(callback) {
5599                     return sinonSandboxedTest.apply(this, arguments);
5600                 };
5601             }
5603             return sinonSandboxedTest;
5604         }
5606         test.config = {
5607             injectIntoThis: true,
5608             injectInto: null,
5609             properties: ["spy", "stub", "mock", "clock", "server", "requests"],
5610             useFakeTimers: true,
5611             useFakeServer: true
5612         };
5614         sinon.test = test;
5615         return test;
5616     }
5618     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5619     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5621     function loadDependencies(require, exports, module) {
5622         var sinon = require("./util/core");
5623         require("./sandbox");
5624         module.exports = makeApi(sinon);
5625     }
5627     if (isAMD) {
5628         define(loadDependencies);
5629     } else if (isNode) {
5630         loadDependencies(require, module.exports, module);
5631     } else if (sinon) {
5632         makeApi(sinon);
5633     }
5634 }(typeof sinon == "object" && sinon || null));
5637  * @depend util/core.js
5638  * @depend test.js
5639  */
5641  * Test case, sandboxes all test functions
5643  * @author Christian Johansen (christian@cjohansen.no)
5644  * @license BSD
5646  * Copyright (c) 2010-2013 Christian Johansen
5647  */
5649 (function (sinon) {
5650     function createTest(property, setUp, tearDown) {
5651         return function () {
5652             if (setUp) {
5653                 setUp.apply(this, arguments);
5654             }
5656             var exception, result;
5658             try {
5659                 result = property.apply(this, arguments);
5660             } catch (e) {
5661                 exception = e;
5662             }
5664             if (tearDown) {
5665                 tearDown.apply(this, arguments);
5666             }
5668             if (exception) {
5669                 throw exception;
5670             }
5672             return result;
5673         };
5674     }
5676     function makeApi(sinon) {
5677         function testCase(tests, prefix) {
5678             if (!tests || typeof tests != "object") {
5679                 throw new TypeError("sinon.testCase needs an object with test functions");
5680             }
5682             prefix = prefix || "test";
5683             var rPrefix = new RegExp("^" + prefix);
5684             var methods = {}, testName, property, method;
5685             var setUp = tests.setUp;
5686             var tearDown = tests.tearDown;
5688             for (testName in tests) {
5689                 if (tests.hasOwnProperty(testName) && !/^(setUp|tearDown)$/.test(testName)) {
5690                     property = tests[testName];
5692                     if (typeof property == "function" && rPrefix.test(testName)) {
5693                         method = property;
5695                         if (setUp || tearDown) {
5696                             method = createTest(property, setUp, tearDown);
5697                         }
5699                         methods[testName] = sinon.test(method);
5700                     } else {
5701                         methods[testName] = tests[testName];
5702                     }
5703                 }
5704             }
5706             return methods;
5707         }
5709         sinon.testCase = testCase;
5710         return testCase;
5711     }
5713     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5714     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5716     function loadDependencies(require, exports, module) {
5717         var sinon = require("./util/core");
5718         require("./test");
5719         module.exports = makeApi(sinon);
5720     }
5722     if (isAMD) {
5723         define(loadDependencies);
5724     } else if (isNode) {
5725         loadDependencies(require, module.exports, module);
5726     } else if (!sinon) {
5727         return;
5728     } else {
5729         makeApi(sinon);
5730     }
5731 }(typeof sinon == "object" && sinon || null));
5734  * @depend times_in_words.js
5735  * @depend util/core.js
5736  * @depend match.js
5737  * @depend format.js
5738  */
5740  * Assertions matching the test spy retrieval interface.
5742  * @author Christian Johansen (christian@cjohansen.no)
5743  * @license BSD
5745  * Copyright (c) 2010-2013 Christian Johansen
5746  */
5748 (function (sinon, global) {
5749     var slice = Array.prototype.slice;
5751     function makeApi(sinon) {
5752         var assert;
5754         function verifyIsStub() {
5755             var method;
5757             for (var i = 0, l = arguments.length; i < l; ++i) {
5758                 method = arguments[i];
5760                 if (!method) {
5761                     assert.fail("fake is not a spy");
5762                 }
5764                 if (method.proxy && method.proxy.isSinonProxy) {
5765                     verifyIsStub(method.proxy);
5766                 } else {
5767                     if (typeof method != "function") {
5768                         assert.fail(method + " is not a function");
5769                     }
5771                     if (typeof method.getCall != "function") {
5772                         assert.fail(method + " is not stubbed");
5773                     }
5774                 }
5776             }
5777         }
5779         function failAssertion(object, msg) {
5780             object = object || global;
5781             var failMethod = object.fail || assert.fail;
5782             failMethod.call(object, msg);
5783         }
5785         function mirrorPropAsAssertion(name, method, message) {
5786             if (arguments.length == 2) {
5787                 message = method;
5788                 method = name;
5789             }
5791             assert[name] = function (fake) {
5792                 verifyIsStub(fake);
5794                 var args = slice.call(arguments, 1);
5795                 var failed = false;
5797                 if (typeof method == "function") {
5798                     failed = !method(fake);
5799                 } else {
5800                     failed = typeof fake[method] == "function" ?
5801                         !fake[method].apply(fake, args) : !fake[method];
5802                 }
5804                 if (failed) {
5805                     failAssertion(this, (fake.printf || fake.proxy.printf).apply(fake, [message].concat(args)));
5806                 } else {
5807                     assert.pass(name);
5808                 }
5809             };
5810         }
5812         function exposedName(prefix, prop) {
5813             return !prefix || /^fail/.test(prop) ? prop :
5814                 prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
5815         }
5817         assert = {
5818             failException: "AssertError",
5820             fail: function fail(message) {
5821                 var error = new Error(message);
5822                 error.name = this.failException || assert.failException;
5824                 throw error;
5825             },
5827             pass: function pass(assertion) {},
5829             callOrder: function assertCallOrder() {
5830                 verifyIsStub.apply(null, arguments);
5831                 var expected = "", actual = "";
5833                 if (!sinon.calledInOrder(arguments)) {
5834                     try {
5835                         expected = [].join.call(arguments, ", ");
5836                         var calls = slice.call(arguments);
5837                         var i = calls.length;
5838                         while (i) {
5839                             if (!calls[--i].called) {
5840                                 calls.splice(i, 1);
5841                             }
5842                         }
5843                         actual = sinon.orderByFirstCall(calls).join(", ");
5844                     } catch (e) {
5845                         // If this fails, we'll just fall back to the blank string
5846                     }
5848                     failAssertion(this, "expected " + expected + " to be " +
5849                                 "called in order but were called as " + actual);
5850                 } else {
5851                     assert.pass("callOrder");
5852                 }
5853             },
5855             callCount: function assertCallCount(method, count) {
5856                 verifyIsStub(method);
5858                 if (method.callCount != count) {
5859                     var msg = "expected %n to be called " + sinon.timesInWords(count) +
5860                         " but was called %c%C";
5861                     failAssertion(this, method.printf(msg));
5862                 } else {
5863                     assert.pass("callCount");
5864                 }
5865             },
5867             expose: function expose(target, options) {
5868                 if (!target) {
5869                     throw new TypeError("target is null or undefined");
5870                 }
5872                 var o = options || {};
5873                 var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
5874                 var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
5876                 for (var method in this) {
5877                     if (method != "expose" && (includeFail || !/^(fail)/.test(method))) {
5878                         target[exposedName(prefix, method)] = this[method];
5879                     }
5880                 }
5882                 return target;
5883             },
5885             match: function match(actual, expectation) {
5886                 var matcher = sinon.match(expectation);
5887                 if (matcher.test(actual)) {
5888                     assert.pass("match");
5889                 } else {
5890                     var formatted = [
5891                         "expected value to match",
5892                         "    expected = " + sinon.format(expectation),
5893                         "    actual = " + sinon.format(actual)
5894                     ]
5895                     failAssertion(this, formatted.join("\n"));
5896                 }
5897             }
5898         };
5900         mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
5901         mirrorPropAsAssertion("notCalled", function (spy) {
5902             return !spy.called;
5903         }, "expected %n to not have been called but was called %c%C");
5904         mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
5905         mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
5906         mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
5907         mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
5908         mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
5909         mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
5910         mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
5911         mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
5912         mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
5913         mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
5914         mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
5915         mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
5916         mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
5917         mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
5918         mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
5919         mirrorPropAsAssertion("threw", "%n did not throw exception%C");
5920         mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
5922         sinon.assert = assert;
5923         return assert;
5924     }
5926     var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5927     var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5929     function loadDependencies(require, exports, module) {
5930         var sinon = require("./util/core");
5931         require("./match");
5932         require("./format");
5933         module.exports = makeApi(sinon);
5934     }
5936     if (isAMD) {
5937         define(loadDependencies);
5938     } else if (isNode) {
5939         loadDependencies(require, module.exports, module);
5940     } else if (!sinon) {
5941         return;
5942     } else {
5943         makeApi(sinon);
5944     }
5946 }(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
5948   return sinon;
5949 }));