]> git.proxmox.com Git - mirror_novnc.git/blob - vendor/sinon.js
Merge pull request #774 from novnc/refactor/es6-module-loader
[mirror_novnc.git] / vendor / sinon.js
1 /**
2 * Sinon.JS 1.17.6, 2016/09/19
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 */
35
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");
68
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 }
76
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 }
83
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 }
106
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 }
126
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 }
140
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 }
154
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 }
164
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 }
181
182
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) {
199
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 = {};
212
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) {
219
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)) {
226
227 return true;
228 }
229
230 return false;
231 }
232
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) {
239
240 var i;
241 for (i = 0; i < objects.length; i++) {
242 if (objects[i] === obj) {
243 return i;
244 }
245 }
246
247 return -1;
248 }
249
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;
254
255 // == null also matches undefined
256 if (obj1 === obj2 ||
257 isNaN(obj1) || isNaN(obj2) ||
258 obj1 == null || obj2 == null ||
259 type1 !== "object" || type2 !== "object") {
260
261 return identical(obj1, obj2);
262 }
263
264 // Elements are only equal if identical(expected, actual)
265 if (isElement(obj1) || isElement(obj2)) { return false; }
266
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 }
273
274 if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
275 if (obj1.toString() !== obj2.toString()) { return false; }
276 }
277
278 var class1 = getClass(obj1);
279 var class2 = getClass(obj2);
280 var keys1 = keys(obj1);
281 var keys2 = keys(obj2);
282
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 }
291
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;
298
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 }
304
305 // Start of the cyclic logic
306
307 value1 = obj1[key];
308 value2 = obj2[key];
309
310 isObject1 = isObject(value1);
311 isObject2 = isObject(value2);
312
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;
318
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) + ']';
329
330 // stop recursion if current objects are already compared
331 if (compared[newPath1 + newPath2]) {
332 return true;
333 }
334
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 }
344
345 // remember that the current objects are already compared
346 if (isObject1 && isObject2) {
347 compared[newPath1 + newPath2] = true;
348 }
349
350 // End of cyclic logic
351
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 }
358
359 return true;
360
361 }(obj1, obj2, '$1', '$2'));
362 }
363
364 var match;
365
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 }
379
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 }
391
392 if (typeof matcher === "function") {
393 return matcher(object) === true;
394 }
395
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 }
402
403 if (typeof matcher === "number") {
404 return matcher === object;
405 }
406
407 if (typeof matcher === "boolean") {
408 return matcher === object;
409 }
410
411 if (typeof(matcher) === "undefined") {
412 return typeof(object) === "undefined";
413 }
414
415 if (matcher === null) {
416 return object === null;
417 }
418
419 if (getClass(object) === "Array" && getClass(matcher) === "Array") {
420 return arrayContains(object, matcher);
421 }
422
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 }
444
445 throw new Error("Matcher was not a string, a number, a " +
446 "function, a boolean or an object");
447 };
448
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 };
459 });
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 };
472
473 var hasOwn = Object.prototype.hasOwnProperty;
474
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 }
488
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 }
496
497 function constructorName(f, object) {
498 var name = functionName(object && object.constructor);
499 var excludes = f.excludeConstructors ||
500 formatio.excludeConstructors || [];
501
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 }
510
511 return name;
512 }
513
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 }
522
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 }
529
530 if (typeof object === "function" && !(object instanceof RegExp)) {
531 return ascii.func(object);
532 }
533
534 processed = processed || [];
535
536 if (isCircular(object, processed)) { return "[Circular]"; }
537
538 if (Object.prototype.toString.call(object) === "[object Array]") {
539 return ascii.array.call(f, object, processed);
540 }
541
542 if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
543 if (samsam.isElement(object)) { return ascii.element(object); }
544
545 if (typeof object.toString === "function" &&
546 object.toString !== Object.prototype.toString) {
547 return object.toString();
548 }
549
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 }
556
557 return ascii.object.call(f, object, processed, indent);
558 }
559
560 ascii.func = function (func) {
561 return "function " + functionName(func) + "() {}";
562 };
563
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;
571
572 for (i = 0; i < l; ++i) {
573 pieces.push(ascii(this, array[i], processed));
574 }
575
576 if(l < array.length)
577 pieces.push("[... " + (array.length - l) + " more elements]");
578
579 return "[" + pieces.join(", ") + "]";
580 };
581
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;
591
592 for (i = 0; i < l; ++i) {
593 prop = properties[i];
594 obj = object[prop];
595
596 if (isCircular(obj, processed)) {
597 str = "[Circular]";
598 } else {
599 str = ascii(this, obj, processed, indent + 2);
600 }
601
602 str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
603 length += str.length;
604 pieces.push(str);
605 }
606
607 var cons = constructorName(this, object);
608 var prefix = cons ? "[" + cons + "] " : "";
609 var is = "";
610 for (i = 0, k = indent; i < k; ++i) { is += " "; }
611
612 if(l < properties.length)
613 pieces.push("[... " + (properties.length - l) + " more elements]");
614
615 if (length + indent > 80) {
616 return prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" +
617 is + "}";
618 }
619 return prefix + "{ " + pieces.join(", ") + " }";
620 };
621
622 ascii.element = function (element) {
623 var tagName = element.tagName.toLowerCase();
624 var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
625
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 }
634
635 var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
636 var content = element.innerHTML;
637
638 if (content.length > 20) {
639 content = content.substr(0, 20) + "[...]";
640 }
641
642 var res = formatted + pairs.join(" ") + ">" + content +
643 "</" + tagName + ">";
644
645 return res.replace(/ contentEditable="inherit"/, "");
646 };
647
648 function Formatio(options) {
649 for (var opt in options) {
650 this[opt] = options[opt];
651 }
652 }
653
654 Formatio.prototype = {
655 functionName: functionName,
656
657 configure: function (options) {
658 return new Formatio(options);
659 },
660
661 constructorName: function (object) {
662 return constructorName(this, object);
663 },
664
665 ascii: function (object, processed, indent) {
666 return ascii(this, object, processed, indent);
667 }
668 };
669
670 return Formatio.prototype;
671 });
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 /*global global, window*/
675 /**
676 * @author Christian Johansen (christian@cjohansen.no) and contributors
677 * @license BSD
678 *
679 * Copyright (c) 2010-2014 Christian Johansen
680 */
681
682 (function (global) {
683
684 // Make properties writable in IE, as per
685 // http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
686 // JSLint being anal
687 var glbl = global;
688
689 global.setTimeout = glbl.setTimeout;
690 global.clearTimeout = glbl.clearTimeout;
691 global.setInterval = glbl.setInterval;
692 global.clearInterval = glbl.clearInterval;
693 global.Date = glbl.Date;
694
695 // setImmediate is not a standard function
696 // avoid adding the prop to the window object if not present
697 if('setImmediate' in global) {
698 global.setImmediate = glbl.setImmediate;
699 global.clearImmediate = glbl.clearImmediate;
700 }
701
702 // node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
703 // browsers, a number.
704 // see https://github.com/cjohansen/Sinon.JS/pull/436
705
706 var NOOP = function () { return undefined; };
707 var timeoutResult = setTimeout(NOOP, 0);
708 var addTimerReturnsObject = typeof timeoutResult === "object";
709 clearTimeout(timeoutResult);
710
711 var NativeDate = Date;
712 var uniqueTimerId = 1;
713
714 /**
715 * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
716 * number of milliseconds. This is used to support human-readable strings passed
717 * to clock.tick()
718 */
719 function parseTime(str) {
720 if (!str) {
721 return 0;
722 }
723
724 var strings = str.split(":");
725 var l = strings.length, i = l;
726 var ms = 0, parsed;
727
728 if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
729 throw new Error("tick only understands numbers and 'h:m:s'");
730 }
731
732 while (i--) {
733 parsed = parseInt(strings[i], 10);
734
735 if (parsed >= 60) {
736 throw new Error("Invalid time " + str);
737 }
738
739 ms += parsed * Math.pow(60, (l - i - 1));
740 }
741
742 return ms * 1000;
743 }
744
745 /**
746 * Used to grok the `now` parameter to createClock.
747 */
748 function getEpoch(epoch) {
749 if (!epoch) { return 0; }
750 if (typeof epoch.getTime === "function") { return epoch.getTime(); }
751 if (typeof epoch === "number") { return epoch; }
752 throw new TypeError("now should be milliseconds since UNIX epoch");
753 }
754
755 function inRange(from, to, timer) {
756 return timer && timer.callAt >= from && timer.callAt <= to;
757 }
758
759 function mirrorDateProperties(target, source) {
760 var prop;
761 for (prop in source) {
762 if (source.hasOwnProperty(prop)) {
763 target[prop] = source[prop];
764 }
765 }
766
767 // set special now implementation
768 if (source.now) {
769 target.now = function now() {
770 return target.clock.now;
771 };
772 } else {
773 delete target.now;
774 }
775
776 // set special toSource implementation
777 if (source.toSource) {
778 target.toSource = function toSource() {
779 return source.toSource();
780 };
781 } else {
782 delete target.toSource;
783 }
784
785 // set special toString implementation
786 target.toString = function toString() {
787 return source.toString();
788 };
789
790 target.prototype = source.prototype;
791 target.parse = source.parse;
792 target.UTC = source.UTC;
793 target.prototype.toUTCString = source.prototype.toUTCString;
794
795 return target;
796 }
797
798 function createDate() {
799 function ClockDate(year, month, date, hour, minute, second, ms) {
800 // Defensive and verbose to avoid potential harm in passing
801 // explicit undefined when user does not pass argument
802 switch (arguments.length) {
803 case 0:
804 return new NativeDate(ClockDate.clock.now);
805 case 1:
806 return new NativeDate(year);
807 case 2:
808 return new NativeDate(year, month);
809 case 3:
810 return new NativeDate(year, month, date);
811 case 4:
812 return new NativeDate(year, month, date, hour);
813 case 5:
814 return new NativeDate(year, month, date, hour, minute);
815 case 6:
816 return new NativeDate(year, month, date, hour, minute, second);
817 default:
818 return new NativeDate(year, month, date, hour, minute, second, ms);
819 }
820 }
821
822 return mirrorDateProperties(ClockDate, NativeDate);
823 }
824
825 function addTimer(clock, timer) {
826 if (timer.func === undefined) {
827 throw new Error("Callback must be provided to timer calls");
828 }
829
830 if (!clock.timers) {
831 clock.timers = {};
832 }
833
834 timer.id = uniqueTimerId++;
835 timer.createdAt = clock.now;
836 timer.callAt = clock.now + (timer.delay || (clock.duringTick ? 1 : 0));
837
838 clock.timers[timer.id] = timer;
839
840 if (addTimerReturnsObject) {
841 return {
842 id: timer.id,
843 ref: NOOP,
844 unref: NOOP
845 };
846 }
847
848 return timer.id;
849 }
850
851
852 function compareTimers(a, b) {
853 // Sort first by absolute timing
854 if (a.callAt < b.callAt) {
855 return -1;
856 }
857 if (a.callAt > b.callAt) {
858 return 1;
859 }
860
861 // Sort next by immediate, immediate timers take precedence
862 if (a.immediate && !b.immediate) {
863 return -1;
864 }
865 if (!a.immediate && b.immediate) {
866 return 1;
867 }
868
869 // Sort next by creation time, earlier-created timers take precedence
870 if (a.createdAt < b.createdAt) {
871 return -1;
872 }
873 if (a.createdAt > b.createdAt) {
874 return 1;
875 }
876
877 // Sort next by id, lower-id timers take precedence
878 if (a.id < b.id) {
879 return -1;
880 }
881 if (a.id > b.id) {
882 return 1;
883 }
884
885 // As timer ids are unique, no fallback `0` is necessary
886 }
887
888 function firstTimerInRange(clock, from, to) {
889 var timers = clock.timers,
890 timer = null,
891 id,
892 isInRange;
893
894 for (id in timers) {
895 if (timers.hasOwnProperty(id)) {
896 isInRange = inRange(from, to, timers[id]);
897
898 if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
899 timer = timers[id];
900 }
901 }
902 }
903
904 return timer;
905 }
906
907 function callTimer(clock, timer) {
908 var exception;
909
910 if (typeof timer.interval === "number") {
911 clock.timers[timer.id].callAt += timer.interval;
912 } else {
913 delete clock.timers[timer.id];
914 }
915
916 try {
917 if (typeof timer.func === "function") {
918 timer.func.apply(null, timer.args);
919 } else {
920 eval(timer.func);
921 }
922 } catch (e) {
923 exception = e;
924 }
925
926 if (!clock.timers[timer.id]) {
927 if (exception) {
928 throw exception;
929 }
930 return;
931 }
932
933 if (exception) {
934 throw exception;
935 }
936 }
937
938 function timerType(timer) {
939 if (timer.immediate) {
940 return "Immediate";
941 } else if (typeof timer.interval !== "undefined") {
942 return "Interval";
943 } else {
944 return "Timeout";
945 }
946 }
947
948 function clearTimer(clock, timerId, ttype) {
949 if (!timerId) {
950 // null appears to be allowed in most browsers, and appears to be
951 // relied upon by some libraries, like Bootstrap carousel
952 return;
953 }
954
955 if (!clock.timers) {
956 clock.timers = [];
957 }
958
959 // in Node, timerId is an object with .ref()/.unref(), and
960 // its .id field is the actual timer id.
961 if (typeof timerId === "object") {
962 timerId = timerId.id;
963 }
964
965 if (clock.timers.hasOwnProperty(timerId)) {
966 // check that the ID matches a timer of the correct type
967 var timer = clock.timers[timerId];
968 if (timerType(timer) === ttype) {
969 delete clock.timers[timerId];
970 } else {
971 throw new Error("Cannot clear timer: timer created with set" + ttype + "() but cleared with clear" + timerType(timer) + "()");
972 }
973 }
974 }
975
976 function uninstall(clock, target) {
977 var method,
978 i,
979 l;
980
981 for (i = 0, l = clock.methods.length; i < l; i++) {
982 method = clock.methods[i];
983
984 if (target[method].hadOwnProperty) {
985 target[method] = clock["_" + method];
986 } else {
987 try {
988 delete target[method];
989 } catch (ignore) {}
990 }
991 }
992
993 // Prevent multiple executions which will completely remove these props
994 clock.methods = [];
995 }
996
997 function hijackMethod(target, method, clock) {
998 var prop;
999
1000 clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
1001 clock["_" + method] = target[method];
1002
1003 if (method === "Date") {
1004 var date = mirrorDateProperties(clock[method], target[method]);
1005 target[method] = date;
1006 } else {
1007 target[method] = function () {
1008 return clock[method].apply(clock, arguments);
1009 };
1010
1011 for (prop in clock[method]) {
1012 if (clock[method].hasOwnProperty(prop)) {
1013 target[method][prop] = clock[method][prop];
1014 }
1015 }
1016 }
1017
1018 target[method].clock = clock;
1019 }
1020
1021 var timers = {
1022 setTimeout: setTimeout,
1023 clearTimeout: clearTimeout,
1024 setImmediate: global.setImmediate,
1025 clearImmediate: global.clearImmediate,
1026 setInterval: setInterval,
1027 clearInterval: clearInterval,
1028 Date: Date
1029 };
1030
1031 var keys = Object.keys || function (obj) {
1032 var ks = [],
1033 key;
1034
1035 for (key in obj) {
1036 if (obj.hasOwnProperty(key)) {
1037 ks.push(key);
1038 }
1039 }
1040
1041 return ks;
1042 };
1043
1044 exports.timers = timers;
1045
1046 function createClock(now) {
1047 var clock = {
1048 now: getEpoch(now),
1049 timeouts: {},
1050 Date: createDate()
1051 };
1052
1053 clock.Date.clock = clock;
1054
1055 clock.setTimeout = function setTimeout(func, timeout) {
1056 return addTimer(clock, {
1057 func: func,
1058 args: Array.prototype.slice.call(arguments, 2),
1059 delay: timeout
1060 });
1061 };
1062
1063 clock.clearTimeout = function clearTimeout(timerId) {
1064 return clearTimer(clock, timerId, "Timeout");
1065 };
1066
1067 clock.setInterval = function setInterval(func, timeout) {
1068 return addTimer(clock, {
1069 func: func,
1070 args: Array.prototype.slice.call(arguments, 2),
1071 delay: timeout,
1072 interval: timeout
1073 });
1074 };
1075
1076 clock.clearInterval = function clearInterval(timerId) {
1077 return clearTimer(clock, timerId, "Interval");
1078 };
1079
1080 clock.setImmediate = function setImmediate(func) {
1081 return addTimer(clock, {
1082 func: func,
1083 args: Array.prototype.slice.call(arguments, 1),
1084 immediate: true
1085 });
1086 };
1087
1088 clock.clearImmediate = function clearImmediate(timerId) {
1089 return clearTimer(clock, timerId, "Immediate");
1090 };
1091
1092 clock.tick = function tick(ms) {
1093 ms = typeof ms === "number" ? ms : parseTime(ms);
1094 var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
1095 var timer = firstTimerInRange(clock, tickFrom, tickTo);
1096 var oldNow;
1097
1098 clock.duringTick = true;
1099
1100 var firstException;
1101 while (timer && tickFrom <= tickTo) {
1102 if (clock.timers[timer.id]) {
1103 tickFrom = clock.now = timer.callAt;
1104 try {
1105 oldNow = clock.now;
1106 callTimer(clock, timer);
1107 // compensate for any setSystemTime() call during timer callback
1108 if (oldNow !== clock.now) {
1109 tickFrom += clock.now - oldNow;
1110 tickTo += clock.now - oldNow;
1111 previous += clock.now - oldNow;
1112 }
1113 } catch (e) {
1114 firstException = firstException || e;
1115 }
1116 }
1117
1118 timer = firstTimerInRange(clock, previous, tickTo);
1119 previous = tickFrom;
1120 }
1121
1122 clock.duringTick = false;
1123 clock.now = tickTo;
1124
1125 if (firstException) {
1126 throw firstException;
1127 }
1128
1129 return clock.now;
1130 };
1131
1132 clock.reset = function reset() {
1133 clock.timers = {};
1134 };
1135
1136 clock.setSystemTime = function setSystemTime(now) {
1137 // determine time difference
1138 var newNow = getEpoch(now);
1139 var difference = newNow - clock.now;
1140
1141 // update 'system clock'
1142 clock.now = newNow;
1143
1144 // update timers and intervals to keep them stable
1145 for (var id in clock.timers) {
1146 if (clock.timers.hasOwnProperty(id)) {
1147 var timer = clock.timers[id];
1148 timer.createdAt += difference;
1149 timer.callAt += difference;
1150 }
1151 }
1152 };
1153
1154 return clock;
1155 }
1156 exports.createClock = createClock;
1157
1158 exports.install = function install(target, now, toFake) {
1159 var i,
1160 l;
1161
1162 if (typeof target === "number") {
1163 toFake = now;
1164 now = target;
1165 target = null;
1166 }
1167
1168 if (!target) {
1169 target = global;
1170 }
1171
1172 var clock = createClock(now);
1173
1174 clock.uninstall = function () {
1175 uninstall(clock, target);
1176 };
1177
1178 clock.methods = toFake || [];
1179
1180 if (clock.methods.length === 0) {
1181 clock.methods = keys(timers);
1182 }
1183
1184 for (i = 0, l = clock.methods.length; i < l; i++) {
1185 hijackMethod(target, clock.methods[i], clock);
1186 }
1187
1188 return clock;
1189 };
1190
1191 }(global || this));
1192
1193 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1194 },{}]},{},[1])(1)
1195 });
1196 })();
1197 var define;
1198 /**
1199 * Sinon core utilities. For internal use only.
1200 *
1201 * @author Christian Johansen (christian@cjohansen.no)
1202 * @license BSD
1203 *
1204 * Copyright (c) 2010-2013 Christian Johansen
1205 */
1206 var sinon = (function () {
1207 "use strict";
1208 // eslint-disable-line no-unused-vars
1209
1210 var sinonModule;
1211 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1212 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1213
1214 function loadDependencies(require, exports, module) {
1215 sinonModule = module.exports = require("./sinon/util/core");
1216 require("./sinon/extend");
1217 require("./sinon/walk");
1218 require("./sinon/typeOf");
1219 require("./sinon/times_in_words");
1220 require("./sinon/spy");
1221 require("./sinon/call");
1222 require("./sinon/behavior");
1223 require("./sinon/stub");
1224 require("./sinon/mock");
1225 require("./sinon/collection");
1226 require("./sinon/assert");
1227 require("./sinon/sandbox");
1228 require("./sinon/test");
1229 require("./sinon/test_case");
1230 require("./sinon/match");
1231 require("./sinon/format");
1232 require("./sinon/log_error");
1233 }
1234
1235 if (isAMD) {
1236 define(loadDependencies);
1237 } else if (isNode) {
1238 loadDependencies(require, module.exports, module);
1239 sinonModule = module.exports;
1240 } else {
1241 sinonModule = {};
1242 }
1243
1244 return sinonModule;
1245 }());
1246
1247 /**
1248 * @depend ../../sinon.js
1249 */
1250 /**
1251 * Sinon core utilities. For internal use only.
1252 *
1253 * @author Christian Johansen (christian@cjohansen.no)
1254 * @license BSD
1255 *
1256 * Copyright (c) 2010-2013 Christian Johansen
1257 */
1258 (function (sinonGlobal) {
1259
1260 var div = typeof document !== "undefined" && document.createElement("div");
1261 var hasOwn = Object.prototype.hasOwnProperty;
1262
1263 function isDOMNode(obj) {
1264 var success = false;
1265
1266 try {
1267 obj.appendChild(div);
1268 success = div.parentNode === obj;
1269 } catch (e) {
1270 return false;
1271 } finally {
1272 try {
1273 obj.removeChild(div);
1274 } catch (e) {
1275 // Remove failed, not much we can do about that
1276 }
1277 }
1278
1279 return success;
1280 }
1281
1282 function isElement(obj) {
1283 return div && obj && obj.nodeType === 1 && isDOMNode(obj);
1284 }
1285
1286 function isFunction(obj) {
1287 return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
1288 }
1289
1290 function isReallyNaN(val) {
1291 return typeof val === "number" && isNaN(val);
1292 }
1293
1294 function mirrorProperties(target, source) {
1295 for (var prop in source) {
1296 if (!hasOwn.call(target, prop)) {
1297 target[prop] = source[prop];
1298 }
1299 }
1300 }
1301
1302 function isRestorable(obj) {
1303 return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
1304 }
1305
1306 // Cheap way to detect if we have ES5 support.
1307 var hasES5Support = "keys" in Object;
1308
1309 function makeApi(sinon) {
1310 sinon.wrapMethod = function wrapMethod(object, property, method) {
1311 if (!object) {
1312 throw new TypeError("Should wrap property of object");
1313 }
1314
1315 if (typeof method !== "function" && typeof method !== "object") {
1316 throw new TypeError("Method wrapper should be a function or a property descriptor");
1317 }
1318
1319 function checkWrappedMethod(wrappedMethod) {
1320 var error;
1321
1322 if (!isFunction(wrappedMethod)) {
1323 error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
1324 property + " as function");
1325 } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
1326 error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
1327 } else if (wrappedMethod.calledBefore) {
1328 var verb = wrappedMethod.returns ? "stubbed" : "spied on";
1329 error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
1330 }
1331
1332 if (error) {
1333 if (wrappedMethod && wrappedMethod.stackTrace) {
1334 error.stack += "\n--------------\n" + wrappedMethod.stackTrace;
1335 }
1336 throw error;
1337 }
1338 }
1339
1340 var error, wrappedMethod, i;
1341
1342 function simplePropertyAssignment() {
1343 wrappedMethod = object[property];
1344 checkWrappedMethod(wrappedMethod);
1345 object[property] = method;
1346 method.displayName = property;
1347 }
1348
1349 // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
1350 // when using hasOwn.call on objects from other frames.
1351 var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
1352
1353 if (hasES5Support) {
1354 var methodDesc = (typeof method === "function") ? {value: method} : method;
1355 var wrappedMethodDesc = sinon.getPropertyDescriptor(object, property);
1356
1357 if (!wrappedMethodDesc) {
1358 error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
1359 property + " as function");
1360 } else if (wrappedMethodDesc.restore && wrappedMethodDesc.restore.sinon) {
1361 error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
1362 }
1363 if (error) {
1364 if (wrappedMethodDesc && wrappedMethodDesc.stackTrace) {
1365 error.stack += "\n--------------\n" + wrappedMethodDesc.stackTrace;
1366 }
1367 throw error;
1368 }
1369
1370 var types = sinon.objectKeys(methodDesc);
1371 for (i = 0; i < types.length; i++) {
1372 wrappedMethod = wrappedMethodDesc[types[i]];
1373 checkWrappedMethod(wrappedMethod);
1374 }
1375
1376 mirrorProperties(methodDesc, wrappedMethodDesc);
1377 for (i = 0; i < types.length; i++) {
1378 mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]);
1379 }
1380 Object.defineProperty(object, property, methodDesc);
1381
1382 // catch failing assignment
1383 // this is the converse of the check in `.restore` below
1384 if ( typeof method === "function" && object[property] !== method ) {
1385 // correct any wrongdoings caused by the defineProperty call above,
1386 // such as adding new items (if object was a Storage object)
1387 delete object[property];
1388 simplePropertyAssignment();
1389 }
1390 } else {
1391 simplePropertyAssignment();
1392 }
1393
1394 method.displayName = property;
1395
1396 // Set up a stack trace which can be used later to find what line of
1397 // code the original method was created on.
1398 method.stackTrace = (new Error("Stack Trace for original")).stack;
1399
1400 method.restore = function () {
1401 // For prototype properties try to reset by delete first.
1402 // If this fails (ex: localStorage on mobile safari) then force a reset
1403 // via direct assignment.
1404 if (!owned) {
1405 // In some cases `delete` may throw an error
1406 try {
1407 delete object[property];
1408 } catch (e) {} // eslint-disable-line no-empty
1409 // For native code functions `delete` fails without throwing an error
1410 // on Chrome < 43, PhantomJS, etc.
1411 } else if (hasES5Support) {
1412 Object.defineProperty(object, property, wrappedMethodDesc);
1413 }
1414
1415 // Use strict equality comparison to check failures then force a reset
1416 // via direct assignment.
1417 if (object[property] === method) {
1418 object[property] = wrappedMethod;
1419 }
1420 };
1421
1422 method.restore.sinon = true;
1423
1424 if (!hasES5Support) {
1425 mirrorProperties(method, wrappedMethod);
1426 }
1427
1428 return method;
1429 };
1430
1431 sinon.create = function create(proto) {
1432 var F = function () {};
1433 F.prototype = proto;
1434 return new F();
1435 };
1436
1437 sinon.deepEqual = function deepEqual(a, b) {
1438 if (sinon.match && sinon.match.isMatcher(a)) {
1439 return a.test(b);
1440 }
1441
1442 if (typeof a !== "object" || typeof b !== "object") {
1443 return isReallyNaN(a) && isReallyNaN(b) || a === b;
1444 }
1445
1446 if (isElement(a) || isElement(b)) {
1447 return a === b;
1448 }
1449
1450 if (a === b) {
1451 return true;
1452 }
1453
1454 if ((a === null && b !== null) || (a !== null && b === null)) {
1455 return false;
1456 }
1457
1458 if (a instanceof RegExp && b instanceof RegExp) {
1459 return (a.source === b.source) && (a.global === b.global) &&
1460 (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
1461 }
1462
1463 var aString = Object.prototype.toString.call(a);
1464 if (aString !== Object.prototype.toString.call(b)) {
1465 return false;
1466 }
1467
1468 if (aString === "[object Date]") {
1469 return a.valueOf() === b.valueOf();
1470 }
1471
1472 var prop;
1473 var aLength = 0;
1474 var bLength = 0;
1475
1476 if (aString === "[object Array]" && a.length !== b.length) {
1477 return false;
1478 }
1479
1480 for (prop in a) {
1481 if (hasOwn.call(a, prop)) {
1482 aLength += 1;
1483
1484 if (!(prop in b)) {
1485 return false;
1486 }
1487
1488 if (!deepEqual(a[prop], b[prop])) {
1489 return false;
1490 }
1491 }
1492 }
1493
1494 for (prop in b) {
1495 if (hasOwn.call(b, prop)) {
1496 bLength += 1;
1497 }
1498 }
1499
1500 return aLength === bLength;
1501 };
1502
1503 sinon.functionName = function functionName(func) {
1504 var name = func.displayName || func.name;
1505
1506 // Use function decomposition as a last resort to get function
1507 // name. Does not rely on function decomposition to work - if it
1508 // doesn't debugging will be slightly less informative
1509 // (i.e. toString will say 'spy' rather than 'myFunc').
1510 if (!name) {
1511 var matches = func.toString().match(/function ([^\s\(]+)/);
1512 name = matches && matches[1];
1513 }
1514
1515 return name;
1516 };
1517
1518 sinon.functionToString = function toString() {
1519 if (this.getCall && this.callCount) {
1520 var thisValue,
1521 prop;
1522 var i = this.callCount;
1523
1524 while (i--) {
1525 thisValue = this.getCall(i).thisValue;
1526
1527 for (prop in thisValue) {
1528 if (thisValue[prop] === this) {
1529 return prop;
1530 }
1531 }
1532 }
1533 }
1534
1535 return this.displayName || "sinon fake";
1536 };
1537
1538 sinon.objectKeys = function objectKeys(obj) {
1539 if (obj !== Object(obj)) {
1540 throw new TypeError("sinon.objectKeys called on a non-object");
1541 }
1542
1543 var keys = [];
1544 var key;
1545 for (key in obj) {
1546 if (hasOwn.call(obj, key)) {
1547 keys.push(key);
1548 }
1549 }
1550
1551 return keys;
1552 };
1553
1554 sinon.getPropertyDescriptor = function getPropertyDescriptor(object, property) {
1555 var proto = object;
1556 var descriptor;
1557
1558 while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
1559 proto = Object.getPrototypeOf(proto);
1560 }
1561 return descriptor;
1562 };
1563
1564 sinon.getConfig = function (custom) {
1565 var config = {};
1566 custom = custom || {};
1567 var defaults = sinon.defaultConfig;
1568
1569 for (var prop in defaults) {
1570 if (defaults.hasOwnProperty(prop)) {
1571 config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
1572 }
1573 }
1574
1575 return config;
1576 };
1577
1578 sinon.defaultConfig = {
1579 injectIntoThis: true,
1580 injectInto: null,
1581 properties: ["spy", "stub", "mock", "clock", "server", "requests"],
1582 useFakeTimers: true,
1583 useFakeServer: true
1584 };
1585
1586 sinon.timesInWords = function timesInWords(count) {
1587 return count === 1 && "once" ||
1588 count === 2 && "twice" ||
1589 count === 3 && "thrice" ||
1590 (count || 0) + " times";
1591 };
1592
1593 sinon.calledInOrder = function (spies) {
1594 for (var i = 1, l = spies.length; i < l; i++) {
1595 if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
1596 return false;
1597 }
1598 }
1599
1600 return true;
1601 };
1602
1603 sinon.orderByFirstCall = function (spies) {
1604 return spies.sort(function (a, b) {
1605 // uuid, won't ever be equal
1606 var aCall = a.getCall(0);
1607 var bCall = b.getCall(0);
1608 var aId = aCall && aCall.callId || -1;
1609 var bId = bCall && bCall.callId || -1;
1610
1611 return aId < bId ? -1 : 1;
1612 });
1613 };
1614
1615 sinon.createStubInstance = function (constructor) {
1616 if (typeof constructor !== "function") {
1617 throw new TypeError("The constructor should be a function.");
1618 }
1619 return sinon.stub(sinon.create(constructor.prototype));
1620 };
1621
1622 sinon.restore = function (object) {
1623 if (object !== null && typeof object === "object") {
1624 for (var prop in object) {
1625 if (isRestorable(object[prop])) {
1626 object[prop].restore();
1627 }
1628 }
1629 } else if (isRestorable(object)) {
1630 object.restore();
1631 }
1632 };
1633
1634 return sinon;
1635 }
1636
1637 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1638 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1639
1640 function loadDependencies(require, exports) {
1641 makeApi(exports);
1642 }
1643
1644 if (isAMD) {
1645 define(loadDependencies);
1646 return;
1647 }
1648
1649 if (isNode) {
1650 loadDependencies(require, module.exports, module);
1651 return;
1652 }
1653
1654 if (sinonGlobal) {
1655 makeApi(sinonGlobal);
1656 }
1657 }(
1658 typeof sinon === "object" && sinon // eslint-disable-line no-undef
1659 ));
1660
1661 /**
1662 * @depend util/core.js
1663 */
1664 (function (sinonGlobal) {
1665
1666 function makeApi(sinon) {
1667
1668 // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
1669 var hasDontEnumBug = (function () {
1670 var obj = {
1671 constructor: function () {
1672 return "0";
1673 },
1674 toString: function () {
1675 return "1";
1676 },
1677 valueOf: function () {
1678 return "2";
1679 },
1680 toLocaleString: function () {
1681 return "3";
1682 },
1683 prototype: function () {
1684 return "4";
1685 },
1686 isPrototypeOf: function () {
1687 return "5";
1688 },
1689 propertyIsEnumerable: function () {
1690 return "6";
1691 },
1692 hasOwnProperty: function () {
1693 return "7";
1694 },
1695 length: function () {
1696 return "8";
1697 },
1698 unique: function () {
1699 return "9";
1700 }
1701 };
1702
1703 var result = [];
1704 for (var prop in obj) {
1705 if (obj.hasOwnProperty(prop)) {
1706 result.push(obj[prop]());
1707 }
1708 }
1709 return result.join("") !== "0123456789";
1710 })();
1711
1712 /* Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will
1713 * override properties in previous sources.
1714 *
1715 * target - The Object to extend
1716 * sources - Objects to copy properties from.
1717 *
1718 * Returns the extended target
1719 */
1720 function extend(target /*, sources */) {
1721 var sources = Array.prototype.slice.call(arguments, 1);
1722 var source, i, prop;
1723
1724 for (i = 0; i < sources.length; i++) {
1725 source = sources[i];
1726
1727 for (prop in source) {
1728 if (source.hasOwnProperty(prop)) {
1729 target[prop] = source[prop];
1730 }
1731 }
1732
1733 // Make sure we copy (own) toString method even when in JScript with DontEnum bug
1734 // See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
1735 if (hasDontEnumBug && source.hasOwnProperty("toString") && source.toString !== target.toString) {
1736 target.toString = source.toString;
1737 }
1738 }
1739
1740 return target;
1741 }
1742
1743 sinon.extend = extend;
1744 return sinon.extend;
1745 }
1746
1747 function loadDependencies(require, exports, module) {
1748 var sinon = require("./util/core");
1749 module.exports = makeApi(sinon);
1750 }
1751
1752 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1753 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1754
1755 if (isAMD) {
1756 define(loadDependencies);
1757 return;
1758 }
1759
1760 if (isNode) {
1761 loadDependencies(require, module.exports, module);
1762 return;
1763 }
1764
1765 if (sinonGlobal) {
1766 makeApi(sinonGlobal);
1767 }
1768 }(
1769 typeof sinon === "object" && sinon // eslint-disable-line no-undef
1770 ));
1771
1772 /**
1773 * @depend util/core.js
1774 */
1775 (function (sinonGlobal) {
1776
1777 function makeApi(sinon) {
1778
1779 function timesInWords(count) {
1780 switch (count) {
1781 case 1:
1782 return "once";
1783 case 2:
1784 return "twice";
1785 case 3:
1786 return "thrice";
1787 default:
1788 return (count || 0) + " times";
1789 }
1790 }
1791
1792 sinon.timesInWords = timesInWords;
1793 return sinon.timesInWords;
1794 }
1795
1796 function loadDependencies(require, exports, module) {
1797 var core = require("./util/core");
1798 module.exports = makeApi(core);
1799 }
1800
1801 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1802 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1803
1804 if (isAMD) {
1805 define(loadDependencies);
1806 return;
1807 }
1808
1809 if (isNode) {
1810 loadDependencies(require, module.exports, module);
1811 return;
1812 }
1813
1814 if (sinonGlobal) {
1815 makeApi(sinonGlobal);
1816 }
1817 }(
1818 typeof sinon === "object" && sinon // eslint-disable-line no-undef
1819 ));
1820
1821 /**
1822 * @depend util/core.js
1823 */
1824 /**
1825 * Format functions
1826 *
1827 * @author Christian Johansen (christian@cjohansen.no)
1828 * @license BSD
1829 *
1830 * Copyright (c) 2010-2014 Christian Johansen
1831 */
1832 (function (sinonGlobal) {
1833
1834 function makeApi(sinon) {
1835 function typeOf(value) {
1836 if (value === null) {
1837 return "null";
1838 } else if (value === undefined) {
1839 return "undefined";
1840 }
1841 var string = Object.prototype.toString.call(value);
1842 return string.substring(8, string.length - 1).toLowerCase();
1843 }
1844
1845 sinon.typeOf = typeOf;
1846 return sinon.typeOf;
1847 }
1848
1849 function loadDependencies(require, exports, module) {
1850 var core = require("./util/core");
1851 module.exports = makeApi(core);
1852 }
1853
1854 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1855 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1856
1857 if (isAMD) {
1858 define(loadDependencies);
1859 return;
1860 }
1861
1862 if (isNode) {
1863 loadDependencies(require, module.exports, module);
1864 return;
1865 }
1866
1867 if (sinonGlobal) {
1868 makeApi(sinonGlobal);
1869 }
1870 }(
1871 typeof sinon === "object" && sinon // eslint-disable-line no-undef
1872 ));
1873
1874 /**
1875 * @depend util/core.js
1876 * @depend typeOf.js
1877 */
1878 /*jslint eqeqeq: false, onevar: false, plusplus: false*/
1879 /*global module, require, sinon*/
1880 /**
1881 * Match functions
1882 *
1883 * @author Maximilian Antoni (mail@maxantoni.de)
1884 * @license BSD
1885 *
1886 * Copyright (c) 2012 Maximilian Antoni
1887 */
1888 (function (sinonGlobal) {
1889
1890 function makeApi(sinon) {
1891 function assertType(value, type, name) {
1892 var actual = sinon.typeOf(value);
1893 if (actual !== type) {
1894 throw new TypeError("Expected type of " + name + " to be " +
1895 type + ", but was " + actual);
1896 }
1897 }
1898
1899 var matcher = {
1900 toString: function () {
1901 return this.message;
1902 }
1903 };
1904
1905 function isMatcher(object) {
1906 return matcher.isPrototypeOf(object);
1907 }
1908
1909 function matchObject(expectation, actual) {
1910 if (actual === null || actual === undefined) {
1911 return false;
1912 }
1913 for (var key in expectation) {
1914 if (expectation.hasOwnProperty(key)) {
1915 var exp = expectation[key];
1916 var act = actual[key];
1917 if (isMatcher(exp)) {
1918 if (!exp.test(act)) {
1919 return false;
1920 }
1921 } else if (sinon.typeOf(exp) === "object") {
1922 if (!matchObject(exp, act)) {
1923 return false;
1924 }
1925 } else if (!sinon.deepEqual(exp, act)) {
1926 return false;
1927 }
1928 }
1929 }
1930 return true;
1931 }
1932
1933 function match(expectation, message) {
1934 var m = sinon.create(matcher);
1935 var type = sinon.typeOf(expectation);
1936 switch (type) {
1937 case "object":
1938 if (typeof expectation.test === "function") {
1939 m.test = function (actual) {
1940 return expectation.test(actual) === true;
1941 };
1942 m.message = "match(" + sinon.functionName(expectation.test) + ")";
1943 return m;
1944 }
1945 var str = [];
1946 for (var key in expectation) {
1947 if (expectation.hasOwnProperty(key)) {
1948 str.push(key + ": " + expectation[key]);
1949 }
1950 }
1951 m.test = function (actual) {
1952 return matchObject(expectation, actual);
1953 };
1954 m.message = "match(" + str.join(", ") + ")";
1955 break;
1956 case "number":
1957 m.test = function (actual) {
1958 // we need type coercion here
1959 return expectation == actual; // eslint-disable-line eqeqeq
1960 };
1961 break;
1962 case "string":
1963 m.test = function (actual) {
1964 if (typeof actual !== "string") {
1965 return false;
1966 }
1967 return actual.indexOf(expectation) !== -1;
1968 };
1969 m.message = "match(\"" + expectation + "\")";
1970 break;
1971 case "regexp":
1972 m.test = function (actual) {
1973 if (typeof actual !== "string") {
1974 return false;
1975 }
1976 return expectation.test(actual);
1977 };
1978 break;
1979 case "function":
1980 m.test = expectation;
1981 if (message) {
1982 m.message = message;
1983 } else {
1984 m.message = "match(" + sinon.functionName(expectation) + ")";
1985 }
1986 break;
1987 default:
1988 m.test = function (actual) {
1989 return sinon.deepEqual(expectation, actual);
1990 };
1991 }
1992 if (!m.message) {
1993 m.message = "match(" + expectation + ")";
1994 }
1995 return m;
1996 }
1997
1998 matcher.or = function (m2) {
1999 if (!arguments.length) {
2000 throw new TypeError("Matcher expected");
2001 } else if (!isMatcher(m2)) {
2002 m2 = match(m2);
2003 }
2004 var m1 = this;
2005 var or = sinon.create(matcher);
2006 or.test = function (actual) {
2007 return m1.test(actual) || m2.test(actual);
2008 };
2009 or.message = m1.message + ".or(" + m2.message + ")";
2010 return or;
2011 };
2012
2013 matcher.and = function (m2) {
2014 if (!arguments.length) {
2015 throw new TypeError("Matcher expected");
2016 } else if (!isMatcher(m2)) {
2017 m2 = match(m2);
2018 }
2019 var m1 = this;
2020 var and = sinon.create(matcher);
2021 and.test = function (actual) {
2022 return m1.test(actual) && m2.test(actual);
2023 };
2024 and.message = m1.message + ".and(" + m2.message + ")";
2025 return and;
2026 };
2027
2028 match.isMatcher = isMatcher;
2029
2030 match.any = match(function () {
2031 return true;
2032 }, "any");
2033
2034 match.defined = match(function (actual) {
2035 return actual !== null && actual !== undefined;
2036 }, "defined");
2037
2038 match.truthy = match(function (actual) {
2039 return !!actual;
2040 }, "truthy");
2041
2042 match.falsy = match(function (actual) {
2043 return !actual;
2044 }, "falsy");
2045
2046 match.same = function (expectation) {
2047 return match(function (actual) {
2048 return expectation === actual;
2049 }, "same(" + expectation + ")");
2050 };
2051
2052 match.typeOf = function (type) {
2053 assertType(type, "string", "type");
2054 return match(function (actual) {
2055 return sinon.typeOf(actual) === type;
2056 }, "typeOf(\"" + type + "\")");
2057 };
2058
2059 match.instanceOf = function (type) {
2060 assertType(type, "function", "type");
2061 return match(function (actual) {
2062 return actual instanceof type;
2063 }, "instanceOf(" + sinon.functionName(type) + ")");
2064 };
2065
2066 function createPropertyMatcher(propertyTest, messagePrefix) {
2067 return function (property, value) {
2068 assertType(property, "string", "property");
2069 var onlyProperty = arguments.length === 1;
2070 var message = messagePrefix + "(\"" + property + "\"";
2071 if (!onlyProperty) {
2072 message += ", " + value;
2073 }
2074 message += ")";
2075 return match(function (actual) {
2076 if (actual === undefined || actual === null ||
2077 !propertyTest(actual, property)) {
2078 return false;
2079 }
2080 return onlyProperty || sinon.deepEqual(value, actual[property]);
2081 }, message);
2082 };
2083 }
2084
2085 match.has = createPropertyMatcher(function (actual, property) {
2086 if (typeof actual === "object") {
2087 return property in actual;
2088 }
2089 return actual[property] !== undefined;
2090 }, "has");
2091
2092 match.hasOwn = createPropertyMatcher(function (actual, property) {
2093 return actual.hasOwnProperty(property);
2094 }, "hasOwn");
2095
2096 match.bool = match.typeOf("boolean");
2097 match.number = match.typeOf("number");
2098 match.string = match.typeOf("string");
2099 match.object = match.typeOf("object");
2100 match.func = match.typeOf("function");
2101 match.array = match.typeOf("array");
2102 match.regexp = match.typeOf("regexp");
2103 match.date = match.typeOf("date");
2104
2105 sinon.match = match;
2106 return match;
2107 }
2108
2109 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
2110 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2111
2112 function loadDependencies(require, exports, module) {
2113 var sinon = require("./util/core");
2114 require("./typeOf");
2115 module.exports = makeApi(sinon);
2116 }
2117
2118 if (isAMD) {
2119 define(loadDependencies);
2120 return;
2121 }
2122
2123 if (isNode) {
2124 loadDependencies(require, module.exports, module);
2125 return;
2126 }
2127
2128 if (sinonGlobal) {
2129 makeApi(sinonGlobal);
2130 }
2131 }(
2132 typeof sinon === "object" && sinon // eslint-disable-line no-undef
2133 ));
2134
2135 /**
2136 * @depend util/core.js
2137 */
2138 /**
2139 * Format functions
2140 *
2141 * @author Christian Johansen (christian@cjohansen.no)
2142 * @license BSD
2143 *
2144 * Copyright (c) 2010-2014 Christian Johansen
2145 */
2146 (function (sinonGlobal, formatio) {
2147
2148 function makeApi(sinon) {
2149 function valueFormatter(value) {
2150 return "" + value;
2151 }
2152
2153 function getFormatioFormatter() {
2154 var formatter = formatio.configure({
2155 quoteStrings: false,
2156 limitChildrenCount: 250
2157 });
2158
2159 function format() {
2160 return formatter.ascii.apply(formatter, arguments);
2161 }
2162
2163 return format;
2164 }
2165
2166 function getNodeFormatter() {
2167 try {
2168 var util = require("util");
2169 } catch (e) {
2170 /* Node, but no util module - would be very old, but better safe than sorry */
2171 }
2172
2173 function format(v) {
2174 var isObjectWithNativeToString = typeof v === "object" && v.toString === Object.prototype.toString;
2175 return isObjectWithNativeToString ? util.inspect(v) : v;
2176 }
2177
2178 return util ? format : valueFormatter;
2179 }
2180
2181 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
2182 var formatter;
2183
2184 if (isNode) {
2185 try {
2186 formatio = require("formatio");
2187 }
2188 catch (e) {} // eslint-disable-line no-empty
2189 }
2190
2191 if (formatio) {
2192 formatter = getFormatioFormatter();
2193 } else if (isNode) {
2194 formatter = getNodeFormatter();
2195 } else {
2196 formatter = valueFormatter;
2197 }
2198
2199 sinon.format = formatter;
2200 return sinon.format;
2201 }
2202
2203 function loadDependencies(require, exports, module) {
2204 var sinon = require("./util/core");
2205 module.exports = makeApi(sinon);
2206 }
2207
2208 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
2209 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2210
2211 if (isAMD) {
2212 define(loadDependencies);
2213 return;
2214 }
2215
2216 if (isNode) {
2217 loadDependencies(require, module.exports, module);
2218 return;
2219 }
2220
2221 if (sinonGlobal) {
2222 makeApi(sinonGlobal);
2223 }
2224 }(
2225 typeof sinon === "object" && sinon, // eslint-disable-line no-undef
2226 typeof formatio === "object" && formatio // eslint-disable-line no-undef
2227 ));
2228
2229 /**
2230 * @depend util/core.js
2231 * @depend match.js
2232 * @depend format.js
2233 */
2234 /**
2235 * Spy calls
2236 *
2237 * @author Christian Johansen (christian@cjohansen.no)
2238 * @author Maximilian Antoni (mail@maxantoni.de)
2239 * @license BSD
2240 *
2241 * Copyright (c) 2010-2013 Christian Johansen
2242 * Copyright (c) 2013 Maximilian Antoni
2243 */
2244 (function (sinonGlobal) {
2245
2246 var slice = Array.prototype.slice;
2247
2248 function makeApi(sinon) {
2249 function throwYieldError(proxy, text, args) {
2250 var msg = sinon.functionName(proxy) + text;
2251 if (args.length) {
2252 msg += " Received [" + slice.call(args).join(", ") + "]";
2253 }
2254 throw new Error(msg);
2255 }
2256
2257 var callProto = {
2258 calledOn: function calledOn(thisValue) {
2259 if (sinon.match && sinon.match.isMatcher(thisValue)) {
2260 return thisValue.test(this.thisValue);
2261 }
2262 return this.thisValue === thisValue;
2263 },
2264
2265 calledWith: function calledWith() {
2266 var l = arguments.length;
2267 if (l > this.args.length) {
2268 return false;
2269 }
2270 for (var i = 0; i < l; i += 1) {
2271 if (!sinon.deepEqual(arguments[i], this.args[i])) {
2272 return false;
2273 }
2274 }
2275
2276 return true;
2277 },
2278
2279 calledWithMatch: function calledWithMatch() {
2280 var l = arguments.length;
2281 if (l > this.args.length) {
2282 return false;
2283 }
2284 for (var i = 0; i < l; i += 1) {
2285 var actual = this.args[i];
2286 var expectation = arguments[i];
2287 if (!sinon.match || !sinon.match(expectation).test(actual)) {
2288 return false;
2289 }
2290 }
2291 return true;
2292 },
2293
2294 calledWithExactly: function calledWithExactly() {
2295 return arguments.length === this.args.length &&
2296 this.calledWith.apply(this, arguments);
2297 },
2298
2299 notCalledWith: function notCalledWith() {
2300 return !this.calledWith.apply(this, arguments);
2301 },
2302
2303 notCalledWithMatch: function notCalledWithMatch() {
2304 return !this.calledWithMatch.apply(this, arguments);
2305 },
2306
2307 returned: function returned(value) {
2308 return sinon.deepEqual(value, this.returnValue);
2309 },
2310
2311 threw: function threw(error) {
2312 if (typeof error === "undefined" || !this.exception) {
2313 return !!this.exception;
2314 }
2315
2316 return this.exception === error || this.exception.name === error;
2317 },
2318
2319 calledWithNew: function calledWithNew() {
2320 return this.proxy.prototype && this.thisValue instanceof this.proxy;
2321 },
2322
2323 calledBefore: function (other) {
2324 return this.callId < other.callId;
2325 },
2326
2327 calledAfter: function (other) {
2328 return this.callId > other.callId;
2329 },
2330
2331 callArg: function (pos) {
2332 this.args[pos]();
2333 },
2334
2335 callArgOn: function (pos, thisValue) {
2336 this.args[pos].apply(thisValue);
2337 },
2338
2339 callArgWith: function (pos) {
2340 this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
2341 },
2342
2343 callArgOnWith: function (pos, thisValue) {
2344 var args = slice.call(arguments, 2);
2345 this.args[pos].apply(thisValue, args);
2346 },
2347
2348 "yield": function () {
2349 this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
2350 },
2351
2352 yieldOn: function (thisValue) {
2353 var args = this.args;
2354 for (var i = 0, l = args.length; i < l; ++i) {
2355 if (typeof args[i] === "function") {
2356 args[i].apply(thisValue, slice.call(arguments, 1));
2357 return;
2358 }
2359 }
2360 throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
2361 },
2362
2363 yieldTo: function (prop) {
2364 this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
2365 },
2366
2367 yieldToOn: function (prop, thisValue) {
2368 var args = this.args;
2369 for (var i = 0, l = args.length; i < l; ++i) {
2370 if (args[i] && typeof args[i][prop] === "function") {
2371 args[i][prop].apply(thisValue, slice.call(arguments, 2));
2372 return;
2373 }
2374 }
2375 throwYieldError(this.proxy, " cannot yield to '" + prop +
2376 "' since no callback was passed.", args);
2377 },
2378
2379 getStackFrames: function () {
2380 // Omit the error message and the two top stack frames in sinon itself:
2381 return this.stack && this.stack.split("\n").slice(3);
2382 },
2383
2384 toString: function () {
2385 var callStr = this.proxy ? this.proxy.toString() + "(" : "";
2386 var args = [];
2387
2388 if (!this.args) {
2389 return ":(";
2390 }
2391
2392 for (var i = 0, l = this.args.length; i < l; ++i) {
2393 args.push(sinon.format(this.args[i]));
2394 }
2395
2396 callStr = callStr + args.join(", ") + ")";
2397
2398 if (typeof this.returnValue !== "undefined") {
2399 callStr += " => " + sinon.format(this.returnValue);
2400 }
2401
2402 if (this.exception) {
2403 callStr += " !" + this.exception.name;
2404
2405 if (this.exception.message) {
2406 callStr += "(" + this.exception.message + ")";
2407 }
2408 }
2409 if (this.stack) {
2410 callStr += this.getStackFrames()[0].replace(/^\s*(?:at\s+|@)?/, " at ");
2411
2412 }
2413
2414 return callStr;
2415 }
2416 };
2417
2418 callProto.invokeCallback = callProto.yield;
2419
2420 function createSpyCall(spy, thisValue, args, returnValue, exception, id, stack) {
2421 if (typeof id !== "number") {
2422 throw new TypeError("Call id is not a number");
2423 }
2424 var proxyCall = sinon.create(callProto);
2425 proxyCall.proxy = spy;
2426 proxyCall.thisValue = thisValue;
2427 proxyCall.args = args;
2428 proxyCall.returnValue = returnValue;
2429 proxyCall.exception = exception;
2430 proxyCall.callId = id;
2431 proxyCall.stack = stack;
2432
2433 return proxyCall;
2434 }
2435 createSpyCall.toString = callProto.toString; // used by mocks
2436
2437 sinon.spyCall = createSpyCall;
2438 return createSpyCall;
2439 }
2440
2441 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
2442 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2443
2444 function loadDependencies(require, exports, module) {
2445 var sinon = require("./util/core");
2446 require("./match");
2447 require("./format");
2448 module.exports = makeApi(sinon);
2449 }
2450
2451 if (isAMD) {
2452 define(loadDependencies);
2453 return;
2454 }
2455
2456 if (isNode) {
2457 loadDependencies(require, module.exports, module);
2458 return;
2459 }
2460
2461 if (sinonGlobal) {
2462 makeApi(sinonGlobal);
2463 }
2464 }(
2465 typeof sinon === "object" && sinon // eslint-disable-line no-undef
2466 ));
2467
2468 /**
2469 * @depend times_in_words.js
2470 * @depend util/core.js
2471 * @depend extend.js
2472 * @depend call.js
2473 * @depend format.js
2474 */
2475 /**
2476 * Spy functions
2477 *
2478 * @author Christian Johansen (christian@cjohansen.no)
2479 * @license BSD
2480 *
2481 * Copyright (c) 2010-2013 Christian Johansen
2482 */
2483 (function (sinonGlobal) {
2484
2485 function makeApi(sinon) {
2486 var push = Array.prototype.push;
2487 var slice = Array.prototype.slice;
2488 var callId = 0;
2489
2490 function spy(object, property, types) {
2491 if (!property && typeof object === "function") {
2492 return spy.create(object);
2493 }
2494
2495 if (!object && !property) {
2496 return spy.create(function () { });
2497 }
2498
2499 if (types) {
2500 var methodDesc = sinon.getPropertyDescriptor(object, property);
2501 for (var i = 0; i < types.length; i++) {
2502 methodDesc[types[i]] = spy.create(methodDesc[types[i]]);
2503 }
2504 return sinon.wrapMethod(object, property, methodDesc);
2505 }
2506
2507 return sinon.wrapMethod(object, property, spy.create(object[property]));
2508 }
2509
2510 function matchingFake(fakes, args, strict) {
2511 if (!fakes) {
2512 return undefined;
2513 }
2514
2515 for (var i = 0, l = fakes.length; i < l; i++) {
2516 if (fakes[i].matches(args, strict)) {
2517 return fakes[i];
2518 }
2519 }
2520 }
2521
2522 function incrementCallCount() {
2523 this.called = true;
2524 this.callCount += 1;
2525 this.notCalled = false;
2526 this.calledOnce = this.callCount === 1;
2527 this.calledTwice = this.callCount === 2;
2528 this.calledThrice = this.callCount === 3;
2529 }
2530
2531 function createCallProperties() {
2532 this.firstCall = this.getCall(0);
2533 this.secondCall = this.getCall(1);
2534 this.thirdCall = this.getCall(2);
2535 this.lastCall = this.getCall(this.callCount - 1);
2536 }
2537
2538 var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
2539 function createProxy(func, proxyLength) {
2540 // Retain the function length:
2541 var p;
2542 if (proxyLength) {
2543 eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) + // eslint-disable-line no-eval
2544 ") { return p.invoke(func, this, slice.call(arguments)); });");
2545 } else {
2546 p = function proxy() {
2547 return p.invoke(func, this, slice.call(arguments));
2548 };
2549 }
2550 p.isSinonProxy = true;
2551 return p;
2552 }
2553
2554 var uuid = 0;
2555
2556 // Public API
2557 var spyApi = {
2558 reset: function () {
2559 if (this.invoking) {
2560 var err = new Error("Cannot reset Sinon function while invoking it. " +
2561 "Move the call to .reset outside of the callback.");
2562 err.name = "InvalidResetException";
2563 throw err;
2564 }
2565
2566 this.called = false;
2567 this.notCalled = true;
2568 this.calledOnce = false;
2569 this.calledTwice = false;
2570 this.calledThrice = false;
2571 this.callCount = 0;
2572 this.firstCall = null;
2573 this.secondCall = null;
2574 this.thirdCall = null;
2575 this.lastCall = null;
2576 this.args = [];
2577 this.returnValues = [];
2578 this.thisValues = [];
2579 this.exceptions = [];
2580 this.callIds = [];
2581 this.stacks = [];
2582 if (this.fakes) {
2583 for (var i = 0; i < this.fakes.length; i++) {
2584 this.fakes[i].reset();
2585 }
2586 }
2587
2588 return this;
2589 },
2590
2591 create: function create(func, spyLength) {
2592 var name;
2593
2594 if (typeof func !== "function") {
2595 func = function () { };
2596 } else {
2597 name = sinon.functionName(func);
2598 }
2599
2600 if (!spyLength) {
2601 spyLength = func.length;
2602 }
2603
2604 var proxy = createProxy(func, spyLength);
2605
2606 sinon.extend(proxy, spy);
2607 delete proxy.create;
2608 sinon.extend(proxy, func);
2609
2610 proxy.reset();
2611 proxy.prototype = func.prototype;
2612 proxy.displayName = name || "spy";
2613 proxy.toString = sinon.functionToString;
2614 proxy.instantiateFake = sinon.spy.create;
2615 proxy.id = "spy#" + uuid++;
2616
2617 return proxy;
2618 },
2619
2620 invoke: function invoke(func, thisValue, args) {
2621 var matching = matchingFake(this.fakes, args);
2622 var exception, returnValue;
2623
2624 incrementCallCount.call(this);
2625 push.call(this.thisValues, thisValue);
2626 push.call(this.args, args);
2627 push.call(this.callIds, callId++);
2628
2629 // Make call properties available from within the spied function:
2630 createCallProperties.call(this);
2631
2632 try {
2633 this.invoking = true;
2634
2635 if (matching) {
2636 returnValue = matching.invoke(func, thisValue, args);
2637 } else {
2638 returnValue = (this.func || func).apply(thisValue, args);
2639 }
2640
2641 var thisCall = this.getCall(this.callCount - 1);
2642 if (thisCall.calledWithNew() && typeof returnValue !== "object") {
2643 returnValue = thisValue;
2644 }
2645 } catch (e) {
2646 exception = e;
2647 } finally {
2648 delete this.invoking;
2649 }
2650
2651 push.call(this.exceptions, exception);
2652 push.call(this.returnValues, returnValue);
2653 push.call(this.stacks, new Error().stack);
2654
2655 // Make return value and exception available in the calls:
2656 createCallProperties.call(this);
2657
2658 if (exception !== undefined) {
2659 throw exception;
2660 }
2661
2662 return returnValue;
2663 },
2664
2665 named: function named(name) {
2666 this.displayName = name;
2667 return this;
2668 },
2669
2670 getCall: function getCall(i) {
2671 if (i < 0 || i >= this.callCount) {
2672 return null;
2673 }
2674
2675 return sinon.spyCall(this, this.thisValues[i], this.args[i],
2676 this.returnValues[i], this.exceptions[i],
2677 this.callIds[i], this.stacks[i]);
2678 },
2679
2680 getCalls: function () {
2681 var calls = [];
2682 var i;
2683
2684 for (i = 0; i < this.callCount; i++) {
2685 calls.push(this.getCall(i));
2686 }
2687
2688 return calls;
2689 },
2690
2691 calledBefore: function calledBefore(spyFn) {
2692 if (!this.called) {
2693 return false;
2694 }
2695
2696 if (!spyFn.called) {
2697 return true;
2698 }
2699
2700 return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
2701 },
2702
2703 calledAfter: function calledAfter(spyFn) {
2704 if (!this.called || !spyFn.called) {
2705 return false;
2706 }
2707
2708 return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
2709 },
2710
2711 withArgs: function () {
2712 var args = slice.call(arguments);
2713
2714 if (this.fakes) {
2715 var match = matchingFake(this.fakes, args, true);
2716
2717 if (match) {
2718 return match;
2719 }
2720 } else {
2721 this.fakes = [];
2722 }
2723
2724 var original = this;
2725 var fake = this.instantiateFake();
2726 fake.matchingAguments = args;
2727 fake.parent = this;
2728 push.call(this.fakes, fake);
2729
2730 fake.withArgs = function () {
2731 return original.withArgs.apply(original, arguments);
2732 };
2733
2734 for (var i = 0; i < this.args.length; i++) {
2735 if (fake.matches(this.args[i])) {
2736 incrementCallCount.call(fake);
2737 push.call(fake.thisValues, this.thisValues[i]);
2738 push.call(fake.args, this.args[i]);
2739 push.call(fake.returnValues, this.returnValues[i]);
2740 push.call(fake.exceptions, this.exceptions[i]);
2741 push.call(fake.callIds, this.callIds[i]);
2742 }
2743 }
2744 createCallProperties.call(fake);
2745
2746 return fake;
2747 },
2748
2749 matches: function (args, strict) {
2750 var margs = this.matchingAguments;
2751
2752 if (margs.length <= args.length &&
2753 sinon.deepEqual(margs, args.slice(0, margs.length))) {
2754 return !strict || margs.length === args.length;
2755 }
2756 },
2757
2758 printf: function (format) {
2759 var spyInstance = this;
2760 var args = slice.call(arguments, 1);
2761 var formatter;
2762
2763 return (format || "").replace(/%(.)/g, function (match, specifyer) {
2764 formatter = spyApi.formatters[specifyer];
2765
2766 if (typeof formatter === "function") {
2767 return formatter.call(null, spyInstance, args);
2768 } else if (!isNaN(parseInt(specifyer, 10))) {
2769 return sinon.format(args[specifyer - 1]);
2770 }
2771
2772 return "%" + specifyer;
2773 });
2774 }
2775 };
2776
2777 function delegateToCalls(method, matchAny, actual, notCalled) {
2778 spyApi[method] = function () {
2779 if (!this.called) {
2780 if (notCalled) {
2781 return notCalled.apply(this, arguments);
2782 }
2783 return false;
2784 }
2785
2786 var currentCall;
2787 var matches = 0;
2788
2789 for (var i = 0, l = this.callCount; i < l; i += 1) {
2790 currentCall = this.getCall(i);
2791
2792 if (currentCall[actual || method].apply(currentCall, arguments)) {
2793 matches += 1;
2794
2795 if (matchAny) {
2796 return true;
2797 }
2798 }
2799 }
2800
2801 return matches === this.callCount;
2802 };
2803 }
2804
2805 delegateToCalls("calledOn", true);
2806 delegateToCalls("alwaysCalledOn", false, "calledOn");
2807 delegateToCalls("calledWith", true);
2808 delegateToCalls("calledWithMatch", true);
2809 delegateToCalls("alwaysCalledWith", false, "calledWith");
2810 delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
2811 delegateToCalls("calledWithExactly", true);
2812 delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
2813 delegateToCalls("neverCalledWith", false, "notCalledWith", function () {
2814 return true;
2815 });
2816 delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch", function () {
2817 return true;
2818 });
2819 delegateToCalls("threw", true);
2820 delegateToCalls("alwaysThrew", false, "threw");
2821 delegateToCalls("returned", true);
2822 delegateToCalls("alwaysReturned", false, "returned");
2823 delegateToCalls("calledWithNew", true);
2824 delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
2825 delegateToCalls("callArg", false, "callArgWith", function () {
2826 throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
2827 });
2828 spyApi.callArgWith = spyApi.callArg;
2829 delegateToCalls("callArgOn", false, "callArgOnWith", function () {
2830 throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
2831 });
2832 spyApi.callArgOnWith = spyApi.callArgOn;
2833 delegateToCalls("yield", false, "yield", function () {
2834 throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
2835 });
2836 // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
2837 spyApi.invokeCallback = spyApi.yield;
2838 delegateToCalls("yieldOn", false, "yieldOn", function () {
2839 throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
2840 });
2841 delegateToCalls("yieldTo", false, "yieldTo", function (property) {
2842 throw new Error(this.toString() + " cannot yield to '" + property +
2843 "' since it was not yet invoked.");
2844 });
2845 delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
2846 throw new Error(this.toString() + " cannot yield to '" + property +
2847 "' since it was not yet invoked.");
2848 });
2849
2850 spyApi.formatters = {
2851 c: function (spyInstance) {
2852 return sinon.timesInWords(spyInstance.callCount);
2853 },
2854
2855 n: function (spyInstance) {
2856 return spyInstance.toString();
2857 },
2858
2859 C: function (spyInstance) {
2860 var calls = [];
2861
2862 for (var i = 0, l = spyInstance.callCount; i < l; ++i) {
2863 var stringifiedCall = " " + spyInstance.getCall(i).toString();
2864 if (/\n/.test(calls[i - 1])) {
2865 stringifiedCall = "\n" + stringifiedCall;
2866 }
2867 push.call(calls, stringifiedCall);
2868 }
2869
2870 return calls.length > 0 ? "\n" + calls.join("\n") : "";
2871 },
2872
2873 t: function (spyInstance) {
2874 var objects = [];
2875
2876 for (var i = 0, l = spyInstance.callCount; i < l; ++i) {
2877 push.call(objects, sinon.format(spyInstance.thisValues[i]));
2878 }
2879
2880 return objects.join(", ");
2881 },
2882
2883 "*": function (spyInstance, args) {
2884 var formatted = [];
2885
2886 for (var i = 0, l = args.length; i < l; ++i) {
2887 push.call(formatted, sinon.format(args[i]));
2888 }
2889
2890 return formatted.join(", ");
2891 }
2892 };
2893
2894 sinon.extend(spy, spyApi);
2895
2896 spy.spyCall = sinon.spyCall;
2897 sinon.spy = spy;
2898
2899 return spy;
2900 }
2901
2902 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
2903 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2904
2905 function loadDependencies(require, exports, module) {
2906 var core = require("./util/core");
2907 require("./call");
2908 require("./extend");
2909 require("./times_in_words");
2910 require("./format");
2911 module.exports = makeApi(core);
2912 }
2913
2914 if (isAMD) {
2915 define(loadDependencies);
2916 return;
2917 }
2918
2919 if (isNode) {
2920 loadDependencies(require, module.exports, module);
2921 return;
2922 }
2923
2924 if (sinonGlobal) {
2925 makeApi(sinonGlobal);
2926 }
2927 }(
2928 typeof sinon === "object" && sinon // eslint-disable-line no-undef
2929 ));
2930
2931 /**
2932 * @depend util/core.js
2933 * @depend extend.js
2934 */
2935 /**
2936 * Stub behavior
2937 *
2938 * @author Christian Johansen (christian@cjohansen.no)
2939 * @author Tim Fischbach (mail@timfischbach.de)
2940 * @license BSD
2941 *
2942 * Copyright (c) 2010-2013 Christian Johansen
2943 */
2944 (function (sinonGlobal) {
2945
2946 var slice = Array.prototype.slice;
2947 var join = Array.prototype.join;
2948 var useLeftMostCallback = -1;
2949 var useRightMostCallback = -2;
2950
2951 var nextTick = (function () {
2952 if (typeof process === "object" && typeof process.nextTick === "function") {
2953 return process.nextTick;
2954 }
2955
2956 if (typeof setImmediate === "function") {
2957 return setImmediate;
2958 }
2959
2960 return function (callback) {
2961 setTimeout(callback, 0);
2962 };
2963 })();
2964
2965 function throwsException(error, message) {
2966 if (typeof error === "string") {
2967 this.exception = new Error(message || "");
2968 this.exception.name = error;
2969 } else if (!error) {
2970 this.exception = new Error("Error");
2971 } else {
2972 this.exception = error;
2973 }
2974
2975 return this;
2976 }
2977
2978 function getCallback(behavior, args) {
2979 var callArgAt = behavior.callArgAt;
2980
2981 if (callArgAt >= 0) {
2982 return args[callArgAt];
2983 }
2984
2985 var argumentList;
2986
2987 if (callArgAt === useLeftMostCallback) {
2988 argumentList = args;
2989 }
2990
2991 if (callArgAt === useRightMostCallback) {
2992 argumentList = slice.call(args).reverse();
2993 }
2994
2995 var callArgProp = behavior.callArgProp;
2996
2997 for (var i = 0, l = argumentList.length; i < l; ++i) {
2998 if (!callArgProp && typeof argumentList[i] === "function") {
2999 return argumentList[i];
3000 }
3001
3002 if (callArgProp && argumentList[i] &&
3003 typeof argumentList[i][callArgProp] === "function") {
3004 return argumentList[i][callArgProp];
3005 }
3006 }
3007
3008 return null;
3009 }
3010
3011 function makeApi(sinon) {
3012 function getCallbackError(behavior, func, args) {
3013 if (behavior.callArgAt < 0) {
3014 var msg;
3015
3016 if (behavior.callArgProp) {
3017 msg = sinon.functionName(behavior.stub) +
3018 " expected to yield to '" + behavior.callArgProp +
3019 "', but no object with such a property was passed.";
3020 } else {
3021 msg = sinon.functionName(behavior.stub) +
3022 " expected to yield, but no callback was passed.";
3023 }
3024
3025 if (args.length > 0) {
3026 msg += " Received [" + join.call(args, ", ") + "]";
3027 }
3028
3029 return msg;
3030 }
3031
3032 return "argument at index " + behavior.callArgAt + " is not a function: " + func;
3033 }
3034
3035 function callCallback(behavior, args) {
3036 if (typeof behavior.callArgAt === "number") {
3037 var func = getCallback(behavior, args);
3038
3039 if (typeof func !== "function") {
3040 throw new TypeError(getCallbackError(behavior, func, args));
3041 }
3042
3043 if (behavior.callbackAsync) {
3044 nextTick(function () {
3045 func.apply(behavior.callbackContext, behavior.callbackArguments);
3046 });
3047 } else {
3048 func.apply(behavior.callbackContext, behavior.callbackArguments);
3049 }
3050 }
3051 }
3052
3053 var proto = {
3054 create: function create(stub) {
3055 var behavior = sinon.extend({}, sinon.behavior);
3056 delete behavior.create;
3057 behavior.stub = stub;
3058
3059 return behavior;
3060 },
3061
3062 isPresent: function isPresent() {
3063 return (typeof this.callArgAt === "number" ||
3064 this.exception ||
3065 typeof this.returnArgAt === "number" ||
3066 this.returnThis ||
3067 this.returnValueDefined);
3068 },
3069
3070 invoke: function invoke(context, args) {
3071 callCallback(this, args);
3072
3073 if (this.exception) {
3074 throw this.exception;
3075 } else if (typeof this.returnArgAt === "number") {
3076 return args[this.returnArgAt];
3077 } else if (this.returnThis) {
3078 return context;
3079 }
3080
3081 return this.returnValue;
3082 },
3083
3084 onCall: function onCall(index) {
3085 return this.stub.onCall(index);
3086 },
3087
3088 onFirstCall: function onFirstCall() {
3089 return this.stub.onFirstCall();
3090 },
3091
3092 onSecondCall: function onSecondCall() {
3093 return this.stub.onSecondCall();
3094 },
3095
3096 onThirdCall: function onThirdCall() {
3097 return this.stub.onThirdCall();
3098 },
3099
3100 withArgs: function withArgs(/* arguments */) {
3101 throw new Error(
3102 "Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" " +
3103 "is not supported. Use \"stub.withArgs(...).onCall(...)\" " +
3104 "to define sequential behavior for calls with certain arguments."
3105 );
3106 },
3107
3108 callsArg: function callsArg(pos) {
3109 if (typeof pos !== "number") {
3110 throw new TypeError("argument index is not number");
3111 }
3112
3113 this.callArgAt = pos;
3114 this.callbackArguments = [];
3115 this.callbackContext = undefined;
3116 this.callArgProp = undefined;
3117 this.callbackAsync = false;
3118
3119 return this;
3120 },
3121
3122 callsArgOn: function callsArgOn(pos, context) {
3123 if (typeof pos !== "number") {
3124 throw new TypeError("argument index is not number");
3125 }
3126 if (typeof context !== "object") {
3127 throw new TypeError("argument context is not an object");
3128 }
3129
3130 this.callArgAt = pos;
3131 this.callbackArguments = [];
3132 this.callbackContext = context;
3133 this.callArgProp = undefined;
3134 this.callbackAsync = false;
3135
3136 return this;
3137 },
3138
3139 callsArgWith: function callsArgWith(pos) {
3140 if (typeof pos !== "number") {
3141 throw new TypeError("argument index is not number");
3142 }
3143
3144 this.callArgAt = pos;
3145 this.callbackArguments = slice.call(arguments, 1);
3146 this.callbackContext = undefined;
3147 this.callArgProp = undefined;
3148 this.callbackAsync = false;
3149
3150 return this;
3151 },
3152
3153 callsArgOnWith: function callsArgWith(pos, context) {
3154 if (typeof pos !== "number") {
3155 throw new TypeError("argument index is not number");
3156 }
3157 if (typeof context !== "object") {
3158 throw new TypeError("argument context is not an object");
3159 }
3160
3161 this.callArgAt = pos;
3162 this.callbackArguments = slice.call(arguments, 2);
3163 this.callbackContext = context;
3164 this.callArgProp = undefined;
3165 this.callbackAsync = false;
3166
3167 return this;
3168 },
3169
3170 yields: function () {
3171 this.callArgAt = useLeftMostCallback;
3172 this.callbackArguments = slice.call(arguments, 0);
3173 this.callbackContext = undefined;
3174 this.callArgProp = undefined;
3175 this.callbackAsync = false;
3176
3177 return this;
3178 },
3179
3180 yieldsRight: function () {
3181 this.callArgAt = useRightMostCallback;
3182 this.callbackArguments = slice.call(arguments, 0);
3183 this.callbackContext = undefined;
3184 this.callArgProp = undefined;
3185 this.callbackAsync = false;
3186
3187 return this;
3188 },
3189
3190 yieldsOn: function (context) {
3191 if (typeof context !== "object") {
3192 throw new TypeError("argument context is not an object");
3193 }
3194
3195 this.callArgAt = useLeftMostCallback;
3196 this.callbackArguments = slice.call(arguments, 1);
3197 this.callbackContext = context;
3198 this.callArgProp = undefined;
3199 this.callbackAsync = false;
3200
3201 return this;
3202 },
3203
3204 yieldsTo: function (prop) {
3205 this.callArgAt = useLeftMostCallback;
3206 this.callbackArguments = slice.call(arguments, 1);
3207 this.callbackContext = undefined;
3208 this.callArgProp = prop;
3209 this.callbackAsync = false;
3210
3211 return this;
3212 },
3213
3214 yieldsToOn: function (prop, context) {
3215 if (typeof context !== "object") {
3216 throw new TypeError("argument context is not an object");
3217 }
3218
3219 this.callArgAt = useLeftMostCallback;
3220 this.callbackArguments = slice.call(arguments, 2);
3221 this.callbackContext = context;
3222 this.callArgProp = prop;
3223 this.callbackAsync = false;
3224
3225 return this;
3226 },
3227
3228 throws: throwsException,
3229 throwsException: throwsException,
3230
3231 returns: function returns(value) {
3232 this.returnValue = value;
3233 this.returnValueDefined = true;
3234 this.exception = undefined;
3235
3236 return this;
3237 },
3238
3239 returnsArg: function returnsArg(pos) {
3240 if (typeof pos !== "number") {
3241 throw new TypeError("argument index is not number");
3242 }
3243
3244 this.returnArgAt = pos;
3245
3246 return this;
3247 },
3248
3249 returnsThis: function returnsThis() {
3250 this.returnThis = true;
3251
3252 return this;
3253 }
3254 };
3255
3256 function createAsyncVersion(syncFnName) {
3257 return function () {
3258 var result = this[syncFnName].apply(this, arguments);
3259 this.callbackAsync = true;
3260 return result;
3261 };
3262 }
3263
3264 // create asynchronous versions of callsArg* and yields* methods
3265 for (var method in proto) {
3266 // need to avoid creating anotherasync versions of the newly added async methods
3267 if (proto.hasOwnProperty(method) && method.match(/^(callsArg|yields)/) && !method.match(/Async/)) {
3268 proto[method + "Async"] = createAsyncVersion(method);
3269 }
3270 }
3271
3272 sinon.behavior = proto;
3273 return proto;
3274 }
3275
3276 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
3277 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3278
3279 function loadDependencies(require, exports, module) {
3280 var sinon = require("./util/core");
3281 require("./extend");
3282 module.exports = makeApi(sinon);
3283 }
3284
3285 if (isAMD) {
3286 define(loadDependencies);
3287 return;
3288 }
3289
3290 if (isNode) {
3291 loadDependencies(require, module.exports, module);
3292 return;
3293 }
3294
3295 if (sinonGlobal) {
3296 makeApi(sinonGlobal);
3297 }
3298 }(
3299 typeof sinon === "object" && sinon // eslint-disable-line no-undef
3300 ));
3301
3302 /**
3303 * @depend util/core.js
3304 */
3305 (function (sinonGlobal) {
3306
3307 function makeApi(sinon) {
3308 function walkInternal(obj, iterator, context, originalObj, seen) {
3309 var proto, prop;
3310
3311 if (typeof Object.getOwnPropertyNames !== "function") {
3312 // We explicitly want to enumerate through all of the prototype's properties
3313 // in this case, therefore we deliberately leave out an own property check.
3314 /* eslint-disable guard-for-in */
3315 for (prop in obj) {
3316 iterator.call(context, obj[prop], prop, obj);
3317 }
3318 /* eslint-enable guard-for-in */
3319
3320 return;
3321 }
3322
3323 Object.getOwnPropertyNames(obj).forEach(function (k) {
3324 if (!seen[k]) {
3325 seen[k] = true;
3326 var target = typeof Object.getOwnPropertyDescriptor(obj, k).get === "function" ?
3327 originalObj : obj;
3328 iterator.call(context, target[k], k, target);
3329 }
3330 });
3331
3332 proto = Object.getPrototypeOf(obj);
3333 if (proto) {
3334 walkInternal(proto, iterator, context, originalObj, seen);
3335 }
3336 }
3337
3338 /* Public: walks the prototype chain of an object and iterates over every own property
3339 * name encountered. The iterator is called in the same fashion that Array.prototype.forEach
3340 * works, where it is passed the value, key, and own object as the 1st, 2nd, and 3rd positional
3341 * argument, respectively. In cases where Object.getOwnPropertyNames is not available, walk will
3342 * default to using a simple for..in loop.
3343 *
3344 * obj - The object to walk the prototype chain for.
3345 * iterator - The function to be called on each pass of the walk.
3346 * context - (Optional) When given, the iterator will be called with this object as the receiver.
3347 */
3348 function walk(obj, iterator, context) {
3349 return walkInternal(obj, iterator, context, obj, {});
3350 }
3351
3352 sinon.walk = walk;
3353 return sinon.walk;
3354 }
3355
3356 function loadDependencies(require, exports, module) {
3357 var sinon = require("./util/core");
3358 module.exports = makeApi(sinon);
3359 }
3360
3361 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
3362 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3363
3364 if (isAMD) {
3365 define(loadDependencies);
3366 return;
3367 }
3368
3369 if (isNode) {
3370 loadDependencies(require, module.exports, module);
3371 return;
3372 }
3373
3374 if (sinonGlobal) {
3375 makeApi(sinonGlobal);
3376 }
3377 }(
3378 typeof sinon === "object" && sinon // eslint-disable-line no-undef
3379 ));
3380
3381 /**
3382 * @depend util/core.js
3383 * @depend extend.js
3384 * @depend spy.js
3385 * @depend behavior.js
3386 * @depend walk.js
3387 */
3388 /**
3389 * Stub functions
3390 *
3391 * @author Christian Johansen (christian@cjohansen.no)
3392 * @license BSD
3393 *
3394 * Copyright (c) 2010-2013 Christian Johansen
3395 */
3396 (function (sinonGlobal) {
3397
3398 function makeApi(sinon) {
3399 function stub(object, property, func) {
3400 if (!!func && typeof func !== "function" && typeof func !== "object") {
3401 throw new TypeError("Custom stub should be a function or a property descriptor");
3402 }
3403
3404 var wrapper;
3405
3406 if (func) {
3407 if (typeof func === "function") {
3408 wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
3409 } else {
3410 wrapper = func;
3411 if (sinon.spy && sinon.spy.create) {
3412 var types = sinon.objectKeys(wrapper);
3413 for (var i = 0; i < types.length; i++) {
3414 wrapper[types[i]] = sinon.spy.create(wrapper[types[i]]);
3415 }
3416 }
3417 }
3418 } else {
3419 var stubLength = 0;
3420 if (typeof object === "object" && typeof object[property] === "function") {
3421 stubLength = object[property].length;
3422 }
3423 wrapper = stub.create(stubLength);
3424 }
3425
3426 if (!object && typeof property === "undefined") {
3427 return sinon.stub.create();
3428 }
3429
3430 if (typeof property === "undefined" && typeof object === "object") {
3431 sinon.walk(object || {}, function (value, prop, propOwner) {
3432 // we don't want to stub things like toString(), valueOf(), etc. so we only stub if the object
3433 // is not Object.prototype
3434 if (
3435 propOwner !== Object.prototype &&
3436 prop !== "constructor" &&
3437 typeof sinon.getPropertyDescriptor(propOwner, prop).value === "function"
3438 ) {
3439 stub(object, prop);
3440 }
3441 });
3442
3443 return object;
3444 }
3445
3446 return sinon.wrapMethod(object, property, wrapper);
3447 }
3448
3449
3450 /*eslint-disable no-use-before-define*/
3451 function getParentBehaviour(stubInstance) {
3452 return (stubInstance.parent && getCurrentBehavior(stubInstance.parent));
3453 }
3454
3455 function getDefaultBehavior(stubInstance) {
3456 return stubInstance.defaultBehavior ||
3457 getParentBehaviour(stubInstance) ||
3458 sinon.behavior.create(stubInstance);
3459 }
3460
3461 function getCurrentBehavior(stubInstance) {
3462 var behavior = stubInstance.behaviors[stubInstance.callCount - 1];
3463 return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stubInstance);
3464 }
3465 /*eslint-enable no-use-before-define*/
3466
3467 var uuid = 0;
3468
3469 var proto = {
3470 create: function create(stubLength) {
3471 var functionStub = function () {
3472 return getCurrentBehavior(functionStub).invoke(this, arguments);
3473 };
3474
3475 functionStub.id = "stub#" + uuid++;
3476 var orig = functionStub;
3477 functionStub = sinon.spy.create(functionStub, stubLength);
3478 functionStub.func = orig;
3479
3480 sinon.extend(functionStub, stub);
3481 functionStub.instantiateFake = sinon.stub.create;
3482 functionStub.displayName = "stub";
3483 functionStub.toString = sinon.functionToString;
3484
3485 functionStub.defaultBehavior = null;
3486 functionStub.behaviors = [];
3487
3488 return functionStub;
3489 },
3490
3491 resetBehavior: function () {
3492 var i;
3493
3494 this.defaultBehavior = null;
3495 this.behaviors = [];
3496
3497 delete this.returnValue;
3498 delete this.returnArgAt;
3499 this.returnThis = false;
3500
3501 if (this.fakes) {
3502 for (i = 0; i < this.fakes.length; i++) {
3503 this.fakes[i].resetBehavior();
3504 }
3505 }
3506 },
3507
3508 onCall: function onCall(index) {
3509 if (!this.behaviors[index]) {
3510 this.behaviors[index] = sinon.behavior.create(this);
3511 }
3512
3513 return this.behaviors[index];
3514 },
3515
3516 onFirstCall: function onFirstCall() {
3517 return this.onCall(0);
3518 },
3519
3520 onSecondCall: function onSecondCall() {
3521 return this.onCall(1);
3522 },
3523
3524 onThirdCall: function onThirdCall() {
3525 return this.onCall(2);
3526 }
3527 };
3528
3529 function createBehavior(behaviorMethod) {
3530 return function () {
3531 this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
3532 this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
3533 return this;
3534 };
3535 }
3536
3537 for (var method in sinon.behavior) {
3538 if (sinon.behavior.hasOwnProperty(method) &&
3539 !proto.hasOwnProperty(method) &&
3540 method !== "create" &&
3541 method !== "withArgs" &&
3542 method !== "invoke") {
3543 proto[method] = createBehavior(method);
3544 }
3545 }
3546
3547 sinon.extend(stub, proto);
3548 sinon.stub = stub;
3549
3550 return stub;
3551 }
3552
3553 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
3554 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3555
3556 function loadDependencies(require, exports, module) {
3557 var core = require("./util/core");
3558 require("./behavior");
3559 require("./spy");
3560 require("./extend");
3561 module.exports = makeApi(core);
3562 }
3563
3564 if (isAMD) {
3565 define(loadDependencies);
3566 return;
3567 }
3568
3569 if (isNode) {
3570 loadDependencies(require, module.exports, module);
3571 return;
3572 }
3573
3574 if (sinonGlobal) {
3575 makeApi(sinonGlobal);
3576 }
3577 }(
3578 typeof sinon === "object" && sinon // eslint-disable-line no-undef
3579 ));
3580
3581 /**
3582 * @depend times_in_words.js
3583 * @depend util/core.js
3584 * @depend call.js
3585 * @depend extend.js
3586 * @depend match.js
3587 * @depend spy.js
3588 * @depend stub.js
3589 * @depend format.js
3590 */
3591 /**
3592 * Mock functions.
3593 *
3594 * @author Christian Johansen (christian@cjohansen.no)
3595 * @license BSD
3596 *
3597 * Copyright (c) 2010-2013 Christian Johansen
3598 */
3599 (function (sinonGlobal) {
3600
3601 function makeApi(sinon) {
3602 var push = [].push;
3603 var match = sinon.match;
3604
3605 function mock(object) {
3606 // if (typeof console !== undefined && console.warn) {
3607 // console.warn("mock will be removed from Sinon.JS v2.0");
3608 // }
3609
3610 if (!object) {
3611 return sinon.expectation.create("Anonymous mock");
3612 }
3613
3614 return mock.create(object);
3615 }
3616
3617 function each(collection, callback) {
3618 if (!collection) {
3619 return;
3620 }
3621
3622 for (var i = 0, l = collection.length; i < l; i += 1) {
3623 callback(collection[i]);
3624 }
3625 }
3626
3627 function arrayEquals(arr1, arr2, compareLength) {
3628 if (compareLength && (arr1.length !== arr2.length)) {
3629 return false;
3630 }
3631
3632 for (var i = 0, l = arr1.length; i < l; i++) {
3633 if (!sinon.deepEqual(arr1[i], arr2[i])) {
3634 return false;
3635 }
3636 }
3637 return true;
3638 }
3639
3640 sinon.extend(mock, {
3641 create: function create(object) {
3642 if (!object) {
3643 throw new TypeError("object is null");
3644 }
3645
3646 var mockObject = sinon.extend({}, mock);
3647 mockObject.object = object;
3648 delete mockObject.create;
3649
3650 return mockObject;
3651 },
3652
3653 expects: function expects(method) {
3654 if (!method) {
3655 throw new TypeError("method is falsy");
3656 }
3657
3658 if (!this.expectations) {
3659 this.expectations = {};
3660 this.proxies = [];
3661 }
3662
3663 if (!this.expectations[method]) {
3664 this.expectations[method] = [];
3665 var mockObject = this;
3666
3667 sinon.wrapMethod(this.object, method, function () {
3668 return mockObject.invokeMethod(method, this, arguments);
3669 });
3670
3671 push.call(this.proxies, method);
3672 }
3673
3674 var expectation = sinon.expectation.create(method);
3675 push.call(this.expectations[method], expectation);
3676
3677 return expectation;
3678 },
3679
3680 restore: function restore() {
3681 var object = this.object;
3682
3683 each(this.proxies, function (proxy) {
3684 if (typeof object[proxy].restore === "function") {
3685 object[proxy].restore();
3686 }
3687 });
3688 },
3689
3690 verify: function verify() {
3691 var expectations = this.expectations || {};
3692 var messages = [];
3693 var met = [];
3694
3695 each(this.proxies, function (proxy) {
3696 each(expectations[proxy], function (expectation) {
3697 if (!expectation.met()) {
3698 push.call(messages, expectation.toString());
3699 } else {
3700 push.call(met, expectation.toString());
3701 }
3702 });
3703 });
3704
3705 this.restore();
3706
3707 if (messages.length > 0) {
3708 sinon.expectation.fail(messages.concat(met).join("\n"));
3709 } else if (met.length > 0) {
3710 sinon.expectation.pass(messages.concat(met).join("\n"));
3711 }
3712
3713 return true;
3714 },
3715
3716 invokeMethod: function invokeMethod(method, thisValue, args) {
3717 var expectations = this.expectations && this.expectations[method] ? this.expectations[method] : [];
3718 var expectationsWithMatchingArgs = [];
3719 var currentArgs = args || [];
3720 var i, available;
3721
3722 for (i = 0; i < expectations.length; i += 1) {
3723 var expectedArgs = expectations[i].expectedArguments || [];
3724 if (arrayEquals(expectedArgs, currentArgs, expectations[i].expectsExactArgCount)) {
3725 expectationsWithMatchingArgs.push(expectations[i]);
3726 }
3727 }
3728
3729 for (i = 0; i < expectationsWithMatchingArgs.length; i += 1) {
3730 if (!expectationsWithMatchingArgs[i].met() &&
3731 expectationsWithMatchingArgs[i].allowsCall(thisValue, args)) {
3732 return expectationsWithMatchingArgs[i].apply(thisValue, args);
3733 }
3734 }
3735
3736 var messages = [];
3737 var exhausted = 0;
3738
3739 for (i = 0; i < expectationsWithMatchingArgs.length; i += 1) {
3740 if (expectationsWithMatchingArgs[i].allowsCall(thisValue, args)) {
3741 available = available || expectationsWithMatchingArgs[i];
3742 } else {
3743 exhausted += 1;
3744 }
3745 }
3746
3747 if (available && exhausted === 0) {
3748 return available.apply(thisValue, args);
3749 }
3750
3751 for (i = 0; i < expectations.length; i += 1) {
3752 push.call(messages, " " + expectations[i].toString());
3753 }
3754
3755 messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
3756 proxy: method,
3757 args: args
3758 }));
3759
3760 sinon.expectation.fail(messages.join("\n"));
3761 }
3762 });
3763
3764 var times = sinon.timesInWords;
3765 var slice = Array.prototype.slice;
3766
3767 function callCountInWords(callCount) {
3768 if (callCount === 0) {
3769 return "never called";
3770 }
3771
3772 return "called " + times(callCount);
3773 }
3774
3775 function expectedCallCountInWords(expectation) {
3776 var min = expectation.minCalls;
3777 var max = expectation.maxCalls;
3778
3779 if (typeof min === "number" && typeof max === "number") {
3780 var str = times(min);
3781
3782 if (min !== max) {
3783 str = "at least " + str + " and at most " + times(max);
3784 }
3785
3786 return str;
3787 }
3788
3789 if (typeof min === "number") {
3790 return "at least " + times(min);
3791 }
3792
3793 return "at most " + times(max);
3794 }
3795
3796 function receivedMinCalls(expectation) {
3797 var hasMinLimit = typeof expectation.minCalls === "number";
3798 return !hasMinLimit || expectation.callCount >= expectation.minCalls;
3799 }
3800
3801 function receivedMaxCalls(expectation) {
3802 if (typeof expectation.maxCalls !== "number") {
3803 return false;
3804 }
3805
3806 return expectation.callCount === expectation.maxCalls;
3807 }
3808
3809 function verifyMatcher(possibleMatcher, arg) {
3810 var isMatcher = match && match.isMatcher(possibleMatcher);
3811
3812 return isMatcher && possibleMatcher.test(arg) || true;
3813 }
3814
3815 sinon.expectation = {
3816 minCalls: 1,
3817 maxCalls: 1,
3818
3819 create: function create(methodName) {
3820 var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
3821 delete expectation.create;
3822 expectation.method = methodName;
3823
3824 return expectation;
3825 },
3826
3827 invoke: function invoke(func, thisValue, args) {
3828 this.verifyCallAllowed(thisValue, args);
3829
3830 return sinon.spy.invoke.apply(this, arguments);
3831 },
3832
3833 atLeast: function atLeast(num) {
3834 if (typeof num !== "number") {
3835 throw new TypeError("'" + num + "' is not number");
3836 }
3837
3838 if (!this.limitsSet) {
3839 this.maxCalls = null;
3840 this.limitsSet = true;
3841 }
3842
3843 this.minCalls = num;
3844
3845 return this;
3846 },
3847
3848 atMost: function atMost(num) {
3849 if (typeof num !== "number") {
3850 throw new TypeError("'" + num + "' is not number");
3851 }
3852
3853 if (!this.limitsSet) {
3854 this.minCalls = null;
3855 this.limitsSet = true;
3856 }
3857
3858 this.maxCalls = num;
3859
3860 return this;
3861 },
3862
3863 never: function never() {
3864 return this.exactly(0);
3865 },
3866
3867 once: function once() {
3868 return this.exactly(1);
3869 },
3870
3871 twice: function twice() {
3872 return this.exactly(2);
3873 },
3874
3875 thrice: function thrice() {
3876 return this.exactly(3);
3877 },
3878
3879 exactly: function exactly(num) {
3880 if (typeof num !== "number") {
3881 throw new TypeError("'" + num + "' is not a number");
3882 }
3883
3884 this.atLeast(num);
3885 return this.atMost(num);
3886 },
3887
3888 met: function met() {
3889 return !this.failed && receivedMinCalls(this);
3890 },
3891
3892 verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
3893 if (receivedMaxCalls(this)) {
3894 this.failed = true;
3895 sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
3896 }
3897
3898 if ("expectedThis" in this && this.expectedThis !== thisValue) {
3899 sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
3900 this.expectedThis);
3901 }
3902
3903 if (!("expectedArguments" in this)) {
3904 return;
3905 }
3906
3907 if (!args) {
3908 sinon.expectation.fail(this.method + " received no arguments, expected " +
3909 sinon.format(this.expectedArguments));
3910 }
3911
3912 if (args.length < this.expectedArguments.length) {
3913 sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
3914 "), expected " + sinon.format(this.expectedArguments));
3915 }
3916
3917 if (this.expectsExactArgCount &&
3918 args.length !== this.expectedArguments.length) {
3919 sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
3920 "), expected " + sinon.format(this.expectedArguments));
3921 }
3922
3923 for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
3924
3925 if (!verifyMatcher(this.expectedArguments[i], args[i])) {
3926 sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
3927 ", didn't match " + this.expectedArguments.toString());
3928 }
3929
3930 if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
3931 sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
3932 ", expected " + sinon.format(this.expectedArguments));
3933 }
3934 }
3935 },
3936
3937 allowsCall: function allowsCall(thisValue, args) {
3938 if (this.met() && receivedMaxCalls(this)) {
3939 return false;
3940 }
3941
3942 if ("expectedThis" in this && this.expectedThis !== thisValue) {
3943 return false;
3944 }
3945
3946 if (!("expectedArguments" in this)) {
3947 return true;
3948 }
3949
3950 args = args || [];
3951
3952 if (args.length < this.expectedArguments.length) {
3953 return false;
3954 }
3955
3956 if (this.expectsExactArgCount &&
3957 args.length !== this.expectedArguments.length) {
3958 return false;
3959 }
3960
3961 for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
3962 if (!verifyMatcher(this.expectedArguments[i], args[i])) {
3963 return false;
3964 }
3965
3966 if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
3967 return false;
3968 }
3969 }
3970
3971 return true;
3972 },
3973
3974 withArgs: function withArgs() {
3975 this.expectedArguments = slice.call(arguments);
3976 return this;
3977 },
3978
3979 withExactArgs: function withExactArgs() {
3980 this.withArgs.apply(this, arguments);
3981 this.expectsExactArgCount = true;
3982 return this;
3983 },
3984
3985 on: function on(thisValue) {
3986 this.expectedThis = thisValue;
3987 return this;
3988 },
3989
3990 toString: function () {
3991 var args = (this.expectedArguments || []).slice();
3992
3993 if (!this.expectsExactArgCount) {
3994 push.call(args, "[...]");
3995 }
3996
3997 var callStr = sinon.spyCall.toString.call({
3998 proxy: this.method || "anonymous mock expectation",
3999 args: args
4000 });
4001
4002 var message = callStr.replace(", [...", "[, ...") + " " +
4003 expectedCallCountInWords(this);
4004
4005 if (this.met()) {
4006 return "Expectation met: " + message;
4007 }
4008
4009 return "Expected " + message + " (" +
4010 callCountInWords(this.callCount) + ")";
4011 },
4012
4013 verify: function verify() {
4014 if (!this.met()) {
4015 sinon.expectation.fail(this.toString());
4016 } else {
4017 sinon.expectation.pass(this.toString());
4018 }
4019
4020 return true;
4021 },
4022
4023 pass: function pass(message) {
4024 sinon.assert.pass(message);
4025 },
4026
4027 fail: function fail(message) {
4028 var exception = new Error(message);
4029 exception.name = "ExpectationError";
4030
4031 throw exception;
4032 }
4033 };
4034
4035 sinon.mock = mock;
4036 return mock;
4037 }
4038
4039 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4040 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4041
4042 function loadDependencies(require, exports, module) {
4043 var sinon = require("./util/core");
4044 require("./times_in_words");
4045 require("./call");
4046 require("./extend");
4047 require("./match");
4048 require("./spy");
4049 require("./stub");
4050 require("./format");
4051
4052 module.exports = makeApi(sinon);
4053 }
4054
4055 if (isAMD) {
4056 define(loadDependencies);
4057 return;
4058 }
4059
4060 if (isNode) {
4061 loadDependencies(require, module.exports, module);
4062 return;
4063 }
4064
4065 if (sinonGlobal) {
4066 makeApi(sinonGlobal);
4067 }
4068 }(
4069 typeof sinon === "object" && sinon // eslint-disable-line no-undef
4070 ));
4071
4072 /**
4073 * @depend util/core.js
4074 * @depend spy.js
4075 * @depend stub.js
4076 * @depend mock.js
4077 */
4078 /**
4079 * Collections of stubs, spies and mocks.
4080 *
4081 * @author Christian Johansen (christian@cjohansen.no)
4082 * @license BSD
4083 *
4084 * Copyright (c) 2010-2013 Christian Johansen
4085 */
4086 (function (sinonGlobal) {
4087
4088 var push = [].push;
4089 var hasOwnProperty = Object.prototype.hasOwnProperty;
4090
4091 function getFakes(fakeCollection) {
4092 if (!fakeCollection.fakes) {
4093 fakeCollection.fakes = [];
4094 }
4095
4096 return fakeCollection.fakes;
4097 }
4098
4099 function each(fakeCollection, method) {
4100 var fakes = getFakes(fakeCollection);
4101
4102 for (var i = 0, l = fakes.length; i < l; i += 1) {
4103 if (typeof fakes[i][method] === "function") {
4104 fakes[i][method]();
4105 }
4106 }
4107 }
4108
4109 function compact(fakeCollection) {
4110 var fakes = getFakes(fakeCollection);
4111 var i = 0;
4112 while (i < fakes.length) {
4113 fakes.splice(i, 1);
4114 }
4115 }
4116
4117 function makeApi(sinon) {
4118 var collection = {
4119 verify: function resolve() {
4120 each(this, "verify");
4121 },
4122
4123 restore: function restore() {
4124 each(this, "restore");
4125 compact(this);
4126 },
4127
4128 reset: function restore() {
4129 each(this, "reset");
4130 },
4131
4132 verifyAndRestore: function verifyAndRestore() {
4133 var exception;
4134
4135 try {
4136 this.verify();
4137 } catch (e) {
4138 exception = e;
4139 }
4140
4141 this.restore();
4142
4143 if (exception) {
4144 throw exception;
4145 }
4146 },
4147
4148 add: function add(fake) {
4149 push.call(getFakes(this), fake);
4150 return fake;
4151 },
4152
4153 spy: function spy() {
4154 return this.add(sinon.spy.apply(sinon, arguments));
4155 },
4156
4157 stub: function stub(object, property, value) {
4158 if (property) {
4159 var original = object[property];
4160
4161 if (typeof original !== "function") {
4162 if (!hasOwnProperty.call(object, property)) {
4163 throw new TypeError("Cannot stub non-existent own property " + property);
4164 }
4165
4166 object[property] = value;
4167
4168 return this.add({
4169 restore: function () {
4170 object[property] = original;
4171 }
4172 });
4173 }
4174 }
4175 if (!property && !!object && typeof object === "object") {
4176 var stubbedObj = sinon.stub.apply(sinon, arguments);
4177
4178 for (var prop in stubbedObj) {
4179 if (typeof stubbedObj[prop] === "function") {
4180 this.add(stubbedObj[prop]);
4181 }
4182 }
4183
4184 return stubbedObj;
4185 }
4186
4187 return this.add(sinon.stub.apply(sinon, arguments));
4188 },
4189
4190 mock: function mock() {
4191 return this.add(sinon.mock.apply(sinon, arguments));
4192 },
4193
4194 inject: function inject(obj) {
4195 var col = this;
4196
4197 obj.spy = function () {
4198 return col.spy.apply(col, arguments);
4199 };
4200
4201 obj.stub = function () {
4202 return col.stub.apply(col, arguments);
4203 };
4204
4205 obj.mock = function () {
4206 return col.mock.apply(col, arguments);
4207 };
4208
4209 return obj;
4210 }
4211 };
4212
4213 sinon.collection = collection;
4214 return collection;
4215 }
4216
4217 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4218 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4219
4220 function loadDependencies(require, exports, module) {
4221 var sinon = require("./util/core");
4222 require("./mock");
4223 require("./spy");
4224 require("./stub");
4225 module.exports = makeApi(sinon);
4226 }
4227
4228 if (isAMD) {
4229 define(loadDependencies);
4230 return;
4231 }
4232
4233 if (isNode) {
4234 loadDependencies(require, module.exports, module);
4235 return;
4236 }
4237
4238 if (sinonGlobal) {
4239 makeApi(sinonGlobal);
4240 }
4241 }(
4242 typeof sinon === "object" && sinon // eslint-disable-line no-undef
4243 ));
4244
4245 /**
4246 * Fake timer API
4247 * setTimeout
4248 * setInterval
4249 * clearTimeout
4250 * clearInterval
4251 * tick
4252 * reset
4253 * Date
4254 *
4255 * Inspired by jsUnitMockTimeOut from JsUnit
4256 *
4257 * @author Christian Johansen (christian@cjohansen.no)
4258 * @license BSD
4259 *
4260 * Copyright (c) 2010-2013 Christian Johansen
4261 */
4262 (function () {
4263
4264 function makeApi(s, lol) {
4265 /*global lolex */
4266 var llx = typeof lolex !== "undefined" ? lolex : lol;
4267
4268 s.useFakeTimers = function () {
4269 var now;
4270 var methods = Array.prototype.slice.call(arguments);
4271
4272 if (typeof methods[0] === "string") {
4273 now = 0;
4274 } else {
4275 now = methods.shift();
4276 }
4277
4278 var clock = llx.install(now || 0, methods);
4279 clock.restore = clock.uninstall;
4280 return clock;
4281 };
4282
4283 s.clock = {
4284 create: function (now) {
4285 return llx.createClock(now);
4286 }
4287 };
4288
4289 s.timers = {
4290 setTimeout: setTimeout,
4291 clearTimeout: clearTimeout,
4292 setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
4293 clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate : undefined),
4294 setInterval: setInterval,
4295 clearInterval: clearInterval,
4296 Date: Date
4297 };
4298 }
4299
4300 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4301 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4302
4303 function loadDependencies(require, epxorts, module, lolex) {
4304 var core = require("./core");
4305 makeApi(core, lolex);
4306 module.exports = core;
4307 }
4308
4309 if (isAMD) {
4310 define(loadDependencies);
4311 } else if (isNode) {
4312 loadDependencies(require, module.exports, module, require("lolex"));
4313 } else {
4314 makeApi(sinon); // eslint-disable-line no-undef
4315 }
4316 }());
4317
4318 /**
4319 * Minimal Event interface implementation
4320 *
4321 * Original implementation by Sven Fuchs: https://gist.github.com/995028
4322 * Modifications and tests by Christian Johansen.
4323 *
4324 * @author Sven Fuchs (svenfuchs@artweb-design.de)
4325 * @author Christian Johansen (christian@cjohansen.no)
4326 * @license BSD
4327 *
4328 * Copyright (c) 2011 Sven Fuchs, Christian Johansen
4329 */
4330 if (typeof sinon === "undefined") {
4331 this.sinon = {};
4332 }
4333
4334 (function () {
4335
4336 var push = [].push;
4337
4338 function makeApi(sinon) {
4339 sinon.Event = function Event(type, bubbles, cancelable, target) {
4340 this.initEvent(type, bubbles, cancelable, target);
4341 };
4342
4343 sinon.Event.prototype = {
4344 initEvent: function (type, bubbles, cancelable, target) {
4345 this.type = type;
4346 this.bubbles = bubbles;
4347 this.cancelable = cancelable;
4348 this.target = target;
4349 },
4350
4351 stopPropagation: function () {},
4352
4353 preventDefault: function () {
4354 this.defaultPrevented = true;
4355 }
4356 };
4357
4358 sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
4359 this.initEvent(type, false, false, target);
4360 this.loaded = typeof progressEventRaw.loaded === "number" ? progressEventRaw.loaded : null;
4361 this.total = typeof progressEventRaw.total === "number" ? progressEventRaw.total : null;
4362 this.lengthComputable = !!progressEventRaw.total;
4363 };
4364
4365 sinon.ProgressEvent.prototype = new sinon.Event();
4366
4367 sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent;
4368
4369 sinon.CustomEvent = function CustomEvent(type, customData, target) {
4370 this.initEvent(type, false, false, target);
4371 this.detail = customData.detail || null;
4372 };
4373
4374 sinon.CustomEvent.prototype = new sinon.Event();
4375
4376 sinon.CustomEvent.prototype.constructor = sinon.CustomEvent;
4377
4378 sinon.EventTarget = {
4379 addEventListener: function addEventListener(event, listener) {
4380 this.eventListeners = this.eventListeners || {};
4381 this.eventListeners[event] = this.eventListeners[event] || [];
4382 push.call(this.eventListeners[event], listener);
4383 },
4384
4385 removeEventListener: function removeEventListener(event, listener) {
4386 var listeners = this.eventListeners && this.eventListeners[event] || [];
4387
4388 for (var i = 0, l = listeners.length; i < l; ++i) {
4389 if (listeners[i] === listener) {
4390 return listeners.splice(i, 1);
4391 }
4392 }
4393 },
4394
4395 dispatchEvent: function dispatchEvent(event) {
4396 var type = event.type;
4397 var listeners = this.eventListeners && this.eventListeners[type] || [];
4398
4399 for (var i = 0; i < listeners.length; i++) {
4400 if (typeof listeners[i] === "function") {
4401 listeners[i].call(this, event);
4402 } else {
4403 listeners[i].handleEvent(event);
4404 }
4405 }
4406
4407 return !!event.defaultPrevented;
4408 }
4409 };
4410 }
4411
4412 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4413 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4414
4415 function loadDependencies(require) {
4416 var sinon = require("./core");
4417 makeApi(sinon);
4418 }
4419
4420 if (isAMD) {
4421 define(loadDependencies);
4422 } else if (isNode) {
4423 loadDependencies(require);
4424 } else {
4425 makeApi(sinon); // eslint-disable-line no-undef
4426 }
4427 }());
4428
4429 /**
4430 * @depend util/core.js
4431 */
4432 /**
4433 * Logs errors
4434 *
4435 * @author Christian Johansen (christian@cjohansen.no)
4436 * @license BSD
4437 *
4438 * Copyright (c) 2010-2014 Christian Johansen
4439 */
4440 (function (sinonGlobal) {
4441
4442 // cache a reference to setTimeout, so that our reference won't be stubbed out
4443 // when using fake timers and errors will still get logged
4444 // https://github.com/cjohansen/Sinon.JS/issues/381
4445 var realSetTimeout = setTimeout;
4446
4447 function makeApi(sinon) {
4448
4449 function log() {}
4450
4451 function logError(label, err) {
4452 var msg = label + " threw exception: ";
4453
4454 function throwLoggedError() {
4455 err.message = msg + err.message;
4456 throw err;
4457 }
4458
4459 sinon.log(msg + "[" + err.name + "] " + err.message);
4460
4461 if (err.stack) {
4462 sinon.log(err.stack);
4463 }
4464
4465 if (logError.useImmediateExceptions) {
4466 throwLoggedError();
4467 } else {
4468 logError.setTimeout(throwLoggedError, 0);
4469 }
4470 }
4471
4472 // When set to true, any errors logged will be thrown immediately;
4473 // If set to false, the errors will be thrown in separate execution frame.
4474 logError.useImmediateExceptions = false;
4475
4476 // wrap realSetTimeout with something we can stub in tests
4477 logError.setTimeout = function (func, timeout) {
4478 realSetTimeout(func, timeout);
4479 };
4480
4481 var exports = {};
4482 exports.log = sinon.log = log;
4483 exports.logError = sinon.logError = logError;
4484
4485 return exports;
4486 }
4487
4488 function loadDependencies(require, exports, module) {
4489 var sinon = require("./util/core");
4490 module.exports = makeApi(sinon);
4491 }
4492
4493 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4494 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4495
4496 if (isAMD) {
4497 define(loadDependencies);
4498 return;
4499 }
4500
4501 if (isNode) {
4502 loadDependencies(require, module.exports, module);
4503 return;
4504 }
4505
4506 if (sinonGlobal) {
4507 makeApi(sinonGlobal);
4508 }
4509 }(
4510 typeof sinon === "object" && sinon // eslint-disable-line no-undef
4511 ));
4512
4513 /**
4514 * @depend core.js
4515 * @depend ../extend.js
4516 * @depend event.js
4517 * @depend ../log_error.js
4518 */
4519 /**
4520 * Fake XDomainRequest object
4521 */
4522
4523 /**
4524 * Returns the global to prevent assigning values to 'this' when this is undefined.
4525 * This can occur when files are interpreted by node in strict mode.
4526 * @private
4527 */
4528 function getGlobal() {
4529
4530 return typeof window !== "undefined" ? window : global;
4531 }
4532
4533 if (typeof sinon === "undefined") {
4534 if (typeof this === "undefined") {
4535 getGlobal().sinon = {};
4536 } else {
4537 this.sinon = {};
4538 }
4539 }
4540
4541 // wrapper for global
4542 (function (global) {
4543
4544 var xdr = { XDomainRequest: global.XDomainRequest };
4545 xdr.GlobalXDomainRequest = global.XDomainRequest;
4546 xdr.supportsXDR = typeof xdr.GlobalXDomainRequest !== "undefined";
4547 xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false;
4548
4549 function makeApi(sinon) {
4550 sinon.xdr = xdr;
4551
4552 function FakeXDomainRequest() {
4553 this.readyState = FakeXDomainRequest.UNSENT;
4554 this.requestBody = null;
4555 this.requestHeaders = {};
4556 this.status = 0;
4557 this.timeout = null;
4558
4559 if (typeof FakeXDomainRequest.onCreate === "function") {
4560 FakeXDomainRequest.onCreate(this);
4561 }
4562 }
4563
4564 function verifyState(x) {
4565 if (x.readyState !== FakeXDomainRequest.OPENED) {
4566 throw new Error("INVALID_STATE_ERR");
4567 }
4568
4569 if (x.sendFlag) {
4570 throw new Error("INVALID_STATE_ERR");
4571 }
4572 }
4573
4574 function verifyRequestSent(x) {
4575 if (x.readyState === FakeXDomainRequest.UNSENT) {
4576 throw new Error("Request not sent");
4577 }
4578 if (x.readyState === FakeXDomainRequest.DONE) {
4579 throw new Error("Request done");
4580 }
4581 }
4582
4583 function verifyResponseBodyType(body) {
4584 if (typeof body !== "string") {
4585 var error = new Error("Attempted to respond to fake XDomainRequest with " +
4586 body + ", which is not a string.");
4587 error.name = "InvalidBodyException";
4588 throw error;
4589 }
4590 }
4591
4592 sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
4593 open: function open(method, url) {
4594 this.method = method;
4595 this.url = url;
4596
4597 this.responseText = null;
4598 this.sendFlag = false;
4599
4600 this.readyStateChange(FakeXDomainRequest.OPENED);
4601 },
4602
4603 readyStateChange: function readyStateChange(state) {
4604 this.readyState = state;
4605 var eventName = "";
4606 switch (this.readyState) {
4607 case FakeXDomainRequest.UNSENT:
4608 break;
4609 case FakeXDomainRequest.OPENED:
4610 break;
4611 case FakeXDomainRequest.LOADING:
4612 if (this.sendFlag) {
4613 //raise the progress event
4614 eventName = "onprogress";
4615 }
4616 break;
4617 case FakeXDomainRequest.DONE:
4618 if (this.isTimeout) {
4619 eventName = "ontimeout";
4620 } else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
4621 eventName = "onerror";
4622 } else {
4623 eventName = "onload";
4624 }
4625 break;
4626 }
4627
4628 // raising event (if defined)
4629 if (eventName) {
4630 if (typeof this[eventName] === "function") {
4631 try {
4632 this[eventName]();
4633 } catch (e) {
4634 sinon.logError("Fake XHR " + eventName + " handler", e);
4635 }
4636 }
4637 }
4638 },
4639
4640 send: function send(data) {
4641 verifyState(this);
4642
4643 if (!/^(get|head)$/i.test(this.method)) {
4644 this.requestBody = data;
4645 }
4646 this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
4647
4648 this.errorFlag = false;
4649 this.sendFlag = true;
4650 this.readyStateChange(FakeXDomainRequest.OPENED);
4651
4652 if (typeof this.onSend === "function") {
4653 this.onSend(this);
4654 }
4655 },
4656
4657 abort: function abort() {
4658 this.aborted = true;
4659 this.responseText = null;
4660 this.errorFlag = true;
4661
4662 if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
4663 this.readyStateChange(sinon.FakeXDomainRequest.DONE);
4664 this.sendFlag = false;
4665 }
4666 },
4667
4668 setResponseBody: function setResponseBody(body) {
4669 verifyRequestSent(this);
4670 verifyResponseBodyType(body);
4671
4672 var chunkSize = this.chunkSize || 10;
4673 var index = 0;
4674 this.responseText = "";
4675
4676 do {
4677 this.readyStateChange(FakeXDomainRequest.LOADING);
4678 this.responseText += body.substring(index, index + chunkSize);
4679 index += chunkSize;
4680 } while (index < body.length);
4681
4682 this.readyStateChange(FakeXDomainRequest.DONE);
4683 },
4684
4685 respond: function respond(status, contentType, body) {
4686 // content-type ignored, since XDomainRequest does not carry this
4687 // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
4688 // test integration across browsers
4689 this.status = typeof status === "number" ? status : 200;
4690 this.setResponseBody(body || "");
4691 },
4692
4693 simulatetimeout: function simulatetimeout() {
4694 this.status = 0;
4695 this.isTimeout = true;
4696 // Access to this should actually throw an error
4697 this.responseText = undefined;
4698 this.readyStateChange(FakeXDomainRequest.DONE);
4699 }
4700 });
4701
4702 sinon.extend(FakeXDomainRequest, {
4703 UNSENT: 0,
4704 OPENED: 1,
4705 LOADING: 3,
4706 DONE: 4
4707 });
4708
4709 sinon.useFakeXDomainRequest = function useFakeXDomainRequest() {
4710 sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
4711 if (xdr.supportsXDR) {
4712 global.XDomainRequest = xdr.GlobalXDomainRequest;
4713 }
4714
4715 delete sinon.FakeXDomainRequest.restore;
4716
4717 if (keepOnCreate !== true) {
4718 delete sinon.FakeXDomainRequest.onCreate;
4719 }
4720 };
4721 if (xdr.supportsXDR) {
4722 global.XDomainRequest = sinon.FakeXDomainRequest;
4723 }
4724 return sinon.FakeXDomainRequest;
4725 };
4726
4727 sinon.FakeXDomainRequest = FakeXDomainRequest;
4728 }
4729
4730 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
4731 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4732
4733 function loadDependencies(require, exports, module) {
4734 var sinon = require("./core");
4735 require("../extend");
4736 require("./event");
4737 require("../log_error");
4738 makeApi(sinon);
4739 module.exports = sinon;
4740 }
4741
4742 if (isAMD) {
4743 define(loadDependencies);
4744 } else if (isNode) {
4745 loadDependencies(require, module.exports, module);
4746 } else {
4747 makeApi(sinon); // eslint-disable-line no-undef
4748 }
4749 })(typeof global !== "undefined" ? global : self);
4750
4751 /**
4752 * @depend core.js
4753 * @depend ../extend.js
4754 * @depend event.js
4755 * @depend ../log_error.js
4756 */
4757 /**
4758 * Fake XMLHttpRequest object
4759 *
4760 * @author Christian Johansen (christian@cjohansen.no)
4761 * @license BSD
4762 *
4763 * Copyright (c) 2010-2013 Christian Johansen
4764 */
4765 (function (sinonGlobal, global) {
4766
4767 function getWorkingXHR(globalScope) {
4768 var supportsXHR = typeof globalScope.XMLHttpRequest !== "undefined";
4769 if (supportsXHR) {
4770 return globalScope.XMLHttpRequest;
4771 }
4772
4773 var supportsActiveX = typeof globalScope.ActiveXObject !== "undefined";
4774 if (supportsActiveX) {
4775 return function () {
4776 return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0");
4777 };
4778 }
4779
4780 return false;
4781 }
4782
4783 var supportsProgress = typeof ProgressEvent !== "undefined";
4784 var supportsCustomEvent = typeof CustomEvent !== "undefined";
4785 var supportsFormData = typeof FormData !== "undefined";
4786 var supportsArrayBuffer = typeof ArrayBuffer !== "undefined";
4787 var supportsBlob = (function () {
4788 try {
4789 return !!new Blob();
4790 } catch (e) {
4791 return false;
4792 }
4793 })();
4794 var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest };
4795 sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
4796 sinonXhr.GlobalActiveXObject = global.ActiveXObject;
4797 sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject !== "undefined";
4798 sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest !== "undefined";
4799 sinonXhr.workingXHR = getWorkingXHR(global);
4800 sinonXhr.supportsCORS = sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest());
4801
4802 var unsafeHeaders = {
4803 "Accept-Charset": true,
4804 "Accept-Encoding": true,
4805 Connection: true,
4806 "Content-Length": true,
4807 Cookie: true,
4808 Cookie2: true,
4809 "Content-Transfer-Encoding": true,
4810 Date: true,
4811 Expect: true,
4812 Host: true,
4813 "Keep-Alive": true,
4814 Referer: true,
4815 TE: true,
4816 Trailer: true,
4817 "Transfer-Encoding": true,
4818 Upgrade: true,
4819 "User-Agent": true,
4820 Via: true
4821 };
4822
4823 // An upload object is created for each
4824 // FakeXMLHttpRequest and allows upload
4825 // events to be simulated using uploadProgress
4826 // and uploadError.
4827 function UploadProgress() {
4828 this.eventListeners = {
4829 abort: [],
4830 error: [],
4831 load: [],
4832 loadend: [],
4833 progress: []
4834 };
4835 }
4836
4837 UploadProgress.prototype.addEventListener = function addEventListener(event, listener) {
4838 this.eventListeners[event].push(listener);
4839 };
4840
4841 UploadProgress.prototype.removeEventListener = function removeEventListener(event, listener) {
4842 var listeners = this.eventListeners[event] || [];
4843
4844 for (var i = 0, l = listeners.length; i < l; ++i) {
4845 if (listeners[i] === listener) {
4846 return listeners.splice(i, 1);
4847 }
4848 }
4849 };
4850
4851 UploadProgress.prototype.dispatchEvent = function dispatchEvent(event) {
4852 var listeners = this.eventListeners[event.type] || [];
4853
4854 for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
4855 listener(event);
4856 }
4857 };
4858
4859 // Note that for FakeXMLHttpRequest to work pre ES5
4860 // we lose some of the alignment with the spec.
4861 // To ensure as close a match as possible,
4862 // set responseType before calling open, send or respond;
4863 function FakeXMLHttpRequest() {
4864 this.readyState = FakeXMLHttpRequest.UNSENT;
4865 this.requestHeaders = {};
4866 this.requestBody = null;
4867 this.status = 0;
4868 this.statusText = "";
4869 this.upload = new UploadProgress();
4870 this.responseType = "";
4871 this.response = "";
4872 if (sinonXhr.supportsCORS) {
4873 this.withCredentials = false;
4874 }
4875
4876 var xhr = this;
4877 var events = ["loadstart", "load", "abort", "error", "loadend"];
4878
4879 function addEventListener(eventName) {
4880 xhr.addEventListener(eventName, function (event) {
4881 var listener = xhr["on" + eventName];
4882
4883 if (listener && typeof listener === "function") {
4884 listener.call(this, event);
4885 }
4886 });
4887 }
4888
4889 for (var i = events.length - 1; i >= 0; i--) {
4890 addEventListener(events[i]);
4891 }
4892
4893 if (typeof FakeXMLHttpRequest.onCreate === "function") {
4894 FakeXMLHttpRequest.onCreate(this);
4895 }
4896 }
4897
4898 function verifyState(xhr) {
4899 if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
4900 throw new Error("INVALID_STATE_ERR");
4901 }
4902
4903 if (xhr.sendFlag) {
4904 throw new Error("INVALID_STATE_ERR");
4905 }
4906 }
4907
4908 function getHeader(headers, header) {
4909 header = header.toLowerCase();
4910
4911 for (var h in headers) {
4912 if (h.toLowerCase() === header) {
4913 return h;
4914 }
4915 }
4916
4917 return null;
4918 }
4919
4920 // filtering to enable a white-list version of Sinon FakeXhr,
4921 // where whitelisted requests are passed through to real XHR
4922 function each(collection, callback) {
4923 if (!collection) {
4924 return;
4925 }
4926
4927 for (var i = 0, l = collection.length; i < l; i += 1) {
4928 callback(collection[i]);
4929 }
4930 }
4931 function some(collection, callback) {
4932 for (var index = 0; index < collection.length; index++) {
4933 if (callback(collection[index]) === true) {
4934 return true;
4935 }
4936 }
4937 return false;
4938 }
4939 // largest arity in XHR is 5 - XHR#open
4940 var apply = function (obj, method, args) {
4941 switch (args.length) {
4942 case 0: return obj[method]();
4943 case 1: return obj[method](args[0]);
4944 case 2: return obj[method](args[0], args[1]);
4945 case 3: return obj[method](args[0], args[1], args[2]);
4946 case 4: return obj[method](args[0], args[1], args[2], args[3]);
4947 case 5: return obj[method](args[0], args[1], args[2], args[3], args[4]);
4948 }
4949 };
4950
4951 FakeXMLHttpRequest.filters = [];
4952 FakeXMLHttpRequest.addFilter = function addFilter(fn) {
4953 this.filters.push(fn);
4954 };
4955 var IE6Re = /MSIE 6/;
4956 FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) {
4957 var xhr = new sinonXhr.workingXHR(); // eslint-disable-line new-cap
4958
4959 each([
4960 "open",
4961 "setRequestHeader",
4962 "send",
4963 "abort",
4964 "getResponseHeader",
4965 "getAllResponseHeaders",
4966 "addEventListener",
4967 "overrideMimeType",
4968 "removeEventListener"
4969 ], function (method) {
4970 fakeXhr[method] = function () {
4971 return apply(xhr, method, arguments);
4972 };
4973 });
4974
4975 var copyAttrs = function (args) {
4976 each(args, function (attr) {
4977 try {
4978 fakeXhr[attr] = xhr[attr];
4979 } catch (e) {
4980 if (!IE6Re.test(navigator.userAgent)) {
4981 throw e;
4982 }
4983 }
4984 });
4985 };
4986
4987 var stateChange = function stateChange() {
4988 fakeXhr.readyState = xhr.readyState;
4989 if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
4990 copyAttrs(["status", "statusText"]);
4991 }
4992 if (xhr.readyState >= FakeXMLHttpRequest.LOADING) {
4993 copyAttrs(["responseText", "response"]);
4994 }
4995 if (xhr.readyState === FakeXMLHttpRequest.DONE) {
4996 copyAttrs(["responseXML"]);
4997 }
4998 if (fakeXhr.onreadystatechange) {
4999 fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
5000 }
5001 };
5002
5003 if (xhr.addEventListener) {
5004 for (var event in fakeXhr.eventListeners) {
5005 if (fakeXhr.eventListeners.hasOwnProperty(event)) {
5006
5007 /*eslint-disable no-loop-func*/
5008 each(fakeXhr.eventListeners[event], function (handler) {
5009 xhr.addEventListener(event, handler);
5010 });
5011 /*eslint-enable no-loop-func*/
5012 }
5013 }
5014 xhr.addEventListener("readystatechange", stateChange);
5015 } else {
5016 xhr.onreadystatechange = stateChange;
5017 }
5018 apply(xhr, "open", xhrArgs);
5019 };
5020 FakeXMLHttpRequest.useFilters = false;
5021
5022 function verifyRequestOpened(xhr) {
5023 if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
5024 throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
5025 }
5026 }
5027
5028 function verifyRequestSent(xhr) {
5029 if (xhr.readyState === FakeXMLHttpRequest.DONE) {
5030 throw new Error("Request done");
5031 }
5032 }
5033
5034 function verifyHeadersReceived(xhr) {
5035 if (xhr.async && xhr.readyState !== FakeXMLHttpRequest.HEADERS_RECEIVED) {
5036 throw new Error("No headers received");
5037 }
5038 }
5039
5040 function verifyResponseBodyType(body) {
5041 if (typeof body !== "string") {
5042 var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
5043 body + ", which is not a string.");
5044 error.name = "InvalidBodyException";
5045 throw error;
5046 }
5047 }
5048
5049 function convertToArrayBuffer(body) {
5050 var buffer = new ArrayBuffer(body.length);
5051 var view = new Uint8Array(buffer);
5052 for (var i = 0; i < body.length; i++) {
5053 var charCode = body.charCodeAt(i);
5054 if (charCode >= 256) {
5055 throw new TypeError("arraybuffer or blob responseTypes require binary string, " +
5056 "invalid character " + body[i] + " found.");
5057 }
5058 view[i] = charCode;
5059 }
5060 return buffer;
5061 }
5062
5063 function isXmlContentType(contentType) {
5064 return !contentType || /(text\/xml)|(application\/xml)|(\+xml)/.test(contentType);
5065 }
5066
5067 function convertResponseBody(responseType, contentType, body) {
5068 if (responseType === "" || responseType === "text") {
5069 return body;
5070 } else if (supportsArrayBuffer && responseType === "arraybuffer") {
5071 return convertToArrayBuffer(body);
5072 } else if (responseType === "json") {
5073 try {
5074 return JSON.parse(body);
5075 } catch (e) {
5076 // Return parsing failure as null
5077 return null;
5078 }
5079 } else if (supportsBlob && responseType === "blob") {
5080 var blobOptions = {};
5081 if (contentType) {
5082 blobOptions.type = contentType;
5083 }
5084 return new Blob([convertToArrayBuffer(body)], blobOptions);
5085 } else if (responseType === "document") {
5086 if (isXmlContentType(contentType)) {
5087 return FakeXMLHttpRequest.parseXML(body);
5088 }
5089 return null;
5090 }
5091 throw new Error("Invalid responseType " + responseType);
5092 }
5093
5094 function clearResponse(xhr) {
5095 if (xhr.responseType === "" || xhr.responseType === "text") {
5096 xhr.response = xhr.responseText = "";
5097 } else {
5098 xhr.response = xhr.responseText = null;
5099 }
5100 xhr.responseXML = null;
5101 }
5102
5103 FakeXMLHttpRequest.parseXML = function parseXML(text) {
5104 // Treat empty string as parsing failure
5105 if (text !== "") {
5106 try {
5107 if (typeof DOMParser !== "undefined") {
5108 var parser = new DOMParser();
5109 return parser.parseFromString(text, "text/xml");
5110 }
5111 var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
5112 xmlDoc.async = "false";
5113 xmlDoc.loadXML(text);
5114 return xmlDoc;
5115 } catch (e) {
5116 // Unable to parse XML - no biggie
5117 }
5118 }
5119
5120 return null;
5121 };
5122
5123 FakeXMLHttpRequest.statusCodes = {
5124 100: "Continue",
5125 101: "Switching Protocols",
5126 200: "OK",
5127 201: "Created",
5128 202: "Accepted",
5129 203: "Non-Authoritative Information",
5130 204: "No Content",
5131 205: "Reset Content",
5132 206: "Partial Content",
5133 207: "Multi-Status",
5134 300: "Multiple Choice",
5135 301: "Moved Permanently",
5136 302: "Found",
5137 303: "See Other",
5138 304: "Not Modified",
5139 305: "Use Proxy",
5140 307: "Temporary Redirect",
5141 400: "Bad Request",
5142 401: "Unauthorized",
5143 402: "Payment Required",
5144 403: "Forbidden",
5145 404: "Not Found",
5146 405: "Method Not Allowed",
5147 406: "Not Acceptable",
5148 407: "Proxy Authentication Required",
5149 408: "Request Timeout",
5150 409: "Conflict",
5151 410: "Gone",
5152 411: "Length Required",
5153 412: "Precondition Failed",
5154 413: "Request Entity Too Large",
5155 414: "Request-URI Too Long",
5156 415: "Unsupported Media Type",
5157 416: "Requested Range Not Satisfiable",
5158 417: "Expectation Failed",
5159 422: "Unprocessable Entity",
5160 500: "Internal Server Error",
5161 501: "Not Implemented",
5162 502: "Bad Gateway",
5163 503: "Service Unavailable",
5164 504: "Gateway Timeout",
5165 505: "HTTP Version Not Supported"
5166 };
5167
5168 function makeApi(sinon) {
5169 sinon.xhr = sinonXhr;
5170
5171 sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
5172 async: true,
5173
5174 open: function open(method, url, async, username, password) {
5175 this.method = method;
5176 this.url = url;
5177 this.async = typeof async === "boolean" ? async : true;
5178 this.username = username;
5179 this.password = password;
5180 clearResponse(this);
5181 this.requestHeaders = {};
5182 this.sendFlag = false;
5183
5184 if (FakeXMLHttpRequest.useFilters === true) {
5185 var xhrArgs = arguments;
5186 var defake = some(FakeXMLHttpRequest.filters, function (filter) {
5187 return filter.apply(this, xhrArgs);
5188 });
5189 if (defake) {
5190 return FakeXMLHttpRequest.defake(this, arguments);
5191 }
5192 }
5193 this.readyStateChange(FakeXMLHttpRequest.OPENED);
5194 },
5195
5196 readyStateChange: function readyStateChange(state) {
5197 this.readyState = state;
5198
5199 var readyStateChangeEvent = new sinon.Event("readystatechange", false, false, this);
5200 var event, progress;
5201
5202 if (typeof this.onreadystatechange === "function") {
5203 try {
5204 this.onreadystatechange(readyStateChangeEvent);
5205 } catch (e) {
5206 sinon.logError("Fake XHR onreadystatechange handler", e);
5207 }
5208 }
5209
5210 if (this.readyState === FakeXMLHttpRequest.DONE) {
5211 // ensure loaded and total are numbers
5212 progress = {
5213 loaded: this.progress || 0,
5214 total: this.progress || 0
5215 };
5216
5217 if (this.status === 0) {
5218 event = this.aborted ? "abort" : "error";
5219 }
5220 else {
5221 event = "load";
5222 }
5223
5224 if (supportsProgress) {
5225 this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progress, this));
5226 this.upload.dispatchEvent(new sinon.ProgressEvent(event, progress, this));
5227 this.upload.dispatchEvent(new sinon.ProgressEvent("loadend", progress, this));
5228 }
5229
5230 this.dispatchEvent(new sinon.ProgressEvent("progress", progress, this));
5231 this.dispatchEvent(new sinon.ProgressEvent(event, progress, this));
5232 this.dispatchEvent(new sinon.ProgressEvent("loadend", progress, this));
5233 }
5234
5235 this.dispatchEvent(readyStateChangeEvent);
5236 },
5237
5238 setRequestHeader: function setRequestHeader(header, value) {
5239 verifyState(this);
5240
5241 if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
5242 throw new Error("Refused to set unsafe header \"" + header + "\"");
5243 }
5244
5245 if (this.requestHeaders[header]) {
5246 this.requestHeaders[header] += "," + value;
5247 } else {
5248 this.requestHeaders[header] = value;
5249 }
5250 },
5251
5252 // Helps testing
5253 setResponseHeaders: function setResponseHeaders(headers) {
5254 verifyRequestOpened(this);
5255 this.responseHeaders = {};
5256
5257 for (var header in headers) {
5258 if (headers.hasOwnProperty(header)) {
5259 this.responseHeaders[header] = headers[header];
5260 }
5261 }
5262
5263 if (this.async) {
5264 this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
5265 } else {
5266 this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
5267 }
5268 },
5269
5270 // Currently treats ALL data as a DOMString (i.e. no Document)
5271 send: function send(data) {
5272 verifyState(this);
5273
5274 if (!/^(get|head)$/i.test(this.method)) {
5275 var contentType = getHeader(this.requestHeaders, "Content-Type");
5276 if (this.requestHeaders[contentType]) {
5277 var value = this.requestHeaders[contentType].split(";");
5278 this.requestHeaders[contentType] = value[0] + ";charset=utf-8";
5279 } else if (supportsFormData && !(data instanceof FormData)) {
5280 this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
5281 }
5282
5283 this.requestBody = data;
5284 }
5285
5286 this.errorFlag = false;
5287 this.sendFlag = this.async;
5288 clearResponse(this);
5289 this.readyStateChange(FakeXMLHttpRequest.OPENED);
5290
5291 if (typeof this.onSend === "function") {
5292 this.onSend(this);
5293 }
5294
5295 this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
5296 },
5297
5298 abort: function abort() {
5299 this.aborted = true;
5300 clearResponse(this);
5301 this.errorFlag = true;
5302 this.requestHeaders = {};
5303 this.responseHeaders = {};
5304
5305 if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) {
5306 this.readyStateChange(FakeXMLHttpRequest.DONE);
5307 this.sendFlag = false;
5308 }
5309
5310 this.readyState = FakeXMLHttpRequest.UNSENT;
5311 },
5312
5313 error: function error() {
5314 clearResponse(this);
5315 this.errorFlag = true;
5316 this.requestHeaders = {};
5317 this.responseHeaders = {};
5318
5319 this.readyStateChange(FakeXMLHttpRequest.DONE);
5320 },
5321
5322 getResponseHeader: function getResponseHeader(header) {
5323 if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
5324 return null;
5325 }
5326
5327 if (/^Set-Cookie2?$/i.test(header)) {
5328 return null;
5329 }
5330
5331 header = getHeader(this.responseHeaders, header);
5332
5333 return this.responseHeaders[header] || null;
5334 },
5335
5336 getAllResponseHeaders: function getAllResponseHeaders() {
5337 if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
5338 return "";
5339 }
5340
5341 var headers = "";
5342
5343 for (var header in this.responseHeaders) {
5344 if (this.responseHeaders.hasOwnProperty(header) &&
5345 !/^Set-Cookie2?$/i.test(header)) {
5346 headers += header + ": " + this.responseHeaders[header] + "\r\n";
5347 }
5348 }
5349
5350 return headers;
5351 },
5352
5353 setResponseBody: function setResponseBody(body) {
5354 verifyRequestSent(this);
5355 verifyHeadersReceived(this);
5356 verifyResponseBodyType(body);
5357 var contentType = this.getResponseHeader("Content-Type");
5358
5359 var isTextResponse = this.responseType === "" || this.responseType === "text";
5360 clearResponse(this);
5361 if (this.async) {
5362 var chunkSize = this.chunkSize || 10;
5363 var index = 0;
5364
5365 do {
5366 this.readyStateChange(FakeXMLHttpRequest.LOADING);
5367
5368 if (isTextResponse) {
5369 this.responseText = this.response += body.substring(index, index + chunkSize);
5370 }
5371 index += chunkSize;
5372 } while (index < body.length);
5373 }
5374
5375 this.response = convertResponseBody(this.responseType, contentType, body);
5376 if (isTextResponse) {
5377 this.responseText = this.response;
5378 }
5379
5380 if (this.responseType === "document") {
5381 this.responseXML = this.response;
5382 } else if (this.responseType === "" && isXmlContentType(contentType)) {
5383 this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
5384 }
5385 this.progress = body.length;
5386 this.readyStateChange(FakeXMLHttpRequest.DONE);
5387 },
5388
5389 respond: function respond(status, headers, body) {
5390 this.status = typeof status === "number" ? status : 200;
5391 this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
5392 this.setResponseHeaders(headers || {});
5393 this.setResponseBody(body || "");
5394 },
5395
5396 uploadProgress: function uploadProgress(progressEventRaw) {
5397 if (supportsProgress) {
5398 this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
5399 }
5400 },
5401
5402 downloadProgress: function downloadProgress(progressEventRaw) {
5403 if (supportsProgress) {
5404 this.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
5405 }
5406 },
5407
5408 uploadError: function uploadError(error) {
5409 if (supportsCustomEvent) {
5410 this.upload.dispatchEvent(new sinon.CustomEvent("error", {detail: error}));
5411 }
5412 }
5413 });
5414
5415 sinon.extend(FakeXMLHttpRequest, {
5416 UNSENT: 0,
5417 OPENED: 1,
5418 HEADERS_RECEIVED: 2,
5419 LOADING: 3,
5420 DONE: 4
5421 });
5422
5423 sinon.useFakeXMLHttpRequest = function () {
5424 FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
5425 if (sinonXhr.supportsXHR) {
5426 global.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest;
5427 }
5428
5429 if (sinonXhr.supportsActiveX) {
5430 global.ActiveXObject = sinonXhr.GlobalActiveXObject;
5431 }
5432
5433 delete FakeXMLHttpRequest.restore;
5434
5435 if (keepOnCreate !== true) {
5436 delete FakeXMLHttpRequest.onCreate;
5437 }
5438 };
5439 if (sinonXhr.supportsXHR) {
5440 global.XMLHttpRequest = FakeXMLHttpRequest;
5441 }
5442
5443 if (sinonXhr.supportsActiveX) {
5444 global.ActiveXObject = function ActiveXObject(objId) {
5445 if (objId === "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
5446
5447 return new FakeXMLHttpRequest();
5448 }
5449
5450 return new sinonXhr.GlobalActiveXObject(objId);
5451 };
5452 }
5453
5454 return FakeXMLHttpRequest;
5455 };
5456
5457 sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
5458 }
5459
5460 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
5461 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5462
5463 function loadDependencies(require, exports, module) {
5464 var sinon = require("./core");
5465 require("../extend");
5466 require("./event");
5467 require("../log_error");
5468 makeApi(sinon);
5469 module.exports = sinon;
5470 }
5471
5472 if (isAMD) {
5473 define(loadDependencies);
5474 return;
5475 }
5476
5477 if (isNode) {
5478 loadDependencies(require, module.exports, module);
5479 return;
5480 }
5481
5482 if (sinonGlobal) {
5483 makeApi(sinonGlobal);
5484 }
5485 }(
5486 typeof sinon === "object" && sinon, // eslint-disable-line no-undef
5487 typeof global !== "undefined" ? global : self
5488 ));
5489
5490 /**
5491 * @depend fake_xdomain_request.js
5492 * @depend fake_xml_http_request.js
5493 * @depend ../format.js
5494 * @depend ../log_error.js
5495 */
5496 /**
5497 * The Sinon "server" mimics a web server that receives requests from
5498 * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
5499 * both synchronously and asynchronously. To respond synchronuously, canned
5500 * answers have to be provided upfront.
5501 *
5502 * @author Christian Johansen (christian@cjohansen.no)
5503 * @license BSD
5504 *
5505 * Copyright (c) 2010-2013 Christian Johansen
5506 */
5507 (function () {
5508
5509 var push = [].push;
5510
5511 function responseArray(handler) {
5512 var response = handler;
5513
5514 if (Object.prototype.toString.call(handler) !== "[object Array]") {
5515 response = [200, {}, handler];
5516 }
5517
5518 if (typeof response[2] !== "string") {
5519 throw new TypeError("Fake server response body should be string, but was " +
5520 typeof response[2]);
5521 }
5522
5523 return response;
5524 }
5525
5526 var wloc = typeof window !== "undefined" ? window.location : {};
5527 var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
5528
5529 function matchOne(response, reqMethod, reqUrl) {
5530 var rmeth = response.method;
5531 var matchMethod = !rmeth || rmeth.toLowerCase() === reqMethod.toLowerCase();
5532 var url = response.url;
5533 var matchUrl = !url || url === reqUrl || (typeof url.test === "function" && url.test(reqUrl));
5534
5535 return matchMethod && matchUrl;
5536 }
5537
5538 function match(response, request) {
5539 var requestUrl = request.url;
5540
5541 if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
5542 requestUrl = requestUrl.replace(rCurrLoc, "");
5543 }
5544
5545 if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
5546 if (typeof response.response === "function") {
5547 var ru = response.url;
5548 var args = [request].concat(ru && typeof ru.exec === "function" ? ru.exec(requestUrl).slice(1) : []);
5549 return response.response.apply(response, args);
5550 }
5551
5552 return true;
5553 }
5554
5555 return false;
5556 }
5557
5558 function makeApi(sinon) {
5559 sinon.fakeServer = {
5560 create: function (config) {
5561 var server = sinon.create(this);
5562 server.configure(config);
5563 if (!sinon.xhr.supportsCORS) {
5564 this.xhr = sinon.useFakeXDomainRequest();
5565 } else {
5566 this.xhr = sinon.useFakeXMLHttpRequest();
5567 }
5568 server.requests = [];
5569
5570 this.xhr.onCreate = function (xhrObj) {
5571 server.addRequest(xhrObj);
5572 };
5573
5574 return server;
5575 },
5576 configure: function (config) {
5577 var whitelist = {
5578 "autoRespond": true,
5579 "autoRespondAfter": true,
5580 "respondImmediately": true,
5581 "fakeHTTPMethods": true
5582 };
5583 var setting;
5584
5585 config = config || {};
5586 for (setting in config) {
5587 if (whitelist.hasOwnProperty(setting) && config.hasOwnProperty(setting)) {
5588 this[setting] = config[setting];
5589 }
5590 }
5591 },
5592 addRequest: function addRequest(xhrObj) {
5593 var server = this;
5594 push.call(this.requests, xhrObj);
5595
5596 xhrObj.onSend = function () {
5597 server.handleRequest(this);
5598
5599 if (server.respondImmediately) {
5600 server.respond();
5601 } else if (server.autoRespond && !server.responding) {
5602 setTimeout(function () {
5603 server.responding = false;
5604 server.respond();
5605 }, server.autoRespondAfter || 10);
5606
5607 server.responding = true;
5608 }
5609 };
5610 },
5611
5612 getHTTPMethod: function getHTTPMethod(request) {
5613 if (this.fakeHTTPMethods && /post/i.test(request.method)) {
5614 var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
5615 return matches ? matches[1] : request.method;
5616 }
5617
5618 return request.method;
5619 },
5620
5621 handleRequest: function handleRequest(xhr) {
5622 if (xhr.async) {
5623 if (!this.queue) {
5624 this.queue = [];
5625 }
5626
5627 push.call(this.queue, xhr);
5628 } else {
5629 this.processRequest(xhr);
5630 }
5631 },
5632
5633 log: function log(response, request) {
5634 var str;
5635
5636 str = "Request:\n" + sinon.format(request) + "\n\n";
5637 str += "Response:\n" + sinon.format(response) + "\n\n";
5638
5639 sinon.log(str);
5640 },
5641
5642 respondWith: function respondWith(method, url, body) {
5643 if (arguments.length === 1 && typeof method !== "function") {
5644 this.response = responseArray(method);
5645 return;
5646 }
5647
5648 if (!this.responses) {
5649 this.responses = [];
5650 }
5651
5652 if (arguments.length === 1) {
5653 body = method;
5654 url = method = null;
5655 }
5656
5657 if (arguments.length === 2) {
5658 body = url;
5659 url = method;
5660 method = null;
5661 }
5662
5663 push.call(this.responses, {
5664 method: method,
5665 url: url,
5666 response: typeof body === "function" ? body : responseArray(body)
5667 });
5668 },
5669
5670 respond: function respond() {
5671 if (arguments.length > 0) {
5672 this.respondWith.apply(this, arguments);
5673 }
5674
5675 var queue = this.queue || [];
5676 var requests = queue.splice(0, queue.length);
5677
5678 for (var i = 0; i < requests.length; i++) {
5679 this.processRequest(requests[i]);
5680 }
5681 },
5682
5683 processRequest: function processRequest(request) {
5684 try {
5685 if (request.aborted) {
5686 return;
5687 }
5688
5689 var response = this.response || [404, {}, ""];
5690
5691 if (this.responses) {
5692 for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
5693 if (match.call(this, this.responses[i], request)) {
5694 response = this.responses[i].response;
5695 break;
5696 }
5697 }
5698 }
5699
5700 if (request.readyState !== 4) {
5701 this.log(response, request);
5702
5703 request.respond(response[0], response[1], response[2]);
5704 }
5705 } catch (e) {
5706 sinon.logError("Fake server request processing", e);
5707 }
5708 },
5709
5710 restore: function restore() {
5711 return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
5712 }
5713 };
5714 }
5715
5716 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
5717 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5718
5719 function loadDependencies(require, exports, module) {
5720 var sinon = require("./core");
5721 require("./fake_xdomain_request");
5722 require("./fake_xml_http_request");
5723 require("../format");
5724 makeApi(sinon);
5725 module.exports = sinon;
5726 }
5727
5728 if (isAMD) {
5729 define(loadDependencies);
5730 } else if (isNode) {
5731 loadDependencies(require, module.exports, module);
5732 } else {
5733 makeApi(sinon); // eslint-disable-line no-undef
5734 }
5735 }());
5736
5737 /**
5738 * @depend fake_server.js
5739 * @depend fake_timers.js
5740 */
5741 /**
5742 * Add-on for sinon.fakeServer that automatically handles a fake timer along with
5743 * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
5744 * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
5745 * it polls the object for completion with setInterval. Dispite the direct
5746 * motivation, there is nothing jQuery-specific in this file, so it can be used
5747 * in any environment where the ajax implementation depends on setInterval or
5748 * setTimeout.
5749 *
5750 * @author Christian Johansen (christian@cjohansen.no)
5751 * @license BSD
5752 *
5753 * Copyright (c) 2010-2013 Christian Johansen
5754 */
5755 (function () {
5756
5757 function makeApi(sinon) {
5758 function Server() {}
5759 Server.prototype = sinon.fakeServer;
5760
5761 sinon.fakeServerWithClock = new Server();
5762
5763 sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
5764 if (xhr.async) {
5765 if (typeof setTimeout.clock === "object") {
5766 this.clock = setTimeout.clock;
5767 } else {
5768 this.clock = sinon.useFakeTimers();
5769 this.resetClock = true;
5770 }
5771
5772 if (!this.longestTimeout) {
5773 var clockSetTimeout = this.clock.setTimeout;
5774 var clockSetInterval = this.clock.setInterval;
5775 var server = this;
5776
5777 this.clock.setTimeout = function (fn, timeout) {
5778 server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
5779
5780 return clockSetTimeout.apply(this, arguments);
5781 };
5782
5783 this.clock.setInterval = function (fn, timeout) {
5784 server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
5785
5786 return clockSetInterval.apply(this, arguments);
5787 };
5788 }
5789 }
5790
5791 return sinon.fakeServer.addRequest.call(this, xhr);
5792 };
5793
5794 sinon.fakeServerWithClock.respond = function respond() {
5795 var returnVal = sinon.fakeServer.respond.apply(this, arguments);
5796
5797 if (this.clock) {
5798 this.clock.tick(this.longestTimeout || 0);
5799 this.longestTimeout = 0;
5800
5801 if (this.resetClock) {
5802 this.clock.restore();
5803 this.resetClock = false;
5804 }
5805 }
5806
5807 return returnVal;
5808 };
5809
5810 sinon.fakeServerWithClock.restore = function restore() {
5811 if (this.clock) {
5812 this.clock.restore();
5813 }
5814
5815 return sinon.fakeServer.restore.apply(this, arguments);
5816 };
5817 }
5818
5819 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
5820 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5821
5822 function loadDependencies(require) {
5823 var sinon = require("./core");
5824 require("./fake_server");
5825 require("./fake_timers");
5826 makeApi(sinon);
5827 }
5828
5829 if (isAMD) {
5830 define(loadDependencies);
5831 } else if (isNode) {
5832 loadDependencies(require);
5833 } else {
5834 makeApi(sinon); // eslint-disable-line no-undef
5835 }
5836 }());
5837
5838 /**
5839 * @depend util/core.js
5840 * @depend extend.js
5841 * @depend collection.js
5842 * @depend util/fake_timers.js
5843 * @depend util/fake_server_with_clock.js
5844 */
5845 /**
5846 * Manages fake collections as well as fake utilities such as Sinon's
5847 * timers and fake XHR implementation in one convenient object.
5848 *
5849 * @author Christian Johansen (christian@cjohansen.no)
5850 * @license BSD
5851 *
5852 * Copyright (c) 2010-2013 Christian Johansen
5853 */
5854 (function (sinonGlobal) {
5855
5856 function makeApi(sinon) {
5857 var push = [].push;
5858
5859 function exposeValue(sandbox, config, key, value) {
5860 if (!value) {
5861 return;
5862 }
5863
5864 if (config.injectInto && !(key in config.injectInto)) {
5865 config.injectInto[key] = value;
5866 sandbox.injectedKeys.push(key);
5867 } else {
5868 push.call(sandbox.args, value);
5869 }
5870 }
5871
5872 function prepareSandboxFromConfig(config) {
5873 var sandbox = sinon.create(sinon.sandbox);
5874
5875 if (config.useFakeServer) {
5876 if (typeof config.useFakeServer === "object") {
5877 sandbox.serverPrototype = config.useFakeServer;
5878 }
5879
5880 sandbox.useFakeServer();
5881 }
5882
5883 if (config.useFakeTimers) {
5884 if (typeof config.useFakeTimers === "object") {
5885 sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
5886 } else {
5887 sandbox.useFakeTimers();
5888 }
5889 }
5890
5891 return sandbox;
5892 }
5893
5894 sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
5895 useFakeTimers: function useFakeTimers() {
5896 this.clock = sinon.useFakeTimers.apply(sinon, arguments);
5897
5898 return this.add(this.clock);
5899 },
5900
5901 serverPrototype: sinon.fakeServer,
5902
5903 useFakeServer: function useFakeServer() {
5904 var proto = this.serverPrototype || sinon.fakeServer;
5905
5906 if (!proto || !proto.create) {
5907 return null;
5908 }
5909
5910 this.server = proto.create();
5911 return this.add(this.server);
5912 },
5913
5914 inject: function (obj) {
5915 sinon.collection.inject.call(this, obj);
5916
5917 if (this.clock) {
5918 obj.clock = this.clock;
5919 }
5920
5921 if (this.server) {
5922 obj.server = this.server;
5923 obj.requests = this.server.requests;
5924 }
5925
5926 obj.match = sinon.match;
5927
5928 return obj;
5929 },
5930
5931 restore: function () {
5932 if (arguments.length) {
5933 throw new Error("sandbox.restore() does not take any parameters. Perhaps you meant stub.restore()");
5934 }
5935
5936 sinon.collection.restore.apply(this, arguments);
5937 this.restoreContext();
5938 },
5939
5940 restoreContext: function () {
5941 if (this.injectedKeys) {
5942 for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
5943 delete this.injectInto[this.injectedKeys[i]];
5944 }
5945 this.injectedKeys = [];
5946 }
5947 },
5948
5949 create: function (config) {
5950 if (!config) {
5951 return sinon.create(sinon.sandbox);
5952 }
5953
5954 var sandbox = prepareSandboxFromConfig(config);
5955 sandbox.args = sandbox.args || [];
5956 sandbox.injectedKeys = [];
5957 sandbox.injectInto = config.injectInto;
5958 var prop,
5959 value;
5960 var exposed = sandbox.inject({});
5961
5962 if (config.properties) {
5963 for (var i = 0, l = config.properties.length; i < l; i++) {
5964 prop = config.properties[i];
5965 value = exposed[prop] || prop === "sandbox" && sandbox;
5966 exposeValue(sandbox, config, prop, value);
5967 }
5968 } else {
5969 exposeValue(sandbox, config, "sandbox", value);
5970 }
5971
5972 return sandbox;
5973 },
5974
5975 match: sinon.match
5976 });
5977
5978 sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
5979
5980 return sinon.sandbox;
5981 }
5982
5983 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
5984 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5985
5986 function loadDependencies(require, exports, module) {
5987 var sinon = require("./util/core");
5988 require("./extend");
5989 require("./util/fake_server_with_clock");
5990 require("./util/fake_timers");
5991 require("./collection");
5992 module.exports = makeApi(sinon);
5993 }
5994
5995 if (isAMD) {
5996 define(loadDependencies);
5997 return;
5998 }
5999
6000 if (isNode) {
6001 loadDependencies(require, module.exports, module);
6002 return;
6003 }
6004
6005 if (sinonGlobal) {
6006 makeApi(sinonGlobal);
6007 }
6008 }(
6009 typeof sinon === "object" && sinon // eslint-disable-line no-undef
6010 ));
6011
6012 /**
6013 * @depend util/core.js
6014 * @depend sandbox.js
6015 */
6016 /**
6017 * Test function, sandboxes fakes
6018 *
6019 * @author Christian Johansen (christian@cjohansen.no)
6020 * @license BSD
6021 *
6022 * Copyright (c) 2010-2013 Christian Johansen
6023 */
6024 (function (sinonGlobal) {
6025
6026 function makeApi(sinon) {
6027 var slice = Array.prototype.slice;
6028
6029 function test(callback) {
6030 var type = typeof callback;
6031
6032 if (type !== "function") {
6033 throw new TypeError("sinon.test needs to wrap a test function, got " + type);
6034 }
6035
6036 function sinonSandboxedTest() {
6037 var config = sinon.getConfig(sinon.config);
6038 config.injectInto = config.injectIntoThis && this || config.injectInto;
6039 var sandbox = sinon.sandbox.create(config);
6040 var args = slice.call(arguments);
6041 var oldDone = args.length && args[args.length - 1];
6042 var exception, result;
6043
6044 if (typeof oldDone === "function") {
6045 args[args.length - 1] = function sinonDone(res) {
6046 if (res) {
6047 sandbox.restore();
6048 } else {
6049 sandbox.verifyAndRestore();
6050 }
6051 oldDone(res);
6052 };
6053 }
6054
6055 try {
6056 result = callback.apply(this, args.concat(sandbox.args));
6057 } catch (e) {
6058 exception = e;
6059 }
6060
6061 if (typeof exception !== "undefined") {
6062 sandbox.restore();
6063 throw exception;
6064 } else if (typeof oldDone !== "function") {
6065 sandbox.verifyAndRestore();
6066 }
6067
6068 return result;
6069 }
6070
6071 if (callback.length) {
6072 return function sinonAsyncSandboxedTest(done) { // eslint-disable-line no-unused-vars
6073 return sinonSandboxedTest.apply(this, arguments);
6074 };
6075 }
6076
6077 return sinonSandboxedTest;
6078 }
6079
6080 test.config = {
6081 injectIntoThis: true,
6082 injectInto: null,
6083 properties: ["spy", "stub", "mock", "clock", "server", "requests"],
6084 useFakeTimers: true,
6085 useFakeServer: true
6086 };
6087
6088 sinon.test = test;
6089 return test;
6090 }
6091
6092 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
6093 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
6094
6095 function loadDependencies(require, exports, module) {
6096 var core = require("./util/core");
6097 require("./sandbox");
6098 module.exports = makeApi(core);
6099 }
6100
6101 if (isAMD) {
6102 define(loadDependencies);
6103 } else if (isNode) {
6104 loadDependencies(require, module.exports, module);
6105 } else if (sinonGlobal) {
6106 makeApi(sinonGlobal);
6107 }
6108 }(typeof sinon === "object" && sinon || null)); // eslint-disable-line no-undef
6109
6110 /**
6111 * @depend util/core.js
6112 * @depend test.js
6113 */
6114 /**
6115 * Test case, sandboxes all test functions
6116 *
6117 * @author Christian Johansen (christian@cjohansen.no)
6118 * @license BSD
6119 *
6120 * Copyright (c) 2010-2013 Christian Johansen
6121 */
6122 (function (sinonGlobal) {
6123
6124 function createTest(property, setUp, tearDown) {
6125 return function () {
6126 if (setUp) {
6127 setUp.apply(this, arguments);
6128 }
6129
6130 var exception, result;
6131
6132 try {
6133 result = property.apply(this, arguments);
6134 } catch (e) {
6135 exception = e;
6136 }
6137
6138 if (tearDown) {
6139 tearDown.apply(this, arguments);
6140 }
6141
6142 if (exception) {
6143 throw exception;
6144 }
6145
6146 return result;
6147 };
6148 }
6149
6150 function makeApi(sinon) {
6151 function testCase(tests, prefix) {
6152 if (!tests || typeof tests !== "object") {
6153 throw new TypeError("sinon.testCase needs an object with test functions");
6154 }
6155
6156 prefix = prefix || "test";
6157 var rPrefix = new RegExp("^" + prefix);
6158 var methods = {};
6159 var setUp = tests.setUp;
6160 var tearDown = tests.tearDown;
6161 var testName,
6162 property,
6163 method;
6164
6165 for (testName in tests) {
6166 if (tests.hasOwnProperty(testName) && !/^(setUp|tearDown)$/.test(testName)) {
6167 property = tests[testName];
6168
6169 if (typeof property === "function" && rPrefix.test(testName)) {
6170 method = property;
6171
6172 if (setUp || tearDown) {
6173 method = createTest(property, setUp, tearDown);
6174 }
6175
6176 methods[testName] = sinon.test(method);
6177 } else {
6178 methods[testName] = tests[testName];
6179 }
6180 }
6181 }
6182
6183 return methods;
6184 }
6185
6186 sinon.testCase = testCase;
6187 return testCase;
6188 }
6189
6190 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
6191 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
6192
6193 function loadDependencies(require, exports, module) {
6194 var core = require("./util/core");
6195 require("./test");
6196 module.exports = makeApi(core);
6197 }
6198
6199 if (isAMD) {
6200 define(loadDependencies);
6201 return;
6202 }
6203
6204 if (isNode) {
6205 loadDependencies(require, module.exports, module);
6206 return;
6207 }
6208
6209 if (sinonGlobal) {
6210 makeApi(sinonGlobal);
6211 }
6212 }(
6213 typeof sinon === "object" && sinon // eslint-disable-line no-undef
6214 ));
6215
6216 /**
6217 * @depend times_in_words.js
6218 * @depend util/core.js
6219 * @depend match.js
6220 * @depend format.js
6221 */
6222 /**
6223 * Assertions matching the test spy retrieval interface.
6224 *
6225 * @author Christian Johansen (christian@cjohansen.no)
6226 * @license BSD
6227 *
6228 * Copyright (c) 2010-2013 Christian Johansen
6229 */
6230 (function (sinonGlobal, global) {
6231
6232 var slice = Array.prototype.slice;
6233
6234 function makeApi(sinon) {
6235 var assert;
6236
6237 function verifyIsStub() {
6238 var method;
6239
6240 for (var i = 0, l = arguments.length; i < l; ++i) {
6241 method = arguments[i];
6242
6243 if (!method) {
6244 assert.fail("fake is not a spy");
6245 }
6246
6247 if (method.proxy && method.proxy.isSinonProxy) {
6248 verifyIsStub(method.proxy);
6249 } else {
6250 if (typeof method !== "function") {
6251 assert.fail(method + " is not a function");
6252 }
6253
6254 if (typeof method.getCall !== "function") {
6255 assert.fail(method + " is not stubbed");
6256 }
6257 }
6258
6259 }
6260 }
6261
6262 function verifyIsValidAssertion(assertionMethod, assertionArgs) {
6263 switch (assertionMethod) {
6264 case "notCalled":
6265 case "called":
6266 case "calledOnce":
6267 case "calledTwice":
6268 case "calledThrice":
6269 if (assertionArgs.length !== 0) {
6270 assert.fail(assertionMethod +
6271 " takes 1 argument but was called with " +
6272 (assertionArgs.length + 1) + " arguments");
6273 }
6274 break;
6275 default:
6276 break;
6277 }
6278 }
6279
6280 function failAssertion(object, msg) {
6281 object = object || global;
6282 var failMethod = object.fail || assert.fail;
6283 failMethod.call(object, msg);
6284 }
6285
6286 function mirrorPropAsAssertion(name, method, message) {
6287 if (arguments.length === 2) {
6288 message = method;
6289 method = name;
6290 }
6291
6292 assert[name] = function (fake) {
6293 verifyIsStub(fake);
6294
6295 var args = slice.call(arguments, 1);
6296 verifyIsValidAssertion(name, args);
6297
6298 var failed = false;
6299
6300 if (typeof method === "function") {
6301 failed = !method(fake);
6302 } else {
6303 failed = typeof fake[method] === "function" ?
6304 !fake[method].apply(fake, args) : !fake[method];
6305 }
6306
6307 if (failed) {
6308 failAssertion(this, (fake.printf || fake.proxy.printf).apply(fake, [message].concat(args)));
6309 } else {
6310 assert.pass(name);
6311 }
6312 };
6313 }
6314
6315 function exposedName(prefix, prop) {
6316 return !prefix || /^fail/.test(prop) ? prop :
6317 prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
6318 }
6319
6320 assert = {
6321 failException: "AssertError",
6322
6323 fail: function fail(message) {
6324 var error = new Error(message);
6325 error.name = this.failException || assert.failException;
6326
6327 throw error;
6328 },
6329
6330 pass: function pass() {},
6331
6332 callOrder: function assertCallOrder() {
6333 verifyIsStub.apply(null, arguments);
6334 var expected = "";
6335 var actual = "";
6336
6337 if (!sinon.calledInOrder(arguments)) {
6338 try {
6339 expected = [].join.call(arguments, ", ");
6340 var calls = slice.call(arguments);
6341 var i = calls.length;
6342 while (i) {
6343 if (!calls[--i].called) {
6344 calls.splice(i, 1);
6345 }
6346 }
6347 actual = sinon.orderByFirstCall(calls).join(", ");
6348 } catch (e) {
6349 // If this fails, we'll just fall back to the blank string
6350 }
6351
6352 failAssertion(this, "expected " + expected + " to be " +
6353 "called in order but were called as " + actual);
6354 } else {
6355 assert.pass("callOrder");
6356 }
6357 },
6358
6359 callCount: function assertCallCount(method, count) {
6360 verifyIsStub(method);
6361
6362 if (method.callCount !== count) {
6363 var msg = "expected %n to be called " + sinon.timesInWords(count) +
6364 " but was called %c%C";
6365 failAssertion(this, method.printf(msg));
6366 } else {
6367 assert.pass("callCount");
6368 }
6369 },
6370
6371 expose: function expose(target, options) {
6372 if (!target) {
6373 throw new TypeError("target is null or undefined");
6374 }
6375
6376 var o = options || {};
6377 var prefix = typeof o.prefix === "undefined" && "assert" || o.prefix;
6378 var includeFail = typeof o.includeFail === "undefined" || !!o.includeFail;
6379
6380 for (var method in this) {
6381 if (method !== "expose" && (includeFail || !/^(fail)/.test(method))) {
6382 target[exposedName(prefix, method)] = this[method];
6383 }
6384 }
6385
6386 return target;
6387 },
6388
6389 match: function match(actual, expectation) {
6390 var matcher = sinon.match(expectation);
6391 if (matcher.test(actual)) {
6392 assert.pass("match");
6393 } else {
6394 var formatted = [
6395 "expected value to match",
6396 " expected = " + sinon.format(expectation),
6397 " actual = " + sinon.format(actual)
6398 ];
6399
6400 failAssertion(this, formatted.join("\n"));
6401 }
6402 }
6403 };
6404
6405 mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
6406 mirrorPropAsAssertion("notCalled", function (spy) {
6407 return !spy.called;
6408 }, "expected %n to not have been called but was called %c%C");
6409 mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
6410 mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
6411 mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
6412 mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
6413 mirrorPropAsAssertion(
6414 "alwaysCalledOn",
6415 "expected %n to always be called with %1 as this but was called with %t"
6416 );
6417 mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
6418 mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
6419 mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
6420 mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
6421 mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
6422 mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
6423 mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
6424 mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
6425 mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
6426 mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
6427 mirrorPropAsAssertion("threw", "%n did not throw exception%C");
6428 mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
6429
6430 sinon.assert = assert;
6431 return assert;
6432 }
6433
6434 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
6435 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
6436
6437 function loadDependencies(require, exports, module) {
6438 var sinon = require("./util/core");
6439 require("./match");
6440 require("./format");
6441 module.exports = makeApi(sinon);
6442 }
6443
6444 if (isAMD) {
6445 define(loadDependencies);
6446 return;
6447 }
6448
6449 if (isNode) {
6450 loadDependencies(require, module.exports, module);
6451 return;
6452 }
6453
6454 if (sinonGlobal) {
6455 makeApi(sinonGlobal);
6456 }
6457 }(
6458 typeof sinon === "object" && sinon, // eslint-disable-line no-undef
6459 typeof global !== "undefined" ? global : self
6460 ));
6461
6462 return sinon;
6463 }));