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