vendor/assets/javascripts/sinon.js in sinon-rails-1.7.3 vs vendor/assets/javascripts/sinon.js in sinon-rails-1.9.0
- old
+ new
@@ -1,14 +1,14 @@
/**
- * Sinon.JS 1.7.3, 2013/06/20
+ * Sinon.JS 1.9.0, 2014/03/05
*
* @author Christian Johansen (christian@cjohansen.no)
* @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
*
* (The BSD License)
*
- * Copyright (c) 2010-2013, Christian Johansen, christian@cjohansen.no
+ * Copyright (c) 2010-2014, 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,429 +32,589 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
this.sinon = (function () {
-var buster = (function (setTimeout, B) {
- var isNode = typeof require == "function" && typeof module == "object";
- var div = typeof document != "undefined" && document.createElement("div");
- var F = function () {};
+var samsam, formatio;
+function define(mod, deps, fn) { if (mod == "samsam") { samsam = deps(); } else { formatio = fn(samsam); } }
+define.amd = true;
+((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
+ (typeof module === "object" &&
+ function (m) { module.exports = m(); }) || // Node
+ function (m) { this.samsam = m(); } // Browser globals
+)(function () {
+ var o = Object.prototype;
+ var div = typeof document !== "undefined" && document.createElement("div");
- 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);
- };
- },
+ function isNaN(value) {
+ // Unlike global isNaN, this avoids type coercion
+ // typeof check avoids IE host object issues, hat tip to
+ // lodash
+ var val = value; // JsLint thinks value !== value is "weird"
+ return typeof value === "number" && value !== val;
+ }
- partial: function partial(fn) {
- var args = [].slice.call(arguments, 1);
- return function () {
- return fn.apply(this, args.concat([].slice.call(arguments)));
- };
- },
+ function getClass(value) {
+ // Returns the internal [[Class]] by calling Object.prototype.toString
+ // with the provided value as this. Return value is a string, naming the
+ // internal class, e.g. "Array"
+ return o.toString.call(value).split(/[ \]]/)[1];
+ }
- create: function create(object) {
- F.prototype = object;
- return new F();
- },
+ /**
+ * @name samsam.isArguments
+ * @param Object object
+ *
+ * Returns ``true`` if ``object`` is an ``arguments`` object,
+ * ``false`` otherwise.
+ */
+ function isArguments(object) {
+ if (typeof object !== "object" || typeof object.length !== "number" ||
+ getClass(object) === "Array") {
+ return false;
+ }
+ if (typeof object.callee == "function") { return true; }
+ try {
+ object[object.length] = 6;
+ delete object[object.length];
+ } catch (e) {
+ return true;
+ }
+ return false;
+ }
- 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;
- },
+ /**
+ * @name samsam.isElement
+ * @param Object object
+ *
+ * Returns ``true`` if ``object`` is a DOM element node. Unlike
+ * Underscore.js/lodash, this function will return ``false`` if ``object``
+ * is an *element-like* object, i.e. a regular object with a ``nodeType``
+ * property that holds the value ``1``.
+ */
+ function isElement(object) {
+ if (!object || object.nodeType !== 1 || !div) { return false; }
+ try {
+ object.appendChild(div);
+ object.removeChild(div);
+ } catch (e) {
+ return false;
+ }
+ return true;
+ }
- nextTick: function nextTick(callback) {
- if (typeof process != "undefined" && process.nextTick) {
- return process.nextTick(callback);
- }
- setTimeout(callback, 0);
- },
+ /**
+ * @name samsam.keys
+ * @param Object object
+ *
+ * Return an array of own property names.
+ */
+ function keys(object) {
+ var ks = [], prop;
+ for (prop in object) {
+ if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
+ }
+ return ks;
+ }
- 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] || "";
- },
+ /**
+ * @name samsam.isDate
+ * @param Object value
+ *
+ * Returns true if the object is a ``Date``, or *date-like*. Duck typing
+ * of date objects work by checking that the object has a ``getTime``
+ * function whose return value equals the return value from the object's
+ * ``valueOf``.
+ */
+ function isDate(value) {
+ return typeof value.getTime == "function" &&
+ value.getTime() == value.valueOf();
+ }
- isNode: function isNode(obj) {
- if (!div) return false;
- try {
- obj.appendChild(div);
- obj.removeChild(div);
- } catch (e) {
- return false;
- }
- return true;
- },
+ /**
+ * @name samsam.isNegZero
+ * @param Object value
+ *
+ * Returns ``true`` if ``value`` is ``-0``.
+ */
+ function isNegZero(value) {
+ return value === 0 && 1 / value === -Infinity;
+ }
- isElement: function isElement(obj) {
- return obj && obj.nodeType === 1 && buster.isNode(obj);
- },
+ /**
+ * @name samsam.equal
+ * @param Object obj1
+ * @param Object obj2
+ *
+ * Returns ``true`` if two objects are strictly equal. Compared to
+ * ``===`` there are two exceptions:
+ *
+ * - NaN is considered equal to NaN
+ * - -0 and +0 are not considered equal
+ */
+ function identical(obj1, obj2) {
+ if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
+ return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
+ }
+ }
- isArray: function isArray(arr) {
- return Object.prototype.toString.call(arr) == "[object Array]";
- },
- 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]);
+ /**
+ * @name samsam.deepEqual
+ * @param Object obj1
+ * @param Object obj2
+ *
+ * Deep equal comparison. Two values are "deep equal" if:
+ *
+ * - They are equal, according to samsam.identical
+ * - They are both date objects representing the same time
+ * - They are both arrays containing elements that are all deepEqual
+ * - They are objects with the same set of properties, and each property
+ * in ``obj1`` is deepEqual to the corresponding property in ``obj2``
+ *
+ * Supports cyclic objects.
+ */
+ function deepEqualCyclic(obj1, obj2) {
+
+ // used for cyclic comparison
+ // contain already visited objects
+ var objects1 = [],
+ objects2 = [],
+ // contain pathes (position in the object structure)
+ // of the already visited objects
+ // indexes same as in objects arrays
+ paths1 = [],
+ paths2 = [],
+ // contains combinations of already compared objects
+ // in the manner: { "$1['ref']$2['ref']": true }
+ compared = {};
+
+ /**
+ * used to check, if the value of a property is an object
+ * (cyclic logic is only needed for objects)
+ * only needed for cyclic logic
+ */
+ function isObject(value) {
+
+ if (typeof value === 'object' && value !== null &&
+ !(value instanceof Boolean) &&
+ !(value instanceof Date) &&
+ !(value instanceof Number) &&
+ !(value instanceof RegExp) &&
+ !(value instanceof String)) {
+
+ return true;
}
- return result;
- },
- each: function each(arr, callback) {
- for (var i = 0, l = arr.length; i < l; ++i) {
- callback(arr[i]);
+ return false;
+ }
+
+ /**
+ * returns the index of the given object in the
+ * given objects array, -1 if not contained
+ * only needed for cyclic logic
+ */
+ function getIndex(objects, obj) {
+
+ var i;
+ for (i = 0; i < objects.length; i++) {
+ if (objects[i] === obj) {
+ return i;
+ }
}
- },
- map: function map(arr, callback) {
- var results = [];
- for (var i = 0, l = arr.length; i < l; ++i) {
- results.push(callback(arr[i]));
+ return -1;
+ }
+
+ // does the recursion for the deep equal check
+ return (function deepEqual(obj1, obj2, path1, path2) {
+ var type1 = typeof obj1;
+ var type2 = typeof obj2;
+
+ // == null also matches undefined
+ if (obj1 === obj2 ||
+ isNaN(obj1) || isNaN(obj2) ||
+ obj1 == null || obj2 == null ||
+ type1 !== "object" || type2 !== "object") {
+
+ return identical(obj1, obj2);
}
- return results;
- },
- parallel: function parallel(fns, callback) {
- function cb(err, res) {
- if (typeof callback == "function") {
- callback(err, res);
- callback = null;
+ // Elements are only equal if identical(expected, actual)
+ if (isElement(obj1) || isElement(obj2)) { return false; }
+
+ var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
+ if (isDate1 || isDate2) {
+ if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
+ return false;
}
}
- 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); }
- };
+
+ if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
+ if (obj1.toString() !== obj2.toString()) { return false; }
}
- 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 class1 = getClass(obj1);
+ var class2 = getClass(obj2);
+ var keys1 = keys(obj1);
+ var keys2 = keys(obj2);
+
+ if (isArguments(obj1) || isArguments(obj2)) {
+ if (obj1.length !== obj2.length) { return false; }
+ } else {
+ if (type1 !== type2 || class1 !== class2 ||
+ keys1.length !== keys2.length) {
+ return false;
}
}
- 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);
+
+ var key, i, l,
+ // following vars are used for the cyclic logic
+ value1, value2,
+ isObject1, isObject2,
+ index1, index2,
+ newPath1, newPath2;
+
+ for (i = 0, l = keys1.length; i < l; i++) {
+ key = keys1[i];
+ if (!o.hasOwnProperty.call(obj2, key)) {
+ return false;
}
- }
- 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();
- };
- }
- };
+ // Start of the cyclic logic
- if (typeof process === "object" &&
- typeof require === "function" && typeof module === "object") {
- var crypto = require("crypto");
- var path = require("path");
+ value1 = obj1[key];
+ value2 = obj2[key];
- buster.tmpFile = function (fileName) {
- var hashed = crypto.createHash("sha1");
- hashed.update(fileName);
- var tmpfileName = hashed.digest("hex");
+ isObject1 = isObject(value1);
+ isObject2 = isObject(value2);
- if (process.platform == "win32") {
- return path.join(process.env["TEMP"], tmpfileName);
- } else {
- return path.join("/tmp", tmpfileName);
- }
- };
- }
+ // determine, if the objects were already visited
+ // (it's faster to check for isObject first, than to
+ // get -1 from getIndex for non objects)
+ index1 = isObject1 ? getIndex(objects1, value1) : -1;
+ index2 = isObject2 ? getIndex(objects2, value2) : -1;
- 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(); }
+ // determine the new pathes of the objects
+ // - for non cyclic objects the current path will be extended
+ // by current property name
+ // - for cyclic objects the stored path is taken
+ newPath1 = index1 !== -1
+ ? paths1[index1]
+ : path1 + '[' + JSON.stringify(key) + ']';
+ newPath2 = index2 !== -1
+ ? paths2[index2]
+ : path2 + '[' + JSON.stringify(key) + ']';
- for (var i = 0; i < len; i++) {
- if (arr.hasOwnProperty(i) && fun.call(thisp, arr[i], i, arr)) {
+ // stop recursion if current objects are already compared
+ if (compared[newPath1 + newPath2]) {
return true;
}
- }
- return false;
- };
- }
+ // remember the current objects and their pathes
+ if (index1 === -1 && isObject1) {
+ objects1.push(value1);
+ paths1.push(newPath1);
+ }
+ if (index2 === -1 && isObject2) {
+ objects2.push(value2);
+ paths2.push(newPath2);
+ }
- 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(); }
+ // remember that the current objects are already compared
+ if (isObject1 && isObject2) {
+ compared[newPath1 + newPath2] = true;
+ }
- var t = Object(this);
- var len = t.length >>> 0;
- if (typeof fn != "function") { throw new TypeError(); }
+ // End of cyclic logic
- 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); }
+ // neither value1 nor value2 is a cycle
+ // continue with next level
+ if (!deepEqual(value1, value2, newPath1, newPath2)) {
+ return false;
}
}
- return res;
- };
+ return true;
+
+ }(obj1, obj2, '$1', '$2'));
}
- if (isNode) {
- module.exports = buster;
- buster.eventEmitter = require("./buster-event-emitter");
- Object.defineProperty(buster, "defineVersionGetter", {
- get: function () {
- return require("./define-version-getter");
+ var match;
+
+ function arrayContains(array, subset) {
+ if (subset.length === 0) { return true; }
+ var i, l, j, k;
+ for (i = 0, l = array.length; i < l; ++i) {
+ if (match(array[i], subset[0])) {
+ for (j = 0, k = subset.length; j < k; ++j) {
+ if (!match(array[i + j], subset[j])) { return false; }
+ }
+ return true;
}
- });
+ }
+ return false;
}
- return buster.extend(B || {}, buster);
-}(setTimeout, buster));
-if (typeof buster === "undefined") {
- var buster = {};
-}
+ /**
+ * @name samsam.match
+ * @param Object object
+ * @param Object matcher
+ *
+ * Compare arbitrary value ``object`` with matcher.
+ */
+ match = function match(object, matcher) {
+ if (matcher && typeof matcher.test === "function") {
+ return matcher.test(object);
+ }
-if (typeof module === "object" && typeof require === "function") {
- buster = require("buster-core");
-}
+ if (typeof matcher === "function") {
+ return matcher(object) === true;
+ }
-buster.format = buster.format || {};
-buster.format.excludeConstructors = ["Object", /^.$/];
-buster.format.quoteStrings = true;
+ if (typeof matcher === "string") {
+ matcher = matcher.toLowerCase();
+ var notNull = typeof object === "string" || !!object;
+ return notNull &&
+ (String(object)).toLowerCase().indexOf(matcher) >= 0;
+ }
-buster.format.ascii = (function () {
+ if (typeof matcher === "number") {
+ return matcher === object;
+ }
+
+ if (typeof matcher === "boolean") {
+ return matcher === object;
+ }
+
+ if (getClass(object) === "Array" && getClass(matcher) === "Array") {
+ return arrayContains(object, matcher);
+ }
+
+ if (matcher && typeof matcher === "object") {
+ var prop;
+ for (prop in matcher) {
+ if (!match(object[prop], matcher[prop])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ throw new Error("Matcher was not a string, a number, a " +
+ "function, a boolean or an object");
+ };
+
+ return {
+ isArguments: isArguments,
+ isElement: isElement,
+ isDate: isDate,
+ isNegZero: isNegZero,
+ identical: identical,
+ deepEqual: deepEqualCyclic,
+ match: match,
+ keys: keys
+ };
+});
+((typeof define === "function" && define.amd && function (m) {
+ define("formatio", ["samsam"], m);
+}) || (typeof module === "object" && function (m) {
+ module.exports = m(require("samsam"));
+}) || function (m) { this.formatio = m(this.samsam); }
+)(function (samsam) {
+ var formatio = {
+ excludeConstructors: ["Object", /^.$/],
+ quoteStrings: true
+ };
+
var hasOwn = Object.prototype.hasOwnProperty;
var specialObjects = [];
- if (typeof global != "undefined") {
- specialObjects.push({ obj: global, value: "[object global]" });
+ if (typeof global !== "undefined") {
+ specialObjects.push({ object: global, value: "[object global]" });
}
- if (typeof document != "undefined") {
- specialObjects.push({ obj: document, value: "[object HTMLDocument]" });
+ if (typeof document !== "undefined") {
+ specialObjects.push({
+ object: document,
+ value: "[object HTMLDocument]"
+ });
}
- if (typeof window != "undefined") {
- specialObjects.push({ obj: window, value: "[object Window]" });
+ if (typeof window !== "undefined") {
+ specialObjects.push({ object: window, value: "[object Window]" });
}
- function keys(object) {
- var k = Object.keys && Object.keys(object) || [];
+ 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]) || "";
+ }
- if (k.length == 0) {
- for (var prop in object) {
- if (hasOwn.call(object, prop)) {
- k.push(prop);
- }
+ function constructorName(f, object) {
+ var name = functionName(object && object.constructor);
+ var excludes = f.excludeConstructors ||
+ formatio.excludeConstructors || [];
+
+ var i, l;
+ for (i = 0, l = excludes.length; i < l; ++i) {
+ if (typeof excludes[i] === "string" && excludes[i] === name) {
+ return "";
+ } else if (excludes[i].test && excludes[i].test(name)) {
+ return "";
}
}
- return k.sort();
+ return name;
}
function isCircular(object, objects) {
- if (typeof object != "object") {
- return false;
+ if (typeof object !== "object") { return false; }
+ var i, l;
+ for (i = 0, l = objects.length; i < l; ++i) {
+ if (objects[i] === object) { return true; }
}
-
- for (var i = 0, l = objects.length; i < l; ++i) {
- if (objects[i] === object) {
- return true;
- }
- }
-
return false;
}
- function ascii(object, processed, indent) {
- if (typeof object == "string") {
- var quote = typeof this.quoteStrings != "boolean" || this.quoteStrings;
+ function ascii(f, object, processed, indent) {
+ if (typeof object === "string") {
+ var qs = f.quoteStrings;
+ var quote = typeof qs !== "boolean" || qs;
return processed || quote ? '"' + object + '"' : object;
}
- if (typeof object == "function" && !(object instanceof RegExp)) {
+ if (typeof object === "function" && !(object instanceof RegExp)) {
return ascii.func(object);
}
processed = processed || [];
- if (isCircular(object, processed)) {
- return "[Circular]";
- }
+ if (isCircular(object, processed)) { return "[Circular]"; }
- if (Object.prototype.toString.call(object) == "[object Array]") {
- return ascii.array.call(this, object, processed);
+ if (Object.prototype.toString.call(object) === "[object Array]") {
+ return ascii.array.call(f, object, processed);
}
- if (!object) {
- return "" + object;
- }
+ if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
+ if (samsam.isElement(object)) { return ascii.element(object); }
- if (buster.isElement(object)) {
- return ascii.element(object);
- }
-
- if (typeof object.toString == "function" &&
- 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) {
+ var i, l;
+ for (i = 0, l = specialObjects.length; i < l; i++) {
+ if (object === specialObjects[i].object) {
return specialObjects[i].value;
}
}
- return ascii.object.call(this, object, processed, indent);
+ return ascii.object.call(f, object, processed, indent);
}
ascii.func = function (func) {
- return "function " + buster.functionName(func) + "() {}";
+ return "function " + functionName(func) + "() {}";
};
ascii.array = function (array, processed) {
processed = processed || [];
processed.push(array);
- var pieces = [];
-
- for (var i = 0, l = array.length; i < l; ++i) {
- pieces.push(ascii.call(this, array[i], processed));
+ var i, l, pieces = [];
+ for (i = 0, l = array.length; i < l; ++i) {
+ pieces.push(ascii(this, array[i], processed));
}
-
return "[" + pieces.join(", ") + "]";
};
ascii.object = function (object, processed, indent) {
processed = processed || [];
processed.push(object);
indent = indent || 0;
- var pieces = [], properties = keys(object), prop, str, obj;
- var is = "";
+ var pieces = [], properties = samsam.keys(object).sort();
var length = 3;
+ var prop, str, obj, i, l;
- for (var i = 0, l = indent; i < l; ++i) {
- is += " ";
- }
-
for (i = 0, l = properties.length; i < l; ++i) {
prop = properties[i];
obj = object[prop];
if (isCircular(obj, processed)) {
str = "[Circular]";
} else {
- str = ascii.call(this, obj, processed, indent + 2);
+ str = ascii(this, obj, processed, indent + 2);
}
str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
length += str.length;
pieces.push(str);
}
- var cons = ascii.constructorName.call(this, object);
- var prefix = cons ? "[" + cons + "] " : ""
+ var cons = constructorName(this, object);
+ var prefix = cons ? "[" + cons + "] " : "";
+ var is = "";
+ for (i = 0, l = indent; i < l; ++i) { is += " "; }
- return (length + indent) > 80 ?
- prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" + is + "}" :
- prefix + "{ " + pieces.join(", ") + " }";
+ if (length + indent > 80) {
+ return prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" +
+ is + "}";
+ }
+ return prefix + "{ " + pieces.join(", ") + " }";
};
ascii.element = function (element) {
var tagName = element.tagName.toLowerCase();
- var attrs = element.attributes, attribute, pairs = [], attrName;
+ var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
- for (var i = 0, l = attrs.length; i < l; ++i) {
- attribute = attrs.item(i);
- attrName = attribute.nodeName.toLowerCase().replace("html:", "");
-
- if (attrName == "contenteditable" && attribute.nodeValue == "inherit") {
- continue;
+ for (i = 0, l = attrs.length; i < l; ++i) {
+ attr = attrs.item(i);
+ attrName = attr.nodeName.toLowerCase().replace("html:", "");
+ val = attr.nodeValue;
+ if (attrName !== "contenteditable" || val !== "inherit") {
+ if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
}
-
- if (!!attribute.nodeValue) {
- pairs.push(attrName + "=\"" + attribute.nodeValue + "\"");
- }
}
var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
var content = element.innerHTML;
if (content.length > 20) {
content = content.substr(0, 20) + "[...]";
}
- var res = formatted + pairs.join(" ") + ">" + content + "</" + tagName + ">";
+ var res = formatted + pairs.join(" ") + ">" + content +
+ "</" + tagName + ">";
return res.replace(/ contentEditable="inherit"/, "");
};
- ascii.constructorName = function (object) {
- var name = buster.functionName(object && object.constructor);
- var excludes = this.excludeConstructors || buster.format.excludeConstructors || [];
-
- for (var i = 0, l = excludes.length; i < l; ++i) {
- if (typeof excludes[i] == "string" && excludes[i] == name) {
- return "";
- } else if (excludes[i].test && excludes[i].test(name)) {
- return "";
- }
+ function Formatio(options) {
+ for (var opt in options) {
+ this[opt] = options[opt];
}
+ }
- return name;
- };
+ Formatio.prototype = {
+ functionName: functionName,
- return ascii;
-}());
+ configure: function (options) {
+ return new Formatio(options);
+ },
-if (typeof module != "undefined") {
- module.exports = buster.format;
-}
+ constructorName: function (object) {
+ return constructorName(this, object);
+ },
+
+ ascii: function (object, processed, indent) {
+ return ascii(this, object, processed, indent);
+ }
+ };
+
+ return Formatio.prototype;
+});
/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
/*global module, require, __dirname, document*/
/**
* Sinon core utilities. For internal use only.
*
@@ -462,11 +622,11 @@
* @license BSD
*
* Copyright (c) 2010-2013 Christian Johansen
*/
-var sinon = (function (buster) {
+var sinon = (function (formatio) {
var div = typeof document != "undefined" && document.createElement("div");
var hasOwn = Object.prototype.hasOwnProperty;
function isDOMNode(obj) {
var success = false;
@@ -515,30 +675,42 @@
if (typeof method != "function") {
throw new TypeError("Method wrapper should be function");
}
- var wrappedMethod = object[property];
+ var wrappedMethod = object[property],
+ error;
if (!isFunction(wrappedMethod)) {
- throw new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
+ error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
property + " as function");
}
if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
- throw new TypeError("Attempted to wrap " + property + " which is already wrapped");
+ error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
}
if (wrappedMethod.calledBefore) {
var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
- throw new TypeError("Attempted to wrap " + property + " which is already " + verb);
+ error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
}
- // IE 8 does not support hasOwnProperty on the window object.
- var owned = hasOwn.call(object, property);
+ if (error) {
+ if (wrappedMethod._stack) {
+ error.stack += '\n--------------\n' + wrappedMethod._stack;
+ }
+ throw error;
+ }
+
+ // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
+ // when using hasOwn.call on objects from other frames.
+ var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
object[property] = method;
method.displayName = property;
+ // Set up a stack trace which can be used later to find what line of
+ // code the original method was created on.
+ method._stack = (new Error('Stack Trace for original')).stack;
method.restore = function () {
// For prototype properties try to reset by delete first.
// If this fails (ex: localStorage on mobile safari) then force a reset
// via direct assignment.
@@ -598,35 +770,30 @@
if ((a === null && b !== null) || (a !== null && b === null)) {
return false;
}
+ if (a instanceof RegExp && b instanceof RegExp) {
+ return (a.source === b.source) && (a.global === b.global) &&
+ (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
+ }
+
var aString = Object.prototype.toString.call(a);
if (aString != Object.prototype.toString.call(b)) {
return false;
}
- if (aString == "[object Array]") {
- if (a.length !== b.length) {
- return false;
- }
-
- for (var i = 0, l = a.length; i < l; i += 1) {
- if (!deepEqual(a[i], b[i])) {
- return false;
- }
- }
-
- return true;
- }
-
if (aString == "[object Date]") {
return a.valueOf() === b.valueOf();
}
var prop, aLength = 0, bLength = 0;
+ if (aString == "[object Array]" && a.length !== b.length) {
+ return false;
+ }
+
for (prop in a) {
aLength += 1;
if (!deepEqual(a[prop], b[prop])) {
return false;
@@ -729,11 +896,11 @@
},
log: function () {},
logError: function (label, err) {
- var msg = label + " threw exception: "
+ var msg = label + " threw exception: ";
sinon.log(msg + "[" + err.name + "] " + err.message);
if (err.stack) { sinon.log(err.stack); }
setTimeout(function () {
err.message = msg + err.message;
@@ -771,18 +938,25 @@
object.restore();
}
}
};
- var isNode = typeof module == "object" && typeof require == "function";
+ var isNode = typeof module !== "undefined" && module.exports;
+ var isAMD = typeof define === 'function' && typeof define.amd === 'object' && define.amd;
- if (isNode) {
+ if (isAMD) {
+ define(function(){
+ return sinon;
+ });
+ } else if (isNode) {
try {
- buster = { format: require("buster-format") };
+ formatio = require("formatio");
} catch (e) {}
module.exports = sinon;
module.exports.spy = require("./sinon/spy");
+ module.exports.spyCall = require("./sinon/call");
+ module.exports.behavior = require("./sinon/behavior");
module.exports.stub = require("./sinon/stub");
module.exports.mock = require("./sinon/mock");
module.exports.collection = require("./sinon/collection");
module.exports.assert = require("./sinon/assert");
module.exports.sandbox = require("./sinon/sandbox");
@@ -790,13 +964,12 @@
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;
+ if (formatio) {
+ var formatter = formatio.configure({ quoteStrings: false });
sinon.format = function () {
return formatter.ascii.apply(formatter, arguments);
};
} else if (isNode) {
try {
@@ -809,11 +982,11 @@
sorry */
}
}
return sinon;
-}(typeof buster == "object" && buster));
+}(typeof formatio == "object" && formatio));
/* @depend ../sinon.js */
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
/*global module, require, sinon*/
/**
@@ -824,11 +997,11 @@
*
* Copyright (c) 2012 Maximilian Antoni
*/
(function (sinon) {
- var commonJSModule = typeof module == "object" && typeof require == "function";
+ var commonJSModule = typeof module !== 'undefined' && module.exports;
if (!sinon && commonJSModule) {
sinon = require("../sinon");
}
@@ -877,12 +1050,14 @@
}
return true;
}
matcher.or = function (m2) {
- if (!isMatcher(m2)) {
+ if (!arguments.length) {
throw new TypeError("Matcher expected");
+ } else if (!isMatcher(m2)) {
+ m2 = match(m2);
}
var m1 = this;
var or = sinon.create(matcher);
or.test = function (actual) {
return m1.test(actual) || m2.test(actual);
@@ -890,12 +1065,14 @@
or.message = m1.message + ".or(" + m2.message + ")";
return or;
};
matcher.and = function (m2) {
- if (!isMatcher(m2)) {
+ if (!arguments.length) {
throw new TypeError("Matcher expected");
+ } else if (!isMatcher(m2)) {
+ m2 = match(m2);
}
var m1 = this;
var and = sinon.create(matcher);
and.test = function (actual) {
return m1.test(actual) && m2.test(actual);
@@ -1067,17 +1244,20 @@
*
* Copyright (c) 2010-2013 Christian Johansen
* Copyright (c) 2013 Maximilian Antoni
*/
-var commonJSModule = typeof module == "object" && typeof require == "function";
+(function (sinon) {
+ var commonJSModule = typeof module !== 'undefined' && module.exports;
+ if (!sinon && commonJSModule) {
+ sinon = require("../sinon");
+ }
-if (!this.sinon && commonJSModule) {
- var sinon = require("../sinon");
-}
+ if (!sinon) {
+ return;
+ }
-(function (sinon) {
function throwYieldError(proxy, text, args) {
var msg = sinon.functionName(proxy) + text;
if (args.length) {
msg += " Received [" + slice.call(args).join(", ") + "]";
}
@@ -1138,12 +1318,12 @@
}
return this.exception === error || this.exception.name === error;
},
- calledWithNew: function calledWithNew(thisValue) {
- return this.thisValue instanceof this.proxy;
+ calledWithNew: function calledWithNew() {
+ return this.proxy.prototype && this.thisValue instanceof this.proxy;
},
calledBefore: function (other) {
return this.callId < other.callId;
},
@@ -1239,18 +1419,24 @@
proxyCall.returnValue = returnValue;
proxyCall.exception = exception;
proxyCall.callId = id;
return proxyCall;
- };
+ }
createSpyCall.toString = callProto.toString; // used by mocks
- sinon.spyCall = createSpyCall;
+ if (commonJSModule) {
+ module.exports = createSpyCall;
+ } else {
+ sinon.spyCall = createSpyCall;
+ }
}(typeof sinon == "object" && sinon || null));
+
/**
* @depend ../sinon.js
+ * @depend call.js
*/
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
/*global module, require, sinon*/
/**
* Spy functions
@@ -1260,15 +1446,23 @@
*
* Copyright (c) 2010-2013 Christian Johansen
*/
(function (sinon) {
- var commonJSModule = typeof module == "object" && typeof require == "function";
+ var commonJSModule = typeof module !== 'undefined' && module.exports;
var push = Array.prototype.push;
var slice = Array.prototype.slice;
var callId = 0;
+ if (!sinon && commonJSModule) {
+ sinon = require("../sinon");
+ }
+
+ if (!sinon) {
+ return;
+ }
+
function spy(object, property) {
if (!property && typeof object == "function") {
return spy.create(object);
}
@@ -1283,12 +1477,10 @@
function matchingFake(fakes, args, strict) {
if (!fakes) {
return;
}
- var alen = args.length;
-
for (var i = 0, l = fakes.length; i < l; i++) {
if (fakes[i].matches(args, strict)) {
return fakes[i];
}
}
@@ -1391,22 +1583,28 @@
if (matching) {
returnValue = matching.invoke(func, thisValue, args);
} else {
returnValue = (this.func || func).apply(thisValue, args);
}
+
+ var thisCall = this.getCall(this.callCount - 1);
+ if (thisCall.calledWithNew() && typeof returnValue !== 'object') {
+ returnValue = thisValue;
+ }
} catch (e) {
- push.call(this.returnValues, undefined);
exception = e;
- throw e;
- } finally {
- push.call(this.exceptions, exception);
}
+ push.call(this.exceptions, exception);
push.call(this.returnValues, returnValue);
createCallProperties.call(this);
+ if (exception !== undefined) {
+ throw exception;
+ }
+
return returnValue;
},
getCall: function getCall(i) {
if (i < 0 || i >= this.callCount) {
@@ -1416,10 +1614,21 @@
return sinon.spyCall(this, this.thisValues[i], this.args[i],
this.returnValues[i], this.exceptions[i],
this.callIds[i]);
},
+ getCalls: function () {
+ var calls = [];
+ var i;
+
+ for (i = 0; i < this.callCount; i++) {
+ calls.push(this.getCall(i));
+ }
+
+ return calls;
+ },
+
calledBefore: function calledBefore(spyFn) {
if (!this.called) {
return false;
}
@@ -1452,10 +1661,11 @@
}
var original = this;
var fake = this._create();
fake.matchingAguments = args;
+ fake.parent = this;
push.call(this.fakes, fake);
fake.withArgs = function () {
return original.withArgs.apply(original, arguments);
};
@@ -1492,11 +1702,11 @@
return (format || "").replace(/%(.)/g, function (match, specifyer) {
formatter = spyApi.formatters[specifyer];
if (typeof formatter == "function") {
return formatter.call(null, spy, args);
- } else if (!isNaN(parseInt(specifyer), 10)) {
+ } else if (!isNaN(parseInt(specifyer, 10))) {
return sinon.format(args[specifyer - 1]);
}
return "%" + specifyer;
});
@@ -1629,78 +1839,68 @@
}
}(typeof sinon == "object" && sinon || null));
/**
* @depend ../sinon.js
- * @depend spy.js
*/
/*jslint eqeqeq: false, onevar: false*/
-/*global module, require, sinon*/
+/*global module, require, sinon, process, setImmediate, setTimeout*/
/**
- * Stub functions
+ * Stub behavior
*
* @author Christian Johansen (christian@cjohansen.no)
+ * @author Tim Fischbach (mail@timfischbach.de)
* @license BSD
*
* Copyright (c) 2010-2013 Christian Johansen
*/
(function (sinon) {
- var commonJSModule = typeof module == "object" && typeof require == "function";
+ var commonJSModule = typeof module !== 'undefined' && module.exports;
if (!sinon && commonJSModule) {
sinon = require("../sinon");
}
if (!sinon) {
return;
}
- function stub(object, property, func) {
- if (!!func && typeof func != "function") {
- throw new TypeError("Custom stub should be function");
- }
+ var slice = Array.prototype.slice;
+ var join = Array.prototype.join;
+ var proto;
- var wrapper;
-
- if (func) {
- wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
+ var nextTick = (function () {
+ if (typeof process === "object" && typeof process.nextTick === "function") {
+ return process.nextTick;
+ } else if (typeof setImmediate === "function") {
+ return setImmediate;
} else {
- wrapper = stub.create();
+ return function (callback) {
+ setTimeout(callback, 0);
+ };
}
+ })();
- if (!object && !property) {
- return sinon.stub.create();
+ 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;
}
- if (!property && !!object && typeof object == "object") {
- for (var prop in object) {
- if (typeof object[prop] === "function") {
- stub(object, prop);
- }
- }
-
- return object;
- }
-
- return sinon.wrapMethod(object, property, wrapper);
+ return this;
}
- function getChangingValue(stub, property) {
- var index = stub.callCount - 1;
- var values = stub[property];
- var prop = index in values ? values[index] : values[values.length - 1];
- stub[property + "Last"] = prop;
+ function getCallback(behavior, args) {
+ var callArgAt = behavior.callArgAt;
- return prop;
- }
-
- function getCallback(stub, args) {
- var callArgAt = getChangingValue(stub, "callArgAts");
-
if (callArgAt < 0) {
- var callArgProp = getChangingValue(stub, "callArgProps");
+ var callArgProp = behavior.callArgProp;
for (var i = 0, l = args.length; i < l; ++i) {
if (!callArgProp && typeof args[i] == "function") {
return args[i];
}
@@ -1715,284 +1915,413 @@
}
return args[callArgAt];
}
- var join = Array.prototype.join;
-
- function getCallbackError(stub, func, args) {
- if (stub.callArgAtsLast < 0) {
+ function getCallbackError(behavior, func, args) {
+ if (behavior.callArgAt < 0) {
var msg;
- if (stub.callArgPropsLast) {
- msg = sinon.functionName(stub) +
- " expected to yield to '" + stub.callArgPropsLast +
- "', but no object with such a property was passed."
+ if (behavior.callArgProp) {
+ msg = sinon.functionName(behavior.stub) +
+ " expected to yield to '" + behavior.callArgProp +
+ "', but no object with such a property was passed.";
} else {
- msg = sinon.functionName(stub) +
- " expected to yield, but no callback was passed."
+ msg = sinon.functionName(behavior.stub) +
+ " expected to yield, but no callback was passed.";
}
if (args.length > 0) {
msg += " Received [" + join.call(args, ", ") + "]";
}
return msg;
}
- return "argument at index " + stub.callArgAtsLast + " is not a function: " + func;
+ return "argument at index " + behavior.callArgAt + " is not a function: " + func;
}
- var nextTick = (function () {
- if (typeof process === "object" && typeof process.nextTick === "function") {
- return process.nextTick;
- } else if (typeof setImmediate === "function") {
- return setImmediate;
- } else {
- return function (callback) {
- setTimeout(callback, 0);
- };
- }
- })();
+ function callCallback(behavior, args) {
+ if (typeof behavior.callArgAt == "number") {
+ var func = getCallback(behavior, args);
- function callCallback(stub, args) {
- if (stub.callArgAts.length > 0) {
- var func = getCallback(stub, args);
-
if (typeof func != "function") {
- throw new TypeError(getCallbackError(stub, func, args));
+ throw new TypeError(getCallbackError(behavior, func, args));
}
- var callbackArguments = getChangingValue(stub, "callbackArguments");
- var callbackContext = getChangingValue(stub, "callbackContexts");
-
- if (stub.callbackAsync) {
+ if (behavior.callbackAsync) {
nextTick(function() {
- func.apply(callbackContext, callbackArguments);
+ func.apply(behavior.callbackContext, behavior.callbackArguments);
});
} else {
- func.apply(callbackContext, callbackArguments);
+ func.apply(behavior.callbackContext, behavior.callbackArguments);
}
}
}
- var uuid = 0;
+ proto = {
+ create: function(stub) {
+ var behavior = sinon.extend({}, sinon.behavior);
+ delete behavior.create;
+ behavior.stub = stub;
- sinon.extend(stub, (function () {
- var slice = Array.prototype.slice, proto;
+ return behavior;
+ },
- 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;
+ isPresent: function() {
+ return (typeof this.callArgAt == 'number' ||
+ this.exception ||
+ typeof this.returnArgAt == 'number' ||
+ this.returnThis ||
+ this.returnValueDefined);
+ },
+
+ invoke: function(context, args) {
+ callCallback(this, args);
+
+ if (this.exception) {
+ throw this.exception;
+ } else if (typeof this.returnArgAt == 'number') {
+ return args[this.returnArgAt];
+ } else if (this.returnThis) {
+ return context;
}
+ return this.returnValue;
+ },
+
+ onCall: function(index) {
+ return this.stub.onCall(index);
+ },
+
+ onFirstCall: function() {
+ return this.stub.onFirstCall();
+ },
+
+ onSecondCall: function() {
+ return this.stub.onSecondCall();
+ },
+
+ onThirdCall: function() {
+ return this.stub.onThirdCall();
+ },
+
+ withArgs: function(/* arguments */) {
+ throw new Error('Defining a stub by invoking "stub.onCall(...).withArgs(...)" is not supported. ' +
+ 'Use "stub.withArgs(...).onCall(...)" to define sequential behavior for calls with certain arguments.');
+ },
+
+ callsArg: function callsArg(pos) {
+ if (typeof pos != "number") {
+ throw new TypeError("argument index is not number");
+ }
+
+ this.callArgAt = pos;
+ this.callbackArguments = [];
+ this.callbackContext = undefined;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
+
return this;
- }
+ },
- proto = {
- create: function create() {
- var functionStub = function () {
+ callsArgOn: function callsArgOn(pos, context) {
+ if (typeof pos != "number") {
+ throw new TypeError("argument index is not number");
+ }
+ if (typeof context != "object") {
+ throw new TypeError("argument context is not an object");
+ }
- callCallback(functionStub, arguments);
+ this.callArgAt = pos;
+ this.callbackArguments = [];
+ this.callbackContext = context;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
- if (functionStub.exception) {
- throw functionStub.exception;
- } else if (typeof functionStub.returnArgAt == 'number') {
- return arguments[functionStub.returnArgAt];
- } else if (functionStub.returnThis) {
- return this;
- }
- return functionStub.returnValue;
- };
+ return this;
+ },
- functionStub.id = "stub#" + uuid++;
- var orig = functionStub;
- functionStub = sinon.spy.create(functionStub);
- functionStub.func = orig;
+ callsArgWith: function callsArgWith(pos) {
+ if (typeof pos != "number") {
+ throw new TypeError("argument index is not number");
+ }
- functionStub.callArgAts = [];
- functionStub.callbackArguments = [];
- functionStub.callbackContexts = [];
- functionStub.callArgProps = [];
+ this.callArgAt = pos;
+ this.callbackArguments = slice.call(arguments, 1);
+ this.callbackContext = undefined;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
- sinon.extend(functionStub, stub);
- functionStub._create = sinon.stub.create;
- functionStub.displayName = "stub";
- functionStub.toString = sinon.functionToString;
+ return this;
+ },
- return functionStub;
- },
+ callsArgOnWith: function callsArgWith(pos, context) {
+ if (typeof pos != "number") {
+ throw new TypeError("argument index is not number");
+ }
+ if (typeof context != "object") {
+ throw new TypeError("argument context is not an object");
+ }
- resetBehavior: function () {
- var i;
+ this.callArgAt = pos;
+ this.callbackArguments = slice.call(arguments, 2);
+ this.callbackContext = context;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
- this.callArgAts = [];
- this.callbackArguments = [];
- this.callbackContexts = [];
- this.callArgProps = [];
+ return this;
+ },
- delete this.returnValue;
- delete this.returnArgAt;
- this.returnThis = false;
+ yields: function () {
+ this.callArgAt = -1;
+ this.callbackArguments = slice.call(arguments, 0);
+ this.callbackContext = undefined;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
- if (this.fakes) {
- for (i = 0; i < this.fakes.length; i++) {
- this.fakes[i].resetBehavior();
- }
- }
- },
+ return this;
+ },
- returns: function returns(value) {
- this.returnValue = value;
+ yieldsOn: function (context) {
+ if (typeof context != "object") {
+ throw new TypeError("argument context is not an object");
+ }
- return this;
- },
+ this.callArgAt = -1;
+ this.callbackArguments = slice.call(arguments, 1);
+ this.callbackContext = context;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
- returnsArg: function returnsArg(pos) {
- if (typeof pos != "number") {
- throw new TypeError("argument index is not number");
- }
+ return this;
+ },
- this.returnArgAt = pos;
+ yieldsTo: function (prop) {
+ this.callArgAt = -1;
+ this.callbackArguments = slice.call(arguments, 1);
+ this.callbackContext = undefined;
+ this.callArgProp = prop;
+ this.callbackAsync = false;
- return this;
- },
+ return this;
+ },
- returnsThis: function returnsThis() {
- this.returnThis = true;
+ yieldsToOn: function (prop, context) {
+ if (typeof context != "object") {
+ throw new TypeError("argument context is not an object");
+ }
- return this;
- },
+ this.callArgAt = -1;
+ this.callbackArguments = slice.call(arguments, 2);
+ this.callbackContext = context;
+ this.callArgProp = prop;
+ this.callbackAsync = false;
- "throws": throwsException,
- throwsException: throwsException,
+ return this;
+ },
- callsArg: function callsArg(pos) {
- if (typeof pos != "number") {
- throw new TypeError("argument index is not number");
- }
- this.callArgAts.push(pos);
- this.callbackArguments.push([]);
- this.callbackContexts.push(undefined);
- this.callArgProps.push(undefined);
+ "throws": throwsException,
+ throwsException: throwsException,
- return this;
- },
+ returns: function returns(value) {
+ this.returnValue = value;
+ this.returnValueDefined = true;
- callsArgOn: function callsArgOn(pos, context) {
- if (typeof pos != "number") {
- throw new TypeError("argument index is not number");
- }
- if (typeof context != "object") {
- throw new TypeError("argument context is not an object");
- }
+ return this;
+ },
- this.callArgAts.push(pos);
- this.callbackArguments.push([]);
- this.callbackContexts.push(context);
- this.callArgProps.push(undefined);
+ returnsArg: function returnsArg(pos) {
+ if (typeof pos != "number") {
+ throw new TypeError("argument index is not number");
+ }
- return this;
- },
+ this.returnArgAt = pos;
- callsArgWith: function callsArgWith(pos) {
- if (typeof pos != "number") {
- throw new TypeError("argument index is not number");
- }
+ return this;
+ },
- this.callArgAts.push(pos);
- this.callbackArguments.push(slice.call(arguments, 1));
- this.callbackContexts.push(undefined);
- this.callArgProps.push(undefined);
+ returnsThis: function returnsThis() {
+ this.returnThis = true;
- return this;
- },
+ return this;
+ }
+ };
- callsArgOnWith: function callsArgWith(pos, context) {
- if (typeof pos != "number") {
- throw new TypeError("argument index is not number");
- }
- if (typeof context != "object") {
- throw new TypeError("argument context is not an object");
- }
+ // create asynchronous versions of callsArg* and yields* methods
+ for (var method in proto) {
+ // need to avoid creating anotherasync versions of the newly added async methods
+ if (proto.hasOwnProperty(method) &&
+ method.match(/^(callsArg|yields)/) &&
+ !method.match(/Async/)) {
+ proto[method + 'Async'] = (function (syncFnName) {
+ return function () {
+ var result = this[syncFnName].apply(this, arguments);
+ this.callbackAsync = true;
+ return result;
+ };
+ })(method);
+ }
+ }
- this.callArgAts.push(pos);
- this.callbackArguments.push(slice.call(arguments, 2));
- this.callbackContexts.push(context);
- this.callArgProps.push(undefined);
+ if (commonJSModule) {
+ module.exports = proto;
+ } else {
+ sinon.behavior = proto;
+ }
+}(typeof sinon == "object" && sinon || null));
+/**
+ * @depend ../sinon.js
+ * @depend spy.js
+ * @depend behavior.js
+ */
+/*jslint eqeqeq: false, onevar: false*/
+/*global module, require, sinon*/
+/**
+ * Stub functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
- return this;
- },
+(function (sinon) {
+ var commonJSModule = typeof module !== 'undefined' && module.exports;
- yields: function () {
- this.callArgAts.push(-1);
- this.callbackArguments.push(slice.call(arguments, 0));
- this.callbackContexts.push(undefined);
- this.callArgProps.push(undefined);
+ if (!sinon && commonJSModule) {
+ sinon = require("../sinon");
+ }
- return this;
- },
+ if (!sinon) {
+ return;
+ }
- yieldsOn: function (context) {
- if (typeof context != "object") {
- throw new TypeError("argument context is not an object");
+ function stub(object, property, func) {
+ if (!!func && typeof func != "function") {
+ throw new TypeError("Custom stub should be function");
+ }
+
+ var wrapper;
+
+ if (func) {
+ wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
+ } else {
+ wrapper = stub.create();
+ }
+
+ if (!object && typeof property === "undefined") {
+ return sinon.stub.create();
+ }
+
+ if (typeof property === "undefined" && typeof object == "object") {
+ for (var prop in object) {
+ if (typeof object[prop] === "function") {
+ stub(object, prop);
}
+ }
- this.callArgAts.push(-1);
- this.callbackArguments.push(slice.call(arguments, 1));
- this.callbackContexts.push(context);
- this.callArgProps.push(undefined);
+ return object;
+ }
- return this;
+ return sinon.wrapMethod(object, property, wrapper);
+ }
+
+ function getDefaultBehavior(stub) {
+ return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
+ }
+
+ function getParentBehaviour(stub) {
+ return (stub.parent && getCurrentBehavior(stub.parent));
+ }
+
+ function getCurrentBehavior(stub) {
+ var behavior = stub.behaviors[stub.callCount - 1];
+ return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
+ }
+
+ var uuid = 0;
+
+ sinon.extend(stub, (function () {
+ var proto = {
+ create: function create() {
+ var functionStub = function () {
+ return getCurrentBehavior(functionStub).invoke(this, arguments);
+ };
+
+ functionStub.id = "stub#" + uuid++;
+ var orig = functionStub;
+ functionStub = sinon.spy.create(functionStub);
+ functionStub.func = orig;
+
+ sinon.extend(functionStub, stub);
+ functionStub._create = sinon.stub.create;
+ functionStub.displayName = "stub";
+ functionStub.toString = sinon.functionToString;
+
+ functionStub.defaultBehavior = null;
+ functionStub.behaviors = [];
+
+ return functionStub;
},
- yieldsTo: function (prop) {
- this.callArgAts.push(-1);
- this.callbackArguments.push(slice.call(arguments, 1));
- this.callbackContexts.push(undefined);
- this.callArgProps.push(prop);
+ resetBehavior: function () {
+ var i;
- return this;
+ this.defaultBehavior = null;
+ this.behaviors = [];
+
+ delete this.returnValue;
+ delete this.returnArgAt;
+ this.returnThis = false;
+
+ if (this.fakes) {
+ for (i = 0; i < this.fakes.length; i++) {
+ this.fakes[i].resetBehavior();
+ }
+ }
},
- yieldsToOn: function (prop, context) {
- if (typeof context != "object") {
- throw new TypeError("argument context is not an object");
+ onCall: function(index) {
+ if (!this.behaviors[index]) {
+ this.behaviors[index] = sinon.behavior.create(this);
}
- this.callArgAts.push(-1);
- this.callbackArguments.push(slice.call(arguments, 2));
- this.callbackContexts.push(context);
- this.callArgProps.push(prop);
+ return this.behaviors[index];
+ },
- return this;
+ onFirstCall: function() {
+ return this.onCall(0);
+ },
+
+ onSecondCall: function() {
+ return this.onCall(1);
+ },
+
+ onThirdCall: function() {
+ return this.onCall(2);
}
};
- // create asynchronous versions of callsArg* and yields* methods
- for (var method in proto) {
- // need to avoid creating anotherasync versions of the newly added async methods
- if (proto.hasOwnProperty(method) &&
- method.match(/^(callsArg|yields|thenYields$)/) &&
- !method.match(/Async/)) {
- proto[method + 'Async'] = (function (syncFnName) {
- return function () {
- this.callbackAsync = true;
- return this[syncFnName].apply(this, arguments);
+ for (var method in sinon.behavior) {
+ if (sinon.behavior.hasOwnProperty(method) &&
+ !proto.hasOwnProperty(method) &&
+ method != 'create' &&
+ method != 'withArgs' &&
+ method != 'invoke') {
+ proto[method] = (function(behaviorMethod) {
+ return function() {
+ this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
+ this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
+ return this;
};
- })(method);
+ }(method));
}
}
return proto;
-
}()));
if (commonJSModule) {
module.exports = stub;
} else {
@@ -2014,21 +2343,28 @@
*
* Copyright (c) 2010-2013 Christian Johansen
*/
(function (sinon) {
- var commonJSModule = typeof module == "object" && typeof require == "function";
+ var commonJSModule = typeof module !== 'undefined' && module.exports;
var push = [].push;
+ var match;
if (!sinon && commonJSModule) {
sinon = require("../sinon");
}
if (!sinon) {
return;
}
+ match = sinon.match;
+
+ if (!match && commonJSModule) {
+ match = require("./match");
+ }
+
function mock(object) {
if (!object) {
return sinon.expectation.create("Anonymous mock");
}
@@ -2205,10 +2541,18 @@
}
return expectation.callCount == expectation.maxCalls;
}
+ function verifyMatcher(possibleMatcher, arg){
+ if (match && match.isMatcher(possibleMatcher)) {
+ return possibleMatcher.test(arg);
+ } else {
+ return true;
+ }
+ }
+
return {
minCalls: 1,
maxCalls: 1,
create: function create(methodName) {
@@ -2314,10 +2658,16 @@
sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
"), expected " + sinon.format(this.expectedArguments));
}
for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
+
+ if (!verifyMatcher(this.expectedArguments[i],args[i])) {
+ sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
+ ", didn't match " + this.expectedArguments.toString());
+ }
+
if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
", expected " + sinon.format(this.expectedArguments));
}
}
@@ -2346,10 +2696,14 @@
args.length != this.expectedArguments.length) {
return false;
}
for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
+ if (!verifyMatcher(this.expectedArguments[i],args[i])) {
+ return false;
+ }
+
if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
return false;
}
}
@@ -2439,11 +2793,11 @@
*
* Copyright (c) 2010-2013 Christian Johansen
*/
(function (sinon) {
- var commonJSModule = typeof module == "object" && typeof require == "function";
+ var commonJSModule = typeof module !== 'undefined' && module.exports;
var push = [].push;
var hasOwnProperty = Object.prototype.hasOwnProperty;
if (!sinon && commonJSModule) {
sinon = require("../sinon");
@@ -2607,10 +2961,14 @@
function addTimer(args, recurring) {
if (args.length === 0) {
throw new Error("Function requires at least 1 parameter");
}
+ if (typeof args[0] === "undefined") {
+ throw new Error("Callback must be provided to timer calls");
+ }
+
var toId = id++;
var delay = args[1] || 0;
if (!this.timeouts) {
this.timeouts = {};
@@ -2708,10 +3066,20 @@
clearInterval: function clearInterval(timerId) {
this.clearTimeout(timerId);
},
+ setImmediate: function setImmediate(callback) {
+ var passThruArgs = Array.prototype.slice.call(arguments, 1);
+
+ return addTimer.call(this, [callback, 0].concat(passThruArgs), false);
+ },
+
+ clearImmediate: function clearImmediate(timerId) {
+ this.clearTimeout(timerId);
+ },
+
tick: function tick(ms) {
ms = typeof ms == "number" ? ms : parseTime(ms);
var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
var timer = this.firstTimerInRange(tickFrom, tickTo);
@@ -2738,19 +3106,19 @@
return this.now;
},
firstTimerInRange: function (from, to) {
- var timer, smallest, originalTimer;
+ var timer, smallest = null, originalTimer;
for (var id in this.timeouts) {
if (this.timeouts.hasOwnProperty(id)) {
if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
continue;
}
- if (!smallest || this.timeouts[id].callAt < smallest) {
+ if (smallest === null || this.timeouts[id].callAt < smallest) {
originalTimer = this.timeouts[id];
smallest = this.timeouts[id].callAt;
timer = {
func: this.timeouts[id].func,
@@ -2852,25 +3220,43 @@
target.prototype = source.prototype;
target.parse = source.parse;
target.UTC = source.UTC;
target.prototype.toUTCString = source.prototype.toUTCString;
+
+ for (var prop in source) {
+ if (source.hasOwnProperty(prop)) {
+ target[prop] = source[prop];
+ }
+ }
+
return target;
}
var methods = ["Date", "setTimeout", "setInterval",
"clearTimeout", "clearInterval"];
+ if (typeof global.setImmediate !== "undefined") {
+ methods.push("setImmediate");
+ }
+
+ if (typeof global.clearImmediate !== "undefined") {
+ methods.push("clearImmediate");
+ }
+
function restore() {
var method;
for (var i = 0, l = this.methods.length; i < l; i++) {
method = this.methods[i];
+
if (global[method].hadOwnProperty) {
global[method] = this["_" + method];
} else {
- delete global[method];
+ try {
+ delete global[method];
+ } catch (e) {}
}
}
// Prevent multiple executions which will completely remove these props
this.methods = [];
@@ -2917,16 +3303,18 @@
}(typeof global != "undefined" && typeof global !== "function" ? global : this));
sinon.timers = {
setTimeout: setTimeout,
clearTimeout: clearTimeout,
+ setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
+ clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
setInterval: setInterval,
clearInterval: clearInterval,
Date: Date
};
-if (typeof module == "object" && typeof require == "function") {
+if (typeof module !== 'undefined' && module.exports) {
module.exports = sinon;
}
/*jslint eqeqeq: false, onevar: false*/
/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
@@ -2967,18 +3355,37 @@
preventDefault: function () {
this.defaultPrevented = true;
}
};
+ sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
+ this.initEvent(type, false, false, target);
+ this.loaded = progressEventRaw.loaded || null;
+ this.total = progressEventRaw.total || null;
+ };
+
+ sinon.ProgressEvent.prototype = new sinon.Event();
+
+ sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent;
+
+ sinon.CustomEvent = function CustomEvent(type, customData, target) {
+ this.initEvent(type, false, false, target);
+ this.detail = customData.detail || null;
+ };
+
+ sinon.CustomEvent.prototype = new sinon.Event();
+
+ sinon.CustomEvent.prototype.constructor = sinon.CustomEvent;
+
sinon.EventTarget = {
- addEventListener: function addEventListener(event, listener, useCapture) {
+ addEventListener: function addEventListener(event, listener) {
this.eventListeners = this.eventListeners || {};
this.eventListeners[event] = this.eventListeners[event] || [];
push.call(this.eventListeners[event], listener);
},
- removeEventListener: function removeEventListener(event, listener, useCapture) {
+ removeEventListener: function removeEventListener(event, listener) {
var listeners = this.eventListeners && this.eventListeners[event] || [];
for (var i = 0, l = listeners.length; i < l; ++i) {
if (listeners[i] == listener) {
return listeners.splice(i, 1);
@@ -3016,24 +3423,27 @@
* @license BSD
*
* Copyright (c) 2010-2013 Christian Johansen
*/
-if (typeof sinon == "undefined") {
- this.sinon = {};
-}
-sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
-
// wrapper for global
(function(global) {
+ if (typeof sinon === "undefined") {
+ global.sinon = {};
+ }
+
+ var supportsProgress = typeof ProgressEvent !== "undefined";
+ var supportsCustomEvent = typeof CustomEvent !== "undefined";
+ sinon.xhr = { XMLHttpRequest: global.XMLHttpRequest };
var xhr = sinon.xhr;
xhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
xhr.GlobalActiveXObject = global.ActiveXObject;
xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != "undefined";
xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != "undefined";
xhr.workingXHR = xhr.supportsXHR ? xhr.GlobalXMLHttpRequest : xhr.supportsActiveX
? function() { return new xhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
+ xhr.supportsCORS = 'withCredentials' in (new sinon.xhr.GlobalXMLHttpRequest());
/*jsl:ignore*/
var unsafeHeaders = {
"Accept-Charset": true,
"Accept-Encoding": true,
@@ -3060,20 +3470,25 @@
this.readyState = FakeXMLHttpRequest.UNSENT;
this.requestHeaders = {};
this.requestBody = null;
this.status = 0;
this.statusText = "";
+ this.upload = new UploadProgress();
+ if (sinon.xhr.supportsCORS) {
+ this.withCredentials = false;
+ }
+
var xhr = this;
var events = ["loadstart", "load", "abort", "loadend"];
function addEventListener(eventName) {
xhr.addEventListener(eventName, function (event) {
var listener = xhr["on" + eventName];
if (listener && typeof listener == "function") {
- listener(event);
+ listener.call(this, event);
}
});
}
for (var i = events.length - 1; i >= 0; i--) {
@@ -3083,10 +3498,45 @@
if (typeof FakeXMLHttpRequest.onCreate == "function") {
FakeXMLHttpRequest.onCreate(this);
}
}
+ // An upload object is created for each
+ // FakeXMLHttpRequest and allows upload
+ // events to be simulated using uploadProgress
+ // and uploadError.
+ function UploadProgress() {
+ this.eventListeners = {
+ "progress": [],
+ "load": [],
+ "abort": [],
+ "error": []
+ }
+ }
+
+ UploadProgress.prototype.addEventListener = function(event, listener) {
+ this.eventListeners[event].push(listener);
+ };
+
+ UploadProgress.prototype.removeEventListener = function(event, listener) {
+ var listeners = this.eventListeners[event] || [];
+
+ for (var i = 0, l = listeners.length; i < l; ++i) {
+ if (listeners[i] == listener) {
+ return listeners.splice(i, 1);
+ }
+ }
+ };
+
+ UploadProgress.prototype.dispatchEvent = function(event) {
+ var listeners = this.eventListeners[event.type] || [];
+
+ for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
+ listener(event);
+ }
+ };
+
function verifyState(xhr) {
if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
throw new Error("INVALID_STATE_ERR");
}
@@ -3104,11 +3554,11 @@
}
}
function some(collection, callback) {
for (var index = 0; index < collection.length; index++) {
if(callback(collection[index]) === true) return true;
- };
+ }
return false;
}
// largest arity in XHR is 5 - XHR#open
var apply = function(obj,method,args) {
switch(args.length) {
@@ -3116,11 +3566,11 @@
case 1: return obj[method](args[0]);
case 2: return obj[method](args[0],args[1]);
case 3: return obj[method](args[0],args[1],args[2]);
case 4: return obj[method](args[0],args[1],args[2],args[3]);
case 5: return obj[method](args[0],args[1],args[2],args[3],args[4]);
- };
+ }
};
FakeXMLHttpRequest.filters = [];
FakeXMLHttpRequest.addFilter = function(fn) {
this.filters.push(fn)
@@ -3155,11 +3605,11 @@
copyAttrs(["responseText"]);
}
if(xhr.readyState === FakeXMLHttpRequest.DONE) {
copyAttrs(["responseXML"]);
}
- if(fakeXhr.onreadystatechange) fakeXhr.onreadystatechange.call(fakeXhr);
+ if(fakeXhr.onreadystatechange) fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
};
if(xhr.addEventListener) {
for(var event in fakeXhr.eventListeners) {
if(fakeXhr.eventListeners.hasOwnProperty(event)) {
each(fakeXhr.eventListeners[event],function(handler) {
@@ -3173,10 +3623,16 @@
}
apply(xhr,"open",xhrArgs);
};
FakeXMLHttpRequest.useFilters = false;
+ function verifyRequestOpened(xhr) {
+ if (xhr.readyState != FakeXMLHttpRequest.OPENED) {
+ throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
+ }
+ }
+
function verifyRequestSent(xhr) {
if (xhr.readyState == FakeXMLHttpRequest.DONE) {
throw new Error("Request done");
}
}
@@ -3236,10 +3692,14 @@
switch (this.readyState) {
case FakeXMLHttpRequest.DONE:
this.dispatchEvent(new sinon.Event("load", false, false, this));
this.dispatchEvent(new sinon.Event("loadend", false, false, this));
+ this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
+ if (supportsProgress) {
+ this.upload.dispatchEvent(new sinon.ProgressEvent('progress', {loaded: 100, total: 100}));
+ }
break;
}
},
setRequestHeader: function setRequestHeader(header, value) {
@@ -3256,10 +3716,11 @@
}
},
// Helps testing
setResponseHeaders: function setResponseHeaders(headers) {
+ verifyRequestOpened(this);
this.responseHeaders = {};
for (var header in headers) {
if (headers.hasOwnProperty(header)) {
this.responseHeaders[header] = headers[header];
@@ -3311,10 +3772,13 @@
}
this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
this.dispatchEvent(new sinon.Event("abort", false, false, this));
+
+ this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
+
if (typeof this.onerror === "function") {
this.onerror();
}
},
@@ -3390,18 +3854,26 @@
this.readyState = FakeXMLHttpRequest.DONE;
}
},
respond: function respond(status, headers, body) {
- this.setResponseHeaders(headers || {});
this.status = typeof status == "number" ? status : 200;
this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
+ this.setResponseHeaders(headers || {});
this.setResponseBody(body || "");
- if (typeof this.onload === "function"){
- this.onload();
+ },
+
+ uploadProgress: function uploadProgress(progressEventRaw) {
+ if (supportsProgress) {
+ this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
}
+ },
+ uploadError: function uploadError(error) {
+ if (supportsCustomEvent) {
+ this.upload.dispatchEvent(new sinon.CustomEvent("error", {"detail": error}));
+ }
}
});
sinon.extend(FakeXMLHttpRequest, {
UNSENT: 0,
@@ -3504,13 +3976,14 @@
return sinon.FakeXMLHttpRequest;
};
sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
-})(this);
-if (typeof module == "object" && typeof require == "function") {
+})(typeof global === "object" ? global : this);
+
+if (typeof module !== 'undefined' && module.exports) {
module.exports = sinon;
}
/**
* @depend fake_xml_http_request.js
@@ -3568,21 +4041,20 @@
return matchMethod && matchUrl;
}
function match(response, request) {
- var requestMethod = this.getHTTPMethod(request);
var requestUrl = request.url;
if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
requestUrl = requestUrl.replace(rCurrLoc, "");
}
if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
if (typeof response.response == "function") {
var ru = response.url;
- var args = [request].concat(!ru ? [] : requestUrl.match(ru).slice(1));
+ var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
return response.response.apply(response, args);
}
return true;
}
@@ -3616,20 +4088,20 @@
var server = this;
push.call(this.requests, xhrObj);
xhrObj.onSend = function () {
server.handleRequest(this);
- };
- if (this.autoRespond && !this.responding) {
- setTimeout(function () {
- server.responding = false;
- server.respond();
- }, this.autoRespondAfter || 10);
+ if (server.autoRespond && !server.responding) {
+ setTimeout(function () {
+ server.responding = false;
+ server.respond();
+ }, server.autoRespondAfter || 10);
- this.responding = true;
- }
+ server.responding = true;
+ }
+ };
},
getHTTPMethod: function getHTTPMethod(request) {
if (this.fakeHTTPMethods && /post/i.test(request.method)) {
var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
@@ -3678,13 +4150,14 @@
},
respond: function respond() {
if (arguments.length > 0) this.respondWith.apply(this, arguments);
var queue = this.queue || [];
+ var requests = queue.splice(0);
var request;
- while(request = queue.shift()) {
+ while(request = requests.shift()) {
this.processRequest(request);
}
},
processRequest: function processRequest(request) {
@@ -3694,11 +4167,11 @@
}
var response = this.response || [404, {}, ""];
if (this.responses) {
- for (var i = 0, l = this.responses.length; i < l; i++) {
+ for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
if (match.call(this, this.responses[i], request)) {
response = this.responses[i].response;
break;
}
}
@@ -3718,11 +4191,11 @@
return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
}
};
}());
-if (typeof module == "object" && typeof require == "function") {
+if (typeof module !== 'undefined' && module.exports) {
module.exports = sinon;
}
/**
* @depend fake_server.js
@@ -3823,11 +4296,11 @@
* @license BSD
*
* Copyright (c) 2010-2013 Christian Johansen
*/
-if (typeof module == "object" && typeof require == "function") {
+if (typeof module !== 'undefined' && module.exports) {
var sinon = require("../sinon");
sinon.extend(sinon, require("./util/fake_timers"));
}
(function () {
@@ -3836,12 +4309,13 @@
function exposeValue(sandbox, config, key, value) {
if (!value) {
return;
}
- if (config.injectInto) {
+ if (config.injectInto && !(key in config.injectInto)) {
config.injectInto[key] = value;
+ sandbox.injectedKeys.push(key);
} else {
push.call(sandbox.args, value);
}
}
@@ -3900,17 +4374,33 @@
}
return obj;
},
+ restore: function () {
+ sinon.collection.restore.apply(this, arguments);
+ this.restoreContext();
+ },
+
+ restoreContext: function () {
+ if (this.injectedKeys) {
+ for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
+ delete this.injectInto[this.injectedKeys[i]];
+ }
+ this.injectedKeys = [];
+ }
+ },
+
create: function (config) {
if (!config) {
return sinon.create(sinon.sandbox);
}
var sandbox = prepareSandboxFromConfig(config);
sandbox.args = sandbox.args || [];
+ sandbox.injectedKeys = [];
+ sandbox.injectInto = config.injectInto;
var prop, value, exposed = sandbox.inject({});
if (config.properties) {
for (var i = 0, l = config.properties.length; i < l; i++) {
prop = config.properties[i];
@@ -3925,11 +4415,11 @@
}
});
sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
- if (typeof module == "object" && typeof require == "function") {
+ if (typeof module !== 'undefined' && module.exports) {
module.exports = sinon.sandbox;
}
}());
/**
@@ -3948,11 +4438,11 @@
*
* Copyright (c) 2010-2013 Christian Johansen
*/
(function (sinon) {
- var commonJSModule = typeof module == "object" && typeof require == "function";
+ var commonJSModule = typeof module !== 'undefined' && module.exports;
if (!sinon && commonJSModule) {
sinon = require("../sinon");
}
@@ -4021,11 +4511,11 @@
*
* Copyright (c) 2010-2013 Christian Johansen
*/
(function (sinon) {
- var commonJSModule = typeof module == "object" && typeof require == "function";
+ var commonJSModule = typeof module !== 'undefined' && module.exports;
if (!sinon && commonJSModule) {
sinon = require("../sinon");
}
@@ -4118,11 +4608,11 @@
*
* Copyright (c) 2010-2013 Christian Johansen
*/
(function (sinon, global) {
- var commonJSModule = typeof module == "object" && typeof require == "function";
+ var commonJSModule = typeof module !== "undefined" && module.exports;
var slice = Array.prototype.slice;
var assert;
if (!sinon && commonJSModule) {
sinon = require("../sinon");
@@ -4186,11 +4676,11 @@
}
function exposedName(prefix, prop) {
return !prefix || /^fail/.test(prop) ? prop :
prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
- };
+ }
assert = {
failException: "AssertError",
fail: function fail(message) {
@@ -4254,10 +4744,24 @@
target[exposedName(prefix, method)] = this[method];
}
}
return target;
+ },
+
+ match: function match(actual, expectation) {
+ var matcher = sinon.match(expectation);
+ if (matcher.test(actual)) {
+ assert.pass("match");
+ } else {
+ var formatted = [
+ "expected value to match",
+ " expected = " + sinon.format(expectation),
+ " actual = " + sinon.format(actual)
+ ]
+ failAssertion(this, formatted.join("\n"));
+ }
}
};
mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
@@ -4285,6 +4789,6 @@
} else {
sinon.assert = assert;
}
}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
-return sinon;}.call(typeof window != 'undefined' && window || {}));
\ No newline at end of file
+return sinon;}.call(typeof window != 'undefined' && window || {}));