vendor/assets/javascripts/sinon.js in sinon-rails-1.3.2.1 vs vendor/assets/javascripts/sinon.js in sinon-rails-1.4.2
- old
+ new
@@ -1,13 +1,14 @@
/**
- * Sinon.JS 1.3.2, 2012/03/11
+ * Sinon.JS 1.4.2, 2012/07/11
*
* @author Christian Johansen (christian@cjohansen.no)
+ * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
*
* (The BSD License)
*
- * Copyright (c) 2010-2011, Christian Johansen, christian@cjohansen.no
+ * Copyright (c) 2010-2012, Christian Johansen, christian@cjohansen.no
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
@@ -32,112 +33,264 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
"use strict";
var sinon = (function () {
-var buster = (function (buster, setTimeout) {
- function extend(target) {
- if (!target) {
- return;
- }
-
- for (var i = 1, l = arguments.length, prop; i < l; ++i) {
- for (prop in arguments[i]) {
- target[prop] = arguments[i][prop];
- }
- }
-
- return target;
- }
-
+var buster = (function (setTimeout, B) {
+ var isNode = typeof require == "function" && typeof module == "object";
var div = typeof document != "undefined" && document.createElement("div");
+ var F = function () {};
- return extend(buster, {
- bind: function (obj, methOrProp) {
+ var buster = {
+ bind: function bind(obj, methOrProp) {
var method = typeof methOrProp == "string" ? obj[methOrProp] : methOrProp;
var args = Array.prototype.slice.call(arguments, 2);
-
return function () {
var allArgs = args.concat(Array.prototype.slice.call(arguments));
return method.apply(obj, allArgs);
};
},
- create: (function () {
- function F() {}
+ partial: function partial(fn) {
+ var args = [].slice.call(arguments, 1);
+ return function () {
+ return fn.apply(this, args.concat([].slice.call(arguments)));
+ };
+ },
- return function create(object) {
- F.prototype = object;
- return new F();
+ create: function create(object) {
+ F.prototype = object;
+ return new F();
+ },
+
+ extend: function extend(target) {
+ if (!target) { return; }
+ for (var i = 1, l = arguments.length, prop; i < l; ++i) {
+ for (prop in arguments[i]) {
+ target[prop] = arguments[i][prop];
+ }
}
- }()),
+ return target;
+ },
- extend: extend,
-
- nextTick: function (callback) {
+ nextTick: function nextTick(callback) {
if (typeof process != "undefined" && process.nextTick) {
return process.nextTick(callback);
}
-
setTimeout(callback, 0);
},
- functionName: function (func) {
+ functionName: function functionName(func) {
if (!func) return "";
if (func.displayName) return func.displayName;
if (func.name) return func.name;
-
var matches = func.toString().match(/function\s+([^\(]+)/m);
return matches && matches[1] || "";
},
- isNode: function (obj) {
+ isNode: function isNode(obj) {
if (!div) return false;
-
try {
obj.appendChild(div);
obj.removeChild(div);
} catch (e) {
return false;
}
-
return true;
},
- isElement: function (obj) {
- return obj && buster.isNode(obj) && obj.nodeType === 1;
- }
- });
-}(buster || {}, setTimeout));
+ isElement: function isElement(obj) {
+ return obj && obj.nodeType === 1 && buster.isNode(obj);
+ },
-if (typeof module == "object" && typeof require == "function") {
- module.exports = buster;
- buster.eventEmitter = require("./buster-event-emitter");
+ isArray: function isArray(arr) {
+ return Object.prototype.toString.call(arr) == "[object Array]";
+ },
- Object.defineProperty(buster, "defineVersionGetter", {
- get: function () {
- return require("./define-version-getter");
+ flatten: function flatten(arr) {
+ var result = [], arr = arr || [];
+ for (var i = 0, l = arr.length; i < l; ++i) {
+ result = result.concat(buster.isArray(arr[i]) ? flatten(arr[i]) : arr[i]);
+ }
+ return result;
+ },
+
+ each: function each(arr, callback) {
+ for (var i = 0, l = arr.length; i < l; ++i) {
+ callback(arr[i]);
+ }
+ },
+
+ map: function map(arr, callback) {
+ var results = [];
+ for (var i = 0, l = arr.length; i < l; ++i) {
+ results.push(callback(arr[i]));
+ }
+ return results;
+ },
+
+ parallel: function parallel(fns, callback) {
+ function cb(err, res) {
+ if (typeof callback == "function") {
+ callback(err, res);
+ callback = null;
+ }
+ }
+ if (fns.length == 0) { return cb(null, []); }
+ var remaining = fns.length, results = [];
+ function makeDone(num) {
+ return function done(err, result) {
+ if (err) { return cb(err); }
+ results[num] = result;
+ if (--remaining == 0) { cb(null, results); }
+ };
+ }
+ for (var i = 0, l = fns.length; i < l; ++i) {
+ fns[i](makeDone(i));
+ }
+ },
+
+ series: function series(fns, callback) {
+ function cb(err, res) {
+ if (typeof callback == "function") {
+ callback(err, res);
+ }
+ }
+ var remaining = fns.slice();
+ var results = [];
+ function callNext() {
+ if (remaining.length == 0) return cb(null, results);
+ var promise = remaining.shift()(next);
+ if (promise && typeof promise.then == "function") {
+ promise.then(buster.partial(next, null), next);
+ }
+ }
+ function next(err, result) {
+ if (err) return cb(err);
+ results.push(result);
+ callNext();
+ }
+ callNext();
+ },
+
+ countdown: function countdown(num, done) {
+ return function () {
+ if (--num == 0) done();
+ };
}
- });
-}
+ };
+ if (typeof process === "object" &&
+ typeof require === "function" && typeof module === "object") {
+ var crypto = require("crypto");
+ var path = require("path");
-if (typeof require != "undefined") {
+ buster.tmpFile = function (fileName) {
+ var hashed = crypto.createHash("sha1");
+ hashed.update(fileName);
+ var tmpfileName = hashed.digest("hex");
+
+ if (process.platform == "win32") {
+ return path.join(process.env["TEMP"], tmpfileName);
+ } else {
+ return path.join("/tmp", tmpfileName);
+ }
+ };
+ }
+
+ if (Array.prototype.some) {
+ buster.some = function (arr, fn, thisp) {
+ return arr.some(fn, thisp);
+ };
+ } else {
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
+ buster.some = function (arr, fun, thisp) {
+ if (arr == null) { throw new TypeError(); }
+ arr = Object(arr);
+ var len = arr.length >>> 0;
+ if (typeof fun !== "function") { throw new TypeError(); }
+
+ for (var i = 0; i < len; i++) {
+ if (arr.hasOwnProperty(i) && fun.call(thisp, arr[i], i, arr)) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+ }
+
+ if (Array.prototype.filter) {
+ buster.filter = function (arr, fn, thisp) {
+ return arr.filter(fn, thisp);
+ };
+ } else {
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
+ buster.filter = function (fn, thisp) {
+ if (this == null) { throw new TypeError(); }
+
+ var t = Object(this);
+ var len = t.length >>> 0;
+ if (typeof fn != "function") { throw new TypeError(); }
+
+ var res = [];
+ for (var i = 0; i < len; i++) {
+ if (i in t) {
+ var val = t[i]; // in case fun mutates this
+ if (fn.call(thisp, val, i, t)) { res.push(val); }
+ }
+ }
+
+ return res;
+ };
+ }
+
+ if (isNode) {
+ module.exports = buster;
+ buster.eventEmitter = require("./buster-event-emitter");
+ Object.defineProperty(buster, "defineVersionGetter", {
+ get: function () {
+ return require("./define-version-getter");
+ }
+ });
+ }
+
+ return buster.extend(B || {}, buster);
+}(setTimeout, buster));
+if (typeof buster === "undefined") {
+ var buster = {};
+}
+
+if (typeof module === "object" && typeof require === "function") {
buster = require("buster-core");
}
buster.format = buster.format || {};
buster.format.excludeConstructors = ["Object", /^.$/];
buster.format.quoteStrings = true;
buster.format.ascii = (function () {
+
+ var hasOwn = Object.prototype.hasOwnProperty;
+
+ var specialObjects = [];
+ if (typeof global != "undefined") {
+ specialObjects.push({ obj: global, value: "[object global]" });
+ }
+ if (typeof document != "undefined") {
+ specialObjects.push({ obj: document, value: "[object HTMLDocument]" });
+ }
+ if (typeof window != "undefined") {
+ specialObjects.push({ obj: window, value: "[object Window]" });
+ }
+
function keys(object) {
var k = Object.keys && Object.keys(object) || [];
if (k.length == 0) {
for (var prop in object) {
- if (object.hasOwnProperty(prop)) {
+ if (hasOwn.call(object, prop)) {
k.push(prop);
}
}
}
@@ -173,25 +326,32 @@
if (isCircular(object, processed)) {
return "[Circular]";
}
if (Object.prototype.toString.call(object) == "[object Array]") {
- return ascii.array(object);
+ return ascii.array.call(this, object, processed);
}
if (!object) {
return "" + object;
}
if (buster.isElement(object)) {
return ascii.element(object);
}
- if (object.toString !== Object.prototype.toString) {
+ if (typeof object.toString == "function" &&
+ object.toString !== Object.prototype.toString) {
return object.toString();
}
+ for (var i = 0, l = specialObjects.length; i < l; i++) {
+ if (object === specialObjects[i].obj) {
+ return specialObjects[i].value;
+ }
+ }
+
return ascii.object.call(this, object, processed, indent);
}
ascii.func = function (func) {
return "function " + buster.functionName(func) + "() {}";
@@ -201,11 +361,11 @@
processed = processed || [];
processed.push(array);
var pieces = [];
for (var i = 0, l = array.length; i < l; ++i) {
- pieces.push(ascii(array[i], processed));
+ pieces.push(ascii.call(this, array[i], processed));
}
return "[" + pieces.join(", ") + "]";
};
@@ -374,15 +534,19 @@
var owned = hasOwn.call(object, property);
object[property] = method;
method.displayName = property;
method.restore = function () {
- if(owned) {
- object[property] = wrappedMethod;
- } else {
+ // For prototype properties try to reset by delete first.
+ // If this fails (ex: localStorage on mobile safari) then force a reset
+ // via direct assignment.
+ if (!owned) {
delete object[property];
}
+ if (object[property] === method) {
+ object[property] = wrappedMethod;
+ }
};
method.restore.sinon = true;
mirrorProperties(method, wrappedMethod);
@@ -412,10 +576,13 @@
F.prototype = proto;
return new F();
},
deepEqual: function deepEqual(a, b) {
+ if (sinon.match && sinon.match.isMatcher(a)) {
+ return a.test(b);
+ }
if (typeof a != "object" || typeof b != "object") {
return a === b;
}
if (isElement(a) || isElement(b)) {
@@ -563,10 +730,18 @@
setTimeout(function () {
err.message = msg + err.message;
throw err;
}, 0);
+ },
+
+ typeOf: function (value) {
+ if (value === null) {
+ return "null";
+ }
+ var string = Object.prototype.toString.call(value);
+ return string.substring(8, string.length - 1).toLowerCase();
}
};
var isNode = typeof module == "object" && typeof require == "function";
@@ -582,10 +757,11 @@
module.exports.assert = require("./sinon/assert");
module.exports.sandbox = require("./sinon/sandbox");
module.exports.test = require("./sinon/test");
module.exports.testCase = require("./sinon/test_case");
module.exports.assert = require("./sinon/assert");
+ module.exports.match = require("./sinon/match");
}
if (buster) {
var formatter = sinon.create(buster.format);
formatter.quoteStrings = false;
@@ -594,11 +770,11 @@
};
} else if (isNode) {
try {
var util = require("util");
sinon.format = function (value) {
- return typeof value == "object" ? util.inspect(value) : value;
+ return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
};
} catch (e) {
/* Node, but no util module - would be very old, but better safe than
sorry */
}
@@ -609,10 +785,252 @@
/* @depend ../sinon.js */
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
/*global module, require, sinon*/
/**
+ * Match functions
+ *
+ * @author Maximilian Antoni (mail@maxantoni.de)
+ * @license BSD
+ *
+ * Copyright (c) 2012 Maximilian Antoni
+ */
+
+(function (sinon) {
+ var commonJSModule = typeof module == "object" && typeof require == "function";
+
+ if (!sinon && commonJSModule) {
+ sinon = require("../sinon");
+ }
+
+ if (!sinon) {
+ return;
+ }
+
+ function assertType(value, type, name) {
+ var actual = sinon.typeOf(value);
+ if (actual !== type) {
+ throw new TypeError("Expected type of " + name + " to be " +
+ type + ", but was " + actual);
+ }
+ }
+
+ var matcher = {
+ toString: function () {
+ return this.message;
+ }
+ };
+
+ function isMatcher(object) {
+ return matcher.isPrototypeOf(object);
+ }
+
+ function matchObject(expectation, actual) {
+ if (actual === null || actual === undefined) {
+ return false;
+ }
+ for (var key in expectation) {
+ if (expectation.hasOwnProperty(key)) {
+ var exp = expectation[key];
+ var act = actual[key];
+ if (match.isMatcher(exp)) {
+ if (!exp.test(act)) {
+ return false;
+ }
+ } else if (sinon.typeOf(exp) === "object") {
+ if (!matchObject(exp, act)) {
+ return false;
+ }
+ } else if (!sinon.deepEqual(exp, act)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ matcher.or = function (m2) {
+ if (!isMatcher(m2)) {
+ throw new TypeError("Matcher expected");
+ }
+ var m1 = this;
+ var or = sinon.create(matcher);
+ or.test = function (actual) {
+ return m1.test(actual) || m2.test(actual);
+ };
+ or.message = m1.message + ".or(" + m2.message + ")";
+ return or;
+ };
+
+ matcher.and = function (m2) {
+ if (!isMatcher(m2)) {
+ throw new TypeError("Matcher expected");
+ }
+ var m1 = this;
+ var and = sinon.create(matcher);
+ and.test = function (actual) {
+ return m1.test(actual) && m2.test(actual);
+ };
+ and.message = m1.message + ".and(" + m2.message + ")";
+ return and;
+ };
+
+ var match = function (expectation, message) {
+ var m = sinon.create(matcher);
+ var type = sinon.typeOf(expectation);
+ switch (type) {
+ case "object":
+ if (typeof expectation.test === "function") {
+ m.test = function (actual) {
+ return expectation.test(actual) === true;
+ };
+ m.message = "match(" + sinon.functionName(expectation.test) + ")";
+ return m;
+ }
+ var str = [];
+ for (var key in expectation) {
+ if (expectation.hasOwnProperty(key)) {
+ str.push(key + ": " + expectation[key]);
+ }
+ }
+ m.test = function (actual) {
+ return matchObject(expectation, actual);
+ };
+ m.message = "match(" + str.join(", ") + ")";
+ break;
+ case "number":
+ m.test = function (actual) {
+ return expectation == actual;
+ };
+ break;
+ case "string":
+ m.test = function (actual) {
+ if (typeof actual !== "string") {
+ return false;
+ }
+ return actual.indexOf(expectation) !== -1;
+ };
+ m.message = "match(\"" + expectation + "\")";
+ break;
+ case "regexp":
+ m.test = function (actual) {
+ if (typeof actual !== "string") {
+ return false;
+ }
+ return expectation.test(actual);
+ };
+ break;
+ case "function":
+ m.test = expectation;
+ if (message) {
+ m.message = message;
+ } else {
+ m.message = "match(" + sinon.functionName(expectation) + ")";
+ }
+ break;
+ default:
+ m.test = function (actual) {
+ return sinon.deepEqual(expectation, actual);
+ };
+ }
+ if (!m.message) {
+ m.message = "match(" + expectation + ")";
+ }
+ return m;
+ };
+
+ match.isMatcher = isMatcher;
+
+ match.any = match(function () {
+ return true;
+ }, "any");
+
+ match.defined = match(function (actual) {
+ return actual !== null && actual !== undefined;
+ }, "defined");
+
+ match.truthy = match(function (actual) {
+ return !!actual;
+ }, "truthy");
+
+ match.falsy = match(function (actual) {
+ return !actual;
+ }, "falsy");
+
+ match.same = function (expectation) {
+ return match(function (actual) {
+ return expectation === actual;
+ }, "same(" + expectation + ")");
+ };
+
+ match.typeOf = function (type) {
+ assertType(type, "string", "type");
+ return match(function (actual) {
+ return sinon.typeOf(actual) === type;
+ }, "typeOf(\"" + type + "\")");
+ };
+
+ match.instanceOf = function (type) {
+ assertType(type, "function", "type");
+ return match(function (actual) {
+ return actual instanceof type;
+ }, "instanceOf(" + sinon.functionName(type) + ")");
+ };
+
+ function createPropertyMatcher(propertyTest, messagePrefix) {
+ return function (property, value) {
+ assertType(property, "string", "property");
+ var onlyProperty = arguments.length === 1;
+ var message = messagePrefix + "(\"" + property + "\"";
+ if (!onlyProperty) {
+ message += ", " + value;
+ }
+ message += ")";
+ return match(function (actual) {
+ if (actual === undefined || actual === null ||
+ !propertyTest(actual, property)) {
+ return false;
+ }
+ return onlyProperty || sinon.deepEqual(value, actual[property]);
+ }, message);
+ };
+ }
+
+ match.has = createPropertyMatcher(function (actual, property) {
+ if (typeof actual === "object") {
+ return property in actual;
+ }
+ return actual[property] !== undefined;
+ }, "has");
+
+ match.hasOwn = createPropertyMatcher(function (actual, property) {
+ return actual.hasOwnProperty(property);
+ }, "hasOwn");
+
+ match.bool = match.typeOf("boolean");
+ match.number = match.typeOf("number");
+ match.string = match.typeOf("string");
+ match.object = match.typeOf("object");
+ match.func = match.typeOf("function");
+ match.array = match.typeOf("array");
+ match.regexp = match.typeOf("regexp");
+ match.date = match.typeOf("date");
+
+ if (commonJSModule) {
+ module.exports = match;
+ } else {
+ sinon.match = match;
+ }
+}(typeof sinon == "object" && sinon || null));
+
+/**
+ * @depend ../sinon.js
+ * @depend match.js
+ */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
* Spy functions
*
* @author Christian Johansen (christian@cjohansen.no)
* @license BSD
*
@@ -637,11 +1055,11 @@
function spy(object, property) {
if (!property && typeof object == "function") {
return spy.create(object);
}
- if (!object || !property) {
+ if (!object && !property) {
return spy.create(function () {});
}
var method = object[property];
return sinon.wrapMethod(object, property, spy.create(method));
@@ -692,10 +1110,11 @@
}
function incrementCallCount() {
this.called = true;
this.callCount += 1;
+ this.notCalled = false;
this.calledOnce = this.callCount == 1;
this.calledTwice = this.callCount == 2;
this.calledThrice = this.callCount == 3;
}
@@ -710,10 +1129,11 @@
// Public API
var spyApi = {
reset: function () {
this.called = false;
+ this.notCalled = true;
this.calledOnce = false;
this.calledTwice = false;
this.calledThrice = false;
this.callCount = 0;
this.firstCall = null;
@@ -723,10 +1143,15 @@
this.args = [];
this.returnValues = [];
this.thisValues = [];
this.exceptions = [];
this.callIds = [];
+ if (this.fakes) {
+ for (var i = 0; i < this.fakes.length; i++) {
+ this.fakes[i].reset();
+ }
+ }
},
create: function create(func) {
var name;
@@ -880,15 +1305,19 @@
};
delegateToCalls(spyApi, "calledOn", true);
delegateToCalls(spyApi, "alwaysCalledOn", false, "calledOn");
delegateToCalls(spyApi, "calledWith", true);
+ delegateToCalls(spyApi, "calledWithMatch", true);
delegateToCalls(spyApi, "alwaysCalledWith", false, "calledWith");
+ delegateToCalls(spyApi, "alwaysCalledWithMatch", false, "calledWithMatch");
delegateToCalls(spyApi, "calledWithExactly", true);
delegateToCalls(spyApi, "alwaysCalledWithExactly", false, "calledWithExactly");
delegateToCalls(spyApi, "neverCalledWith", false, "notCalledWith",
function () { return true; });
+ delegateToCalls(spyApi, "neverCalledWithMatch", false, "notCalledWithMatch",
+ function () { return true; });
delegateToCalls(spyApi, "threw", true);
delegateToCalls(spyApi, "alwaysThrew", false, "threw");
delegateToCalls(spyApi, "returned", true);
delegateToCalls(spyApi, "alwaysReturned", false, "returned");
delegateToCalls(spyApi, "calledWithNew", true);
@@ -935,11 +1364,17 @@
return objects.join(", ");
},
"*": function (spy, args) {
- return args.join(", ");
+ var formatted = [];
+
+ for (var i = 0, l = args.length; i < l; ++i) {
+ push.call(formatted, sinon.format(args[i]));
+ }
+
+ return formatted.join(", ");
}
};
return spyApi;
}()));
@@ -980,26 +1415,36 @@
}
return true;
},
+ calledWithMatch: function calledWithMatch() {
+ for (var i = 0, l = arguments.length; i < l; i += 1) {
+ var actual = this.args[i];
+ var expectation = arguments[i];
+ if (!sinon.match || !sinon.match(expectation).test(actual)) {
+ return false;
+ }
+ }
+ return true;
+ },
+
calledWithExactly: function calledWithExactly() {
return arguments.length == this.args.length &&
this.calledWith.apply(this, arguments);
},
notCalledWith: function notCalledWith() {
- for (var i = 0, l = arguments.length; i < l; i += 1) {
- if (!sinon.deepEqual(arguments[i], this.args[i])) {
- return true;
- }
- }
- return false;
+ return !this.calledWith.apply(this, arguments);
},
+ notCalledWithMatch: function notCalledWithMatch() {
+ return !this.calledWithMatch.apply(this, arguments);
+ },
+
returned: function returned(value) {
- return this.returnValue === value;
+ return sinon.deepEqual(value, this.returnValue);
},
threw: function threw(error) {
if (typeof error == "undefined" || !this.exception) {
return !!this.exception;
@@ -1193,51 +1638,73 @@
}
return "argument at index " + stub.callArgAt + " is not a function: " + func;
}
+ var nextTick = (function () {
+ if (typeof process === "object" && typeof process.nextTick === "function") {
+ return process.nextTick;
+ } else if (typeof msSetImmediate === "function") {
+ return msSetImmediate.bind(window);
+ } else if (typeof setImmediate === "function") {
+ return setImmediate;
+ } else {
+ return function (callback) {
+ setTimeout(callback, 0);
+ };
+ }
+ })();
+
function callCallback(stub, args) {
if (typeof stub.callArgAt == "number") {
var func = getCallback(stub, args);
if (typeof func != "function") {
throw new TypeError(getCallbackError(stub, func, args));
}
- func.apply(stub.callbackContext, stub.callbackArguments);
+ if (stub.callbackAsync) {
+ nextTick(function() {
+ func.apply(stub.callbackContext, stub.callbackArguments);
+ });
+ } else {
+ func.apply(stub.callbackContext, stub.callbackArguments);
+ }
}
}
var uuid = 0;
sinon.extend(stub, (function () {
- var slice = Array.prototype.slice;
+ var slice = Array.prototype.slice, proto;
function throwsException(error, message) {
if (typeof error == "string") {
this.exception = new Error(message || "");
this.exception.name = error;
} else if (!error) {
this.exception = new Error("Error");
} else {
this.exception = error;
}
-
+
return this;
}
- return {
+ proto = {
create: function create() {
var functionStub = function () {
+
+ callCallback(functionStub, arguments);
+
if (functionStub.exception) {
throw functionStub.exception;
} else if (typeof functionStub.returnArgAt == 'number') {
return arguments[functionStub.returnArgAt];
+ } else if (functionStub.returnThis) {
+ return this;
}
-
- callCallback(functionStub, arguments);
-
return functionStub.returnValue;
};
functionStub.id = "stub#" + uuid++;
var orig = functionStub;
@@ -1260,16 +1727,22 @@
returnsArg: function returnsArg(pos) {
if (typeof pos != "number") {
throw new TypeError("argument index is not number");
}
-
+
this.returnArgAt = pos;
return this;
},
+ returnsThis: function returnsThis() {
+ this.returnThis = true;
+
+ return this;
+ },
+
"throws": throwsException,
throwsException: throwsException,
callsArg: function callsArg(pos) {
if (typeof pos != "number") {
@@ -1361,10 +1834,25 @@
this.callbackContext = context;
return this;
}
};
+
+ // create asynchronous versions of callsArg* and yields* methods
+ for (var method in proto) {
+ if (proto.hasOwnProperty(method) && method.match(/^(callsArg|yields)/)) {
+ proto[method + 'Async'] = (function (syncFnName) {
+ return function () {
+ this.callbackAsync = true;
+ return this[syncFnName].apply(this, arguments);
+ };
+ })(method);
+ }
+ }
+
+ return proto;
+
}()));
if (commonJSModule) {
module.exports = stub;
} else {
@@ -1486,32 +1974,43 @@
this.restore();
if (messages.length > 0) {
sinon.expectation.fail(messages.concat(met).join("\n"));
+ } else {
+ sinon.expectation.pass(messages.concat(met).join("\n"));
}
return true;
},
invokeMethod: function invokeMethod(method, thisValue, args) {
var expectations = this.expectations && this.expectations[method];
- var length = expectations && expectations.length || 0;
+ var length = expectations && expectations.length || 0, i;
- for (var i = 0; i < length; i += 1) {
+ for (i = 0; i < length; i += 1) {
if (!expectations[i].met() &&
expectations[i].allowsCall(thisValue, args)) {
return expectations[i].apply(thisValue, args);
}
}
- var messages = [];
+ var messages = [], available, exhausted = 0;
for (i = 0; i < length; i += 1) {
+ if (expectations[i].allowsCall(thisValue, args)) {
+ available = available || expectations[i];
+ } else {
+ exhausted += 1;
+ }
push.call(messages, " " + expectations[i].toString());
}
+ if (exhausted === 0) {
+ return available.apply(thisValue, args);
+ }
+
messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
proxy: method,
args: args
}));
@@ -1658,11 +2157,11 @@
if (!("expectedArguments" in this)) {
return;
}
- if (!args || args.length === 0) {
+ if (!args) {
sinon.expectation.fail(this.method + " received no arguments, expected " +
this.expectedArguments.join());
}
if (args.length < this.expectedArguments.length) {
@@ -1683,11 +2182,11 @@
}
}
},
allowsCall: function allowsCall(thisValue, args) {
- if (this.met()) {
+ if (this.met() && receivedMaxCalls(this)) {
return false;
}
if ("expectedThis" in this && this.expectedThis !== thisValue) {
return false;
@@ -1756,15 +2255,20 @@
},
verify: function verify() {
if (!this.met()) {
sinon.expectation.fail(this.toString());
+ } else {
+ sinon.expectation.pass(this.toString());
}
return true;
},
+ pass: function(message) {
+ sinon.assert.pass(message);
+ },
fail: function (message) {
var exception = new Error(message);
exception.name = "ExpectationError";
throw exception;
@@ -1884,11 +2388,22 @@
object[property] = original;
}
});
}
}
+ if (!property && !!object && typeof object == "object") {
+ var stubbedObj = sinon.stub.apply(sinon, arguments);
+ for (var prop in stubbedObj) {
+ if (typeof stubbedObj[prop] === "function") {
+ this.add(stubbedObj[prop]);
+ }
+ }
+
+ return stubbedObj;
+ }
+
return this.add(sinon.stub.apply(sinon, arguments));
},
mock: function mock() {
return this.add(sinon.mock.apply(sinon, arguments));
@@ -1960,11 +2475,12 @@
}
this.timeouts[toId] = {
id: toId,
func: args[0],
- callAt: this.now + delay
+ callAt: this.now + delay,
+ invokeArgs: Array.prototype.slice.call(args, 2)
};
if (recurring === true) {
this.timeouts[toId].interval = delay;
}
@@ -2094,23 +2610,30 @@
timer = {
func: this.timeouts[id].func,
callAt: this.timeouts[id].callAt,
interval: this.timeouts[id].interval,
- id: this.timeouts[id].id
+ id: this.timeouts[id].id,
+ invokeArgs: this.timeouts[id].invokeArgs
};
}
}
}
return timer || null;
},
callTimer: function (timer) {
+ if (typeof timer.interval == "number") {
+ this.timeouts[timer.id].callAt += timer.interval;
+ } else {
+ delete this.timeouts[timer.id];
+ }
+
try {
if (typeof timer.func == "function") {
- timer.func.call(null);
+ timer.func.apply(null, timer.invokeArgs);
} else {
eval(timer.func);
}
} catch (e) {
var exception = e;
@@ -2121,16 +2644,10 @@
throw exception;
}
return;
}
- if (typeof timer.interval == "number") {
- this.timeouts[timer.id].callAt += timer.interval;
- } else {
- delete this.timeouts[timer.id];
- }
-
if (exception) {
throw exception;
}
},
@@ -2202,15 +2719,23 @@
function restore() {
var method;
for (var i = 0, l = this.methods.length; i < l; i++) {
method = this.methods[i];
- global[method] = this["_" + method];
+ if (global[method].hadOwnProperty) {
+ global[method] = this["_" + method];
+ } else {
+ delete global[method];
+ }
}
+
+ // Prevent multiple executions which will completely remove these props
+ this.methods = [];
}
function stubGlobal(method, clock) {
+ clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
clock["_" + method] = global[method];
if (method == "Date") {
var date = mirrorDateProperties(clock[method], global[method]);
global[method] = date;
@@ -2847,11 +3372,11 @@
}
return response;
}
- var wloc = window.location;
+ var wloc = typeof window !== "undefined" ? window.location : {};
var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
function matchOne(response, reqMethod, reqUrl) {
var rmeth = response.method;
var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
@@ -3531,22 +4056,26 @@
mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
+ mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
+ mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
+ mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
+ mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
+ mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
mirrorPropAsAssertion("threw", "%n did not throw exception%C");
mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
if (commonJSModule) {
module.exports = assert;
} else {
sinon.assert = assert;
}
}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : global));
-return sinon;}.call(typeof window != 'undefined' && window || {}));
-
+return sinon;}.call(typeof window != 'undefined' && window || {}));
\ No newline at end of file