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