2 * Sinon.JS 1.14.1, 2015/03/16
4 * @author Christian Johansen (christian@cjohansen.no)
5 * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
9 * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without modification,
13 * are permitted provided that the following conditions are met:
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.
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.
36 (function (root, factory) {
37 if (typeof define === 'function' && define.amd) {
38 define('sinon', [], function () {
39 return (root.sinon = factory());
41 } else if (typeof exports === 'object') {
42 module.exports = factory();
44 root.sinon = factory();
49 function define(mod, deps, fn) {
50 if (mod == "samsam") {
52 } else if (typeof deps === "function" && mod.length === 0) {
54 } else if (typeof fn === "function") {
55 formatio = fn(samsam);
59 ((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
60 (typeof module === "object" &&
61 function (m) { module.exports = m(); }) || // Node
62 function (m) { this.samsam = m(); } // Browser globals
64 var o = Object.prototype;
65 var div = typeof document !== "undefined" && document.createElement("div");
67 function isNaN(value) {
68 // Unlike global isNaN, this avoids type coercion
69 // typeof check avoids IE host object issues, hat tip to
71 var val = value; // JsLint thinks value !== value is "weird"
72 return typeof value === "number" && value !== val;
75 function getClass(value) {
76 // Returns the internal [[Class]] by calling Object.prototype.toString
77 // with the provided value as this. Return value is a string, naming the
78 // internal class, e.g. "Array"
79 return o.toString.call(value).split(/[ \]]/)[1];
83 * @name samsam.isArguments
84 * @param Object object
86 * Returns ``true`` if ``object`` is an ``arguments`` object,
87 * ``false`` otherwise.
89 function isArguments(object) {
90 if (getClass(object) === 'Arguments') { return true; }
91 if (typeof object !== "object" || typeof object.length !== "number" ||
92 getClass(object) === "Array") {
95 if (typeof object.callee == "function") { return true; }
97 object[object.length] = 6;
98 delete object[object.length];
106 * @name samsam.isElement
107 * @param Object object
109 * Returns ``true`` if ``object`` is a DOM element node. Unlike
110 * Underscore.js/lodash, this function will return ``false`` if ``object``
111 * is an *element-like* object, i.e. a regular object with a ``nodeType``
112 * property that holds the value ``1``.
114 function isElement(object) {
115 if (!object || object.nodeType !== 1 || !div) { return false; }
117 object.appendChild(div);
118 object.removeChild(div);
127 * @param Object object
129 * Return an array of own property names.
131 function keys(object) {
133 for (prop in object) {
134 if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
140 * @name samsam.isDate
141 * @param Object value
143 * Returns true if the object is a ``Date``, or *date-like*. Duck typing
144 * of date objects work by checking that the object has a ``getTime``
145 * function whose return value equals the return value from the object's
148 function isDate(value) {
149 return typeof value.getTime == "function" &&
150 value.getTime() == value.valueOf();
154 * @name samsam.isNegZero
155 * @param Object value
157 * Returns ``true`` if ``value`` is ``-0``.
159 function isNegZero(value) {
160 return value === 0 && 1 / value === -Infinity;
168 * Returns ``true`` if two objects are strictly equal. Compared to
169 * ``===`` there are two exceptions:
171 * - NaN is considered equal to NaN
172 * - -0 and +0 are not considered equal
174 function identical(obj1, obj2) {
175 if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
176 return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
182 * @name samsam.deepEqual
186 * Deep equal comparison. Two values are "deep equal" if:
188 * - They are equal, according to samsam.identical
189 * - They are both date objects representing the same time
190 * - They are both arrays containing elements that are all deepEqual
191 * - They are objects with the same set of properties, and each property
192 * in ``obj1`` is deepEqual to the corresponding property in ``obj2``
194 * Supports cyclic objects.
196 function deepEqualCyclic(obj1, obj2) {
198 // used for cyclic comparison
199 // contain already visited objects
202 // contain pathes (position in the object structure)
203 // of the already visited objects
204 // indexes same as in objects arrays
207 // contains combinations of already compared objects
208 // in the manner: { "$1['ref']$2['ref']": true }
212 * used to check, if the value of a property is an object
213 * (cyclic logic is only needed for objects)
214 * only needed for cyclic logic
216 function isObject(value) {
218 if (typeof value === 'object' && value !== null &&
219 !(value instanceof Boolean) &&
220 !(value instanceof Date) &&
221 !(value instanceof Number) &&
222 !(value instanceof RegExp) &&
223 !(value instanceof String)) {
232 * returns the index of the given object in the
233 * given objects array, -1 if not contained
234 * only needed for cyclic logic
236 function getIndex(objects, obj) {
239 for (i = 0; i < objects.length; i++) {
240 if (objects[i] === obj) {
248 // does the recursion for the deep equal check
249 return (function deepEqual(obj1, obj2, path1, path2) {
250 var type1 = typeof obj1;
251 var type2 = typeof obj2;
253 // == null also matches undefined
255 isNaN(obj1) || isNaN(obj2) ||
256 obj1 == null || obj2 == null ||
257 type1 !== "object" || type2 !== "object") {
259 return identical(obj1, obj2);
262 // Elements are only equal if identical(expected, actual)
263 if (isElement(obj1) || isElement(obj2)) { return false; }
265 var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
266 if (isDate1 || isDate2) {
267 if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
272 if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
273 if (obj1.toString() !== obj2.toString()) { return false; }
276 var class1 = getClass(obj1);
277 var class2 = getClass(obj2);
278 var keys1 = keys(obj1);
279 var keys2 = keys(obj2);
281 if (isArguments(obj1) || isArguments(obj2)) {
282 if (obj1.length !== obj2.length) { return false; }
284 if (type1 !== type2 || class1 !== class2 ||
285 keys1.length !== keys2.length) {
291 // following vars are used for the cyclic logic
293 isObject1, isObject2,
297 for (i = 0, l = keys1.length; i < l; i++) {
299 if (!o.hasOwnProperty.call(obj2, key)) {
303 // Start of the cyclic logic
308 isObject1 = isObject(value1);
309 isObject2 = isObject(value2);
311 // determine, if the objects were already visited
312 // (it's faster to check for isObject first, than to
313 // get -1 from getIndex for non objects)
314 index1 = isObject1 ? getIndex(objects1, value1) : -1;
315 index2 = isObject2 ? getIndex(objects2, value2) : -1;
317 // determine the new pathes of the objects
318 // - for non cyclic objects the current path will be extended
319 // by current property name
320 // - for cyclic objects the stored path is taken
321 newPath1 = index1 !== -1
323 : path1 + '[' + JSON.stringify(key) + ']';
324 newPath2 = index2 !== -1
326 : path2 + '[' + JSON.stringify(key) + ']';
328 // stop recursion if current objects are already compared
329 if (compared[newPath1 + newPath2]) {
333 // remember the current objects and their pathes
334 if (index1 === -1 && isObject1) {
335 objects1.push(value1);
336 paths1.push(newPath1);
338 if (index2 === -1 && isObject2) {
339 objects2.push(value2);
340 paths2.push(newPath2);
343 // remember that the current objects are already compared
344 if (isObject1 && isObject2) {
345 compared[newPath1 + newPath2] = true;
348 // End of cyclic logic
350 // neither value1 nor value2 is a cycle
351 // continue with next level
352 if (!deepEqual(value1, value2, newPath1, newPath2)) {
359 }(obj1, obj2, '$1', '$2'));
364 function arrayContains(array, subset) {
365 if (subset.length === 0) { return true; }
367 for (i = 0, l = array.length; i < l; ++i) {
368 if (match(array[i], subset[0])) {
369 for (j = 0, k = subset.length; j < k; ++j) {
370 if (!match(array[i + j], subset[j])) { return false; }
380 * @param Object object
381 * @param Object matcher
383 * Compare arbitrary value ``object`` with matcher.
385 match = function match(object, matcher) {
386 if (matcher && typeof matcher.test === "function") {
387 return matcher.test(object);
390 if (typeof matcher === "function") {
391 return matcher(object) === true;
394 if (typeof matcher === "string") {
395 matcher = matcher.toLowerCase();
396 var notNull = typeof object === "string" || !!object;
398 (String(object)).toLowerCase().indexOf(matcher) >= 0;
401 if (typeof matcher === "number") {
402 return matcher === object;
405 if (typeof matcher === "boolean") {
406 return matcher === object;
409 if (typeof(matcher) === "undefined") {
410 return typeof(object) === "undefined";
413 if (matcher === null) {
414 return object === null;
417 if (getClass(object) === "Array" && getClass(matcher) === "Array") {
418 return arrayContains(object, matcher);
421 if (matcher && typeof matcher === "object") {
422 if (matcher === object) {
426 for (prop in matcher) {
427 var value = object[prop];
428 if (typeof value === "undefined" &&
429 typeof object.getAttribute === "function") {
430 value = object.getAttribute(prop);
432 if (matcher[prop] === null || typeof matcher[prop] === 'undefined') {
433 if (value !== matcher[prop]) {
436 } else if (typeof value === "undefined" || !match(value, matcher[prop])) {
443 throw new Error("Matcher was not a string, a number, a " +
444 "function, a boolean or an object");
448 isArguments: isArguments,
449 isElement: isElement,
451 isNegZero: isNegZero,
452 identical: identical,
453 deepEqual: deepEqualCyclic,
458 ((typeof define === "function" && define.amd && function (m) {
459 define("formatio", ["samsam"], m);
460 }) || (typeof module === "object" && function (m) {
461 module.exports = m(require("samsam"));
462 }) || function (m) { this.formatio = m(this.samsam); }
463 )(function (samsam) {
466 excludeConstructors: ["Object", /^.$/],
468 limitChildrenCount: 0
471 var hasOwn = Object.prototype.hasOwnProperty;
473 var specialObjects = [];
474 if (typeof global !== "undefined") {
475 specialObjects.push({ object: global, value: "[object global]" });
477 if (typeof document !== "undefined") {
478 specialObjects.push({
480 value: "[object HTMLDocument]"
483 if (typeof window !== "undefined") {
484 specialObjects.push({ object: window, value: "[object Window]" });
487 function functionName(func) {
488 if (!func) { return ""; }
489 if (func.displayName) { return func.displayName; }
490 if (func.name) { return func.name; }
491 var matches = func.toString().match(/function\s+([^\(]+)/m);
492 return (matches && matches[1]) || "";
495 function constructorName(f, object) {
496 var name = functionName(object && object.constructor);
497 var excludes = f.excludeConstructors ||
498 formatio.excludeConstructors || [];
501 for (i = 0, l = excludes.length; i < l; ++i) {
502 if (typeof excludes[i] === "string" && excludes[i] === name) {
504 } else if (excludes[i].test && excludes[i].test(name)) {
512 function isCircular(object, objects) {
513 if (typeof object !== "object") { return false; }
515 for (i = 0, l = objects.length; i < l; ++i) {
516 if (objects[i] === object) { return true; }
521 function ascii(f, object, processed, indent) {
522 if (typeof object === "string") {
523 var qs = f.quoteStrings;
524 var quote = typeof qs !== "boolean" || qs;
525 return processed || quote ? '"' + object + '"' : object;
528 if (typeof object === "function" && !(object instanceof RegExp)) {
529 return ascii.func(object);
532 processed = processed || [];
534 if (isCircular(object, processed)) { return "[Circular]"; }
536 if (Object.prototype.toString.call(object) === "[object Array]") {
537 return ascii.array.call(f, object, processed);
540 if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
541 if (samsam.isElement(object)) { return ascii.element(object); }
543 if (typeof object.toString === "function" &&
544 object.toString !== Object.prototype.toString) {
545 return object.toString();
549 for (i = 0, l = specialObjects.length; i < l; i++) {
550 if (object === specialObjects[i].object) {
551 return specialObjects[i].value;
555 return ascii.object.call(f, object, processed, indent);
558 ascii.func = function (func) {
559 return "function " + functionName(func) + "() {}";
562 ascii.array = function (array, processed) {
563 processed = processed || [];
564 processed.push(array);
567 l = (this.limitChildrenCount > 0) ?
568 Math.min(this.limitChildrenCount, array.length) : array.length;
570 for (i = 0; i < l; ++i) {
571 pieces.push(ascii(this, array[i], processed));
575 pieces.push("[... " + (array.length - l) + " more elements]");
577 return "[" + pieces.join(", ") + "]";
580 ascii.object = function (object, processed, indent) {
581 processed = processed || [];
582 processed.push(object);
583 indent = indent || 0;
584 var pieces = [], properties = samsam.keys(object).sort();
586 var prop, str, obj, i, k, l;
587 l = (this.limitChildrenCount > 0) ?
588 Math.min(this.limitChildrenCount, properties.length) : properties.length;
590 for (i = 0; i < l; ++i) {
591 prop = properties[i];
594 if (isCircular(obj, processed)) {
597 str = ascii(this, obj, processed, indent + 2);
600 str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
601 length += str.length;
605 var cons = constructorName(this, object);
606 var prefix = cons ? "[" + cons + "] " : "";
608 for (i = 0, k = indent; i < k; ++i) { is += " "; }
610 if(l < properties.length)
611 pieces.push("[... " + (properties.length - l) + " more elements]");
613 if (length + indent > 80) {
614 return prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" +
617 return prefix + "{ " + pieces.join(", ") + " }";
620 ascii.element = function (element) {
621 var tagName = element.tagName.toLowerCase();
622 var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
624 for (i = 0, l = attrs.length; i < l; ++i) {
625 attr = attrs.item(i);
626 attrName = attr.nodeName.toLowerCase().replace("html:", "");
627 val = attr.nodeValue;
628 if (attrName !== "contenteditable" || val !== "inherit") {
629 if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
633 var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
634 var content = element.innerHTML;
636 if (content.length > 20) {
637 content = content.substr(0, 20) + "[...]";
640 var res = formatted + pairs.join(" ") + ">" + content +
641 "</" + tagName + ">";
643 return res.replace(/ contentEditable="inherit"/, "");
646 function Formatio(options) {
647 for (var opt in options) {
648 this[opt] = options[opt];
652 Formatio.prototype = {
653 functionName: functionName,
655 configure: function (options) {
656 return new Formatio(options);
659 constructorName: function (object) {
660 return constructorName(this, object);
663 ascii: function (object, processed, indent) {
664 return ascii(this, object, processed, indent);
668 return Formatio.prototype;
670 !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){
672 /*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
675 * @author Christian Johansen (christian@cjohansen.no) and contributors
678 * Copyright (c) 2010-2014 Christian Johansen
681 // node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
682 // browsers, a number.
683 // see https://github.com/cjohansen/Sinon.JS/pull/436
684 var timeoutResult = setTimeout(function() {}, 0);
685 var addTimerReturnsObject = typeof timeoutResult === "object";
686 clearTimeout(timeoutResult);
688 var NativeDate = Date;
692 * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
693 * number of milliseconds. This is used to support human-readable strings passed
696 function parseTime(str) {
701 var strings = str.split(":");
702 var l = strings.length, i = l;
705 if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
706 throw new Error("tick only understands numbers and 'h:m:s'");
710 parsed = parseInt(strings[i], 10);
713 throw new Error("Invalid time " + str);
716 ms += parsed * Math.pow(60, (l - i - 1));
723 * Used to grok the `now` parameter to createClock.
725 function getEpoch(epoch) {
726 if (!epoch) { return 0; }
727 if (typeof epoch.getTime === "function") { return epoch.getTime(); }
728 if (typeof epoch === "number") { return epoch; }
729 throw new TypeError("now should be milliseconds since UNIX epoch");
732 function inRange(from, to, timer) {
733 return timer && timer.callAt >= from && timer.callAt <= to;
736 function mirrorDateProperties(target, source) {
738 target.now = function now() {
739 return target.clock.now;
745 if (source.toSource) {
746 target.toSource = function toSource() {
747 return source.toSource();
750 delete target.toSource;
753 target.toString = function toString() {
754 return source.toString();
757 target.prototype = source.prototype;
758 target.parse = source.parse;
759 target.UTC = source.UTC;
760 target.prototype.toUTCString = source.prototype.toUTCString;
762 for (var prop in source) {
763 if (source.hasOwnProperty(prop)) {
764 target[prop] = source[prop];
771 function createDate() {
772 function ClockDate(year, month, date, hour, minute, second, ms) {
773 // Defensive and verbose to avoid potential harm in passing
774 // explicit undefined when user does not pass argument
775 switch (arguments.length) {
777 return new NativeDate(ClockDate.clock.now);
779 return new NativeDate(year);
781 return new NativeDate(year, month);
783 return new NativeDate(year, month, date);
785 return new NativeDate(year, month, date, hour);
787 return new NativeDate(year, month, date, hour, minute);
789 return new NativeDate(year, month, date, hour, minute, second);
791 return new NativeDate(year, month, date, hour, minute, second, ms);
795 return mirrorDateProperties(ClockDate, NativeDate);
798 function addTimer(clock, timer) {
799 if (typeof timer.func === "undefined") {
800 throw new Error("Callback must be provided to timer calls");
808 timer.createdAt = clock.now;
809 timer.callAt = clock.now + (timer.delay || 0);
811 clock.timers[timer.id] = timer;
813 if (addTimerReturnsObject) {
825 function firstTimerInRange(clock, from, to) {
826 var timers = clock.timers, timer = null;
828 for (var id in timers) {
829 if (!inRange(from, to, timers[id])) {
833 if (!timer || ~compareTimers(timer, timers[id])) {
841 function compareTimers(a, b) {
842 // Sort first by absolute timing
843 if (a.callAt < b.callAt) {
846 if (a.callAt > b.callAt) {
850 // Sort next by immediate, immediate timers take precedence
851 if (a.immediate && !b.immediate) {
854 if (!a.immediate && b.immediate) {
858 // Sort next by creation time, earlier-created timers take precedence
859 if (a.createdAt < b.createdAt) {
862 if (a.createdAt > b.createdAt) {
866 // Sort next by id, lower-id timers take precedence
874 // As timer ids are unique, no fallback `0` is necessary
877 function callTimer(clock, timer) {
878 if (typeof timer.interval == "number") {
879 clock.timers[timer.id].callAt += timer.interval;
881 delete clock.timers[timer.id];
885 if (typeof timer.func == "function") {
886 timer.func.apply(null, timer.args);
894 if (!clock.timers[timer.id]) {
906 function uninstall(clock, target) {
909 for (var i = 0, l = clock.methods.length; i < l; i++) {
910 method = clock.methods[i];
912 if (target[method].hadOwnProperty) {
913 target[method] = clock["_" + method];
916 delete target[method];
921 // Prevent multiple executions which will completely remove these props
925 function hijackMethod(target, method, clock) {
926 clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
927 clock["_" + method] = target[method];
929 if (method == "Date") {
930 var date = mirrorDateProperties(clock[method], target[method]);
931 target[method] = date;
933 target[method] = function () {
934 return clock[method].apply(clock, arguments);
937 for (var prop in clock[method]) {
938 if (clock[method].hasOwnProperty(prop)) {
939 target[method][prop] = clock[method][prop];
944 target[method].clock = clock;
948 setTimeout: setTimeout,
949 clearTimeout: clearTimeout,
950 setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
951 clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
952 setInterval: setInterval,
953 clearInterval: clearInterval,
957 var keys = Object.keys || function (obj) {
959 for (var key in obj) {
965 exports.timers = timers;
967 var createClock = exports.createClock = function (now) {
974 clock.Date.clock = clock;
976 clock.setTimeout = function setTimeout(func, timeout) {
977 return addTimer(clock, {
979 args: Array.prototype.slice.call(arguments, 2),
984 clock.clearTimeout = function clearTimeout(timerId) {
986 // null appears to be allowed in most browsers, and appears to be
987 // relied upon by some libraries, like Bootstrap carousel
993 // in Node, timerId is an object with .ref()/.unref(), and
994 // its .id field is the actual timer id.
995 if (typeof timerId === "object") {
998 if (timerId in clock.timers) {
999 delete clock.timers[timerId];
1003 clock.setInterval = function setInterval(func, timeout) {
1004 return addTimer(clock, {
1006 args: Array.prototype.slice.call(arguments, 2),
1012 clock.clearInterval = function clearInterval(timerId) {
1013 clock.clearTimeout(timerId);
1016 clock.setImmediate = function setImmediate(func) {
1017 return addTimer(clock, {
1019 args: Array.prototype.slice.call(arguments, 1),
1024 clock.clearImmediate = function clearImmediate(timerId) {
1025 clock.clearTimeout(timerId);
1028 clock.tick = function tick(ms) {
1029 ms = typeof ms == "number" ? ms : parseTime(ms);
1030 var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
1031 var timer = firstTimerInRange(clock, tickFrom, tickTo);
1034 while (timer && tickFrom <= tickTo) {
1035 if (clock.timers[timer.id]) {
1036 tickFrom = clock.now = timer.callAt;
1038 callTimer(clock, timer);
1040 firstException = firstException || e;
1044 timer = firstTimerInRange(clock, previous, tickTo);
1045 previous = tickFrom;
1050 if (firstException) {
1051 throw firstException;
1057 clock.reset = function reset() {
1064 exports.install = function install(target, now, toFake) {
1065 if (typeof target === "number") {
1075 var clock = createClock(now);
1077 clock.uninstall = function () {
1078 uninstall(clock, target);
1081 clock.methods = toFake || [];
1083 if (clock.methods.length === 0) {
1084 clock.methods = keys(timers);
1087 for (var i = 0, l = clock.methods.length; i < l; i++) {
1088 hijackMethod(target, clock.methods[i], clock);
1094 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1100 * Sinon core utilities. For internal use only.
1102 * @author Christian Johansen (christian@cjohansen.no)
1105 * Copyright (c) 2010-2013 Christian Johansen
1108 var sinon = (function () {
1112 var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
1113 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1115 function loadDependencies(require, exports, module) {
1116 sinon = module.exports = require("./sinon/util/core");
1117 require("./sinon/extend");
1118 require("./sinon/typeOf");
1119 require("./sinon/times_in_words");
1120 require("./sinon/spy");
1121 require("./sinon/call");
1122 require("./sinon/behavior");
1123 require("./sinon/stub");
1124 require("./sinon/mock");
1125 require("./sinon/collection");
1126 require("./sinon/assert");
1127 require("./sinon/sandbox");
1128 require("./sinon/test");
1129 require("./sinon/test_case");
1130 require("./sinon/match");
1131 require("./sinon/format");
1132 require("./sinon/log_error");
1136 define(loadDependencies);
1137 } else if (isNode) {
1138 loadDependencies(require, module.exports, module);
1139 sinon = module.exports;
1148 * @depend ../../sinon.js
1151 * Sinon core utilities. For internal use only.
1153 * @author Christian Johansen (christian@cjohansen.no)
1156 * Copyright (c) 2010-2013 Christian Johansen
1160 var div = typeof document != "undefined" && document.createElement("div");
1161 var hasOwn = Object.prototype.hasOwnProperty;
1163 function isDOMNode(obj) {
1164 var success = false;
1167 obj.appendChild(div);
1168 success = div.parentNode == obj;
1173 obj.removeChild(div);
1175 // Remove failed, not much we can do about that
1182 function isElement(obj) {
1183 return div && obj && obj.nodeType === 1 && isDOMNode(obj);
1186 function isFunction(obj) {
1187 return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
1190 function isReallyNaN(val) {
1191 return typeof val === "number" && isNaN(val);
1194 function mirrorProperties(target, source) {
1195 for (var prop in source) {
1196 if (!hasOwn.call(target, prop)) {
1197 target[prop] = source[prop];
1202 function isRestorable(obj) {
1203 return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
1206 // Cheap way to detect if we have ES5 support.
1207 var hasES5Support = "keys" in Object;
1209 function makeApi(sinon) {
1210 sinon.wrapMethod = function wrapMethod(object, property, method) {
1212 throw new TypeError("Should wrap property of object");
1215 if (typeof method != "function" && typeof method != "object") {
1216 throw new TypeError("Method wrapper should be a function or a property descriptor");
1219 function checkWrappedMethod(wrappedMethod) {
1220 if (!isFunction(wrappedMethod)) {
1221 error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
1222 property + " as function");
1223 } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
1224 error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
1225 } else if (wrappedMethod.calledBefore) {
1226 var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
1227 error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
1231 if (wrappedMethod && wrappedMethod.stackTrace) {
1232 error.stack += "\n--------------\n" + wrappedMethod.stackTrace;
1238 var error, wrappedMethod;
1240 // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
1241 // when using hasOwn.call on objects from other frames.
1242 var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
1244 if (hasES5Support) {
1245 var methodDesc = (typeof method == "function") ? {value: method} : method,
1246 wrappedMethodDesc = sinon.getPropertyDescriptor(object, property),
1249 if (!wrappedMethodDesc) {
1250 error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
1251 property + " as function");
1252 } else if (wrappedMethodDesc.restore && wrappedMethodDesc.restore.sinon) {
1253 error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
1256 if (wrappedMethodDesc && wrappedMethodDesc.stackTrace) {
1257 error.stack += "\n--------------\n" + wrappedMethodDesc.stackTrace;
1262 var types = sinon.objectKeys(methodDesc);
1263 for (i = 0; i < types.length; i++) {
1264 wrappedMethod = wrappedMethodDesc[types[i]];
1265 checkWrappedMethod(wrappedMethod);
1268 mirrorProperties(methodDesc, wrappedMethodDesc);
1269 for (i = 0; i < types.length; i++) {
1270 mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]);
1272 Object.defineProperty(object, property, methodDesc);
1274 wrappedMethod = object[property];
1275 checkWrappedMethod(wrappedMethod);
1276 object[property] = method;
1277 method.displayName = property;
1280 method.displayName = property;
1282 // Set up a stack trace which can be used later to find what line of
1283 // code the original method was created on.
1284 method.stackTrace = (new Error("Stack Trace for original")).stack;
1286 method.restore = function () {
1287 // For prototype properties try to reset by delete first.
1288 // If this fails (ex: localStorage on mobile safari) then force a reset
1289 // via direct assignment.
1292 delete object[property];
1294 // For native code functions `delete` fails without throwing an error
1295 // on Chrome < 43, PhantomJS, etc.
1296 // Use strict equality comparison to check failures then force a reset
1297 // via direct assignment.
1298 if (object[property] === method) {
1299 object[property] = wrappedMethod;
1301 } else if (hasES5Support) {
1302 Object.defineProperty(object, property, wrappedMethodDesc);
1305 if (!hasES5Support && object[property] === method) {
1306 object[property] = wrappedMethod;
1310 method.restore.sinon = true;
1312 if (!hasES5Support) {
1313 mirrorProperties(method, wrappedMethod);
1319 sinon.create = function create(proto) {
1320 var F = function () {};
1321 F.prototype = proto;
1325 sinon.deepEqual = function deepEqual(a, b) {
1326 if (sinon.match && sinon.match.isMatcher(a)) {
1330 if (typeof a != "object" || typeof b != "object") {
1331 if (isReallyNaN(a) && isReallyNaN(b)) {
1338 if (isElement(a) || isElement(b)) {
1346 if ((a === null && b !== null) || (a !== null && b === null)) {
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);
1355 var aString = Object.prototype.toString.call(a);
1356 if (aString != Object.prototype.toString.call(b)) {
1360 if (aString == "[object Date]") {
1361 return a.valueOf() === b.valueOf();
1364 var prop, aLength = 0, bLength = 0;
1366 if (aString == "[object Array]" && a.length !== b.length) {
1377 if (!deepEqual(a[prop], b[prop])) {
1386 return aLength == bLength;
1389 sinon.functionName = function functionName(func) {
1390 var name = func.displayName || func.name;
1392 // Use function decomposition as a last resort to get function
1393 // name. Does not rely on function decomposition to work - if it
1394 // doesn't debugging will be slightly less informative
1395 // (i.e. toString will say 'spy' rather than 'myFunc').
1397 var matches = func.toString().match(/function ([^\s\(]+)/);
1398 name = matches && matches[1];
1404 sinon.functionToString = function toString() {
1405 if (this.getCall && this.callCount) {
1406 var thisValue, prop, i = this.callCount;
1409 thisValue = this.getCall(i).thisValue;
1411 for (prop in thisValue) {
1412 if (thisValue[prop] === this) {
1419 return this.displayName || "sinon fake";
1422 sinon.objectKeys = function objectKeys(obj) {
1423 if (obj !== Object(obj)) {
1424 throw new TypeError("sinon.objectKeys called on a non-object");
1430 if (hasOwn.call(obj, key)) {
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);
1446 sinon.getConfig = function (custom) {
1448 custom = custom || {};
1449 var defaults = sinon.defaultConfig;
1451 for (var prop in defaults) {
1452 if (defaults.hasOwnProperty(prop)) {
1453 config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
1460 sinon.defaultConfig = {
1461 injectIntoThis: true,
1463 properties: ["spy", "stub", "mock", "clock", "server", "requests"],
1464 useFakeTimers: true,
1468 sinon.timesInWords = function timesInWords(count) {
1469 return count == 1 && "once" ||
1470 count == 2 && "twice" ||
1471 count == 3 && "thrice" ||
1472 (count || 0) + " times";
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) {
1485 sinon.orderByFirstCall = function (spies) {
1486 return spies.sort(function (a, b) {
1487 // uuid, won't ever be equal
1488 var aCall = a.getCall(0);
1489 var bCall = b.getCall(0);
1490 var aId = aCall && aCall.callId || -1;
1491 var bId = bCall && bCall.callId || -1;
1493 return aId < bId ? -1 : 1;
1497 sinon.createStubInstance = function (constructor) {
1498 if (typeof constructor !== "function") {
1499 throw new TypeError("The constructor should be a function.");
1501 return sinon.stub(sinon.create(constructor.prototype));
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();
1511 } else if (isRestorable(object)) {
1519 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
1520 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1522 function loadDependencies(require, exports) {
1527 define(loadDependencies);
1528 } else if (isNode) {
1529 loadDependencies(require, module.exports);
1530 } else if (!sinon) {
1535 }(typeof sinon == "object" && sinon || null));
1538 * @depend util/core.js
1542 function makeApi(sinon) {
1544 // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
1545 var hasDontEnumBug = (function () {
1547 constructor: function () {
1550 toString: function () {
1553 valueOf: function () {
1556 toLocaleString: function () {
1559 prototype: function () {
1562 isPrototypeOf: function () {
1565 propertyIsEnumerable: function () {
1568 hasOwnProperty: function () {
1571 length: function () {
1574 unique: function () {
1580 for (var prop in obj) {
1581 result.push(obj[prop]());
1583 return result.join("") !== "0123456789";
1586 /* Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will
1587 * override properties in previous sources.
1589 * target - The Object to extend
1590 * sources - Objects to copy properties from.
1592 * Returns the extended target
1594 function extend(target /*, sources */) {
1595 var sources = Array.prototype.slice.call(arguments, 1),
1598 for (i = 0; i < sources.length; i++) {
1599 source = sources[i];
1601 for (prop in source) {
1602 if (source.hasOwnProperty(prop)) {
1603 target[prop] = source[prop];
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;
1617 sinon.extend = extend;
1618 return sinon.extend;
1621 function loadDependencies(require, exports, module) {
1622 var sinon = require("./util/core");
1623 module.exports = makeApi(sinon);
1626 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
1627 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1630 define(loadDependencies);
1631 } else if (isNode) {
1632 loadDependencies(require, module.exports, module);
1633 } else if (!sinon) {
1638 }(typeof sinon == "object" && sinon || null));
1641 * @depend util/core.js
1645 function makeApi(sinon) {
1647 function timesInWords(count) {
1656 return (count || 0) + " times";
1660 sinon.timesInWords = timesInWords;
1661 return sinon.timesInWords;
1664 function loadDependencies(require, exports, module) {
1665 var sinon = require("./util/core");
1666 module.exports = makeApi(sinon);
1669 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
1670 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1673 define(loadDependencies);
1674 } else if (isNode) {
1675 loadDependencies(require, module.exports, module);
1676 } else if (!sinon) {
1681 }(typeof sinon == "object" && sinon || null));
1684 * @depend util/core.js
1689 * @author Christian Johansen (christian@cjohansen.no)
1692 * Copyright (c) 2010-2014 Christian Johansen
1695 (function (sinon, formatio) {
1696 function makeApi(sinon) {
1697 function typeOf(value) {
1698 if (value === null) {
1700 } else if (value === undefined) {
1703 var string = Object.prototype.toString.call(value);
1704 return string.substring(8, string.length - 1).toLowerCase();
1707 sinon.typeOf = typeOf;
1708 return sinon.typeOf;
1711 function loadDependencies(require, exports, module) {
1712 var sinon = require("./util/core");
1713 module.exports = makeApi(sinon);
1716 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
1717 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1720 define(loadDependencies);
1721 } else if (isNode) {
1722 loadDependencies(require, module.exports, module);
1723 } else if (!sinon) {
1729 (typeof sinon == "object" && sinon || null),
1730 (typeof formatio == "object" && formatio)
1734 * @depend util/core.js
1737 /*jslint eqeqeq: false, onevar: false, plusplus: false*/
1738 /*global module, require, sinon*/
1742 * @author Maximilian Antoni (mail@maxantoni.de)
1745 * Copyright (c) 2012 Maximilian Antoni
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);
1759 toString: function () {
1760 return this.message;
1764 function isMatcher(object) {
1765 return matcher.isPrototypeOf(object);
1768 function matchObject(expectation, actual) {
1769 if (actual === null || actual === undefined) {
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)) {
1780 } else if (sinon.typeOf(exp) === "object") {
1781 if (!matchObject(exp, act)) {
1784 } else if (!sinon.deepEqual(exp, act)) {
1792 matcher.or = function (m2) {
1793 if (!arguments.length) {
1794 throw new TypeError("Matcher expected");
1795 } else if (!isMatcher(m2)) {
1799 var or = sinon.create(matcher);
1800 or.test = function (actual) {
1801 return m1.test(actual) || m2.test(actual);
1803 or.message = m1.message + ".or(" + m2.message + ")";
1807 matcher.and = function (m2) {
1808 if (!arguments.length) {
1809 throw new TypeError("Matcher expected");
1810 } else if (!isMatcher(m2)) {
1814 var and = sinon.create(matcher);
1815 and.test = function (actual) {
1816 return m1.test(actual) && m2.test(actual);
1818 and.message = m1.message + ".and(" + m2.message + ")";
1822 var match = function (expectation, message) {
1823 var m = sinon.create(matcher);
1824 var type = sinon.typeOf(expectation);
1827 if (typeof expectation.test === "function") {
1828 m.test = function (actual) {
1829 return expectation.test(actual) === true;
1831 m.message = "match(" + sinon.functionName(expectation.test) + ")";
1835 for (var key in expectation) {
1836 if (expectation.hasOwnProperty(key)) {
1837 str.push(key + ": " + expectation[key]);
1840 m.test = function (actual) {
1841 return matchObject(expectation, actual);
1843 m.message = "match(" + str.join(", ") + ")";
1846 m.test = function (actual) {
1847 return expectation == actual;
1851 m.test = function (actual) {
1852 if (typeof actual !== "string") {
1855 return actual.indexOf(expectation) !== -1;
1857 m.message = "match(\"" + expectation + "\")";
1860 m.test = function (actual) {
1861 if (typeof actual !== "string") {
1864 return expectation.test(actual);
1868 m.test = expectation;
1870 m.message = message;
1872 m.message = "match(" + sinon.functionName(expectation) + ")";
1876 m.test = function (actual) {
1877 return sinon.deepEqual(expectation, actual);
1881 m.message = "match(" + expectation + ")";
1886 match.isMatcher = isMatcher;
1888 match.any = match(function () {
1892 match.defined = match(function (actual) {
1893 return actual !== null && actual !== undefined;
1896 match.truthy = match(function (actual) {
1900 match.falsy = match(function (actual) {
1904 match.same = function (expectation) {
1905 return match(function (actual) {
1906 return expectation === actual;
1907 }, "same(" + expectation + ")");
1910 match.typeOf = function (type) {
1911 assertType(type, "string", "type");
1912 return match(function (actual) {
1913 return sinon.typeOf(actual) === type;
1914 }, "typeOf(\"" + type + "\")");
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) + ")");
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;
1933 return match(function (actual) {
1934 if (actual === undefined || actual === null ||
1935 !propertyTest(actual, property)) {
1938 return onlyProperty || sinon.deepEqual(value, actual[property]);
1943 match.has = createPropertyMatcher(function (actual, property) {
1944 if (typeof actual === "object") {
1945 return property in actual;
1947 return actual[property] !== undefined;
1950 match.hasOwn = createPropertyMatcher(function (actual, property) {
1951 return actual.hasOwnProperty(property);
1954 match.bool = match.typeOf("boolean");
1955 match.number = match.typeOf("number");
1956 match.string = match.typeOf("string");
1957 match.object = match.typeOf("object");
1958 match.func = match.typeOf("function");
1959 match.array = match.typeOf("array");
1960 match.regexp = match.typeOf("regexp");
1961 match.date = match.typeOf("date");
1963 sinon.match = match;
1967 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
1968 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
1970 function loadDependencies(require, exports, module) {
1971 var sinon = require("./util/core");
1972 require("./typeOf");
1973 module.exports = makeApi(sinon);
1977 define(loadDependencies);
1978 } else if (isNode) {
1979 loadDependencies(require, module.exports, module);
1980 } else if (!sinon) {
1985 }(typeof sinon == "object" && sinon || null));
1988 * @depend util/core.js
1993 * @author Christian Johansen (christian@cjohansen.no)
1996 * Copyright (c) 2010-2014 Christian Johansen
1999 (function (sinon, formatio) {
2000 function makeApi(sinon) {
2001 function valueFormatter(value) {
2005 function getFormatioFormatter() {
2006 var formatter = formatio.configure({
2007 quoteStrings: false,
2008 limitChildrenCount: 250
2012 return formatter.ascii.apply(formatter, arguments);
2018 function getNodeFormatter(value) {
2019 function format(value) {
2020 return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
2024 var util = require("util");
2026 /* Node, but no util module - would be very old, but better safe than sorry */
2029 return util ? format : valueFormatter;
2032 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function",
2037 formatio = require("formatio");
2042 formatter = getFormatioFormatter()
2043 } else if (isNode) {
2044 formatter = getNodeFormatter();
2046 formatter = valueFormatter;
2049 sinon.format = formatter;
2050 return sinon.format;
2053 function loadDependencies(require, exports, module) {
2054 var sinon = require("./util/core");
2055 module.exports = makeApi(sinon);
2058 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
2059 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2062 define(loadDependencies);
2063 } else if (isNode) {
2064 loadDependencies(require, module.exports, module);
2065 } else if (!sinon) {
2071 (typeof sinon == "object" && sinon || null),
2072 (typeof formatio == "object" && formatio)
2076 * @depend util/core.js
2083 * @author Christian Johansen (christian@cjohansen.no)
2084 * @author Maximilian Antoni (mail@maxantoni.de)
2087 * Copyright (c) 2010-2013 Christian Johansen
2088 * Copyright (c) 2013 Maximilian Antoni
2092 function makeApi(sinon) {
2093 function throwYieldError(proxy, text, args) {
2094 var msg = sinon.functionName(proxy) + text;
2096 msg += " Received [" + slice.call(args).join(", ") + "]";
2098 throw new Error(msg);
2101 var slice = Array.prototype.slice;
2104 calledOn: function calledOn(thisValue) {
2105 if (sinon.match && sinon.match.isMatcher(thisValue)) {
2106 return thisValue.test(this.thisValue);
2108 return this.thisValue === thisValue;
2111 calledWith: function calledWith() {
2112 var l = arguments.length;
2113 if (l > this.args.length) {
2116 for (var i = 0; i < l; i += 1) {
2117 if (!sinon.deepEqual(arguments[i], this.args[i])) {
2125 calledWithMatch: function calledWithMatch() {
2126 var l = arguments.length;
2127 if (l > this.args.length) {
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)) {
2140 calledWithExactly: function calledWithExactly() {
2141 return arguments.length == this.args.length &&
2142 this.calledWith.apply(this, arguments);
2145 notCalledWith: function notCalledWith() {
2146 return !this.calledWith.apply(this, arguments);
2149 notCalledWithMatch: function notCalledWithMatch() {
2150 return !this.calledWithMatch.apply(this, arguments);
2153 returned: function returned(value) {
2154 return sinon.deepEqual(value, this.returnValue);
2157 threw: function threw(error) {
2158 if (typeof error === "undefined" || !this.exception) {
2159 return !!this.exception;
2162 return this.exception === error || this.exception.name === error;
2165 calledWithNew: function calledWithNew() {
2166 return this.proxy.prototype && this.thisValue instanceof this.proxy;
2169 calledBefore: function (other) {
2170 return this.callId < other.callId;
2173 calledAfter: function (other) {
2174 return this.callId > other.callId;
2177 callArg: function (pos) {
2181 callArgOn: function (pos, thisValue) {
2182 this.args[pos].apply(thisValue);
2185 callArgWith: function (pos) {
2186 this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
2189 callArgOnWith: function (pos, thisValue) {
2190 var args = slice.call(arguments, 2);
2191 this.args[pos].apply(thisValue, args);
2194 yield: function () {
2195 this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
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));
2206 throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
2209 yieldTo: function (prop) {
2210 this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
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));
2221 throwYieldError(this.proxy, " cannot yield to '" + prop +
2222 "' since no callback was passed.", args);
2225 toString: function () {
2226 var callStr = this.proxy.toString() + "(";
2229 for (var i = 0, l = this.args.length; i < l; ++i) {
2230 args.push(sinon.format(this.args[i]));
2233 callStr = callStr + args.join(", ") + ")";
2235 if (typeof this.returnValue != "undefined") {
2236 callStr += " => " + sinon.format(this.returnValue);
2239 if (this.exception) {
2240 callStr += " !" + this.exception.name;
2242 if (this.exception.message) {
2243 callStr += "(" + this.exception.message + ")";
2251 callProto.invokeCallback = callProto.yield;
2253 function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
2254 if (typeof id !== "number") {
2255 throw new TypeError("Call id is not a number");
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;
2267 createSpyCall.toString = callProto.toString; // used by mocks
2269 sinon.spyCall = createSpyCall;
2270 return createSpyCall;
2273 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
2274 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2276 function loadDependencies(require, exports, module) {
2277 var sinon = require("./util/core");
2279 require("./format");
2280 module.exports = makeApi(sinon);
2284 define(loadDependencies);
2285 } else if (isNode) {
2286 loadDependencies(require, module.exports, module);
2287 } else if (!sinon) {
2292 }(typeof sinon == "object" && sinon || null));
2295 * @depend times_in_words.js
2296 * @depend util/core.js
2304 * @author Christian Johansen (christian@cjohansen.no)
2307 * Copyright (c) 2010-2013 Christian Johansen
2312 function makeApi(sinon) {
2313 var push = Array.prototype.push;
2314 var slice = Array.prototype.slice;
2317 function spy(object, property, types) {
2318 if (!property && typeof object == "function") {
2319 return spy.create(object);
2322 if (!object && !property) {
2323 return spy.create(function () { });
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]]);
2331 return sinon.wrapMethod(object, property, methodDesc);
2333 var method = object[property];
2334 return sinon.wrapMethod(object, property, spy.create(method));
2338 function matchingFake(fakes, args, strict) {
2343 for (var i = 0, l = fakes.length; i < l; i++) {
2344 if (fakes[i].matches(args, strict)) {
2350 function incrementCallCount() {
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;
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);
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:
2371 eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) +
2372 ") { return p.invoke(func, this, slice.call(arguments)); });");
2374 p = function proxy() {
2375 return p.invoke(func, this, slice.call(arguments));
2385 reset: function () {
2386 if (this.invoking) {
2387 var err = new Error("Cannot reset Sinon function while invoking it. " +
2388 "Move the call to .reset outside of the callback.");
2389 err.name = "InvalidResetException";
2393 this.called = false;
2394 this.notCalled = true;
2395 this.calledOnce = false;
2396 this.calledTwice = false;
2397 this.calledThrice = false;
2399 this.firstCall = null;
2400 this.secondCall = null;
2401 this.thirdCall = null;
2402 this.lastCall = null;
2404 this.returnValues = [];
2405 this.thisValues = [];
2406 this.exceptions = [];
2409 for (var i = 0; i < this.fakes.length; i++) {
2410 this.fakes[i].reset();
2417 create: function create(func, spyLength) {
2420 if (typeof func != "function") {
2421 func = function () { };
2423 name = sinon.functionName(func);
2427 spyLength = func.length;
2430 var proxy = createProxy(func, spyLength);
2432 sinon.extend(proxy, spy);
2433 delete proxy.create;
2434 sinon.extend(proxy, func);
2437 proxy.prototype = func.prototype;
2438 proxy.displayName = name || "spy";
2439 proxy.toString = sinon.functionToString;
2440 proxy.instantiateFake = sinon.spy.create;
2441 proxy.id = "spy#" + uuid++;
2446 invoke: function invoke(func, thisValue, args) {
2447 var matching = matchingFake(this.fakes, args);
2448 var exception, returnValue;
2450 incrementCallCount.call(this);
2451 push.call(this.thisValues, thisValue);
2452 push.call(this.args, args);
2453 push.call(this.callIds, callId++);
2455 // Make call properties available from within the spied function:
2456 createCallProperties.call(this);
2459 this.invoking = true;
2462 returnValue = matching.invoke(func, thisValue, args);
2464 returnValue = (this.func || func).apply(thisValue, args);
2467 var thisCall = this.getCall(this.callCount - 1);
2468 if (thisCall.calledWithNew() && typeof returnValue !== "object") {
2469 returnValue = thisValue;
2474 delete this.invoking;
2477 push.call(this.exceptions, exception);
2478 push.call(this.returnValues, returnValue);
2480 // Make return value and exception available in the calls:
2481 createCallProperties.call(this);
2483 if (exception !== undefined) {
2490 named: function named(name) {
2491 this.displayName = name;
2495 getCall: function getCall(i) {
2496 if (i < 0 || i >= this.callCount) {
2500 return sinon.spyCall(this, this.thisValues[i], this.args[i],
2501 this.returnValues[i], this.exceptions[i],
2505 getCalls: function () {
2509 for (i = 0; i < this.callCount; i++) {
2510 calls.push(this.getCall(i));
2516 calledBefore: function calledBefore(spyFn) {
2521 if (!spyFn.called) {
2525 return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
2528 calledAfter: function calledAfter(spyFn) {
2529 if (!this.called || !spyFn.called) {
2533 return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
2536 withArgs: function () {
2537 var args = slice.call(arguments);
2540 var match = matchingFake(this.fakes, args, true);
2549 var original = this;
2550 var fake = this.instantiateFake();
2551 fake.matchingAguments = args;
2553 push.call(this.fakes, fake);
2555 fake.withArgs = function () {
2556 return original.withArgs.apply(original, arguments);
2559 for (var i = 0; i < this.args.length; i++) {
2560 if (fake.matches(this.args[i])) {
2561 incrementCallCount.call(fake);
2562 push.call(fake.thisValues, this.thisValues[i]);
2563 push.call(fake.args, this.args[i]);
2564 push.call(fake.returnValues, this.returnValues[i]);
2565 push.call(fake.exceptions, this.exceptions[i]);
2566 push.call(fake.callIds, this.callIds[i]);
2569 createCallProperties.call(fake);
2574 matches: function (args, strict) {
2575 var margs = this.matchingAguments;
2577 if (margs.length <= args.length &&
2578 sinon.deepEqual(margs, args.slice(0, margs.length))) {
2579 return !strict || margs.length == args.length;
2583 printf: function (format) {
2585 var args = slice.call(arguments, 1);
2588 return (format || "").replace(/%(.)/g, function (match, specifyer) {
2589 formatter = spyApi.formatters[specifyer];
2591 if (typeof formatter == "function") {
2592 return formatter.call(null, spy, args);
2593 } else if (!isNaN(parseInt(specifyer, 10))) {
2594 return sinon.format(args[specifyer - 1]);
2597 return "%" + specifyer;
2602 function delegateToCalls(method, matchAny, actual, notCalled) {
2603 spyApi[method] = function () {
2606 return notCalled.apply(this, arguments);
2614 for (var i = 0, l = this.callCount; i < l; i += 1) {
2615 currentCall = this.getCall(i);
2617 if (currentCall[actual || method].apply(currentCall, arguments)) {
2626 return matches === this.callCount;
2630 delegateToCalls("calledOn", true);
2631 delegateToCalls("alwaysCalledOn", false, "calledOn");
2632 delegateToCalls("calledWith", true);
2633 delegateToCalls("calledWithMatch", true);
2634 delegateToCalls("alwaysCalledWith", false, "calledWith");
2635 delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
2636 delegateToCalls("calledWithExactly", true);
2637 delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
2638 delegateToCalls("neverCalledWith", false, "notCalledWith",
2639 function () { return true; });
2640 delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch",
2641 function () { return true; });
2642 delegateToCalls("threw", true);
2643 delegateToCalls("alwaysThrew", false, "threw");
2644 delegateToCalls("returned", true);
2645 delegateToCalls("alwaysReturned", false, "returned");
2646 delegateToCalls("calledWithNew", true);
2647 delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
2648 delegateToCalls("callArg", false, "callArgWith", function () {
2649 throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
2651 spyApi.callArgWith = spyApi.callArg;
2652 delegateToCalls("callArgOn", false, "callArgOnWith", function () {
2653 throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
2655 spyApi.callArgOnWith = spyApi.callArgOn;
2656 delegateToCalls("yield", false, "yield", function () {
2657 throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
2659 // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
2660 spyApi.invokeCallback = spyApi.yield;
2661 delegateToCalls("yieldOn", false, "yieldOn", function () {
2662 throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
2664 delegateToCalls("yieldTo", false, "yieldTo", function (property) {
2665 throw new Error(this.toString() + " cannot yield to '" + property +
2666 "' since it was not yet invoked.");
2668 delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
2669 throw new Error(this.toString() + " cannot yield to '" + property +
2670 "' since it was not yet invoked.");
2673 spyApi.formatters = {
2675 return sinon.timesInWords(spy.callCount);
2679 return spy.toString();
2685 for (var i = 0, l = spy.callCount; i < l; ++i) {
2686 var stringifiedCall = " " + spy.getCall(i).toString();
2687 if (/\n/.test(calls[i - 1])) {
2688 stringifiedCall = "\n" + stringifiedCall;
2690 push.call(calls, stringifiedCall);
2693 return calls.length > 0 ? "\n" + calls.join("\n") : "";
2699 for (var i = 0, l = spy.callCount; i < l; ++i) {
2700 push.call(objects, sinon.format(spy.thisValues[i]));
2703 return objects.join(", ");
2706 "*": function (spy, args) {
2709 for (var i = 0, l = args.length; i < l; ++i) {
2710 push.call(formatted, sinon.format(args[i]));
2713 return formatted.join(", ");
2717 sinon.extend(spy, spyApi);
2719 spy.spyCall = sinon.spyCall;
2725 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
2726 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
2728 function loadDependencies(require, exports, module) {
2729 var sinon = require("./util/core");
2731 require("./extend");
2732 require("./times_in_words");
2733 require("./format");
2734 module.exports = makeApi(sinon);
2738 define(loadDependencies);
2739 } else if (isNode) {
2740 loadDependencies(require, module.exports, module);
2741 } else if (!sinon) {
2746 }(typeof sinon == "object" && sinon || null));
2749 * @depend util/core.js
2755 * @author Christian Johansen (christian@cjohansen.no)
2756 * @author Tim Fischbach (mail@timfischbach.de)
2759 * Copyright (c) 2010-2013 Christian Johansen
2763 var slice = Array.prototype.slice;
2764 var join = Array.prototype.join;
2765 var useLeftMostCallback = -1;
2766 var useRightMostCallback = -2;
2768 var nextTick = (function () {
2769 if (typeof process === "object" && typeof process.nextTick === "function") {
2770 return process.nextTick;
2771 } else if (typeof setImmediate === "function") {
2772 return setImmediate;
2774 return function (callback) {
2775 setTimeout(callback, 0);
2780 function throwsException(error, message) {
2781 if (typeof error == "string") {
2782 this.exception = new Error(message || "");
2783 this.exception.name = error;
2784 } else if (!error) {
2785 this.exception = new Error("Error");
2787 this.exception = error;
2793 function getCallback(behavior, args) {
2794 var callArgAt = behavior.callArgAt;
2796 if (callArgAt >= 0) {
2797 return args[callArgAt];
2802 if (callArgAt === useLeftMostCallback) {
2803 argumentList = args;
2806 if (callArgAt === useRightMostCallback) {
2807 argumentList = slice.call(args).reverse();
2810 var callArgProp = behavior.callArgProp;
2812 for (var i = 0, l = argumentList.length; i < l; ++i) {
2813 if (!callArgProp && typeof argumentList[i] == "function") {
2814 return argumentList[i];
2817 if (callArgProp && argumentList[i] &&
2818 typeof argumentList[i][callArgProp] == "function") {
2819 return argumentList[i][callArgProp];
2826 function makeApi(sinon) {
2827 function getCallbackError(behavior, func, args) {
2828 if (behavior.callArgAt < 0) {
2831 if (behavior.callArgProp) {
2832 msg = sinon.functionName(behavior.stub) +
2833 " expected to yield to '" + behavior.callArgProp +
2834 "', but no object with such a property was passed.";
2836 msg = sinon.functionName(behavior.stub) +
2837 " expected to yield, but no callback was passed.";
2840 if (args.length > 0) {
2841 msg += " Received [" + join.call(args, ", ") + "]";
2847 return "argument at index " + behavior.callArgAt + " is not a function: " + func;
2850 function callCallback(behavior, args) {
2851 if (typeof behavior.callArgAt == "number") {
2852 var func = getCallback(behavior, args);
2854 if (typeof func != "function") {
2855 throw new TypeError(getCallbackError(behavior, func, args));
2858 if (behavior.callbackAsync) {
2859 nextTick(function () {
2860 func.apply(behavior.callbackContext, behavior.callbackArguments);
2863 func.apply(behavior.callbackContext, behavior.callbackArguments);
2869 create: function create(stub) {
2870 var behavior = sinon.extend({}, sinon.behavior);
2871 delete behavior.create;
2872 behavior.stub = stub;
2877 isPresent: function isPresent() {
2878 return (typeof this.callArgAt == "number" ||
2880 typeof this.returnArgAt == "number" ||
2882 this.returnValueDefined);
2885 invoke: function invoke(context, args) {
2886 callCallback(this, args);
2888 if (this.exception) {
2889 throw this.exception;
2890 } else if (typeof this.returnArgAt == "number") {
2891 return args[this.returnArgAt];
2892 } else if (this.returnThis) {
2896 return this.returnValue;
2899 onCall: function onCall(index) {
2900 return this.stub.onCall(index);
2903 onFirstCall: function onFirstCall() {
2904 return this.stub.onFirstCall();
2907 onSecondCall: function onSecondCall() {
2908 return this.stub.onSecondCall();
2911 onThirdCall: function onThirdCall() {
2912 return this.stub.onThirdCall();
2915 withArgs: function withArgs(/* arguments */) {
2916 throw new Error("Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" is not supported. " +
2917 "Use \"stub.withArgs(...).onCall(...)\" to define sequential behavior for calls with certain arguments.");
2920 callsArg: function callsArg(pos) {
2921 if (typeof pos != "number") {
2922 throw new TypeError("argument index is not number");
2925 this.callArgAt = pos;
2926 this.callbackArguments = [];
2927 this.callbackContext = undefined;
2928 this.callArgProp = undefined;
2929 this.callbackAsync = false;
2934 callsArgOn: function callsArgOn(pos, context) {
2935 if (typeof pos != "number") {
2936 throw new TypeError("argument index is not number");
2938 if (typeof context != "object") {
2939 throw new TypeError("argument context is not an object");
2942 this.callArgAt = pos;
2943 this.callbackArguments = [];
2944 this.callbackContext = context;
2945 this.callArgProp = undefined;
2946 this.callbackAsync = false;
2951 callsArgWith: function callsArgWith(pos) {
2952 if (typeof pos != "number") {
2953 throw new TypeError("argument index is not number");
2956 this.callArgAt = pos;
2957 this.callbackArguments = slice.call(arguments, 1);
2958 this.callbackContext = undefined;
2959 this.callArgProp = undefined;
2960 this.callbackAsync = false;
2965 callsArgOnWith: function callsArgWith(pos, context) {
2966 if (typeof pos != "number") {
2967 throw new TypeError("argument index is not number");
2969 if (typeof context != "object") {
2970 throw new TypeError("argument context is not an object");
2973 this.callArgAt = pos;
2974 this.callbackArguments = slice.call(arguments, 2);
2975 this.callbackContext = context;
2976 this.callArgProp = undefined;
2977 this.callbackAsync = false;
2982 yields: function () {
2983 this.callArgAt = useLeftMostCallback;
2984 this.callbackArguments = slice.call(arguments, 0);
2985 this.callbackContext = undefined;
2986 this.callArgProp = undefined;
2987 this.callbackAsync = false;
2992 yieldsRight: function () {
2993 this.callArgAt = useRightMostCallback;
2994 this.callbackArguments = slice.call(arguments, 0);
2995 this.callbackContext = undefined;
2996 this.callArgProp = undefined;
2997 this.callbackAsync = false;
3002 yieldsOn: function (context) {
3003 if (typeof context != "object") {
3004 throw new TypeError("argument context is not an object");
3007 this.callArgAt = useLeftMostCallback;
3008 this.callbackArguments = slice.call(arguments, 1);
3009 this.callbackContext = context;
3010 this.callArgProp = undefined;
3011 this.callbackAsync = false;
3016 yieldsTo: function (prop) {
3017 this.callArgAt = useLeftMostCallback;
3018 this.callbackArguments = slice.call(arguments, 1);
3019 this.callbackContext = undefined;
3020 this.callArgProp = prop;
3021 this.callbackAsync = false;
3026 yieldsToOn: function (prop, context) {
3027 if (typeof context != "object") {
3028 throw new TypeError("argument context is not an object");
3031 this.callArgAt = useLeftMostCallback;
3032 this.callbackArguments = slice.call(arguments, 2);
3033 this.callbackContext = context;
3034 this.callArgProp = prop;
3035 this.callbackAsync = false;
3040 throws: throwsException,
3041 throwsException: throwsException,
3043 returns: function returns(value) {
3044 this.returnValue = value;
3045 this.returnValueDefined = true;
3050 returnsArg: function returnsArg(pos) {
3051 if (typeof pos != "number") {
3052 throw new TypeError("argument index is not number");
3055 this.returnArgAt = pos;
3060 returnsThis: function returnsThis() {
3061 this.returnThis = true;
3067 // create asynchronous versions of callsArg* and yields* methods
3068 for (var method in proto) {
3069 // need to avoid creating anotherasync versions of the newly added async methods
3070 if (proto.hasOwnProperty(method) &&
3071 method.match(/^(callsArg|yields)/) &&
3072 !method.match(/Async/)) {
3073 proto[method + "Async"] = (function (syncFnName) {
3074 return function () {
3075 var result = this[syncFnName].apply(this, arguments);
3076 this.callbackAsync = true;
3083 sinon.behavior = proto;
3087 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
3088 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3090 function loadDependencies(require, exports, module) {
3091 var sinon = require("./util/core");
3092 require("./extend");
3093 module.exports = makeApi(sinon);
3097 define(loadDependencies);
3098 } else if (isNode) {
3099 loadDependencies(require, module.exports, module);
3100 } else if (!sinon) {
3105 }(typeof sinon == "object" && sinon || null));
3108 * @depend util/core.js
3111 * @depend behavior.js
3116 * @author Christian Johansen (christian@cjohansen.no)
3119 * Copyright (c) 2010-2013 Christian Johansen
3123 function makeApi(sinon) {
3124 function stub(object, property, func) {
3125 if (!!func && typeof func != "function" && typeof func != "object") {
3126 throw new TypeError("Custom stub should be a function or a property descriptor");
3132 if (typeof func == "function") {
3133 wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
3136 if (sinon.spy && sinon.spy.create) {
3137 var types = sinon.objectKeys(wrapper);
3138 for (var i = 0; i < types.length; i++) {
3139 wrapper[types[i]] = sinon.spy.create(wrapper[types[i]]);
3145 if (typeof object == "object" && typeof object[property] == "function") {
3146 stubLength = object[property].length;
3148 wrapper = stub.create(stubLength);
3151 if (!object && typeof property === "undefined") {
3152 return sinon.stub.create();
3155 if (typeof property === "undefined" && typeof object == "object") {
3156 for (var prop in object) {
3157 if (typeof object[prop] === "function") {
3165 return sinon.wrapMethod(object, property, wrapper);
3168 function getDefaultBehavior(stub) {
3169 return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
3172 function getParentBehaviour(stub) {
3173 return (stub.parent && getCurrentBehavior(stub.parent));
3176 function getCurrentBehavior(stub) {
3177 var behavior = stub.behaviors[stub.callCount - 1];
3178 return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
3184 create: function create(stubLength) {
3185 var functionStub = function () {
3186 return getCurrentBehavior(functionStub).invoke(this, arguments);
3189 functionStub.id = "stub#" + uuid++;
3190 var orig = functionStub;
3191 functionStub = sinon.spy.create(functionStub, stubLength);
3192 functionStub.func = orig;
3194 sinon.extend(functionStub, stub);
3195 functionStub.instantiateFake = sinon.stub.create;
3196 functionStub.displayName = "stub";
3197 functionStub.toString = sinon.functionToString;
3199 functionStub.defaultBehavior = null;
3200 functionStub.behaviors = [];
3202 return functionStub;
3205 resetBehavior: function () {
3208 this.defaultBehavior = null;
3209 this.behaviors = [];
3211 delete this.returnValue;
3212 delete this.returnArgAt;
3213 this.returnThis = false;
3216 for (i = 0; i < this.fakes.length; i++) {
3217 this.fakes[i].resetBehavior();
3222 onCall: function onCall(index) {
3223 if (!this.behaviors[index]) {
3224 this.behaviors[index] = sinon.behavior.create(this);
3227 return this.behaviors[index];
3230 onFirstCall: function onFirstCall() {
3231 return this.onCall(0);
3234 onSecondCall: function onSecondCall() {
3235 return this.onCall(1);
3238 onThirdCall: function onThirdCall() {
3239 return this.onCall(2);
3243 for (var method in sinon.behavior) {
3244 if (sinon.behavior.hasOwnProperty(method) &&
3245 !proto.hasOwnProperty(method) &&
3246 method != "create" &&
3247 method != "withArgs" &&
3248 method != "invoke") {
3249 proto[method] = (function (behaviorMethod) {
3250 return function () {
3251 this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
3252 this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
3259 sinon.extend(stub, proto);
3265 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
3266 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3268 function loadDependencies(require, exports, module) {
3269 var sinon = require("./util/core");
3270 require("./behavior");
3272 require("./extend");
3273 module.exports = makeApi(sinon);
3277 define(loadDependencies);
3278 } else if (isNode) {
3279 loadDependencies(require, module.exports, module);
3280 } else if (!sinon) {
3285 }(typeof sinon == "object" && sinon || null));
3288 * @depend times_in_words.js
3289 * @depend util/core.js
3300 * @author Christian Johansen (christian@cjohansen.no)
3303 * Copyright (c) 2010-2013 Christian Johansen
3307 function makeApi(sinon) {
3309 var match = sinon.match;
3311 function mock(object) {
3313 return sinon.expectation.create("Anonymous mock");
3316 return mock.create(object);
3319 function each(collection, callback) {
3324 for (var i = 0, l = collection.length; i < l; i += 1) {
3325 callback(collection[i]);
3329 sinon.extend(mock, {
3330 create: function create(object) {
3332 throw new TypeError("object is null");
3335 var mockObject = sinon.extend({}, mock);
3336 mockObject.object = object;
3337 delete mockObject.create;
3342 expects: function expects(method) {
3344 throw new TypeError("method is falsy");
3347 if (!this.expectations) {
3348 this.expectations = {};
3352 if (!this.expectations[method]) {
3353 this.expectations[method] = [];
3354 var mockObject = this;
3356 sinon.wrapMethod(this.object, method, function () {
3357 return mockObject.invokeMethod(method, this, arguments);
3360 push.call(this.proxies, method);
3363 var expectation = sinon.expectation.create(method);
3364 push.call(this.expectations[method], expectation);
3369 restore: function restore() {
3370 var object = this.object;
3372 each(this.proxies, function (proxy) {
3373 if (typeof object[proxy].restore == "function") {
3374 object[proxy].restore();
3379 verify: function verify() {
3380 var expectations = this.expectations || {};
3381 var messages = [], met = [];
3383 each(this.proxies, function (proxy) {
3384 each(expectations[proxy], function (expectation) {
3385 if (!expectation.met()) {
3386 push.call(messages, expectation.toString());
3388 push.call(met, expectation.toString());
3395 if (messages.length > 0) {
3396 sinon.expectation.fail(messages.concat(met).join("\n"));
3397 } else if (met.length > 0) {
3398 sinon.expectation.pass(messages.concat(met).join("\n"));
3404 invokeMethod: function invokeMethod(method, thisValue, args) {
3405 var expectations = this.expectations && this.expectations[method];
3406 var length = expectations && expectations.length || 0, i;
3408 for (i = 0; i < length; i += 1) {
3409 if (!expectations[i].met() &&
3410 expectations[i].allowsCall(thisValue, args)) {
3411 return expectations[i].apply(thisValue, args);
3415 var messages = [], available, exhausted = 0;
3417 for (i = 0; i < length; i += 1) {
3418 if (expectations[i].allowsCall(thisValue, args)) {
3419 available = available || expectations[i];
3423 push.call(messages, " " + expectations[i].toString());
3426 if (exhausted === 0) {
3427 return available.apply(thisValue, args);
3430 messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
3435 sinon.expectation.fail(messages.join("\n"));
3439 var times = sinon.timesInWords;
3440 var slice = Array.prototype.slice;
3442 function callCountInWords(callCount) {
3443 if (callCount == 0) {
3444 return "never called";
3446 return "called " + times(callCount);
3450 function expectedCallCountInWords(expectation) {
3451 var min = expectation.minCalls;
3452 var max = expectation.maxCalls;
3454 if (typeof min == "number" && typeof max == "number") {
3455 var str = times(min);
3458 str = "at least " + str + " and at most " + times(max);
3464 if (typeof min == "number") {
3465 return "at least " + times(min);
3468 return "at most " + times(max);
3471 function receivedMinCalls(expectation) {
3472 var hasMinLimit = typeof expectation.minCalls == "number";
3473 return !hasMinLimit || expectation.callCount >= expectation.minCalls;
3476 function receivedMaxCalls(expectation) {
3477 if (typeof expectation.maxCalls != "number") {
3481 return expectation.callCount == expectation.maxCalls;
3484 function verifyMatcher(possibleMatcher, arg) {
3485 if (match && match.isMatcher(possibleMatcher)) {
3486 return possibleMatcher.test(arg);
3492 sinon.expectation = {
3496 create: function create(methodName) {
3497 var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
3498 delete expectation.create;
3499 expectation.method = methodName;
3504 invoke: function invoke(func, thisValue, args) {
3505 this.verifyCallAllowed(thisValue, args);
3507 return sinon.spy.invoke.apply(this, arguments);
3510 atLeast: function atLeast(num) {
3511 if (typeof num != "number") {
3512 throw new TypeError("'" + num + "' is not number");
3515 if (!this.limitsSet) {
3516 this.maxCalls = null;
3517 this.limitsSet = true;
3520 this.minCalls = num;
3525 atMost: function atMost(num) {
3526 if (typeof num != "number") {
3527 throw new TypeError("'" + num + "' is not number");
3530 if (!this.limitsSet) {
3531 this.minCalls = null;
3532 this.limitsSet = true;
3535 this.maxCalls = num;
3540 never: function never() {
3541 return this.exactly(0);
3544 once: function once() {
3545 return this.exactly(1);
3548 twice: function twice() {
3549 return this.exactly(2);
3552 thrice: function thrice() {
3553 return this.exactly(3);
3556 exactly: function exactly(num) {
3557 if (typeof num != "number") {
3558 throw new TypeError("'" + num + "' is not a number");
3562 return this.atMost(num);
3565 met: function met() {
3566 return !this.failed && receivedMinCalls(this);
3569 verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
3570 if (receivedMaxCalls(this)) {
3572 sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
3575 if ("expectedThis" in this && this.expectedThis !== thisValue) {
3576 sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
3580 if (!("expectedArguments" in this)) {
3585 sinon.expectation.fail(this.method + " received no arguments, expected " +
3586 sinon.format(this.expectedArguments));
3589 if (args.length < this.expectedArguments.length) {
3590 sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
3591 "), expected " + sinon.format(this.expectedArguments));
3594 if (this.expectsExactArgCount &&
3595 args.length != this.expectedArguments.length) {
3596 sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
3597 "), expected " + sinon.format(this.expectedArguments));
3600 for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
3602 if (!verifyMatcher(this.expectedArguments[i], args[i])) {
3603 sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
3604 ", didn't match " + this.expectedArguments.toString());
3607 if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
3608 sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
3609 ", expected " + sinon.format(this.expectedArguments));
3614 allowsCall: function allowsCall(thisValue, args) {
3615 if (this.met() && receivedMaxCalls(this)) {
3619 if ("expectedThis" in this && this.expectedThis !== thisValue) {
3623 if (!("expectedArguments" in this)) {
3629 if (args.length < this.expectedArguments.length) {
3633 if (this.expectsExactArgCount &&
3634 args.length != this.expectedArguments.length) {
3638 for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
3639 if (!verifyMatcher(this.expectedArguments[i], args[i])) {
3643 if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
3651 withArgs: function withArgs() {
3652 this.expectedArguments = slice.call(arguments);
3656 withExactArgs: function withExactArgs() {
3657 this.withArgs.apply(this, arguments);
3658 this.expectsExactArgCount = true;
3662 on: function on(thisValue) {
3663 this.expectedThis = thisValue;
3667 toString: function () {
3668 var args = (this.expectedArguments || []).slice();
3670 if (!this.expectsExactArgCount) {
3671 push.call(args, "[...]");
3674 var callStr = sinon.spyCall.toString.call({
3675 proxy: this.method || "anonymous mock expectation",
3679 var message = callStr.replace(", [...", "[, ...") + " " +
3680 expectedCallCountInWords(this);
3683 return "Expectation met: " + message;
3686 return "Expected " + message + " (" +
3687 callCountInWords(this.callCount) + ")";
3690 verify: function verify() {
3692 sinon.expectation.fail(this.toString());
3694 sinon.expectation.pass(this.toString());
3700 pass: function pass(message) {
3701 sinon.assert.pass(message);
3704 fail: function fail(message) {
3705 var exception = new Error(message);
3706 exception.name = "ExpectationError";
3716 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
3717 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3719 function loadDependencies(require, exports, module) {
3720 var sinon = require("./util/core");
3721 require("./times_in_words");
3723 require("./extend");
3727 require("./format");
3729 module.exports = makeApi(sinon);
3733 define(loadDependencies);
3734 } else if (isNode) {
3735 loadDependencies(require, module.exports, module);
3736 } else if (!sinon) {
3741 }(typeof sinon == "object" && sinon || null));
3744 * @depend util/core.js
3750 * Collections of stubs, spies and mocks.
3752 * @author Christian Johansen (christian@cjohansen.no)
3755 * Copyright (c) 2010-2013 Christian Johansen
3760 var hasOwnProperty = Object.prototype.hasOwnProperty;
3762 function getFakes(fakeCollection) {
3763 if (!fakeCollection.fakes) {
3764 fakeCollection.fakes = [];
3767 return fakeCollection.fakes;
3770 function each(fakeCollection, method) {
3771 var fakes = getFakes(fakeCollection);
3773 for (var i = 0, l = fakes.length; i < l; i += 1) {
3774 if (typeof fakes[i][method] == "function") {
3780 function compact(fakeCollection) {
3781 var fakes = getFakes(fakeCollection);
3783 while (i < fakes.length) {
3788 function makeApi(sinon) {
3790 verify: function resolve() {
3791 each(this, "verify");
3794 restore: function restore() {
3795 each(this, "restore");
3799 reset: function restore() {
3800 each(this, "reset");
3803 verifyAndRestore: function verifyAndRestore() {
3819 add: function add(fake) {
3820 push.call(getFakes(this), fake);
3824 spy: function spy() {
3825 return this.add(sinon.spy.apply(sinon, arguments));
3828 stub: function stub(object, property, value) {
3830 var original = object[property];
3832 if (typeof original != "function") {
3833 if (!hasOwnProperty.call(object, property)) {
3834 throw new TypeError("Cannot stub non-existent own property " + property);
3837 object[property] = value;
3840 restore: function () {
3841 object[property] = original;
3846 if (!property && !!object && typeof object == "object") {
3847 var stubbedObj = sinon.stub.apply(sinon, arguments);
3849 for (var prop in stubbedObj) {
3850 if (typeof stubbedObj[prop] === "function") {
3851 this.add(stubbedObj[prop]);
3858 return this.add(sinon.stub.apply(sinon, arguments));
3861 mock: function mock() {
3862 return this.add(sinon.mock.apply(sinon, arguments));
3865 inject: function inject(obj) {
3868 obj.spy = function () {
3869 return col.spy.apply(col, arguments);
3872 obj.stub = function () {
3873 return col.stub.apply(col, arguments);
3876 obj.mock = function () {
3877 return col.mock.apply(col, arguments);
3884 sinon.collection = collection;
3888 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
3889 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3891 function loadDependencies(require, exports, module) {
3892 var sinon = require("./util/core");
3896 module.exports = makeApi(sinon);
3900 define(loadDependencies);
3901 } else if (isNode) {
3902 loadDependencies(require, module.exports, module);
3903 } else if (!sinon) {
3908 }(typeof sinon == "object" && sinon || null));
3922 * Inspired by jsUnitMockTimeOut from JsUnit
3924 * @author Christian Johansen (christian@cjohansen.no)
3927 * Copyright (c) 2010-2013 Christian Johansen
3930 if (typeof sinon == "undefined") {
3934 (function (global) {
3935 function makeApi(sinon, lol) {
3936 var llx = typeof lolex !== "undefined" ? lolex : lol;
3938 sinon.useFakeTimers = function () {
3939 var now, methods = Array.prototype.slice.call(arguments);
3941 if (typeof methods[0] === "string") {
3944 now = methods.shift();
3947 var clock = llx.install(now || 0, methods);
3948 clock.restore = clock.uninstall;
3953 create: function (now) {
3954 return llx.createClock(now);
3959 setTimeout: setTimeout,
3960 clearTimeout: clearTimeout,
3961 setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
3962 clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate : undefined),
3963 setInterval: setInterval,
3964 clearInterval: clearInterval,
3969 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
3970 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
3972 function loadDependencies(require, epxorts, module, lolex) {
3973 var sinon = require("./core");
3974 makeApi(sinon, lolex);
3975 module.exports = sinon;
3979 define(loadDependencies);
3980 } else if (isNode) {
3981 loadDependencies(require, module.exports, module, require("lolex"));
3985 }(typeof global != "undefined" && typeof global !== "function" ? global : this));
3988 * Minimal Event interface implementation
3990 * Original implementation by Sven Fuchs: https://gist.github.com/995028
3991 * Modifications and tests by Christian Johansen.
3993 * @author Sven Fuchs (svenfuchs@artweb-design.de)
3994 * @author Christian Johansen (christian@cjohansen.no)
3997 * Copyright (c) 2011 Sven Fuchs, Christian Johansen
4000 if (typeof sinon == "undefined") {
4007 function makeApi(sinon) {
4008 sinon.Event = function Event(type, bubbles, cancelable, target) {
4009 this.initEvent(type, bubbles, cancelable, target);
4012 sinon.Event.prototype = {
4013 initEvent: function (type, bubbles, cancelable, target) {
4015 this.bubbles = bubbles;
4016 this.cancelable = cancelable;
4017 this.target = target;
4020 stopPropagation: function () {},
4022 preventDefault: function () {
4023 this.defaultPrevented = true;
4027 sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
4028 this.initEvent(type, false, false, target);
4029 this.loaded = progressEventRaw.loaded || null;
4030 this.total = progressEventRaw.total || null;
4031 this.lengthComputable = !!progressEventRaw.total;
4034 sinon.ProgressEvent.prototype = new sinon.Event();
4036 sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent;
4038 sinon.CustomEvent = function CustomEvent(type, customData, target) {
4039 this.initEvent(type, false, false, target);
4040 this.detail = customData.detail || null;
4043 sinon.CustomEvent.prototype = new sinon.Event();
4045 sinon.CustomEvent.prototype.constructor = sinon.CustomEvent;
4047 sinon.EventTarget = {
4048 addEventListener: function addEventListener(event, listener) {
4049 this.eventListeners = this.eventListeners || {};
4050 this.eventListeners[event] = this.eventListeners[event] || [];
4051 push.call(this.eventListeners[event], listener);
4054 removeEventListener: function removeEventListener(event, listener) {
4055 var listeners = this.eventListeners && this.eventListeners[event] || [];
4057 for (var i = 0, l = listeners.length; i < l; ++i) {
4058 if (listeners[i] == listener) {
4059 return listeners.splice(i, 1);
4064 dispatchEvent: function dispatchEvent(event) {
4065 var type = event.type;
4066 var listeners = this.eventListeners && this.eventListeners[type] || [];
4068 for (var i = 0; i < listeners.length; i++) {
4069 if (typeof listeners[i] == "function") {
4070 listeners[i].call(this, event);
4072 listeners[i].handleEvent(event);
4076 return !!event.defaultPrevented;
4081 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
4082 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4084 function loadDependencies(require) {
4085 var sinon = require("./core");
4090 define(loadDependencies);
4091 } else if (isNode) {
4092 loadDependencies(require);
4099 * @depend util/core.js
4104 * @author Christian Johansen (christian@cjohansen.no)
4107 * Copyright (c) 2010-2014 Christian Johansen
4111 // cache a reference to setTimeout, so that our reference won't be stubbed out
4112 // when using fake timers and errors will still get logged
4113 // https://github.com/cjohansen/Sinon.JS/issues/381
4114 var realSetTimeout = setTimeout;
4116 function makeApi(sinon) {
4120 function logError(label, err) {
4121 var msg = label + " threw exception: ";
4123 sinon.log(msg + "[" + err.name + "] " + err.message);
4126 sinon.log(err.stack);
4129 logError.setTimeout(function () {
4130 err.message = msg + err.message;
4135 // wrap realSetTimeout with something we can stub in tests
4136 logError.setTimeout = function (func, timeout) {
4137 realSetTimeout(func, timeout);
4141 exports.log = sinon.log = log;
4142 exports.logError = sinon.logError = logError;
4147 function loadDependencies(require, exports, module) {
4148 var sinon = require("./util/core");
4149 module.exports = makeApi(sinon);
4152 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
4153 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4156 define(loadDependencies);
4157 } else if (isNode) {
4158 loadDependencies(require, module.exports, module);
4159 } else if (!sinon) {
4164 }(typeof sinon == "object" && sinon || null));
4168 * @depend ../extend.js
4170 * @depend ../log_error.js
4173 * Fake XDomainRequest object
4176 if (typeof sinon == "undefined") {
4180 // wrapper for global
4181 (function (global) {
4182 var xdr = { XDomainRequest: global.XDomainRequest };
4183 xdr.GlobalXDomainRequest = global.XDomainRequest;
4184 xdr.supportsXDR = typeof xdr.GlobalXDomainRequest != "undefined";
4185 xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false;
4187 function makeApi(sinon) {
4190 function FakeXDomainRequest() {
4191 this.readyState = FakeXDomainRequest.UNSENT;
4192 this.requestBody = null;
4193 this.requestHeaders = {};
4195 this.timeout = null;
4197 if (typeof FakeXDomainRequest.onCreate == "function") {
4198 FakeXDomainRequest.onCreate(this);
4202 function verifyState(xdr) {
4203 if (xdr.readyState !== FakeXDomainRequest.OPENED) {
4204 throw new Error("INVALID_STATE_ERR");
4208 throw new Error("INVALID_STATE_ERR");
4212 function verifyRequestSent(xdr) {
4213 if (xdr.readyState == FakeXDomainRequest.UNSENT) {
4214 throw new Error("Request not sent");
4216 if (xdr.readyState == FakeXDomainRequest.DONE) {
4217 throw new Error("Request done");
4221 function verifyResponseBodyType(body) {
4222 if (typeof body != "string") {
4223 var error = new Error("Attempted to respond to fake XDomainRequest with " +
4224 body + ", which is not a string.");
4225 error.name = "InvalidBodyException";
4230 sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
4231 open: function open(method, url) {
4232 this.method = method;
4235 this.responseText = null;
4236 this.sendFlag = false;
4238 this.readyStateChange(FakeXDomainRequest.OPENED);
4241 readyStateChange: function readyStateChange(state) {
4242 this.readyState = state;
4244 switch (this.readyState) {
4245 case FakeXDomainRequest.UNSENT:
4247 case FakeXDomainRequest.OPENED:
4249 case FakeXDomainRequest.LOADING:
4250 if (this.sendFlag) {
4251 //raise the progress event
4252 eventName = "onprogress";
4255 case FakeXDomainRequest.DONE:
4256 if (this.isTimeout) {
4257 eventName = "ontimeout"
4258 } else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
4259 eventName = "onerror";
4261 eventName = "onload"
4266 // raising event (if defined)
4268 if (typeof this[eventName] == "function") {
4272 sinon.logError("Fake XHR " + eventName + " handler", e);
4278 send: function send(data) {
4281 if (!/^(get|head)$/i.test(this.method)) {
4282 this.requestBody = data;
4284 this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
4286 this.errorFlag = false;
4287 this.sendFlag = true;
4288 this.readyStateChange(FakeXDomainRequest.OPENED);
4290 if (typeof this.onSend == "function") {
4295 abort: function abort() {
4296 this.aborted = true;
4297 this.responseText = null;
4298 this.errorFlag = true;
4300 if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
4301 this.readyStateChange(sinon.FakeXDomainRequest.DONE);
4302 this.sendFlag = false;
4306 setResponseBody: function setResponseBody(body) {
4307 verifyRequestSent(this);
4308 verifyResponseBodyType(body);
4310 var chunkSize = this.chunkSize || 10;
4312 this.responseText = "";
4315 this.readyStateChange(FakeXDomainRequest.LOADING);
4316 this.responseText += body.substring(index, index + chunkSize);
4318 } while (index < body.length);
4320 this.readyStateChange(FakeXDomainRequest.DONE);
4323 respond: function respond(status, contentType, body) {
4324 // content-type ignored, since XDomainRequest does not carry this
4325 // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
4326 // test integration across browsers
4327 this.status = typeof status == "number" ? status : 200;
4328 this.setResponseBody(body || "");
4331 simulatetimeout: function simulatetimeout() {
4333 this.isTimeout = true;
4334 // Access to this should actually throw an error
4335 this.responseText = undefined;
4336 this.readyStateChange(FakeXDomainRequest.DONE);
4340 sinon.extend(FakeXDomainRequest, {
4347 sinon.useFakeXDomainRequest = function useFakeXDomainRequest() {
4348 sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
4349 if (xdr.supportsXDR) {
4350 global.XDomainRequest = xdr.GlobalXDomainRequest;
4353 delete sinon.FakeXDomainRequest.restore;
4355 if (keepOnCreate !== true) {
4356 delete sinon.FakeXDomainRequest.onCreate;
4359 if (xdr.supportsXDR) {
4360 global.XDomainRequest = sinon.FakeXDomainRequest;
4362 return sinon.FakeXDomainRequest;
4365 sinon.FakeXDomainRequest = FakeXDomainRequest;
4368 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
4369 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4371 function loadDependencies(require, exports, module) {
4372 var sinon = require("./core");
4373 require("../extend");
4375 require("../log_error");
4377 module.exports = sinon;
4381 define(loadDependencies);
4382 } else if (isNode) {
4383 loadDependencies(require, module.exports, module);
4391 * @depend ../extend.js
4393 * @depend ../log_error.js
4396 * Fake XMLHttpRequest object
4398 * @author Christian Johansen (christian@cjohansen.no)
4401 * Copyright (c) 2010-2013 Christian Johansen
4404 (function (global) {
4406 var supportsProgress = typeof ProgressEvent !== "undefined";
4407 var supportsCustomEvent = typeof CustomEvent !== "undefined";
4408 var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest };
4409 sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
4410 sinonXhr.GlobalActiveXObject = global.ActiveXObject;
4411 sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject != "undefined";
4412 sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest != "undefined";
4413 sinonXhr.workingXHR = sinonXhr.supportsXHR ? sinonXhr.GlobalXMLHttpRequest : sinonXhr.supportsActiveX
4414 ? function () { return new sinonXhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
4415 sinonXhr.supportsCORS = sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest());
4418 var unsafeHeaders = {
4419 "Accept-Charset": true,
4420 "Accept-Encoding": true,
4422 "Content-Length": true,
4425 "Content-Transfer-Encoding": true,
4433 "Transfer-Encoding": true,
4440 function FakeXMLHttpRequest() {
4441 this.readyState = FakeXMLHttpRequest.UNSENT;
4442 this.requestHeaders = {};
4443 this.requestBody = null;
4445 this.statusText = "";
4446 this.upload = new UploadProgress();
4447 if (sinonXhr.supportsCORS) {
4448 this.withCredentials = false;
4452 var events = ["loadstart", "load", "abort", "loadend"];
4454 function addEventListener(eventName) {
4455 xhr.addEventListener(eventName, function (event) {
4456 var listener = xhr["on" + eventName];
4458 if (listener && typeof listener == "function") {
4459 listener.call(this, event);
4464 for (var i = events.length - 1; i >= 0; i--) {
4465 addEventListener(events[i]);
4468 if (typeof FakeXMLHttpRequest.onCreate == "function") {
4469 FakeXMLHttpRequest.onCreate(this);
4473 // An upload object is created for each
4474 // FakeXMLHttpRequest and allows upload
4475 // events to be simulated using uploadProgress
4477 function UploadProgress() {
4478 this.eventListeners = {
4486 UploadProgress.prototype.addEventListener = function addEventListener(event, listener) {
4487 this.eventListeners[event].push(listener);
4490 UploadProgress.prototype.removeEventListener = function removeEventListener(event, listener) {
4491 var listeners = this.eventListeners[event] || [];
4493 for (var i = 0, l = listeners.length; i < l; ++i) {
4494 if (listeners[i] == listener) {
4495 return listeners.splice(i, 1);
4500 UploadProgress.prototype.dispatchEvent = function dispatchEvent(event) {
4501 var listeners = this.eventListeners[event.type] || [];
4503 for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
4508 function verifyState(xhr) {
4509 if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
4510 throw new Error("INVALID_STATE_ERR");
4514 throw new Error("INVALID_STATE_ERR");
4518 function getHeader(headers, header) {
4519 header = header.toLowerCase();
4521 for (var h in headers) {
4522 if (h.toLowerCase() == header) {
4530 // filtering to enable a white-list version of Sinon FakeXhr,
4531 // where whitelisted requests are passed through to real XHR
4532 function each(collection, callback) {
4537 for (var i = 0, l = collection.length; i < l; i += 1) {
4538 callback(collection[i]);
4541 function some(collection, callback) {
4542 for (var index = 0; index < collection.length; index++) {
4543 if (callback(collection[index]) === true) {
4549 // largest arity in XHR is 5 - XHR#open
4550 var apply = function (obj, method, args) {
4551 switch (args.length) {
4552 case 0: return obj[method]();
4553 case 1: return obj[method](args[0]);
4554 case 2: return obj[method](args[0], args[1]);
4555 case 3: return obj[method](args[0], args[1], args[2]);
4556 case 4: return obj[method](args[0], args[1], args[2], args[3]);
4557 case 5: return obj[method](args[0], args[1], args[2], args[3], args[4]);
4561 FakeXMLHttpRequest.filters = [];
4562 FakeXMLHttpRequest.addFilter = function addFilter(fn) {
4563 this.filters.push(fn)
4565 var IE6Re = /MSIE 6/;
4566 FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) {
4567 var xhr = new sinonXhr.workingXHR();
4573 "getResponseHeader",
4574 "getAllResponseHeaders",
4577 "removeEventListener"
4578 ], function (method) {
4579 fakeXhr[method] = function () {
4580 return apply(xhr, method, arguments);
4584 var copyAttrs = function (args) {
4585 each(args, function (attr) {
4587 fakeXhr[attr] = xhr[attr]
4589 if (!IE6Re.test(navigator.userAgent)) {
4596 var stateChange = function stateChange() {
4597 fakeXhr.readyState = xhr.readyState;
4598 if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
4599 copyAttrs(["status", "statusText"]);
4601 if (xhr.readyState >= FakeXMLHttpRequest.LOADING) {
4602 copyAttrs(["responseText", "response"]);
4604 if (xhr.readyState === FakeXMLHttpRequest.DONE) {
4605 copyAttrs(["responseXML"]);
4607 if (fakeXhr.onreadystatechange) {
4608 fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
4612 if (xhr.addEventListener) {
4613 for (var event in fakeXhr.eventListeners) {
4614 if (fakeXhr.eventListeners.hasOwnProperty(event)) {
4615 each(fakeXhr.eventListeners[event], function (handler) {
4616 xhr.addEventListener(event, handler);
4620 xhr.addEventListener("readystatechange", stateChange);
4622 xhr.onreadystatechange = stateChange;
4624 apply(xhr, "open", xhrArgs);
4626 FakeXMLHttpRequest.useFilters = false;
4628 function verifyRequestOpened(xhr) {
4629 if (xhr.readyState != FakeXMLHttpRequest.OPENED) {
4630 throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
4634 function verifyRequestSent(xhr) {
4635 if (xhr.readyState == FakeXMLHttpRequest.DONE) {
4636 throw new Error("Request done");
4640 function verifyHeadersReceived(xhr) {
4641 if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
4642 throw new Error("No headers received");
4646 function verifyResponseBodyType(body) {
4647 if (typeof body != "string") {
4648 var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
4649 body + ", which is not a string.");
4650 error.name = "InvalidBodyException";
4655 FakeXMLHttpRequest.parseXML = function parseXML(text) {
4658 if (typeof DOMParser != "undefined") {
4659 var parser = new DOMParser();
4660 xmlDoc = parser.parseFromString(text, "text/xml");
4662 xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
4663 xmlDoc.async = "false";
4664 xmlDoc.loadXML(text);
4670 FakeXMLHttpRequest.statusCodes = {
4672 101: "Switching Protocols",
4676 203: "Non-Authoritative Information",
4678 205: "Reset Content",
4679 206: "Partial Content",
4680 207: "Multi-Status",
4681 300: "Multiple Choice",
4682 301: "Moved Permanently",
4685 304: "Not Modified",
4687 307: "Temporary Redirect",
4689 401: "Unauthorized",
4690 402: "Payment Required",
4693 405: "Method Not Allowed",
4694 406: "Not Acceptable",
4695 407: "Proxy Authentication Required",
4696 408: "Request Timeout",
4699 411: "Length Required",
4700 412: "Precondition Failed",
4701 413: "Request Entity Too Large",
4702 414: "Request-URI Too Long",
4703 415: "Unsupported Media Type",
4704 416: "Requested Range Not Satisfiable",
4705 417: "Expectation Failed",
4706 422: "Unprocessable Entity",
4707 500: "Internal Server Error",
4708 501: "Not Implemented",
4710 503: "Service Unavailable",
4711 504: "Gateway Timeout",
4712 505: "HTTP Version Not Supported"
4715 function makeApi(sinon) {
4716 sinon.xhr = sinonXhr;
4718 sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
4721 open: function open(method, url, async, username, password) {
4722 this.method = method;
4724 this.async = typeof async == "boolean" ? async : true;
4725 this.username = username;
4726 this.password = password;
4727 this.responseText = null;
4728 this.responseXML = null;
4729 this.requestHeaders = {};
4730 this.sendFlag = false;
4732 if (FakeXMLHttpRequest.useFilters === true) {
4733 var xhrArgs = arguments;
4734 var defake = some(FakeXMLHttpRequest.filters, function (filter) {
4735 return filter.apply(this, xhrArgs)
4738 return FakeXMLHttpRequest.defake(this, arguments);
4741 this.readyStateChange(FakeXMLHttpRequest.OPENED);
4744 readyStateChange: function readyStateChange(state) {
4745 this.readyState = state;
4747 if (typeof this.onreadystatechange == "function") {
4749 this.onreadystatechange();
4751 sinon.logError("Fake XHR onreadystatechange handler", e);
4755 this.dispatchEvent(new sinon.Event("readystatechange"));
4757 switch (this.readyState) {
4758 case FakeXMLHttpRequest.DONE:
4759 this.dispatchEvent(new sinon.Event("load", false, false, this));
4760 this.dispatchEvent(new sinon.Event("loadend", false, false, this));
4761 this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
4762 if (supportsProgress) {
4763 this.upload.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
4764 this.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
4770 setRequestHeader: function setRequestHeader(header, value) {
4773 if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
4774 throw new Error("Refused to set unsafe header \"" + header + "\"");
4777 if (this.requestHeaders[header]) {
4778 this.requestHeaders[header] += "," + value;
4780 this.requestHeaders[header] = value;
4785 setResponseHeaders: function setResponseHeaders(headers) {
4786 verifyRequestOpened(this);
4787 this.responseHeaders = {};
4789 for (var header in headers) {
4790 if (headers.hasOwnProperty(header)) {
4791 this.responseHeaders[header] = headers[header];
4796 this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
4798 this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
4802 // Currently treats ALL data as a DOMString (i.e. no Document)
4803 send: function send(data) {
4806 if (!/^(get|head)$/i.test(this.method)) {
4807 var contentType = getHeader(this.requestHeaders, "Content-Type");
4808 if (this.requestHeaders[contentType]) {
4809 var value = this.requestHeaders[contentType].split(";");
4810 this.requestHeaders[contentType] = value[0] + ";charset=utf-8";
4811 } else if (!(data instanceof FormData)) {
4812 this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
4815 this.requestBody = data;
4818 this.errorFlag = false;
4819 this.sendFlag = this.async;
4820 this.readyStateChange(FakeXMLHttpRequest.OPENED);
4822 if (typeof this.onSend == "function") {
4826 this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
4829 abort: function abort() {
4830 this.aborted = true;
4831 this.responseText = null;
4832 this.errorFlag = true;
4833 this.requestHeaders = {};
4835 if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) {
4836 this.readyStateChange(FakeXMLHttpRequest.DONE);
4837 this.sendFlag = false;
4840 this.readyState = FakeXMLHttpRequest.UNSENT;
4842 this.dispatchEvent(new sinon.Event("abort", false, false, this));
4844 this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
4846 if (typeof this.onerror === "function") {
4851 getResponseHeader: function getResponseHeader(header) {
4852 if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
4856 if (/^Set-Cookie2?$/i.test(header)) {
4860 header = getHeader(this.responseHeaders, header);
4862 return this.responseHeaders[header] || null;
4865 getAllResponseHeaders: function getAllResponseHeaders() {
4866 if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
4872 for (var header in this.responseHeaders) {
4873 if (this.responseHeaders.hasOwnProperty(header) &&
4874 !/^Set-Cookie2?$/i.test(header)) {
4875 headers += header + ": " + this.responseHeaders[header] + "\r\n";
4882 setResponseBody: function setResponseBody(body) {
4883 verifyRequestSent(this);
4884 verifyHeadersReceived(this);
4885 verifyResponseBodyType(body);
4887 var chunkSize = this.chunkSize || 10;
4889 this.responseText = "";
4893 this.readyStateChange(FakeXMLHttpRequest.LOADING);
4896 this.responseText += body.substring(index, index + chunkSize);
4898 } while (index < body.length);
4900 var type = this.getResponseHeader("Content-Type");
4902 if (this.responseText &&
4903 (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
4905 this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
4907 // Unable to parse XML - no biggie
4911 this.readyStateChange(FakeXMLHttpRequest.DONE);
4914 respond: function respond(status, headers, body) {
4915 this.status = typeof status == "number" ? status : 200;
4916 this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
4917 this.setResponseHeaders(headers || {});
4918 this.setResponseBody(body || "");
4921 uploadProgress: function uploadProgress(progressEventRaw) {
4922 if (supportsProgress) {
4923 this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
4927 downloadProgress: function downloadProgress(progressEventRaw) {
4928 if (supportsProgress) {
4929 this.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
4933 uploadError: function uploadError(error) {
4934 if (supportsCustomEvent) {
4935 this.upload.dispatchEvent(new sinon.CustomEvent("error", {detail: error}));
4940 sinon.extend(FakeXMLHttpRequest, {
4943 HEADERS_RECEIVED: 2,
4948 sinon.useFakeXMLHttpRequest = function () {
4949 FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
4950 if (sinonXhr.supportsXHR) {
4951 global.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest;
4954 if (sinonXhr.supportsActiveX) {
4955 global.ActiveXObject = sinonXhr.GlobalActiveXObject;
4958 delete FakeXMLHttpRequest.restore;
4960 if (keepOnCreate !== true) {
4961 delete FakeXMLHttpRequest.onCreate;
4964 if (sinonXhr.supportsXHR) {
4965 global.XMLHttpRequest = FakeXMLHttpRequest;
4968 if (sinonXhr.supportsActiveX) {
4969 global.ActiveXObject = function ActiveXObject(objId) {
4970 if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
4972 return new FakeXMLHttpRequest();
4975 return new sinonXhr.GlobalActiveXObject(objId);
4979 return FakeXMLHttpRequest;
4982 sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
4985 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
4986 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
4988 function loadDependencies(require, exports, module) {
4989 var sinon = require("./core");
4990 require("../extend");
4992 require("../log_error");
4994 module.exports = sinon;
4998 define(loadDependencies);
4999 } else if (isNode) {
5000 loadDependencies(require, module.exports, module);
5001 } else if (typeof sinon === "undefined") {
5007 })(typeof global !== "undefined" ? global : this);
5010 * @depend fake_xdomain_request.js
5011 * @depend fake_xml_http_request.js
5012 * @depend ../format.js
5013 * @depend ../log_error.js
5016 * The Sinon "server" mimics a web server that receives requests from
5017 * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
5018 * both synchronously and asynchronously. To respond synchronuously, canned
5019 * answers have to be provided upfront.
5021 * @author Christian Johansen (christian@cjohansen.no)
5024 * Copyright (c) 2010-2013 Christian Johansen
5027 if (typeof sinon == "undefined") {
5035 function create(proto) {
5036 F.prototype = proto;
5040 function responseArray(handler) {
5041 var response = handler;
5043 if (Object.prototype.toString.call(handler) != "[object Array]") {
5044 response = [200, {}, handler];
5047 if (typeof response[2] != "string") {
5048 throw new TypeError("Fake server response body should be string, but was " +
5049 typeof response[2]);
5055 var wloc = typeof window !== "undefined" ? window.location : {};
5056 var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
5058 function matchOne(response, reqMethod, reqUrl) {
5059 var rmeth = response.method;
5060 var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
5061 var url = response.url;
5062 var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
5064 return matchMethod && matchUrl;
5067 function match(response, request) {
5068 var requestUrl = request.url;
5070 if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
5071 requestUrl = requestUrl.replace(rCurrLoc, "");
5074 if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
5075 if (typeof response.response == "function") {
5076 var ru = response.url;
5077 var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
5078 return response.response.apply(response, args);
5087 function makeApi(sinon) {
5088 sinon.fakeServer = {
5089 create: function () {
5090 var server = create(this);
5091 if (!sinon.xhr.supportsCORS) {
5092 this.xhr = sinon.useFakeXDomainRequest();
5094 this.xhr = sinon.useFakeXMLHttpRequest();
5096 server.requests = [];
5098 this.xhr.onCreate = function (xhrObj) {
5099 server.addRequest(xhrObj);
5105 addRequest: function addRequest(xhrObj) {
5107 push.call(this.requests, xhrObj);
5109 xhrObj.onSend = function () {
5110 server.handleRequest(this);
5112 if (server.respondImmediately) {
5114 } else if (server.autoRespond && !server.responding) {
5115 setTimeout(function () {
5116 server.responding = false;
5118 }, server.autoRespondAfter || 10);
5120 server.responding = true;
5125 getHTTPMethod: function getHTTPMethod(request) {
5126 if (this.fakeHTTPMethods && /post/i.test(request.method)) {
5127 var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
5128 return !!matches ? matches[1] : request.method;
5131 return request.method;
5134 handleRequest: function handleRequest(xhr) {
5140 push.call(this.queue, xhr);
5142 this.processRequest(xhr);
5146 log: function log(response, request) {
5149 str = "Request:\n" + sinon.format(request) + "\n\n";
5150 str += "Response:\n" + sinon.format(response) + "\n\n";
5155 respondWith: function respondWith(method, url, body) {
5156 if (arguments.length == 1 && typeof method != "function") {
5157 this.response = responseArray(method);
5161 if (!this.responses) { this.responses = []; }
5163 if (arguments.length == 1) {
5165 url = method = null;
5168 if (arguments.length == 2) {
5174 push.call(this.responses, {
5177 response: typeof body == "function" ? body : responseArray(body)
5181 respond: function respond() {
5182 if (arguments.length > 0) {
5183 this.respondWith.apply(this, arguments);
5186 var queue = this.queue || [];
5187 var requests = queue.splice(0, queue.length);
5190 while (request = requests.shift()) {
5191 this.processRequest(request);
5195 processRequest: function processRequest(request) {
5197 if (request.aborted) {
5201 var response = this.response || [404, {}, ""];
5203 if (this.responses) {
5204 for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
5205 if (match.call(this, this.responses[i], request)) {
5206 response = this.responses[i].response;
5212 if (request.readyState != 4) {
5213 this.log(response, request);
5215 request.respond(response[0], response[1], response[2]);
5218 sinon.logError("Fake server request processing", e);
5222 restore: function restore() {
5223 return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
5228 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5229 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5231 function loadDependencies(require, exports, module) {
5232 var sinon = require("./core");
5233 require("./fake_xdomain_request");
5234 require("./fake_xml_http_request");
5235 require("../format");
5237 module.exports = sinon;
5241 define(loadDependencies);
5242 } else if (isNode) {
5243 loadDependencies(require, module.exports, module);
5250 * @depend fake_server.js
5251 * @depend fake_timers.js
5254 * Add-on for sinon.fakeServer that automatically handles a fake timer along with
5255 * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
5256 * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
5257 * it polls the object for completion with setInterval. Dispite the direct
5258 * motivation, there is nothing jQuery-specific in this file, so it can be used
5259 * in any environment where the ajax implementation depends on setInterval or
5262 * @author Christian Johansen (christian@cjohansen.no)
5265 * Copyright (c) 2010-2013 Christian Johansen
5269 function makeApi(sinon) {
5270 function Server() {}
5271 Server.prototype = sinon.fakeServer;
5273 sinon.fakeServerWithClock = new Server();
5275 sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
5277 if (typeof setTimeout.clock == "object") {
5278 this.clock = setTimeout.clock;
5280 this.clock = sinon.useFakeTimers();
5281 this.resetClock = true;
5284 if (!this.longestTimeout) {
5285 var clockSetTimeout = this.clock.setTimeout;
5286 var clockSetInterval = this.clock.setInterval;
5289 this.clock.setTimeout = function (fn, timeout) {
5290 server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
5292 return clockSetTimeout.apply(this, arguments);
5295 this.clock.setInterval = function (fn, timeout) {
5296 server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
5298 return clockSetInterval.apply(this, arguments);
5303 return sinon.fakeServer.addRequest.call(this, xhr);
5306 sinon.fakeServerWithClock.respond = function respond() {
5307 var returnVal = sinon.fakeServer.respond.apply(this, arguments);
5310 this.clock.tick(this.longestTimeout || 0);
5311 this.longestTimeout = 0;
5313 if (this.resetClock) {
5314 this.clock.restore();
5315 this.resetClock = false;
5322 sinon.fakeServerWithClock.restore = function restore() {
5324 this.clock.restore();
5327 return sinon.fakeServer.restore.apply(this, arguments);
5331 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5332 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5334 function loadDependencies(require) {
5335 var sinon = require("./core");
5336 require("./fake_server");
5337 require("./fake_timers");
5342 define(loadDependencies);
5343 } else if (isNode) {
5344 loadDependencies(require);
5351 * @depend util/core.js
5353 * @depend collection.js
5354 * @depend util/fake_timers.js
5355 * @depend util/fake_server_with_clock.js
5358 * Manages fake collections as well as fake utilities such as Sinon's
5359 * timers and fake XHR implementation in one convenient object.
5361 * @author Christian Johansen (christian@cjohansen.no)
5364 * Copyright (c) 2010-2013 Christian Johansen
5368 function makeApi(sinon) {
5371 function exposeValue(sandbox, config, key, value) {
5376 if (config.injectInto && !(key in config.injectInto)) {
5377 config.injectInto[key] = value;
5378 sandbox.injectedKeys.push(key);
5380 push.call(sandbox.args, value);
5384 function prepareSandboxFromConfig(config) {
5385 var sandbox = sinon.create(sinon.sandbox);
5387 if (config.useFakeServer) {
5388 if (typeof config.useFakeServer == "object") {
5389 sandbox.serverPrototype = config.useFakeServer;
5392 sandbox.useFakeServer();
5395 if (config.useFakeTimers) {
5396 if (typeof config.useFakeTimers == "object") {
5397 sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
5399 sandbox.useFakeTimers();
5406 sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
5407 useFakeTimers: function useFakeTimers() {
5408 this.clock = sinon.useFakeTimers.apply(sinon, arguments);
5410 return this.add(this.clock);
5413 serverPrototype: sinon.fakeServer,
5415 useFakeServer: function useFakeServer() {
5416 var proto = this.serverPrototype || sinon.fakeServer;
5418 if (!proto || !proto.create) {
5422 this.server = proto.create();
5423 return this.add(this.server);
5426 inject: function (obj) {
5427 sinon.collection.inject.call(this, obj);
5430 obj.clock = this.clock;
5434 obj.server = this.server;
5435 obj.requests = this.server.requests;
5438 obj.match = sinon.match;
5443 restore: function () {
5444 sinon.collection.restore.apply(this, arguments);
5445 this.restoreContext();
5448 restoreContext: function () {
5449 if (this.injectedKeys) {
5450 for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
5451 delete this.injectInto[this.injectedKeys[i]];
5453 this.injectedKeys = [];
5457 create: function (config) {
5459 return sinon.create(sinon.sandbox);
5462 var sandbox = prepareSandboxFromConfig(config);
5463 sandbox.args = sandbox.args || [];
5464 sandbox.injectedKeys = [];
5465 sandbox.injectInto = config.injectInto;
5466 var prop, value, exposed = sandbox.inject({});
5468 if (config.properties) {
5469 for (var i = 0, l = config.properties.length; i < l; i++) {
5470 prop = config.properties[i];
5471 value = exposed[prop] || prop == "sandbox" && sandbox;
5472 exposeValue(sandbox, config, prop, value);
5475 exposeValue(sandbox, config, "sandbox", value);
5484 sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
5486 return sinon.sandbox;
5489 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5490 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5492 function loadDependencies(require, exports, module) {
5493 var sinon = require("./util/core");
5494 require("./extend");
5495 require("./util/fake_server_with_clock");
5496 require("./util/fake_timers");
5497 require("./collection");
5498 module.exports = makeApi(sinon);
5502 define(loadDependencies);
5503 } else if (isNode) {
5504 loadDependencies(require, module.exports, module);
5505 } else if (!sinon) {
5513 * @depend util/core.js
5514 * @depend sandbox.js
5517 * Test function, sandboxes fakes
5519 * @author Christian Johansen (christian@cjohansen.no)
5522 * Copyright (c) 2010-2013 Christian Johansen
5526 function makeApi(sinon) {
5527 var slice = Array.prototype.slice;
5529 function test(callback) {
5530 var type = typeof callback;
5532 if (type != "function") {
5533 throw new TypeError("sinon.test needs to wrap a test function, got " + type);
5536 function sinonSandboxedTest() {
5537 var config = sinon.getConfig(sinon.config);
5538 config.injectInto = config.injectIntoThis && this || config.injectInto;
5539 var sandbox = sinon.sandbox.create(config);
5540 var args = slice.call(arguments);
5541 var oldDone = args.length && args[args.length - 1];
5542 var exception, result;
5544 if (typeof oldDone == "function") {
5545 args[args.length - 1] = function sinonDone(result) {
5550 sandbox.verifyAndRestore();
5557 result = callback.apply(this, args.concat(sandbox.args));
5562 if (typeof oldDone != "function") {
5563 if (typeof exception !== "undefined") {
5567 sandbox.verifyAndRestore();
5574 if (callback.length) {
5575 return function sinonAsyncSandboxedTest(callback) {
5576 return sinonSandboxedTest.apply(this, arguments);
5580 return sinonSandboxedTest;
5584 injectIntoThis: true,
5586 properties: ["spy", "stub", "mock", "clock", "server", "requests"],
5587 useFakeTimers: true,
5595 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5596 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5598 function loadDependencies(require, exports, module) {
5599 var sinon = require("./util/core");
5600 require("./sandbox");
5601 module.exports = makeApi(sinon);
5605 define(loadDependencies);
5606 } else if (isNode) {
5607 loadDependencies(require, module.exports, module);
5611 }(typeof sinon == "object" && sinon || null));
5614 * @depend util/core.js
5618 * Test case, sandboxes all test functions
5620 * @author Christian Johansen (christian@cjohansen.no)
5623 * Copyright (c) 2010-2013 Christian Johansen
5627 function createTest(property, setUp, tearDown) {
5628 return function () {
5630 setUp.apply(this, arguments);
5633 var exception, result;
5636 result = property.apply(this, arguments);
5642 tearDown.apply(this, arguments);
5653 function makeApi(sinon) {
5654 function testCase(tests, prefix) {
5656 if (!tests || typeof tests != "object") {
5657 throw new TypeError("sinon.testCase needs an object with test functions");
5661 prefix = prefix || "test";
5662 var rPrefix = new RegExp("^" + prefix);
5663 var methods = {}, testName, property, method;
5664 var setUp = tests.setUp;
5665 var tearDown = tests.tearDown;
5667 for (testName in tests) {
5668 if (tests.hasOwnProperty(testName)) {
5669 property = tests[testName];
5671 if (/^(setUp|tearDown)$/.test(testName)) {
5675 if (typeof property == "function" && rPrefix.test(testName)) {
5678 if (setUp || tearDown) {
5679 method = createTest(property, setUp, tearDown);
5682 methods[testName] = sinon.test(method);
5684 methods[testName] = tests[testName];
5692 sinon.testCase = testCase;
5696 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5697 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5699 function loadDependencies(require, exports, module) {
5700 var sinon = require("./util/core");
5702 module.exports = makeApi(sinon);
5706 define(loadDependencies);
5707 } else if (isNode) {
5708 loadDependencies(require, module.exports, module);
5709 } else if (!sinon) {
5714 }(typeof sinon == "object" && sinon || null));
5717 * @depend times_in_words.js
5718 * @depend util/core.js
5723 * Assertions matching the test spy retrieval interface.
5725 * @author Christian Johansen (christian@cjohansen.no)
5728 * Copyright (c) 2010-2013 Christian Johansen
5731 (function (sinon, global) {
5732 var slice = Array.prototype.slice;
5734 function makeApi(sinon) {
5737 function verifyIsStub() {
5740 for (var i = 0, l = arguments.length; i < l; ++i) {
5741 method = arguments[i];
5744 assert.fail("fake is not a spy");
5748 verifyIsStub(method.proxy);
5750 if (typeof method != "function") {
5751 assert.fail(method + " is not a function");
5754 if (typeof method.getCall != "function") {
5755 assert.fail(method + " is not stubbed");
5762 function failAssertion(object, msg) {
5763 object = object || global;
5764 var failMethod = object.fail || assert.fail;
5765 failMethod.call(object, msg);
5768 function mirrorPropAsAssertion(name, method, message) {
5769 if (arguments.length == 2) {
5774 assert[name] = function (fake) {
5777 var args = slice.call(arguments, 1);
5780 if (typeof method == "function") {
5781 failed = !method(fake);
5783 failed = typeof fake[method] == "function" ?
5784 !fake[method].apply(fake, args) : !fake[method];
5788 failAssertion(this, (fake.printf || fake.proxy.printf).apply(fake, [message].concat(args)));
5795 function exposedName(prefix, prop) {
5796 return !prefix || /^fail/.test(prop) ? prop :
5797 prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
5801 failException: "AssertError",
5803 fail: function fail(message) {
5804 var error = new Error(message);
5805 error.name = this.failException || assert.failException;
5810 pass: function pass(assertion) {},
5812 callOrder: function assertCallOrder() {
5813 verifyIsStub.apply(null, arguments);
5814 var expected = "", actual = "";
5816 if (!sinon.calledInOrder(arguments)) {
5818 expected = [].join.call(arguments, ", ");
5819 var calls = slice.call(arguments);
5820 var i = calls.length;
5822 if (!calls[--i].called) {
5826 actual = sinon.orderByFirstCall(calls).join(", ");
5828 // If this fails, we'll just fall back to the blank string
5831 failAssertion(this, "expected " + expected + " to be " +
5832 "called in order but were called as " + actual);
5834 assert.pass("callOrder");
5838 callCount: function assertCallCount(method, count) {
5839 verifyIsStub(method);
5841 if (method.callCount != count) {
5842 var msg = "expected %n to be called " + sinon.timesInWords(count) +
5843 " but was called %c%C";
5844 failAssertion(this, method.printf(msg));
5846 assert.pass("callCount");
5850 expose: function expose(target, options) {
5852 throw new TypeError("target is null or undefined");
5855 var o = options || {};
5856 var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
5857 var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
5859 for (var method in this) {
5860 if (method != "expose" && (includeFail || !/^(fail)/.test(method))) {
5861 target[exposedName(prefix, method)] = this[method];
5868 match: function match(actual, expectation) {
5869 var matcher = sinon.match(expectation);
5870 if (matcher.test(actual)) {
5871 assert.pass("match");
5874 "expected value to match",
5875 " expected = " + sinon.format(expectation),
5876 " actual = " + sinon.format(actual)
5878 failAssertion(this, formatted.join("\n"));
5883 mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
5884 mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
5885 "expected %n to not have been called but was called %c%C");
5886 mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
5887 mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
5888 mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
5889 mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
5890 mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
5891 mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
5892 mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
5893 mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
5894 mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
5895 mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
5896 mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
5897 mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
5898 mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
5899 mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
5900 mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
5901 mirrorPropAsAssertion("threw", "%n did not throw exception%C");
5902 mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
5904 sinon.assert = assert;
5908 var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
5909 var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
5911 function loadDependencies(require, exports, module) {
5912 var sinon = require("./util/core");
5914 require("./format");
5915 module.exports = makeApi(sinon);
5919 define(loadDependencies);
5920 } else if (isNode) {
5921 loadDependencies(require, module.exports, module);
5922 } else if (!sinon) {
5928 }(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));