2 * Sinon.JS 1.7.3, 2013/06/20
4 * @author Christian Johansen (christian@cjohansen.no)
5 * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
9 * Copyright (c) 2010-2013, 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 this.sinon = (function () {
37 var buster = (function (setTimeout, B) {
38 var isNode = typeof require == "function" && typeof module == "object";
39 var div = typeof document != "undefined" && document.createElement("div");
40 var F = function () {};
43 bind: function bind(obj, methOrProp) {
44 var method = typeof methOrProp == "string" ? obj[methOrProp] : methOrProp;
45 var args = Array.prototype.slice.call(arguments, 2);
47 var allArgs = args.concat(Array.prototype.slice.call(arguments));
48 return method.apply(obj, allArgs);
52 partial: function partial(fn) {
53 var args = [].slice.call(arguments, 1);
55 return fn.apply(this, args.concat([].slice.call(arguments)));
59 create: function create(object) {
64 extend: function extend(target) {
65 if (!target) { return; }
66 for (var i = 1, l = arguments.length, prop; i < l; ++i) {
67 for (prop in arguments[i]) {
68 target[prop] = arguments[i][prop];
74 nextTick: function nextTick(callback) {
75 if (typeof process != "undefined" && process.nextTick) {
76 return process.nextTick(callback);
78 setTimeout(callback, 0);
81 functionName: function functionName(func) {
83 if (func.displayName) return func.displayName;
84 if (func.name) return func.name;
85 var matches = func.toString().match(/function\s+([^\(]+)/m);
86 return matches && matches[1] || "";
89 isNode: function isNode(obj) {
90 if (!div) return false;
100 isElement: function isElement(obj) {
101 return obj && obj.nodeType === 1 && buster.isNode(obj);
104 isArray: function isArray(arr) {
105 return Object.prototype.toString.call(arr) == "[object Array]";
108 flatten: function flatten(arr) {
109 var result = [], arr = arr || [];
110 for (var i = 0, l = arr.length; i < l; ++i) {
111 result = result.concat(buster.isArray(arr[i]) ? flatten(arr[i]) : arr[i]);
116 each: function each(arr, callback) {
117 for (var i = 0, l = arr.length; i < l; ++i) {
122 map: function map(arr, callback) {
124 for (var i = 0, l = arr.length; i < l; ++i) {
125 results.push(callback(arr[i]));
130 parallel: function parallel(fns, callback) {
131 function cb(err, res) {
132 if (typeof callback == "function") {
137 if (fns.length == 0) { return cb(null, []); }
138 var remaining = fns.length, results = [];
139 function makeDone(num) {
140 return function done(err, result) {
141 if (err) { return cb(err); }
142 results[num] = result;
143 if (--remaining == 0) { cb(null, results); }
146 for (var i = 0, l = fns.length; i < l; ++i) {
151 series: function series(fns, callback) {
152 function cb(err, res) {
153 if (typeof callback == "function") {
157 var remaining = fns.slice();
159 function callNext() {
160 if (remaining.length == 0) return cb(null, results);
161 var promise = remaining.shift()(next);
162 if (promise && typeof promise.then == "function") {
163 promise.then(buster.partial(next, null), next);
166 function next(err, result) {
167 if (err) return cb(err);
168 results.push(result);
174 countdown: function countdown(num, done) {
176 if (--num == 0) done();
181 if (typeof process === "object" &&
182 typeof require === "function" && typeof module === "object") {
183 var crypto = require("crypto");
184 var path = require("path");
186 buster.tmpFile = function (fileName) {
187 var hashed = crypto.createHash("sha1");
188 hashed.update(fileName);
189 var tmpfileName = hashed.digest("hex");
191 if (process.platform == "win32") {
192 return path.join(process.env["TEMP"], tmpfileName);
194 return path.join("/tmp", tmpfileName);
199 if (Array.prototype.some) {
200 buster.some = function (arr, fn, thisp) {
201 return arr.some(fn, thisp);
204 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
205 buster.some = function (arr, fun, thisp) {
206 if (arr == null) { throw new TypeError(); }
208 var len = arr.length >>> 0;
209 if (typeof fun !== "function") { throw new TypeError(); }
211 for (var i = 0; i < len; i++) {
212 if (arr.hasOwnProperty(i) && fun.call(thisp, arr[i], i, arr)) {
221 if (Array.prototype.filter) {
222 buster.filter = function (arr, fn, thisp) {
223 return arr.filter(fn, thisp);
226 // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
227 buster.filter = function (fn, thisp) {
228 if (this == null) { throw new TypeError(); }
230 var t = Object(this);
231 var len = t.length >>> 0;
232 if (typeof fn != "function") { throw new TypeError(); }
235 for (var i = 0; i < len; i++) {
237 var val = t[i]; // in case fun mutates this
238 if (fn.call(thisp, val, i, t)) { res.push(val); }
247 module.exports = buster;
248 buster.eventEmitter = require("./buster-event-emitter");
249 Object.defineProperty(buster, "defineVersionGetter", {
251 return require("./define-version-getter");
256 return buster.extend(B || {}, buster);
257 }(setTimeout, buster));
258 if (typeof buster === "undefined") {
262 if (typeof module === "object" && typeof require === "function") {
263 buster = require("buster-core");
266 buster.format = buster.format || {};
267 buster.format.excludeConstructors = ["Object", /^.$/];
268 buster.format.quoteStrings = true;
270 buster.format.ascii = (function () {
272 var hasOwn = Object.prototype.hasOwnProperty;
274 var specialObjects = [];
275 if (typeof global != "undefined") {
276 specialObjects.push({ obj: global, value: "[object global]" });
278 if (typeof document != "undefined") {
279 specialObjects.push({ obj: document, value: "[object HTMLDocument]" });
281 if (typeof window != "undefined") {
282 specialObjects.push({ obj: window, value: "[object Window]" });
285 function keys(object) {
286 var k = Object.keys && Object.keys(object) || [];
289 for (var prop in object) {
290 if (hasOwn.call(object, prop)) {
299 function isCircular(object, objects) {
300 if (typeof object != "object") {
304 for (var i = 0, l = objects.length; i < l; ++i) {
305 if (objects[i] === object) {
313 function ascii(object, processed, indent) {
314 if (typeof object == "string") {
315 var quote = typeof this.quoteStrings != "boolean" || this.quoteStrings;
316 return processed || quote ? '"' + object + '"' : object;
319 if (typeof object == "function" && !(object instanceof RegExp)) {
320 return ascii.func(object);
323 processed = processed || [];
325 if (isCircular(object, processed)) {
329 if (Object.prototype.toString.call(object) == "[object Array]") {
330 return ascii.array.call(this, object, processed);
337 if (buster.isElement(object)) {
338 return ascii.element(object);
341 if (typeof object.toString == "function" &&
342 object.toString !== Object.prototype.toString) {
343 return object.toString();
346 for (var i = 0, l = specialObjects.length; i < l; i++) {
347 if (object === specialObjects[i].obj) {
348 return specialObjects[i].value;
352 return ascii.object.call(this, object, processed, indent);
355 ascii.func = function (func) {
356 return "function " + buster.functionName(func) + "() {}";
359 ascii.array = function (array, processed) {
360 processed = processed || [];
361 processed.push(array);
364 for (var i = 0, l = array.length; i < l; ++i) {
365 pieces.push(ascii.call(this, array[i], processed));
368 return "[" + pieces.join(", ") + "]";
371 ascii.object = function (object, processed, indent) {
372 processed = processed || [];
373 processed.push(object);
374 indent = indent || 0;
375 var pieces = [], properties = keys(object), prop, str, obj;
379 for (var i = 0, l = indent; i < l; ++i) {
383 for (i = 0, l = properties.length; i < l; ++i) {
384 prop = properties[i];
387 if (isCircular(obj, processed)) {
390 str = ascii.call(this, obj, processed, indent + 2);
393 str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
394 length += str.length;
398 var cons = ascii.constructorName.call(this, object);
399 var prefix = cons ? "[" + cons + "] " : ""
401 return (length + indent) > 80 ?
402 prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" + is + "}" :
403 prefix + "{ " + pieces.join(", ") + " }";
406 ascii.element = function (element) {
407 var tagName = element.tagName.toLowerCase();
408 var attrs = element.attributes, attribute, pairs = [], attrName;
410 for (var i = 0, l = attrs.length; i < l; ++i) {
411 attribute = attrs.item(i);
412 attrName = attribute.nodeName.toLowerCase().replace("html:", "");
414 if (attrName == "contenteditable" && attribute.nodeValue == "inherit") {
418 if (!!attribute.nodeValue) {
419 pairs.push(attrName + "=\"" + attribute.nodeValue + "\"");
423 var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
424 var content = element.innerHTML;
426 if (content.length > 20) {
427 content = content.substr(0, 20) + "[...]";
430 var res = formatted + pairs.join(" ") + ">" + content + "</" + tagName + ">";
432 return res.replace(/ contentEditable="inherit"/, "");
435 ascii.constructorName = function (object) {
436 var name = buster.functionName(object && object.constructor);
437 var excludes = this.excludeConstructors || buster.format.excludeConstructors || [];
439 for (var i = 0, l = excludes.length; i < l; ++i) {
440 if (typeof excludes[i] == "string" && excludes[i] == name) {
442 } else if (excludes[i].test && excludes[i].test(name)) {
453 if (typeof module != "undefined") {
454 module.exports = buster.format;
456 /*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
457 /*global module, require, __dirname, document*/
459 * Sinon core utilities. For internal use only.
461 * @author Christian Johansen (christian@cjohansen.no)
464 * Copyright (c) 2010-2013 Christian Johansen
467 var sinon = (function (buster) {
468 var div = typeof document != "undefined" && document.createElement("div");
469 var hasOwn = Object.prototype.hasOwnProperty;
471 function isDOMNode(obj) {
475 obj.appendChild(div);
476 success = div.parentNode == obj;
481 obj.removeChild(div);
483 // Remove failed, not much we can do about that
490 function isElement(obj) {
491 return div && obj && obj.nodeType === 1 && isDOMNode(obj);
494 function isFunction(obj) {
495 return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
498 function mirrorProperties(target, source) {
499 for (var prop in source) {
500 if (!hasOwn.call(target, prop)) {
501 target[prop] = source[prop];
506 function isRestorable (obj) {
507 return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
511 wrapMethod: function wrapMethod(object, property, method) {
513 throw new TypeError("Should wrap property of object");
516 if (typeof method != "function") {
517 throw new TypeError("Method wrapper should be function");
520 var wrappedMethod = object[property];
522 if (!isFunction(wrappedMethod)) {
523 throw new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
524 property + " as function");
527 if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
528 throw new TypeError("Attempted to wrap " + property + " which is already wrapped");
531 if (wrappedMethod.calledBefore) {
532 var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
533 throw new TypeError("Attempted to wrap " + property + " which is already " + verb);
536 // IE 8 does not support hasOwnProperty on the window object.
537 var owned = hasOwn.call(object, property);
538 object[property] = method;
539 method.displayName = property;
541 method.restore = function () {
542 // For prototype properties try to reset by delete first.
543 // If this fails (ex: localStorage on mobile safari) then force a reset
544 // via direct assignment.
546 delete object[property];
548 if (object[property] === method) {
549 object[property] = wrappedMethod;
553 method.restore.sinon = true;
554 mirrorProperties(method, wrappedMethod);
559 extend: function extend(target) {
560 for (var i = 1, l = arguments.length; i < l; i += 1) {
561 for (var prop in arguments[i]) {
562 if (arguments[i].hasOwnProperty(prop)) {
563 target[prop] = arguments[i][prop];
566 // DONT ENUM bug, only care about toString
567 if (arguments[i].hasOwnProperty("toString") &&
568 arguments[i].toString != target.toString) {
569 target.toString = arguments[i].toString;
577 create: function create(proto) {
578 var F = function () {};
583 deepEqual: function deepEqual(a, b) {
584 if (sinon.match && sinon.match.isMatcher(a)) {
587 if (typeof a != "object" || typeof b != "object") {
591 if (isElement(a) || isElement(b)) {
599 if ((a === null && b !== null) || (a !== null && b === null)) {
603 var aString = Object.prototype.toString.call(a);
604 if (aString != Object.prototype.toString.call(b)) {
608 if (aString == "[object Array]") {
609 if (a.length !== b.length) {
613 for (var i = 0, l = a.length; i < l; i += 1) {
614 if (!deepEqual(a[i], b[i])) {
622 if (aString == "[object Date]") {
623 return a.valueOf() === b.valueOf();
626 var prop, aLength = 0, bLength = 0;
631 if (!deepEqual(a[prop], b[prop])) {
640 return aLength == bLength;
643 functionName: function functionName(func) {
644 var name = func.displayName || func.name;
646 // Use function decomposition as a last resort to get function
647 // name. Does not rely on function decomposition to work - if it
648 // doesn't debugging will be slightly less informative
649 // (i.e. toString will say 'spy' rather than 'myFunc').
651 var matches = func.toString().match(/function ([^\s\(]+)/);
652 name = matches && matches[1];
658 functionToString: function toString() {
659 if (this.getCall && this.callCount) {
660 var thisValue, prop, i = this.callCount;
663 thisValue = this.getCall(i).thisValue;
665 for (prop in thisValue) {
666 if (thisValue[prop] === this) {
673 return this.displayName || "sinon fake";
676 getConfig: function (custom) {
678 custom = custom || {};
679 var defaults = sinon.defaultConfig;
681 for (var prop in defaults) {
682 if (defaults.hasOwnProperty(prop)) {
683 config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
690 format: function (val) {
695 injectIntoThis: true,
697 properties: ["spy", "stub", "mock", "clock", "server", "requests"],
702 timesInWords: function timesInWords(count) {
703 return count == 1 && "once" ||
704 count == 2 && "twice" ||
705 count == 3 && "thrice" ||
706 (count || 0) + " times";
709 calledInOrder: function (spies) {
710 for (var i = 1, l = spies.length; i < l; i++) {
711 if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
719 orderByFirstCall: function (spies) {
720 return spies.sort(function (a, b) {
721 // uuid, won't ever be equal
722 var aCall = a.getCall(0);
723 var bCall = b.getCall(0);
724 var aId = aCall && aCall.callId || -1;
725 var bId = bCall && bCall.callId || -1;
727 return aId < bId ? -1 : 1;
733 logError: function (label, err) {
734 var msg = label + " threw exception: "
735 sinon.log(msg + "[" + err.name + "] " + err.message);
736 if (err.stack) { sinon.log(err.stack); }
738 setTimeout(function () {
739 err.message = msg + err.message;
744 typeOf: function (value) {
745 if (value === null) {
748 else if (value === undefined) {
751 var string = Object.prototype.toString.call(value);
752 return string.substring(8, string.length - 1).toLowerCase();
755 createStubInstance: function (constructor) {
756 if (typeof constructor !== "function") {
757 throw new TypeError("The constructor should be a function.");
759 return sinon.stub(sinon.create(constructor.prototype));
762 restore: function (object) {
763 if (object !== null && typeof object === "object") {
764 for (var prop in object) {
765 if (isRestorable(object[prop])) {
766 object[prop].restore();
770 else if (isRestorable(object)) {
776 var isNode = typeof module == "object" && typeof require == "function";
780 buster = { format: require("buster-format") };
782 module.exports = sinon;
783 module.exports.spy = require("./sinon/spy");
784 module.exports.stub = require("./sinon/stub");
785 module.exports.mock = require("./sinon/mock");
786 module.exports.collection = require("./sinon/collection");
787 module.exports.assert = require("./sinon/assert");
788 module.exports.sandbox = require("./sinon/sandbox");
789 module.exports.test = require("./sinon/test");
790 module.exports.testCase = require("./sinon/test_case");
791 module.exports.assert = require("./sinon/assert");
792 module.exports.match = require("./sinon/match");
796 var formatter = sinon.create(buster.format);
797 formatter.quoteStrings = false;
798 sinon.format = function () {
799 return formatter.ascii.apply(formatter, arguments);
803 var util = require("util");
804 sinon.format = function (value) {
805 return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
808 /* Node, but no util module - would be very old, but better safe than
814 }(typeof buster == "object" && buster));
816 /* @depend ../sinon.js */
817 /*jslint eqeqeq: false, onevar: false, plusplus: false*/
818 /*global module, require, sinon*/
822 * @author Maximilian Antoni (mail@maxantoni.de)
825 * Copyright (c) 2012 Maximilian Antoni
829 var commonJSModule = typeof module == "object" && typeof require == "function";
831 if (!sinon && commonJSModule) {
832 sinon = require("../sinon");
839 function assertType(value, type, name) {
840 var actual = sinon.typeOf(value);
841 if (actual !== type) {
842 throw new TypeError("Expected type of " + name + " to be " +
843 type + ", but was " + actual);
848 toString: function () {
853 function isMatcher(object) {
854 return matcher.isPrototypeOf(object);
857 function matchObject(expectation, actual) {
858 if (actual === null || actual === undefined) {
861 for (var key in expectation) {
862 if (expectation.hasOwnProperty(key)) {
863 var exp = expectation[key];
864 var act = actual[key];
865 if (match.isMatcher(exp)) {
866 if (!exp.test(act)) {
869 } else if (sinon.typeOf(exp) === "object") {
870 if (!matchObject(exp, act)) {
873 } else if (!sinon.deepEqual(exp, act)) {
881 matcher.or = function (m2) {
882 if (!isMatcher(m2)) {
883 throw new TypeError("Matcher expected");
886 var or = sinon.create(matcher);
887 or.test = function (actual) {
888 return m1.test(actual) || m2.test(actual);
890 or.message = m1.message + ".or(" + m2.message + ")";
894 matcher.and = function (m2) {
895 if (!isMatcher(m2)) {
896 throw new TypeError("Matcher expected");
899 var and = sinon.create(matcher);
900 and.test = function (actual) {
901 return m1.test(actual) && m2.test(actual);
903 and.message = m1.message + ".and(" + m2.message + ")";
907 var match = function (expectation, message) {
908 var m = sinon.create(matcher);
909 var type = sinon.typeOf(expectation);
912 if (typeof expectation.test === "function") {
913 m.test = function (actual) {
914 return expectation.test(actual) === true;
916 m.message = "match(" + sinon.functionName(expectation.test) + ")";
920 for (var key in expectation) {
921 if (expectation.hasOwnProperty(key)) {
922 str.push(key + ": " + expectation[key]);
925 m.test = function (actual) {
926 return matchObject(expectation, actual);
928 m.message = "match(" + str.join(", ") + ")";
931 m.test = function (actual) {
932 return expectation == actual;
936 m.test = function (actual) {
937 if (typeof actual !== "string") {
940 return actual.indexOf(expectation) !== -1;
942 m.message = "match(\"" + expectation + "\")";
945 m.test = function (actual) {
946 if (typeof actual !== "string") {
949 return expectation.test(actual);
953 m.test = expectation;
957 m.message = "match(" + sinon.functionName(expectation) + ")";
961 m.test = function (actual) {
962 return sinon.deepEqual(expectation, actual);
966 m.message = "match(" + expectation + ")";
971 match.isMatcher = isMatcher;
973 match.any = match(function () {
977 match.defined = match(function (actual) {
978 return actual !== null && actual !== undefined;
981 match.truthy = match(function (actual) {
985 match.falsy = match(function (actual) {
989 match.same = function (expectation) {
990 return match(function (actual) {
991 return expectation === actual;
992 }, "same(" + expectation + ")");
995 match.typeOf = function (type) {
996 assertType(type, "string", "type");
997 return match(function (actual) {
998 return sinon.typeOf(actual) === type;
999 }, "typeOf(\"" + type + "\")");
1002 match.instanceOf = function (type) {
1003 assertType(type, "function", "type");
1004 return match(function (actual) {
1005 return actual instanceof type;
1006 }, "instanceOf(" + sinon.functionName(type) + ")");
1009 function createPropertyMatcher(propertyTest, messagePrefix) {
1010 return function (property, value) {
1011 assertType(property, "string", "property");
1012 var onlyProperty = arguments.length === 1;
1013 var message = messagePrefix + "(\"" + property + "\"";
1014 if (!onlyProperty) {
1015 message += ", " + value;
1018 return match(function (actual) {
1019 if (actual === undefined || actual === null ||
1020 !propertyTest(actual, property)) {
1023 return onlyProperty || sinon.deepEqual(value, actual[property]);
1028 match.has = createPropertyMatcher(function (actual, property) {
1029 if (typeof actual === "object") {
1030 return property in actual;
1032 return actual[property] !== undefined;
1035 match.hasOwn = createPropertyMatcher(function (actual, property) {
1036 return actual.hasOwnProperty(property);
1039 match.bool = match.typeOf("boolean");
1040 match.number = match.typeOf("number");
1041 match.string = match.typeOf("string");
1042 match.object = match.typeOf("object");
1043 match.func = match.typeOf("function");
1044 match.array = match.typeOf("array");
1045 match.regexp = match.typeOf("regexp");
1046 match.date = match.typeOf("date");
1048 if (commonJSModule) {
1049 module.exports = match;
1051 sinon.match = match;
1053 }(typeof sinon == "object" && sinon || null));
1056 * @depend ../sinon.js
1059 /*jslint eqeqeq: false, onevar: false, plusplus: false*/
1060 /*global module, require, sinon*/
1064 * @author Christian Johansen (christian@cjohansen.no)
1065 * @author Maximilian Antoni (mail@maxantoni.de)
1068 * Copyright (c) 2010-2013 Christian Johansen
1069 * Copyright (c) 2013 Maximilian Antoni
1072 var commonJSModule = typeof module == "object" && typeof require == "function";
1074 if (!this.sinon && commonJSModule) {
1075 var sinon = require("../sinon");
1079 function throwYieldError(proxy, text, args) {
1080 var msg = sinon.functionName(proxy) + text;
1082 msg += " Received [" + slice.call(args).join(", ") + "]";
1084 throw new Error(msg);
1087 var slice = Array.prototype.slice;
1090 calledOn: function calledOn(thisValue) {
1091 if (sinon.match && sinon.match.isMatcher(thisValue)) {
1092 return thisValue.test(this.thisValue);
1094 return this.thisValue === thisValue;
1097 calledWith: function calledWith() {
1098 for (var i = 0, l = arguments.length; i < l; i += 1) {
1099 if (!sinon.deepEqual(arguments[i], this.args[i])) {
1107 calledWithMatch: function calledWithMatch() {
1108 for (var i = 0, l = arguments.length; i < l; i += 1) {
1109 var actual = this.args[i];
1110 var expectation = arguments[i];
1111 if (!sinon.match || !sinon.match(expectation).test(actual)) {
1118 calledWithExactly: function calledWithExactly() {
1119 return arguments.length == this.args.length &&
1120 this.calledWith.apply(this, arguments);
1123 notCalledWith: function notCalledWith() {
1124 return !this.calledWith.apply(this, arguments);
1127 notCalledWithMatch: function notCalledWithMatch() {
1128 return !this.calledWithMatch.apply(this, arguments);
1131 returned: function returned(value) {
1132 return sinon.deepEqual(value, this.returnValue);
1135 threw: function threw(error) {
1136 if (typeof error === "undefined" || !this.exception) {
1137 return !!this.exception;
1140 return this.exception === error || this.exception.name === error;
1143 calledWithNew: function calledWithNew(thisValue) {
1144 return this.thisValue instanceof this.proxy;
1147 calledBefore: function (other) {
1148 return this.callId < other.callId;
1151 calledAfter: function (other) {
1152 return this.callId > other.callId;
1155 callArg: function (pos) {
1159 callArgOn: function (pos, thisValue) {
1160 this.args[pos].apply(thisValue);
1163 callArgWith: function (pos) {
1164 this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
1167 callArgOnWith: function (pos, thisValue) {
1168 var args = slice.call(arguments, 2);
1169 this.args[pos].apply(thisValue, args);
1172 "yield": function () {
1173 this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
1176 yieldOn: function (thisValue) {
1177 var args = this.args;
1178 for (var i = 0, l = args.length; i < l; ++i) {
1179 if (typeof args[i] === "function") {
1180 args[i].apply(thisValue, slice.call(arguments, 1));
1184 throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
1187 yieldTo: function (prop) {
1188 this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
1191 yieldToOn: function (prop, thisValue) {
1192 var args = this.args;
1193 for (var i = 0, l = args.length; i < l; ++i) {
1194 if (args[i] && typeof args[i][prop] === "function") {
1195 args[i][prop].apply(thisValue, slice.call(arguments, 2));
1199 throwYieldError(this.proxy, " cannot yield to '" + prop +
1200 "' since no callback was passed.", args);
1203 toString: function () {
1204 var callStr = this.proxy.toString() + "(";
1207 for (var i = 0, l = this.args.length; i < l; ++i) {
1208 args.push(sinon.format(this.args[i]));
1211 callStr = callStr + args.join(", ") + ")";
1213 if (typeof this.returnValue != "undefined") {
1214 callStr += " => " + sinon.format(this.returnValue);
1217 if (this.exception) {
1218 callStr += " !" + this.exception.name;
1220 if (this.exception.message) {
1221 callStr += "(" + this.exception.message + ")";
1229 callProto.invokeCallback = callProto.yield;
1231 function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
1232 if (typeof id !== "number") {
1233 throw new TypeError("Call id is not a number");
1235 var proxyCall = sinon.create(callProto);
1236 proxyCall.proxy = spy;
1237 proxyCall.thisValue = thisValue;
1238 proxyCall.args = args;
1239 proxyCall.returnValue = returnValue;
1240 proxyCall.exception = exception;
1241 proxyCall.callId = id;
1245 createSpyCall.toString = callProto.toString; // used by mocks
1247 sinon.spyCall = createSpyCall;
1248 }(typeof sinon == "object" && sinon || null));
1251 * @depend ../sinon.js
1253 /*jslint eqeqeq: false, onevar: false, plusplus: false*/
1254 /*global module, require, sinon*/
1258 * @author Christian Johansen (christian@cjohansen.no)
1261 * Copyright (c) 2010-2013 Christian Johansen
1265 var commonJSModule = typeof module == "object" && typeof require == "function";
1266 var push = Array.prototype.push;
1267 var slice = Array.prototype.slice;
1270 function spy(object, property) {
1271 if (!property && typeof object == "function") {
1272 return spy.create(object);
1275 if (!object && !property) {
1276 return spy.create(function () { });
1279 var method = object[property];
1280 return sinon.wrapMethod(object, property, spy.create(method));
1283 function matchingFake(fakes, args, strict) {
1288 var alen = args.length;
1290 for (var i = 0, l = fakes.length; i < l; i++) {
1291 if (fakes[i].matches(args, strict)) {
1297 function incrementCallCount() {
1299 this.callCount += 1;
1300 this.notCalled = false;
1301 this.calledOnce = this.callCount == 1;
1302 this.calledTwice = this.callCount == 2;
1303 this.calledThrice = this.callCount == 3;
1306 function createCallProperties() {
1307 this.firstCall = this.getCall(0);
1308 this.secondCall = this.getCall(1);
1309 this.thirdCall = this.getCall(2);
1310 this.lastCall = this.getCall(this.callCount - 1);
1313 var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
1314 function createProxy(func) {
1315 // Retain the function length:
1318 eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
1319 ") { return p.invoke(func, this, slice.call(arguments)); });");
1322 p = function proxy() {
1323 return p.invoke(func, this, slice.call(arguments));
1333 reset: function () {
1334 this.called = false;
1335 this.notCalled = true;
1336 this.calledOnce = false;
1337 this.calledTwice = false;
1338 this.calledThrice = false;
1340 this.firstCall = null;
1341 this.secondCall = null;
1342 this.thirdCall = null;
1343 this.lastCall = null;
1345 this.returnValues = [];
1346 this.thisValues = [];
1347 this.exceptions = [];
1350 for (var i = 0; i < this.fakes.length; i++) {
1351 this.fakes[i].reset();
1356 create: function create(func) {
1359 if (typeof func != "function") {
1360 func = function () { };
1362 name = sinon.functionName(func);
1365 var proxy = createProxy(func);
1367 sinon.extend(proxy, spy);
1368 delete proxy.create;
1369 sinon.extend(proxy, func);
1372 proxy.prototype = func.prototype;
1373 proxy.displayName = name || "spy";
1374 proxy.toString = sinon.functionToString;
1375 proxy._create = sinon.spy.create;
1376 proxy.id = "spy#" + uuid++;
1381 invoke: function invoke(func, thisValue, args) {
1382 var matching = matchingFake(this.fakes, args);
1383 var exception, returnValue;
1385 incrementCallCount.call(this);
1386 push.call(this.thisValues, thisValue);
1387 push.call(this.args, args);
1388 push.call(this.callIds, callId++);
1392 returnValue = matching.invoke(func, thisValue, args);
1394 returnValue = (this.func || func).apply(thisValue, args);
1397 push.call(this.returnValues, undefined);
1401 push.call(this.exceptions, exception);
1404 push.call(this.returnValues, returnValue);
1406 createCallProperties.call(this);
1411 getCall: function getCall(i) {
1412 if (i < 0 || i >= this.callCount) {
1416 return sinon.spyCall(this, this.thisValues[i], this.args[i],
1417 this.returnValues[i], this.exceptions[i],
1421 calledBefore: function calledBefore(spyFn) {
1426 if (!spyFn.called) {
1430 return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
1433 calledAfter: function calledAfter(spyFn) {
1434 if (!this.called || !spyFn.called) {
1438 return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
1441 withArgs: function () {
1442 var args = slice.call(arguments);
1445 var match = matchingFake(this.fakes, args, true);
1454 var original = this;
1455 var fake = this._create();
1456 fake.matchingAguments = args;
1457 push.call(this.fakes, fake);
1459 fake.withArgs = function () {
1460 return original.withArgs.apply(original, arguments);
1463 for (var i = 0; i < this.args.length; i++) {
1464 if (fake.matches(this.args[i])) {
1465 incrementCallCount.call(fake);
1466 push.call(fake.thisValues, this.thisValues[i]);
1467 push.call(fake.args, this.args[i]);
1468 push.call(fake.returnValues, this.returnValues[i]);
1469 push.call(fake.exceptions, this.exceptions[i]);
1470 push.call(fake.callIds, this.callIds[i]);
1473 createCallProperties.call(fake);
1478 matches: function (args, strict) {
1479 var margs = this.matchingAguments;
1481 if (margs.length <= args.length &&
1482 sinon.deepEqual(margs, args.slice(0, margs.length))) {
1483 return !strict || margs.length == args.length;
1487 printf: function (format) {
1489 var args = slice.call(arguments, 1);
1492 return (format || "").replace(/%(.)/g, function (match, specifyer) {
1493 formatter = spyApi.formatters[specifyer];
1495 if (typeof formatter == "function") {
1496 return formatter.call(null, spy, args);
1497 } else if (!isNaN(parseInt(specifyer), 10)) {
1498 return sinon.format(args[specifyer - 1]);
1501 return "%" + specifyer;
1506 function delegateToCalls(method, matchAny, actual, notCalled) {
1507 spyApi[method] = function () {
1510 return notCalled.apply(this, arguments);
1518 for (var i = 0, l = this.callCount; i < l; i += 1) {
1519 currentCall = this.getCall(i);
1521 if (currentCall[actual || method].apply(currentCall, arguments)) {
1530 return matches === this.callCount;
1534 delegateToCalls("calledOn", true);
1535 delegateToCalls("alwaysCalledOn", false, "calledOn");
1536 delegateToCalls("calledWith", true);
1537 delegateToCalls("calledWithMatch", true);
1538 delegateToCalls("alwaysCalledWith", false, "calledWith");
1539 delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
1540 delegateToCalls("calledWithExactly", true);
1541 delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
1542 delegateToCalls("neverCalledWith", false, "notCalledWith",
1543 function () { return true; });
1544 delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch",
1545 function () { return true; });
1546 delegateToCalls("threw", true);
1547 delegateToCalls("alwaysThrew", false, "threw");
1548 delegateToCalls("returned", true);
1549 delegateToCalls("alwaysReturned", false, "returned");
1550 delegateToCalls("calledWithNew", true);
1551 delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
1552 delegateToCalls("callArg", false, "callArgWith", function () {
1553 throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
1555 spyApi.callArgWith = spyApi.callArg;
1556 delegateToCalls("callArgOn", false, "callArgOnWith", function () {
1557 throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
1559 spyApi.callArgOnWith = spyApi.callArgOn;
1560 delegateToCalls("yield", false, "yield", function () {
1561 throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
1563 // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
1564 spyApi.invokeCallback = spyApi.yield;
1565 delegateToCalls("yieldOn", false, "yieldOn", function () {
1566 throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
1568 delegateToCalls("yieldTo", false, "yieldTo", function (property) {
1569 throw new Error(this.toString() + " cannot yield to '" + property +
1570 "' since it was not yet invoked.");
1572 delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
1573 throw new Error(this.toString() + " cannot yield to '" + property +
1574 "' since it was not yet invoked.");
1577 spyApi.formatters = {
1578 "c": function (spy) {
1579 return sinon.timesInWords(spy.callCount);
1582 "n": function (spy) {
1583 return spy.toString();
1586 "C": function (spy) {
1589 for (var i = 0, l = spy.callCount; i < l; ++i) {
1590 var stringifiedCall = " " + spy.getCall(i).toString();
1591 if (/\n/.test(calls[i - 1])) {
1592 stringifiedCall = "\n" + stringifiedCall;
1594 push.call(calls, stringifiedCall);
1597 return calls.length > 0 ? "\n" + calls.join("\n") : "";
1600 "t": function (spy) {
1603 for (var i = 0, l = spy.callCount; i < l; ++i) {
1604 push.call(objects, sinon.format(spy.thisValues[i]));
1607 return objects.join(", ");
1610 "*": function (spy, args) {
1613 for (var i = 0, l = args.length; i < l; ++i) {
1614 push.call(formatted, sinon.format(args[i]));
1617 return formatted.join(", ");
1621 sinon.extend(spy, spyApi);
1623 spy.spyCall = sinon.spyCall;
1625 if (commonJSModule) {
1626 module.exports = spy;
1630 }(typeof sinon == "object" && sinon || null));
1633 * @depend ../sinon.js
1636 /*jslint eqeqeq: false, onevar: false*/
1637 /*global module, require, sinon*/
1641 * @author Christian Johansen (christian@cjohansen.no)
1644 * Copyright (c) 2010-2013 Christian Johansen
1648 var commonJSModule = typeof module == "object" && typeof require == "function";
1650 if (!sinon && commonJSModule) {
1651 sinon = require("../sinon");
1658 function stub(object, property, func) {
1659 if (!!func && typeof func != "function") {
1660 throw new TypeError("Custom stub should be function");
1666 wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
1668 wrapper = stub.create();
1671 if (!object && !property) {
1672 return sinon.stub.create();
1675 if (!property && !!object && typeof object == "object") {
1676 for (var prop in object) {
1677 if (typeof object[prop] === "function") {
1685 return sinon.wrapMethod(object, property, wrapper);
1688 function getChangingValue(stub, property) {
1689 var index = stub.callCount - 1;
1690 var values = stub[property];
1691 var prop = index in values ? values[index] : values[values.length - 1];
1692 stub[property + "Last"] = prop;
1697 function getCallback(stub, args) {
1698 var callArgAt = getChangingValue(stub, "callArgAts");
1700 if (callArgAt < 0) {
1701 var callArgProp = getChangingValue(stub, "callArgProps");
1703 for (var i = 0, l = args.length; i < l; ++i) {
1704 if (!callArgProp && typeof args[i] == "function") {
1708 if (callArgProp && args[i] &&
1709 typeof args[i][callArgProp] == "function") {
1710 return args[i][callArgProp];
1717 return args[callArgAt];
1720 var join = Array.prototype.join;
1722 function getCallbackError(stub, func, args) {
1723 if (stub.callArgAtsLast < 0) {
1726 if (stub.callArgPropsLast) {
1727 msg = sinon.functionName(stub) +
1728 " expected to yield to '" + stub.callArgPropsLast +
1729 "', but no object with such a property was passed."
1731 msg = sinon.functionName(stub) +
1732 " expected to yield, but no callback was passed."
1735 if (args.length > 0) {
1736 msg += " Received [" + join.call(args, ", ") + "]";
1742 return "argument at index " + stub.callArgAtsLast + " is not a function: " + func;
1745 var nextTick = (function () {
1746 if (typeof process === "object" && typeof process.nextTick === "function") {
1747 return process.nextTick;
1748 } else if (typeof setImmediate === "function") {
1749 return setImmediate;
1751 return function (callback) {
1752 setTimeout(callback, 0);
1757 function callCallback(stub, args) {
1758 if (stub.callArgAts.length > 0) {
1759 var func = getCallback(stub, args);
1761 if (typeof func != "function") {
1762 throw new TypeError(getCallbackError(stub, func, args));
1765 var callbackArguments = getChangingValue(stub, "callbackArguments");
1766 var callbackContext = getChangingValue(stub, "callbackContexts");
1768 if (stub.callbackAsync) {
1769 nextTick(function() {
1770 func.apply(callbackContext, callbackArguments);
1773 func.apply(callbackContext, callbackArguments);
1780 sinon.extend(stub, (function () {
1781 var slice = Array.prototype.slice, proto;
1783 function throwsException(error, message) {
1784 if (typeof error == "string") {
1785 this.exception = new Error(message || "");
1786 this.exception.name = error;
1787 } else if (!error) {
1788 this.exception = new Error("Error");
1790 this.exception = error;
1797 create: function create() {
1798 var functionStub = function () {
1800 callCallback(functionStub, arguments);
1802 if (functionStub.exception) {
1803 throw functionStub.exception;
1804 } else if (typeof functionStub.returnArgAt == 'number') {
1805 return arguments[functionStub.returnArgAt];
1806 } else if (functionStub.returnThis) {
1809 return functionStub.returnValue;
1812 functionStub.id = "stub#" + uuid++;
1813 var orig = functionStub;
1814 functionStub = sinon.spy.create(functionStub);
1815 functionStub.func = orig;
1817 functionStub.callArgAts = [];
1818 functionStub.callbackArguments = [];
1819 functionStub.callbackContexts = [];
1820 functionStub.callArgProps = [];
1822 sinon.extend(functionStub, stub);
1823 functionStub._create = sinon.stub.create;
1824 functionStub.displayName = "stub";
1825 functionStub.toString = sinon.functionToString;
1827 return functionStub;
1830 resetBehavior: function () {
1833 this.callArgAts = [];
1834 this.callbackArguments = [];
1835 this.callbackContexts = [];
1836 this.callArgProps = [];
1838 delete this.returnValue;
1839 delete this.returnArgAt;
1840 this.returnThis = false;
1843 for (i = 0; i < this.fakes.length; i++) {
1844 this.fakes[i].resetBehavior();
1849 returns: function returns(value) {
1850 this.returnValue = value;
1855 returnsArg: function returnsArg(pos) {
1856 if (typeof pos != "number") {
1857 throw new TypeError("argument index is not number");
1860 this.returnArgAt = pos;
1865 returnsThis: function returnsThis() {
1866 this.returnThis = true;
1871 "throws": throwsException,
1872 throwsException: throwsException,
1874 callsArg: function callsArg(pos) {
1875 if (typeof pos != "number") {
1876 throw new TypeError("argument index is not number");
1879 this.callArgAts.push(pos);
1880 this.callbackArguments.push([]);
1881 this.callbackContexts.push(undefined);
1882 this.callArgProps.push(undefined);
1887 callsArgOn: function callsArgOn(pos, context) {
1888 if (typeof pos != "number") {
1889 throw new TypeError("argument index is not number");
1891 if (typeof context != "object") {
1892 throw new TypeError("argument context is not an object");
1895 this.callArgAts.push(pos);
1896 this.callbackArguments.push([]);
1897 this.callbackContexts.push(context);
1898 this.callArgProps.push(undefined);
1903 callsArgWith: function callsArgWith(pos) {
1904 if (typeof pos != "number") {
1905 throw new TypeError("argument index is not number");
1908 this.callArgAts.push(pos);
1909 this.callbackArguments.push(slice.call(arguments, 1));
1910 this.callbackContexts.push(undefined);
1911 this.callArgProps.push(undefined);
1916 callsArgOnWith: function callsArgWith(pos, context) {
1917 if (typeof pos != "number") {
1918 throw new TypeError("argument index is not number");
1920 if (typeof context != "object") {
1921 throw new TypeError("argument context is not an object");
1924 this.callArgAts.push(pos);
1925 this.callbackArguments.push(slice.call(arguments, 2));
1926 this.callbackContexts.push(context);
1927 this.callArgProps.push(undefined);
1932 yields: function () {
1933 this.callArgAts.push(-1);
1934 this.callbackArguments.push(slice.call(arguments, 0));
1935 this.callbackContexts.push(undefined);
1936 this.callArgProps.push(undefined);
1941 yieldsOn: function (context) {
1942 if (typeof context != "object") {
1943 throw new TypeError("argument context is not an object");
1946 this.callArgAts.push(-1);
1947 this.callbackArguments.push(slice.call(arguments, 1));
1948 this.callbackContexts.push(context);
1949 this.callArgProps.push(undefined);
1954 yieldsTo: function (prop) {
1955 this.callArgAts.push(-1);
1956 this.callbackArguments.push(slice.call(arguments, 1));
1957 this.callbackContexts.push(undefined);
1958 this.callArgProps.push(prop);
1963 yieldsToOn: function (prop, context) {
1964 if (typeof context != "object") {
1965 throw new TypeError("argument context is not an object");
1968 this.callArgAts.push(-1);
1969 this.callbackArguments.push(slice.call(arguments, 2));
1970 this.callbackContexts.push(context);
1971 this.callArgProps.push(prop);
1977 // create asynchronous versions of callsArg* and yields* methods
1978 for (var method in proto) {
1979 // need to avoid creating anotherasync versions of the newly added async methods
1980 if (proto.hasOwnProperty(method) &&
1981 method.match(/^(callsArg|yields|thenYields$)/) &&
1982 !method.match(/Async/)) {
1983 proto[method + 'Async'] = (function (syncFnName) {
1984 return function () {
1985 this.callbackAsync = true;
1986 return this[syncFnName].apply(this, arguments);
1996 if (commonJSModule) {
1997 module.exports = stub;
2001 }(typeof sinon == "object" && sinon || null));
2004 * @depend ../sinon.js
2007 /*jslint eqeqeq: false, onevar: false, nomen: false*/
2008 /*global module, require, sinon*/
2012 * @author Christian Johansen (christian@cjohansen.no)
2015 * Copyright (c) 2010-2013 Christian Johansen
2019 var commonJSModule = typeof module == "object" && typeof require == "function";
2022 if (!sinon && commonJSModule) {
2023 sinon = require("../sinon");
2030 function mock(object) {
2032 return sinon.expectation.create("Anonymous mock");
2035 return mock.create(object);
2040 sinon.extend(mock, (function () {
2041 function each(collection, callback) {
2046 for (var i = 0, l = collection.length; i < l; i += 1) {
2047 callback(collection[i]);
2052 create: function create(object) {
2054 throw new TypeError("object is null");
2057 var mockObject = sinon.extend({}, mock);
2058 mockObject.object = object;
2059 delete mockObject.create;
2064 expects: function expects(method) {
2066 throw new TypeError("method is falsy");
2069 if (!this.expectations) {
2070 this.expectations = {};
2074 if (!this.expectations[method]) {
2075 this.expectations[method] = [];
2076 var mockObject = this;
2078 sinon.wrapMethod(this.object, method, function () {
2079 return mockObject.invokeMethod(method, this, arguments);
2082 push.call(this.proxies, method);
2085 var expectation = sinon.expectation.create(method);
2086 push.call(this.expectations[method], expectation);
2091 restore: function restore() {
2092 var object = this.object;
2094 each(this.proxies, function (proxy) {
2095 if (typeof object[proxy].restore == "function") {
2096 object[proxy].restore();
2101 verify: function verify() {
2102 var expectations = this.expectations || {};
2103 var messages = [], met = [];
2105 each(this.proxies, function (proxy) {
2106 each(expectations[proxy], function (expectation) {
2107 if (!expectation.met()) {
2108 push.call(messages, expectation.toString());
2110 push.call(met, expectation.toString());
2117 if (messages.length > 0) {
2118 sinon.expectation.fail(messages.concat(met).join("\n"));
2120 sinon.expectation.pass(messages.concat(met).join("\n"));
2126 invokeMethod: function invokeMethod(method, thisValue, args) {
2127 var expectations = this.expectations && this.expectations[method];
2128 var length = expectations && expectations.length || 0, i;
2130 for (i = 0; i < length; i += 1) {
2131 if (!expectations[i].met() &&
2132 expectations[i].allowsCall(thisValue, args)) {
2133 return expectations[i].apply(thisValue, args);
2137 var messages = [], available, exhausted = 0;
2139 for (i = 0; i < length; i += 1) {
2140 if (expectations[i].allowsCall(thisValue, args)) {
2141 available = available || expectations[i];
2145 push.call(messages, " " + expectations[i].toString());
2148 if (exhausted === 0) {
2149 return available.apply(thisValue, args);
2152 messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
2157 sinon.expectation.fail(messages.join("\n"));
2162 var times = sinon.timesInWords;
2164 sinon.expectation = (function () {
2165 var slice = Array.prototype.slice;
2166 var _invoke = sinon.spy.invoke;
2168 function callCountInWords(callCount) {
2169 if (callCount == 0) {
2170 return "never called";
2172 return "called " + times(callCount);
2176 function expectedCallCountInWords(expectation) {
2177 var min = expectation.minCalls;
2178 var max = expectation.maxCalls;
2180 if (typeof min == "number" && typeof max == "number") {
2181 var str = times(min);
2184 str = "at least " + str + " and at most " + times(max);
2190 if (typeof min == "number") {
2191 return "at least " + times(min);
2194 return "at most " + times(max);
2197 function receivedMinCalls(expectation) {
2198 var hasMinLimit = typeof expectation.minCalls == "number";
2199 return !hasMinLimit || expectation.callCount >= expectation.minCalls;
2202 function receivedMaxCalls(expectation) {
2203 if (typeof expectation.maxCalls != "number") {
2207 return expectation.callCount == expectation.maxCalls;
2214 create: function create(methodName) {
2215 var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
2216 delete expectation.create;
2217 expectation.method = methodName;
2222 invoke: function invoke(func, thisValue, args) {
2223 this.verifyCallAllowed(thisValue, args);
2225 return _invoke.apply(this, arguments);
2228 atLeast: function atLeast(num) {
2229 if (typeof num != "number") {
2230 throw new TypeError("'" + num + "' is not number");
2233 if (!this.limitsSet) {
2234 this.maxCalls = null;
2235 this.limitsSet = true;
2238 this.minCalls = num;
2243 atMost: function atMost(num) {
2244 if (typeof num != "number") {
2245 throw new TypeError("'" + num + "' is not number");
2248 if (!this.limitsSet) {
2249 this.minCalls = null;
2250 this.limitsSet = true;
2253 this.maxCalls = num;
2258 never: function never() {
2259 return this.exactly(0);
2262 once: function once() {
2263 return this.exactly(1);
2266 twice: function twice() {
2267 return this.exactly(2);
2270 thrice: function thrice() {
2271 return this.exactly(3);
2274 exactly: function exactly(num) {
2275 if (typeof num != "number") {
2276 throw new TypeError("'" + num + "' is not a number");
2280 return this.atMost(num);
2283 met: function met() {
2284 return !this.failed && receivedMinCalls(this);
2287 verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
2288 if (receivedMaxCalls(this)) {
2290 sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
2293 if ("expectedThis" in this && this.expectedThis !== thisValue) {
2294 sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
2298 if (!("expectedArguments" in this)) {
2303 sinon.expectation.fail(this.method + " received no arguments, expected " +
2304 sinon.format(this.expectedArguments));
2307 if (args.length < this.expectedArguments.length) {
2308 sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
2309 "), expected " + sinon.format(this.expectedArguments));
2312 if (this.expectsExactArgCount &&
2313 args.length != this.expectedArguments.length) {
2314 sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
2315 "), expected " + sinon.format(this.expectedArguments));
2318 for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
2319 if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
2320 sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
2321 ", expected " + sinon.format(this.expectedArguments));
2326 allowsCall: function allowsCall(thisValue, args) {
2327 if (this.met() && receivedMaxCalls(this)) {
2331 if ("expectedThis" in this && this.expectedThis !== thisValue) {
2335 if (!("expectedArguments" in this)) {
2341 if (args.length < this.expectedArguments.length) {
2345 if (this.expectsExactArgCount &&
2346 args.length != this.expectedArguments.length) {
2350 for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
2351 if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
2359 withArgs: function withArgs() {
2360 this.expectedArguments = slice.call(arguments);
2364 withExactArgs: function withExactArgs() {
2365 this.withArgs.apply(this, arguments);
2366 this.expectsExactArgCount = true;
2370 on: function on(thisValue) {
2371 this.expectedThis = thisValue;
2375 toString: function () {
2376 var args = (this.expectedArguments || []).slice();
2378 if (!this.expectsExactArgCount) {
2379 push.call(args, "[...]");
2382 var callStr = sinon.spyCall.toString.call({
2383 proxy: this.method || "anonymous mock expectation",
2387 var message = callStr.replace(", [...", "[, ...") + " " +
2388 expectedCallCountInWords(this);
2391 return "Expectation met: " + message;
2394 return "Expected " + message + " (" +
2395 callCountInWords(this.callCount) + ")";
2398 verify: function verify() {
2400 sinon.expectation.fail(this.toString());
2402 sinon.expectation.pass(this.toString());
2408 pass: function(message) {
2409 sinon.assert.pass(message);
2411 fail: function (message) {
2412 var exception = new Error(message);
2413 exception.name = "ExpectationError";
2420 if (commonJSModule) {
2421 module.exports = mock;
2425 }(typeof sinon == "object" && sinon || null));
2428 * @depend ../sinon.js
2432 /*jslint eqeqeq: false, onevar: false, forin: true*/
2433 /*global module, require, sinon*/
2435 * Collections of stubs, spies and mocks.
2437 * @author Christian Johansen (christian@cjohansen.no)
2440 * Copyright (c) 2010-2013 Christian Johansen
2444 var commonJSModule = typeof module == "object" && typeof require == "function";
2446 var hasOwnProperty = Object.prototype.hasOwnProperty;
2448 if (!sinon && commonJSModule) {
2449 sinon = require("../sinon");
2456 function getFakes(fakeCollection) {
2457 if (!fakeCollection.fakes) {
2458 fakeCollection.fakes = [];
2461 return fakeCollection.fakes;
2464 function each(fakeCollection, method) {
2465 var fakes = getFakes(fakeCollection);
2467 for (var i = 0, l = fakes.length; i < l; i += 1) {
2468 if (typeof fakes[i][method] == "function") {
2474 function compact(fakeCollection) {
2475 var fakes = getFakes(fakeCollection);
2477 while (i < fakes.length) {
2483 verify: function resolve() {
2484 each(this, "verify");
2487 restore: function restore() {
2488 each(this, "restore");
2492 verifyAndRestore: function verifyAndRestore() {
2508 add: function add(fake) {
2509 push.call(getFakes(this), fake);
2513 spy: function spy() {
2514 return this.add(sinon.spy.apply(sinon, arguments));
2517 stub: function stub(object, property, value) {
2519 var original = object[property];
2521 if (typeof original != "function") {
2522 if (!hasOwnProperty.call(object, property)) {
2523 throw new TypeError("Cannot stub non-existent own property " + property);
2526 object[property] = value;
2529 restore: function () {
2530 object[property] = original;
2535 if (!property && !!object && typeof object == "object") {
2536 var stubbedObj = sinon.stub.apply(sinon, arguments);
2538 for (var prop in stubbedObj) {
2539 if (typeof stubbedObj[prop] === "function") {
2540 this.add(stubbedObj[prop]);
2547 return this.add(sinon.stub.apply(sinon, arguments));
2550 mock: function mock() {
2551 return this.add(sinon.mock.apply(sinon, arguments));
2554 inject: function inject(obj) {
2557 obj.spy = function () {
2558 return col.spy.apply(col, arguments);
2561 obj.stub = function () {
2562 return col.stub.apply(col, arguments);
2565 obj.mock = function () {
2566 return col.mock.apply(col, arguments);
2573 if (commonJSModule) {
2574 module.exports = collection;
2576 sinon.collection = collection;
2578 }(typeof sinon == "object" && sinon || null));
2580 /*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
2581 /*global module, require, window*/
2592 * Inspired by jsUnitMockTimeOut from JsUnit
2594 * @author Christian Johansen (christian@cjohansen.no)
2597 * Copyright (c) 2010-2013 Christian Johansen
2600 if (typeof sinon == "undefined") {
2604 (function (global) {
2607 function addTimer(args, recurring) {
2608 if (args.length === 0) {
2609 throw new Error("Function requires at least 1 parameter");
2613 var delay = args[1] || 0;
2615 if (!this.timeouts) {
2619 this.timeouts[toId] = {
2622 callAt: this.now + delay,
2623 invokeArgs: Array.prototype.slice.call(args, 2)
2626 if (recurring === true) {
2627 this.timeouts[toId].interval = delay;
2633 function parseTime(str) {
2638 var strings = str.split(":");
2639 var l = strings.length, i = l;
2642 if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
2643 throw new Error("tick only understands numbers and 'h:m:s'");
2647 parsed = parseInt(strings[i], 10);
2650 throw new Error("Invalid time " + str);
2653 ms += parsed * Math.pow(60, (l - i - 1));
2659 function createObject(object) {
2662 if (Object.create) {
2663 newObject = Object.create(object);
2665 var F = function () {};
2666 F.prototype = object;
2667 newObject = new F();
2670 newObject.Date.clock = newObject;
2677 create: function create(now) {
2678 var clock = createObject(this);
2680 if (typeof now == "number") {
2684 if (!!now && typeof now == "object") {
2685 throw new TypeError("now should be milliseconds since UNIX epoch");
2691 setTimeout: function setTimeout(callback, timeout) {
2692 return addTimer.call(this, arguments, false);
2695 clearTimeout: function clearTimeout(timerId) {
2696 if (!this.timeouts) {
2700 if (timerId in this.timeouts) {
2701 delete this.timeouts[timerId];
2705 setInterval: function setInterval(callback, timeout) {
2706 return addTimer.call(this, arguments, true);
2709 clearInterval: function clearInterval(timerId) {
2710 this.clearTimeout(timerId);
2713 tick: function tick(ms) {
2714 ms = typeof ms == "number" ? ms : parseTime(ms);
2715 var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
2716 var timer = this.firstTimerInRange(tickFrom, tickTo);
2719 while (timer && tickFrom <= tickTo) {
2720 if (this.timeouts[timer.id]) {
2721 tickFrom = this.now = timer.callAt;
2723 this.callTimer(timer);
2725 firstException = firstException || e;
2729 timer = this.firstTimerInRange(previous, tickTo);
2730 previous = tickFrom;
2735 if (firstException) {
2736 throw firstException;
2742 firstTimerInRange: function (from, to) {
2743 var timer, smallest, originalTimer;
2745 for (var id in this.timeouts) {
2746 if (this.timeouts.hasOwnProperty(id)) {
2747 if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
2751 if (!smallest || this.timeouts[id].callAt < smallest) {
2752 originalTimer = this.timeouts[id];
2753 smallest = this.timeouts[id].callAt;
2756 func: this.timeouts[id].func,
2757 callAt: this.timeouts[id].callAt,
2758 interval: this.timeouts[id].interval,
2759 id: this.timeouts[id].id,
2760 invokeArgs: this.timeouts[id].invokeArgs
2766 return timer || null;
2769 callTimer: function (timer) {
2770 if (typeof timer.interval == "number") {
2771 this.timeouts[timer.id].callAt += timer.interval;
2773 delete this.timeouts[timer.id];
2777 if (typeof timer.func == "function") {
2778 timer.func.apply(null, timer.invokeArgs);
2786 if (!this.timeouts[timer.id]) {
2798 reset: function reset() {
2802 Date: (function () {
2803 var NativeDate = Date;
2805 function ClockDate(year, month, date, hour, minute, second, ms) {
2806 // Defensive and verbose to avoid potential harm in passing
2807 // explicit undefined when user does not pass argument
2808 switch (arguments.length) {
2810 return new NativeDate(ClockDate.clock.now);
2812 return new NativeDate(year);
2814 return new NativeDate(year, month);
2816 return new NativeDate(year, month, date);
2818 return new NativeDate(year, month, date, hour);
2820 return new NativeDate(year, month, date, hour, minute);
2822 return new NativeDate(year, month, date, hour, minute, second);
2824 return new NativeDate(year, month, date, hour, minute, second, ms);
2828 return mirrorDateProperties(ClockDate, NativeDate);
2832 function mirrorDateProperties(target, source) {
2834 target.now = function now() {
2835 return target.clock.now;
2841 if (source.toSource) {
2842 target.toSource = function toSource() {
2843 return source.toSource();
2846 delete target.toSource;
2849 target.toString = function toString() {
2850 return source.toString();
2853 target.prototype = source.prototype;
2854 target.parse = source.parse;
2855 target.UTC = source.UTC;
2856 target.prototype.toUTCString = source.prototype.toUTCString;
2860 var methods = ["Date", "setTimeout", "setInterval",
2861 "clearTimeout", "clearInterval"];
2863 function restore() {
2866 for (var i = 0, l = this.methods.length; i < l; i++) {
2867 method = this.methods[i];
2868 if (global[method].hadOwnProperty) {
2869 global[method] = this["_" + method];
2871 delete global[method];
2875 // Prevent multiple executions which will completely remove these props
2879 function stubGlobal(method, clock) {
2880 clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
2881 clock["_" + method] = global[method];
2883 if (method == "Date") {
2884 var date = mirrorDateProperties(clock[method], global[method]);
2885 global[method] = date;
2887 global[method] = function () {
2888 return clock[method].apply(clock, arguments);
2891 for (var prop in clock[method]) {
2892 if (clock[method].hasOwnProperty(prop)) {
2893 global[method][prop] = clock[method][prop];
2898 global[method].clock = clock;
2901 sinon.useFakeTimers = function useFakeTimers(now) {
2902 var clock = sinon.clock.create(now);
2903 clock.restore = restore;
2904 clock.methods = Array.prototype.slice.call(arguments,
2905 typeof now == "number" ? 1 : 0);
2907 if (clock.methods.length === 0) {
2908 clock.methods = methods;
2911 for (var i = 0, l = clock.methods.length; i < l; i++) {
2912 stubGlobal(clock.methods[i], clock);
2917 }(typeof global != "undefined" && typeof global !== "function" ? global : this));
2920 setTimeout: setTimeout,
2921 clearTimeout: clearTimeout,
2922 setInterval: setInterval,
2923 clearInterval: clearInterval,
2927 if (typeof module == "object" && typeof require == "function") {
2928 module.exports = sinon;
2931 /*jslint eqeqeq: false, onevar: false*/
2932 /*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
2934 * Minimal Event interface implementation
2936 * Original implementation by Sven Fuchs: https://gist.github.com/995028
2937 * Modifications and tests by Christian Johansen.
2939 * @author Sven Fuchs (svenfuchs@artweb-design.de)
2940 * @author Christian Johansen (christian@cjohansen.no)
2943 * Copyright (c) 2011 Sven Fuchs, Christian Johansen
2946 if (typeof sinon == "undefined") {
2953 sinon.Event = function Event(type, bubbles, cancelable, target) {
2954 this.initEvent(type, bubbles, cancelable, target);
2957 sinon.Event.prototype = {
2958 initEvent: function(type, bubbles, cancelable, target) {
2960 this.bubbles = bubbles;
2961 this.cancelable = cancelable;
2962 this.target = target;
2965 stopPropagation: function () {},
2967 preventDefault: function () {
2968 this.defaultPrevented = true;
2972 sinon.EventTarget = {
2973 addEventListener: function addEventListener(event, listener, useCapture) {
2974 this.eventListeners = this.eventListeners || {};
2975 this.eventListeners[event] = this.eventListeners[event] || [];
2976 push.call(this.eventListeners[event], listener);
2979 removeEventListener: function removeEventListener(event, listener, useCapture) {
2980 var listeners = this.eventListeners && this.eventListeners[event] || [];
2982 for (var i = 0, l = listeners.length; i < l; ++i) {
2983 if (listeners[i] == listener) {
2984 return listeners.splice(i, 1);
2989 dispatchEvent: function dispatchEvent(event) {
2990 var type = event.type;
2991 var listeners = this.eventListeners && this.eventListeners[type] || [];
2993 for (var i = 0; i < listeners.length; i++) {
2994 if (typeof listeners[i] == "function") {
2995 listeners[i].call(this, event);
2997 listeners[i].handleEvent(event);
3001 return !!event.defaultPrevented;
3007 * @depend ../../sinon.js
3010 /*jslint eqeqeq: false, onevar: false*/
3011 /*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
3013 * Fake XMLHttpRequest object
3015 * @author Christian Johansen (christian@cjohansen.no)
3018 * Copyright (c) 2010-2013 Christian Johansen
3021 if (typeof sinon == "undefined") {
3024 sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
3026 // wrapper for global
3028 var xhr = sinon.xhr;
3029 xhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
3030 xhr.GlobalActiveXObject = global.ActiveXObject;
3031 xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != "undefined";
3032 xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != "undefined";
3033 xhr.workingXHR = xhr.supportsXHR ? xhr.GlobalXMLHttpRequest : xhr.supportsActiveX
3034 ? function() { return new xhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
3037 var unsafeHeaders = {
3038 "Accept-Charset": true,
3039 "Accept-Encoding": true,
3041 "Content-Length": true,
3044 "Content-Transfer-Encoding": true,
3052 "Transfer-Encoding": true,
3059 function FakeXMLHttpRequest() {
3060 this.readyState = FakeXMLHttpRequest.UNSENT;
3061 this.requestHeaders = {};
3062 this.requestBody = null;
3064 this.statusText = "";
3067 var events = ["loadstart", "load", "abort", "loadend"];
3069 function addEventListener(eventName) {
3070 xhr.addEventListener(eventName, function (event) {
3071 var listener = xhr["on" + eventName];
3073 if (listener && typeof listener == "function") {
3079 for (var i = events.length - 1; i >= 0; i--) {
3080 addEventListener(events[i]);
3083 if (typeof FakeXMLHttpRequest.onCreate == "function") {
3084 FakeXMLHttpRequest.onCreate(this);
3088 function verifyState(xhr) {
3089 if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
3090 throw new Error("INVALID_STATE_ERR");
3094 throw new Error("INVALID_STATE_ERR");
3098 // filtering to enable a white-list version of Sinon FakeXhr,
3099 // where whitelisted requests are passed through to real XHR
3100 function each(collection, callback) {
3101 if (!collection) return;
3102 for (var i = 0, l = collection.length; i < l; i += 1) {
3103 callback(collection[i]);
3106 function some(collection, callback) {
3107 for (var index = 0; index < collection.length; index++) {
3108 if(callback(collection[index]) === true) return true;
3112 // largest arity in XHR is 5 - XHR#open
3113 var apply = function(obj,method,args) {
3114 switch(args.length) {
3115 case 0: return obj[method]();
3116 case 1: return obj[method](args[0]);
3117 case 2: return obj[method](args[0],args[1]);
3118 case 3: return obj[method](args[0],args[1],args[2]);
3119 case 4: return obj[method](args[0],args[1],args[2],args[3]);
3120 case 5: return obj[method](args[0],args[1],args[2],args[3],args[4]);
3124 FakeXMLHttpRequest.filters = [];
3125 FakeXMLHttpRequest.addFilter = function(fn) {
3126 this.filters.push(fn)
3128 var IE6Re = /MSIE 6/;
3129 FakeXMLHttpRequest.defake = function(fakeXhr,xhrArgs) {
3130 var xhr = new sinon.xhr.workingXHR();
3131 each(["open","setRequestHeader","send","abort","getResponseHeader",
3132 "getAllResponseHeaders","addEventListener","overrideMimeType","removeEventListener"],
3134 fakeXhr[method] = function() {
3135 return apply(xhr,method,arguments);
3139 var copyAttrs = function(args) {
3140 each(args, function(attr) {
3142 fakeXhr[attr] = xhr[attr]
3144 if(!IE6Re.test(navigator.userAgent)) throw e;
3149 var stateChange = function() {
3150 fakeXhr.readyState = xhr.readyState;
3151 if(xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
3152 copyAttrs(["status","statusText"]);
3154 if(xhr.readyState >= FakeXMLHttpRequest.LOADING) {
3155 copyAttrs(["responseText"]);
3157 if(xhr.readyState === FakeXMLHttpRequest.DONE) {
3158 copyAttrs(["responseXML"]);
3160 if(fakeXhr.onreadystatechange) fakeXhr.onreadystatechange.call(fakeXhr);
3162 if(xhr.addEventListener) {
3163 for(var event in fakeXhr.eventListeners) {
3164 if(fakeXhr.eventListeners.hasOwnProperty(event)) {
3165 each(fakeXhr.eventListeners[event],function(handler) {
3166 xhr.addEventListener(event, handler);
3170 xhr.addEventListener("readystatechange",stateChange);
3172 xhr.onreadystatechange = stateChange;
3174 apply(xhr,"open",xhrArgs);
3176 FakeXMLHttpRequest.useFilters = false;
3178 function verifyRequestSent(xhr) {
3179 if (xhr.readyState == FakeXMLHttpRequest.DONE) {
3180 throw new Error("Request done");
3184 function verifyHeadersReceived(xhr) {
3185 if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
3186 throw new Error("No headers received");
3190 function verifyResponseBodyType(body) {
3191 if (typeof body != "string") {
3192 var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
3193 body + ", which is not a string.");
3194 error.name = "InvalidBodyException";
3199 sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
3202 open: function open(method, url, async, username, password) {
3203 this.method = method;
3205 this.async = typeof async == "boolean" ? async : true;
3206 this.username = username;
3207 this.password = password;
3208 this.responseText = null;
3209 this.responseXML = null;
3210 this.requestHeaders = {};
3211 this.sendFlag = false;
3212 if(sinon.FakeXMLHttpRequest.useFilters === true) {
3213 var xhrArgs = arguments;
3214 var defake = some(FakeXMLHttpRequest.filters,function(filter) {
3215 return filter.apply(this,xhrArgs)
3218 return sinon.FakeXMLHttpRequest.defake(this,arguments);
3221 this.readyStateChange(FakeXMLHttpRequest.OPENED);
3224 readyStateChange: function readyStateChange(state) {
3225 this.readyState = state;
3227 if (typeof this.onreadystatechange == "function") {
3229 this.onreadystatechange();
3231 sinon.logError("Fake XHR onreadystatechange handler", e);
3235 this.dispatchEvent(new sinon.Event("readystatechange"));
3237 switch (this.readyState) {
3238 case FakeXMLHttpRequest.DONE:
3239 this.dispatchEvent(new sinon.Event("load", false, false, this));
3240 this.dispatchEvent(new sinon.Event("loadend", false, false, this));
3245 setRequestHeader: function setRequestHeader(header, value) {
3248 if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
3249 throw new Error("Refused to set unsafe header \"" + header + "\"");
3252 if (this.requestHeaders[header]) {
3253 this.requestHeaders[header] += "," + value;
3255 this.requestHeaders[header] = value;
3260 setResponseHeaders: function setResponseHeaders(headers) {
3261 this.responseHeaders = {};
3263 for (var header in headers) {
3264 if (headers.hasOwnProperty(header)) {
3265 this.responseHeaders[header] = headers[header];
3270 this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
3272 this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
3276 // Currently treats ALL data as a DOMString (i.e. no Document)
3277 send: function send(data) {
3280 if (!/^(get|head)$/i.test(this.method)) {
3281 if (this.requestHeaders["Content-Type"]) {
3282 var value = this.requestHeaders["Content-Type"].split(";");
3283 this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
3285 this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
3288 this.requestBody = data;
3291 this.errorFlag = false;
3292 this.sendFlag = this.async;
3293 this.readyStateChange(FakeXMLHttpRequest.OPENED);
3295 if (typeof this.onSend == "function") {
3299 this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
3302 abort: function abort() {
3303 this.aborted = true;
3304 this.responseText = null;
3305 this.errorFlag = true;
3306 this.requestHeaders = {};
3308 if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
3309 this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
3310 this.sendFlag = false;
3313 this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
3315 this.dispatchEvent(new sinon.Event("abort", false, false, this));
3316 if (typeof this.onerror === "function") {
3321 getResponseHeader: function getResponseHeader(header) {
3322 if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
3326 if (/^Set-Cookie2?$/i.test(header)) {
3330 header = header.toLowerCase();
3332 for (var h in this.responseHeaders) {
3333 if (h.toLowerCase() == header) {
3334 return this.responseHeaders[h];
3341 getAllResponseHeaders: function getAllResponseHeaders() {
3342 if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
3348 for (var header in this.responseHeaders) {
3349 if (this.responseHeaders.hasOwnProperty(header) &&
3350 !/^Set-Cookie2?$/i.test(header)) {
3351 headers += header + ": " + this.responseHeaders[header] + "\r\n";
3358 setResponseBody: function setResponseBody(body) {
3359 verifyRequestSent(this);
3360 verifyHeadersReceived(this);
3361 verifyResponseBodyType(body);
3363 var chunkSize = this.chunkSize || 10;
3365 this.responseText = "";
3369 this.readyStateChange(FakeXMLHttpRequest.LOADING);
3372 this.responseText += body.substring(index, index + chunkSize);
3374 } while (index < body.length);
3376 var type = this.getResponseHeader("Content-Type");
3378 if (this.responseText &&
3379 (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
3381 this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
3383 // Unable to parse XML - no biggie
3388 this.readyStateChange(FakeXMLHttpRequest.DONE);
3390 this.readyState = FakeXMLHttpRequest.DONE;
3394 respond: function respond(status, headers, body) {
3395 this.setResponseHeaders(headers || {});
3396 this.status = typeof status == "number" ? status : 200;
3397 this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
3398 this.setResponseBody(body || "");
3399 if (typeof this.onload === "function"){
3406 sinon.extend(FakeXMLHttpRequest, {
3409 HEADERS_RECEIVED: 2,
3414 // Borrowed from JSpec
3415 FakeXMLHttpRequest.parseXML = function parseXML(text) {
3418 if (typeof DOMParser != "undefined") {
3419 var parser = new DOMParser();
3420 xmlDoc = parser.parseFromString(text, "text/xml");
3422 xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
3423 xmlDoc.async = "false";
3424 xmlDoc.loadXML(text);
3430 FakeXMLHttpRequest.statusCodes = {
3432 101: "Switching Protocols",
3436 203: "Non-Authoritative Information",
3438 205: "Reset Content",
3439 206: "Partial Content",
3440 300: "Multiple Choice",
3441 301: "Moved Permanently",
3444 304: "Not Modified",
3446 307: "Temporary Redirect",
3448 401: "Unauthorized",
3449 402: "Payment Required",
3452 405: "Method Not Allowed",
3453 406: "Not Acceptable",
3454 407: "Proxy Authentication Required",
3455 408: "Request Timeout",
3458 411: "Length Required",
3459 412: "Precondition Failed",
3460 413: "Request Entity Too Large",
3461 414: "Request-URI Too Long",
3462 415: "Unsupported Media Type",
3463 416: "Requested Range Not Satisfiable",
3464 417: "Expectation Failed",
3465 422: "Unprocessable Entity",
3466 500: "Internal Server Error",
3467 501: "Not Implemented",
3469 503: "Service Unavailable",
3470 504: "Gateway Timeout",
3471 505: "HTTP Version Not Supported"
3474 sinon.useFakeXMLHttpRequest = function () {
3475 sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
3476 if (xhr.supportsXHR) {
3477 global.XMLHttpRequest = xhr.GlobalXMLHttpRequest;
3480 if (xhr.supportsActiveX) {
3481 global.ActiveXObject = xhr.GlobalActiveXObject;
3484 delete sinon.FakeXMLHttpRequest.restore;
3486 if (keepOnCreate !== true) {
3487 delete sinon.FakeXMLHttpRequest.onCreate;
3490 if (xhr.supportsXHR) {
3491 global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
3494 if (xhr.supportsActiveX) {
3495 global.ActiveXObject = function ActiveXObject(objId) {
3496 if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
3498 return new sinon.FakeXMLHttpRequest();
3501 return new xhr.GlobalActiveXObject(objId);
3505 return sinon.FakeXMLHttpRequest;
3508 sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
3511 if (typeof module == "object" && typeof require == "function") {
3512 module.exports = sinon;
3516 * @depend fake_xml_http_request.js
3518 /*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
3519 /*global module, require, window*/
3521 * The Sinon "server" mimics a web server that receives requests from
3522 * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
3523 * both synchronously and asynchronously. To respond synchronuously, canned
3524 * answers have to be provided upfront.
3526 * @author Christian Johansen (christian@cjohansen.no)
3529 * Copyright (c) 2010-2013 Christian Johansen
3532 if (typeof sinon == "undefined") {
3536 sinon.fakeServer = (function () {
3540 function create(proto) {
3541 F.prototype = proto;
3545 function responseArray(handler) {
3546 var response = handler;
3548 if (Object.prototype.toString.call(handler) != "[object Array]") {
3549 response = [200, {}, handler];
3552 if (typeof response[2] != "string") {
3553 throw new TypeError("Fake server response body should be string, but was " +
3554 typeof response[2]);
3560 var wloc = typeof window !== "undefined" ? window.location : {};
3561 var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
3563 function matchOne(response, reqMethod, reqUrl) {
3564 var rmeth = response.method;
3565 var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
3566 var url = response.url;
3567 var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
3569 return matchMethod && matchUrl;
3572 function match(response, request) {
3573 var requestMethod = this.getHTTPMethod(request);
3574 var requestUrl = request.url;
3576 if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
3577 requestUrl = requestUrl.replace(rCurrLoc, "");
3580 if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
3581 if (typeof response.response == "function") {
3582 var ru = response.url;
3583 var args = [request].concat(!ru ? [] : requestUrl.match(ru).slice(1));
3584 return response.response.apply(response, args);
3593 function log(response, request) {
3596 str = "Request:\n" + sinon.format(request) + "\n\n";
3597 str += "Response:\n" + sinon.format(response) + "\n\n";
3603 create: function () {
3604 var server = create(this);
3605 this.xhr = sinon.useFakeXMLHttpRequest();
3606 server.requests = [];
3608 this.xhr.onCreate = function (xhrObj) {
3609 server.addRequest(xhrObj);
3615 addRequest: function addRequest(xhrObj) {
3617 push.call(this.requests, xhrObj);
3619 xhrObj.onSend = function () {
3620 server.handleRequest(this);
3623 if (this.autoRespond && !this.responding) {
3624 setTimeout(function () {
3625 server.responding = false;
3627 }, this.autoRespondAfter || 10);
3629 this.responding = true;
3633 getHTTPMethod: function getHTTPMethod(request) {
3634 if (this.fakeHTTPMethods && /post/i.test(request.method)) {
3635 var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
3636 return !!matches ? matches[1] : request.method;
3639 return request.method;
3642 handleRequest: function handleRequest(xhr) {
3648 push.call(this.queue, xhr);
3650 this.processRequest(xhr);
3654 respondWith: function respondWith(method, url, body) {
3655 if (arguments.length == 1 && typeof method != "function") {
3656 this.response = responseArray(method);
3660 if (!this.responses) { this.responses = []; }
3662 if (arguments.length == 1) {
3664 url = method = null;
3667 if (arguments.length == 2) {
3673 push.call(this.responses, {
3676 response: typeof body == "function" ? body : responseArray(body)
3680 respond: function respond() {
3681 if (arguments.length > 0) this.respondWith.apply(this, arguments);
3682 var queue = this.queue || [];
3685 while(request = queue.shift()) {
3686 this.processRequest(request);
3690 processRequest: function processRequest(request) {
3692 if (request.aborted) {
3696 var response = this.response || [404, {}, ""];
3698 if (this.responses) {
3699 for (var i = 0, l = this.responses.length; i < l; i++) {
3700 if (match.call(this, this.responses[i], request)) {
3701 response = this.responses[i].response;
3707 if (request.readyState != 4) {
3708 log(response, request);
3710 request.respond(response[0], response[1], response[2]);
3713 sinon.logError("Fake server request processing", e);
3717 restore: function restore() {
3718 return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
3723 if (typeof module == "object" && typeof require == "function") {
3724 module.exports = sinon;
3728 * @depend fake_server.js
3729 * @depend fake_timers.js
3731 /*jslint browser: true, eqeqeq: false, onevar: false*/
3734 * Add-on for sinon.fakeServer that automatically handles a fake timer along with
3735 * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
3736 * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
3737 * it polls the object for completion with setInterval. Dispite the direct
3738 * motivation, there is nothing jQuery-specific in this file, so it can be used
3739 * in any environment where the ajax implementation depends on setInterval or
3742 * @author Christian Johansen (christian@cjohansen.no)
3745 * Copyright (c) 2010-2013 Christian Johansen
3749 function Server() {}
3750 Server.prototype = sinon.fakeServer;
3752 sinon.fakeServerWithClock = new Server();
3754 sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
3756 if (typeof setTimeout.clock == "object") {
3757 this.clock = setTimeout.clock;
3759 this.clock = sinon.useFakeTimers();
3760 this.resetClock = true;
3763 if (!this.longestTimeout) {
3764 var clockSetTimeout = this.clock.setTimeout;
3765 var clockSetInterval = this.clock.setInterval;
3768 this.clock.setTimeout = function (fn, timeout) {
3769 server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
3771 return clockSetTimeout.apply(this, arguments);
3774 this.clock.setInterval = function (fn, timeout) {
3775 server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
3777 return clockSetInterval.apply(this, arguments);
3782 return sinon.fakeServer.addRequest.call(this, xhr);
3785 sinon.fakeServerWithClock.respond = function respond() {
3786 var returnVal = sinon.fakeServer.respond.apply(this, arguments);
3789 this.clock.tick(this.longestTimeout || 0);
3790 this.longestTimeout = 0;
3792 if (this.resetClock) {
3793 this.clock.restore();
3794 this.resetClock = false;
3801 sinon.fakeServerWithClock.restore = function restore() {
3803 this.clock.restore();
3806 return sinon.fakeServer.restore.apply(this, arguments);
3811 * @depend ../sinon.js
3812 * @depend collection.js
3813 * @depend util/fake_timers.js
3814 * @depend util/fake_server_with_clock.js
3816 /*jslint eqeqeq: false, onevar: false, plusplus: false*/
3817 /*global require, module*/
3819 * Manages fake collections as well as fake utilities such as Sinon's
3820 * timers and fake XHR implementation in one convenient object.
3822 * @author Christian Johansen (christian@cjohansen.no)
3825 * Copyright (c) 2010-2013 Christian Johansen
3828 if (typeof module == "object" && typeof require == "function") {
3829 var sinon = require("../sinon");
3830 sinon.extend(sinon, require("./util/fake_timers"));
3836 function exposeValue(sandbox, config, key, value) {
3841 if (config.injectInto) {
3842 config.injectInto[key] = value;
3844 push.call(sandbox.args, value);
3848 function prepareSandboxFromConfig(config) {
3849 var sandbox = sinon.create(sinon.sandbox);
3851 if (config.useFakeServer) {
3852 if (typeof config.useFakeServer == "object") {
3853 sandbox.serverPrototype = config.useFakeServer;
3856 sandbox.useFakeServer();
3859 if (config.useFakeTimers) {
3860 if (typeof config.useFakeTimers == "object") {
3861 sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
3863 sandbox.useFakeTimers();
3870 sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
3871 useFakeTimers: function useFakeTimers() {
3872 this.clock = sinon.useFakeTimers.apply(sinon, arguments);
3874 return this.add(this.clock);
3877 serverPrototype: sinon.fakeServer,
3879 useFakeServer: function useFakeServer() {
3880 var proto = this.serverPrototype || sinon.fakeServer;
3882 if (!proto || !proto.create) {
3886 this.server = proto.create();
3887 return this.add(this.server);
3890 inject: function (obj) {
3891 sinon.collection.inject.call(this, obj);
3894 obj.clock = this.clock;
3898 obj.server = this.server;
3899 obj.requests = this.server.requests;
3905 create: function (config) {
3907 return sinon.create(sinon.sandbox);
3910 var sandbox = prepareSandboxFromConfig(config);
3911 sandbox.args = sandbox.args || [];
3912 var prop, value, exposed = sandbox.inject({});
3914 if (config.properties) {
3915 for (var i = 0, l = config.properties.length; i < l; i++) {
3916 prop = config.properties[i];
3917 value = exposed[prop] || prop == "sandbox" && sandbox;
3918 exposeValue(sandbox, config, prop, value);
3921 exposeValue(sandbox, config, "sandbox", value);
3928 sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
3930 if (typeof module == "object" && typeof require == "function") {
3931 module.exports = sinon.sandbox;
3936 * @depend ../sinon.js
3939 * @depend sandbox.js
3941 /*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
3942 /*global module, require, sinon*/
3944 * Test function, sandboxes fakes
3946 * @author Christian Johansen (christian@cjohansen.no)
3949 * Copyright (c) 2010-2013 Christian Johansen
3953 var commonJSModule = typeof module == "object" && typeof require == "function";
3955 if (!sinon && commonJSModule) {
3956 sinon = require("../sinon");
3963 function test(callback) {
3964 var type = typeof callback;
3966 if (type != "function") {
3967 throw new TypeError("sinon.test needs to wrap a test function, got " + type);
3970 return function () {
3971 var config = sinon.getConfig(sinon.config);
3972 config.injectInto = config.injectIntoThis && this || config.injectInto;
3973 var sandbox = sinon.sandbox.create(config);
3974 var exception, result;
3975 var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
3978 result = callback.apply(this, args);
3983 if (typeof exception !== "undefined") {
3988 sandbox.verifyAndRestore();
3996 injectIntoThis: true,
3998 properties: ["spy", "stub", "mock", "clock", "server", "requests"],
3999 useFakeTimers: true,
4003 if (commonJSModule) {
4004 module.exports = test;
4008 }(typeof sinon == "object" && sinon || null));
4011 * @depend ../sinon.js
4014 /*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
4015 /*global module, require, sinon*/
4017 * Test case, sandboxes all test functions
4019 * @author Christian Johansen (christian@cjohansen.no)
4022 * Copyright (c) 2010-2013 Christian Johansen
4026 var commonJSModule = typeof module == "object" && typeof require == "function";
4028 if (!sinon && commonJSModule) {
4029 sinon = require("../sinon");
4032 if (!sinon || !Object.prototype.hasOwnProperty) {
4036 function createTest(property, setUp, tearDown) {
4037 return function () {
4039 setUp.apply(this, arguments);
4042 var exception, result;
4045 result = property.apply(this, arguments);
4051 tearDown.apply(this, arguments);
4062 function testCase(tests, prefix) {
4064 if (!tests || typeof tests != "object") {
4065 throw new TypeError("sinon.testCase needs an object with test functions");
4069 prefix = prefix || "test";
4070 var rPrefix = new RegExp("^" + prefix);
4071 var methods = {}, testName, property, method;
4072 var setUp = tests.setUp;
4073 var tearDown = tests.tearDown;
4075 for (testName in tests) {
4076 if (tests.hasOwnProperty(testName)) {
4077 property = tests[testName];
4079 if (/^(setUp|tearDown)$/.test(testName)) {
4083 if (typeof property == "function" && rPrefix.test(testName)) {
4086 if (setUp || tearDown) {
4087 method = createTest(property, setUp, tearDown);
4090 methods[testName] = sinon.test(method);
4092 methods[testName] = tests[testName];
4100 if (commonJSModule) {
4101 module.exports = testCase;
4103 sinon.testCase = testCase;
4105 }(typeof sinon == "object" && sinon || null));
4108 * @depend ../sinon.js
4111 /*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
4112 /*global module, require, sinon*/
4114 * Assertions matching the test spy retrieval interface.
4116 * @author Christian Johansen (christian@cjohansen.no)
4119 * Copyright (c) 2010-2013 Christian Johansen
4122 (function (sinon, global) {
4123 var commonJSModule = typeof module == "object" && typeof require == "function";
4124 var slice = Array.prototype.slice;
4127 if (!sinon && commonJSModule) {
4128 sinon = require("../sinon");
4135 function verifyIsStub() {
4138 for (var i = 0, l = arguments.length; i < l; ++i) {
4139 method = arguments[i];
4142 assert.fail("fake is not a spy");
4145 if (typeof method != "function") {
4146 assert.fail(method + " is not a function");
4149 if (typeof method.getCall != "function") {
4150 assert.fail(method + " is not stubbed");
4155 function failAssertion(object, msg) {
4156 object = object || global;
4157 var failMethod = object.fail || assert.fail;
4158 failMethod.call(object, msg);
4161 function mirrorPropAsAssertion(name, method, message) {
4162 if (arguments.length == 2) {
4167 assert[name] = function (fake) {
4170 var args = slice.call(arguments, 1);
4173 if (typeof method == "function") {
4174 failed = !method(fake);
4176 failed = typeof fake[method] == "function" ?
4177 !fake[method].apply(fake, args) : !fake[method];
4181 failAssertion(this, fake.printf.apply(fake, [message].concat(args)));
4188 function exposedName(prefix, prop) {
4189 return !prefix || /^fail/.test(prop) ? prop :
4190 prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
4194 failException: "AssertError",
4196 fail: function fail(message) {
4197 var error = new Error(message);
4198 error.name = this.failException || assert.failException;
4203 pass: function pass(assertion) {},
4205 callOrder: function assertCallOrder() {
4206 verifyIsStub.apply(null, arguments);
4207 var expected = "", actual = "";
4209 if (!sinon.calledInOrder(arguments)) {
4211 expected = [].join.call(arguments, ", ");
4212 var calls = slice.call(arguments);
4213 var i = calls.length;
4215 if (!calls[--i].called) {
4219 actual = sinon.orderByFirstCall(calls).join(", ");
4221 // If this fails, we'll just fall back to the blank string
4224 failAssertion(this, "expected " + expected + " to be " +
4225 "called in order but were called as " + actual);
4227 assert.pass("callOrder");
4231 callCount: function assertCallCount(method, count) {
4232 verifyIsStub(method);
4234 if (method.callCount != count) {
4235 var msg = "expected %n to be called " + sinon.timesInWords(count) +
4236 " but was called %c%C";
4237 failAssertion(this, method.printf(msg));
4239 assert.pass("callCount");
4243 expose: function expose(target, options) {
4245 throw new TypeError("target is null or undefined");
4248 var o = options || {};
4249 var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
4250 var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
4252 for (var method in this) {
4253 if (method != "export" && (includeFail || !/^(fail)/.test(method))) {
4254 target[exposedName(prefix, method)] = this[method];
4262 mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
4263 mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
4264 "expected %n to not have been called but was called %c%C");
4265 mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
4266 mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
4267 mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
4268 mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
4269 mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
4270 mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
4271 mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
4272 mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
4273 mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
4274 mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
4275 mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
4276 mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
4277 mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
4278 mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
4279 mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
4280 mirrorPropAsAssertion("threw", "%n did not throw exception%C");
4281 mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
4283 if (commonJSModule) {
4284 module.exports = assert;
4286 sinon.assert = assert;
4288 }(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
4290 return sinon;}.call(typeof window != 'undefined' && window || {}));