From f37e8e7b899748ad34b4dc2b89f0566a6bd609d2 Mon Sep 17 00:00:00 2001 From: Lars Jung Date: Tue, 31 May 2016 02:00:19 +0200 Subject: [PATCH] Update sinon to 1.17.3. --- .eslintignore | 4 +- test/vendor/sinon.js | 2394 +++++++++++++++++++++++++----------------- 2 files changed, 1452 insertions(+), 946 deletions(-) diff --git a/.eslintignore b/.eslintignore index 8de72900..7cba1cff 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,3 @@ -**/build/** -**/node_modules/** +build/** +node_modules/** **/vendor/** diff --git a/test/vendor/sinon.js b/test/vendor/sinon.js index 3a33c1fd..4ef8edf9 100644 --- a/test/vendor/sinon.js +++ b/test/vendor/sinon.js @@ -1,17 +1,17 @@ /** - * Sinon.JS 1.14.1, 2015/03/16 + * Sinon.JS 1.17.3, 2016/01/27 * * @author Christian Johansen (christian@cjohansen.no) * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS * * (The BSD License) - * + * * 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: - * + * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, @@ -20,7 +20,7 @@ * * Neither the name of Christian Johansen nor the names of his contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -34,6 +34,7 @@ */ (function (root, factory) { + 'use strict'; if (typeof define === 'function' && define.amd) { define('sinon', [], function () { return (root.sinon = factory()); @@ -44,7 +45,8 @@ root.sinon = factory(); } }(this, function () { - var samsam, formatio; + 'use strict'; + var samsam, formatio, lolex; (function () { function define(mod, deps, fn) { if (mod == "samsam") { @@ -461,7 +463,7 @@ module.exports = m(require("samsam")); }) || function (m) { this.formatio = m(this.samsam); } )(function (samsam) { - + var formatio = { excludeConstructors: ["Object", /^.$/], quoteStrings: true, @@ -564,7 +566,7 @@ processed.push(array); var pieces = []; var i, l; - l = (this.limitChildrenCount > 0) ? + l = (this.limitChildrenCount > 0) ? Math.min(this.limitChildrenCount, array.length) : array.length; for (i = 0; i < l; ++i) { @@ -584,7 +586,7 @@ var pieces = [], properties = samsam.keys(object).sort(); var length = 3; var prop, str, obj, i, k, l; - l = (this.limitChildrenCount > 0) ? + l = (this.limitChildrenCount > 0) ? Math.min(this.limitChildrenCount, properties.length) : properties.length; for (i = 0; i < l; ++i) { @@ -669,8 +671,7 @@ }); !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.lolex=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) { - throw new Error("tick only understands numbers and 'h:m:s'"); - } + var NOOP = function () { return undefined; }; + var timeoutResult = setTimeout(NOOP, 0); + var addTimerReturnsObject = typeof timeoutResult === "object"; + clearTimeout(timeoutResult); - while (i--) { - parsed = parseInt(strings[i], 10); + var NativeDate = Date; + var uniqueTimerId = 1; - if (parsed >= 60) { - throw new Error("Invalid time " + str); + /** + * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into + * number of milliseconds. This is used to support human-readable strings passed + * to clock.tick() + */ + function parseTime(str) { + if (!str) { + return 0; } - ms += parsed * Math.pow(60, (l - i - 1)); - } + var strings = str.split(":"); + var l = strings.length, i = l; + var ms = 0, parsed; - return ms * 1000; -} - -/** - * Used to grok the `now` parameter to createClock. - */ -function getEpoch(epoch) { - if (!epoch) { return 0; } - if (typeof epoch.getTime === "function") { return epoch.getTime(); } - if (typeof epoch === "number") { return epoch; } - throw new TypeError("now should be milliseconds since UNIX epoch"); -} - -function inRange(from, to, timer) { - return timer && timer.callAt >= from && timer.callAt <= to; -} - -function mirrorDateProperties(target, source) { - if (source.now) { - target.now = function now() { - return target.clock.now; - }; - } else { - delete target.now; - } - - if (source.toSource) { - target.toSource = function toSource() { - return source.toSource(); - }; - } else { - delete target.toSource; - } - - target.toString = function toString() { - return source.toString(); - }; - - 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]; + if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) { + throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits"); } - } - return target; -} + while (i--) { + parsed = parseInt(strings[i], 10); -function createDate() { - function ClockDate(year, month, date, hour, minute, second, ms) { - // Defensive and verbose to avoid potential harm in passing - // explicit undefined when user does not pass argument - switch (arguments.length) { - case 0: - return new NativeDate(ClockDate.clock.now); - case 1: - return new NativeDate(year); - case 2: - return new NativeDate(year, month); - case 3: - return new NativeDate(year, month, date); - case 4: - return new NativeDate(year, month, date, hour); - case 5: - return new NativeDate(year, month, date, hour, minute); - case 6: - return new NativeDate(year, month, date, hour, minute, second); - default: - return new NativeDate(year, month, date, hour, minute, second, ms); + if (parsed >= 60) { + throw new Error("Invalid time " + str); + } + + ms += parsed * Math.pow(60, (l - i - 1)); } + + return ms * 1000; } - return mirrorDateProperties(ClockDate, NativeDate); -} - -function addTimer(clock, timer) { - if (typeof timer.func === "undefined") { - throw new Error("Callback must be provided to timer calls"); + /** + * Used to grok the `now` parameter to createClock. + */ + function getEpoch(epoch) { + if (!epoch) { return 0; } + if (typeof epoch.getTime === "function") { return epoch.getTime(); } + if (typeof epoch === "number") { return epoch; } + throw new TypeError("now should be milliseconds since UNIX epoch"); } - if (!clock.timers) { - clock.timers = {}; + function inRange(from, to, timer) { + return timer && timer.callAt >= from && timer.callAt <= to; } - timer.id = id++; - timer.createdAt = clock.now; - timer.callAt = clock.now + (timer.delay || 0); + function mirrorDateProperties(target, source) { + var prop; + for (prop in source) { + if (source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } - clock.timers[timer.id] = timer; + // set special now implementation + if (source.now) { + target.now = function now() { + return target.clock.now; + }; + } else { + delete target.now; + } - if (addTimerReturnsObject) { - return { - id: timer.id, - ref: function() {}, - unref: function() {} + // set special toSource implementation + if (source.toSource) { + target.toSource = function toSource() { + return source.toSource(); + }; + } else { + delete target.toSource; + } + + // set special toString implementation + target.toString = function toString() { + return source.toString(); }; + + target.prototype = source.prototype; + target.parse = source.parse; + target.UTC = source.UTC; + target.prototype.toUTCString = source.prototype.toUTCString; + + return target; } - else { + + function createDate() { + function ClockDate(year, month, date, hour, minute, second, ms) { + // Defensive and verbose to avoid potential harm in passing + // explicit undefined when user does not pass argument + switch (arguments.length) { + case 0: + return new NativeDate(ClockDate.clock.now); + case 1: + return new NativeDate(year); + case 2: + return new NativeDate(year, month); + case 3: + return new NativeDate(year, month, date); + case 4: + return new NativeDate(year, month, date, hour); + case 5: + return new NativeDate(year, month, date, hour, minute); + case 6: + return new NativeDate(year, month, date, hour, minute, second); + default: + return new NativeDate(year, month, date, hour, minute, second, ms); + } + } + + return mirrorDateProperties(ClockDate, NativeDate); + } + + function addTimer(clock, timer) { + if (timer.func === undefined) { + throw new Error("Callback must be provided to timer calls"); + } + + if (!clock.timers) { + clock.timers = {}; + } + + timer.id = uniqueTimerId++; + timer.createdAt = clock.now; + timer.callAt = clock.now + (timer.delay || (clock.duringTick ? 1 : 0)); + + clock.timers[timer.id] = timer; + + if (addTimerReturnsObject) { + return { + id: timer.id, + ref: NOOP, + unref: NOOP + }; + } + return timer.id; } -} -function firstTimerInRange(clock, from, to) { - var timers = clock.timers, timer = null; - for (var id in timers) { - if (!inRange(from, to, timers[id])) { - continue; + function compareTimers(a, b) { + // Sort first by absolute timing + if (a.callAt < b.callAt) { + return -1; + } + if (a.callAt > b.callAt) { + return 1; } - if (!timer || ~compareTimers(timer, timers[id])) { - timer = timers[id]; + // Sort next by immediate, immediate timers take precedence + if (a.immediate && !b.immediate) { + return -1; } + if (!a.immediate && b.immediate) { + return 1; + } + + // Sort next by creation time, earlier-created timers take precedence + if (a.createdAt < b.createdAt) { + return -1; + } + if (a.createdAt > b.createdAt) { + return 1; + } + + // Sort next by id, lower-id timers take precedence + if (a.id < b.id) { + return -1; + } + if (a.id > b.id) { + return 1; + } + + // As timer ids are unique, no fallback `0` is necessary } - return timer; -} + function firstTimerInRange(clock, from, to) { + var timers = clock.timers, + timer = null, + id, + isInRange; -function compareTimers(a, b) { - // Sort first by absolute timing - if (a.callAt < b.callAt) { - return -1; - } - if (a.callAt > b.callAt) { - return 1; + for (id in timers) { + if (timers.hasOwnProperty(id)) { + isInRange = inRange(from, to, timers[id]); + + if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) { + timer = timers[id]; + } + } + } + + return timer; } - // Sort next by immediate, immediate timers take precedence - if (a.immediate && !b.immediate) { - return -1; - } - if (!a.immediate && b.immediate) { - return 1; + function firstTimer(clock) { + var timers = clock.timers, + timer = null, + id; + + for (id in timers) { + if (timers.hasOwnProperty(id)) { + if (!timer || compareTimers(timer, timers[id]) === 1) { + timer = timers[id]; + } + } + } + + return timer; } - // Sort next by creation time, earlier-created timers take precedence - if (a.createdAt < b.createdAt) { - return -1; - } - if (a.createdAt > b.createdAt) { - return 1; - } + function callTimer(clock, timer) { + var exception; - // Sort next by id, lower-id timers take precedence - if (a.id < b.id) { - return -1; - } - if (a.id > b.id) { - return 1; - } - - // As timer ids are unique, no fallback `0` is necessary -} - -function callTimer(clock, timer) { - if (typeof timer.interval == "number") { - clock.timers[timer.id].callAt += timer.interval; - } else { - delete clock.timers[timer.id]; - } - - try { - if (typeof timer.func == "function") { - timer.func.apply(null, timer.args); + if (typeof timer.interval === "number") { + clock.timers[timer.id].callAt += timer.interval; } else { - eval(timer.func); + delete clock.timers[timer.id]; + } + + try { + if (typeof timer.func === "function") { + timer.func.apply(null, timer.args); + } else { + eval(timer.func); + } + } catch (e) { + exception = e; + } + + if (!clock.timers[timer.id]) { + if (exception) { + throw exception; + } + return; } - } catch (e) { - var exception = e; - } - if (!clock.timers[timer.id]) { if (exception) { throw exception; } - return; } - if (exception) { - throw exception; - } -} - -function uninstall(clock, target) { - var method; - - for (var i = 0, l = clock.methods.length; i < l; i++) { - method = clock.methods[i]; - - if (target[method].hadOwnProperty) { - target[method] = clock["_" + method]; + function timerType(timer) { + if (timer.immediate) { + return "Immediate"; + } else if (typeof timer.interval !== "undefined") { + return "Interval"; } else { - try { - delete target[method]; - } catch (e) {} + return "Timeout"; } } - // Prevent multiple executions which will completely remove these props - clock.methods = []; -} - -function hijackMethod(target, method, clock) { - clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method); - clock["_" + method] = target[method]; - - if (method == "Date") { - var date = mirrorDateProperties(clock[method], target[method]); - target[method] = date; - } else { - target[method] = function () { - return clock[method].apply(clock, arguments); - }; - - for (var prop in clock[method]) { - if (clock[method].hasOwnProperty(prop)) { - target[method][prop] = clock[method][prop]; - } - } - } - - target[method].clock = clock; -} - -var timers = { - setTimeout: setTimeout, - clearTimeout: clearTimeout, - setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined), - clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined), - setInterval: setInterval, - clearInterval: clearInterval, - Date: Date -}; - -var keys = Object.keys || function (obj) { - var ks = []; - for (var key in obj) { - ks.push(key); - } - return ks; -}; - -exports.timers = timers; - -var createClock = exports.createClock = function (now) { - var clock = { - now: getEpoch(now), - timeouts: {}, - Date: createDate() - }; - - clock.Date.clock = clock; - - clock.setTimeout = function setTimeout(func, timeout) { - return addTimer(clock, { - func: func, - args: Array.prototype.slice.call(arguments, 2), - delay: timeout - }); - }; - - clock.clearTimeout = function clearTimeout(timerId) { + function clearTimer(clock, timerId, ttype) { if (!timerId) { // null appears to be allowed in most browsers, and appears to be // relied upon by some libraries, like Bootstrap carousel return; } + if (!clock.timers) { clock.timers = []; } + // in Node, timerId is an object with .ref()/.unref(), and // its .id field is the actual timer id. if (typeof timerId === "object") { - timerId = timerId.id + timerId = timerId.id; } - if (timerId in clock.timers) { - delete clock.timers[timerId]; + + if (clock.timers.hasOwnProperty(timerId)) { + // check that the ID matches a timer of the correct type + var timer = clock.timers[timerId]; + if (timerType(timer) === ttype) { + delete clock.timers[timerId]; + } else { + throw new Error("Cannot clear timer: timer created with set" + ttype + "() but cleared with clear" + timerType(timer) + "()"); + } } - }; + } - clock.setInterval = function setInterval(func, timeout) { - return addTimer(clock, { - func: func, - args: Array.prototype.slice.call(arguments, 2), - delay: timeout, - interval: timeout - }); - }; + function uninstall(clock, target) { + var method, + i, + l; - clock.clearInterval = function clearInterval(timerId) { - clock.clearTimeout(timerId); - }; + for (i = 0, l = clock.methods.length; i < l; i++) { + method = clock.methods[i]; - clock.setImmediate = function setImmediate(func) { - return addTimer(clock, { - func: func, - args: Array.prototype.slice.call(arguments, 1), - immediate: true - }); - }; - - clock.clearImmediate = function clearImmediate(timerId) { - clock.clearTimeout(timerId); - }; - - clock.tick = function tick(ms) { - ms = typeof ms == "number" ? ms : parseTime(ms); - var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now; - var timer = firstTimerInRange(clock, tickFrom, tickTo); - - var firstException; - while (timer && tickFrom <= tickTo) { - if (clock.timers[timer.id]) { - tickFrom = clock.now = timer.callAt; + if (target[method].hadOwnProperty) { + target[method] = clock["_" + method]; + } else { try { - callTimer(clock, timer); - } catch (e) { - firstException = firstException || e; + delete target[method]; + } catch (ignore) {} + } + } + + // Prevent multiple executions which will completely remove these props + clock.methods = []; + } + + function hijackMethod(target, method, clock) { + var prop; + + clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method); + clock["_" + method] = target[method]; + + if (method === "Date") { + var date = mirrorDateProperties(clock[method], target[method]); + target[method] = date; + } else { + target[method] = function () { + return clock[method].apply(clock, arguments); + }; + + for (prop in clock[method]) { + if (clock[method].hasOwnProperty(prop)) { + target[method][prop] = clock[method][prop]; } } - - timer = firstTimerInRange(clock, previous, tickTo); - previous = tickFrom; } - clock.now = tickTo; + target[method].clock = clock; + } - if (firstException) { - throw firstException; + var timers = { + setTimeout: setTimeout, + clearTimeout: clearTimeout, + setImmediate: global.setImmediate, + clearImmediate: global.clearImmediate, + setInterval: setInterval, + clearInterval: clearInterval, + Date: Date + }; + + var keys = Object.keys || function (obj) { + var ks = [], + key; + + for (key in obj) { + if (obj.hasOwnProperty(key)) { + ks.push(key); + } } - return clock.now; + return ks; }; - clock.reset = function reset() { - clock.timers = {}; + exports.timers = timers; + + function createClock(now) { + var clock = { + now: getEpoch(now), + timeouts: {}, + Date: createDate() + }; + + clock.Date.clock = clock; + + clock.setTimeout = function setTimeout(func, timeout) { + return addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 2), + delay: timeout + }); + }; + + clock.clearTimeout = function clearTimeout(timerId) { + return clearTimer(clock, timerId, "Timeout"); + }; + + clock.setInterval = function setInterval(func, timeout) { + return addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 2), + delay: timeout, + interval: timeout + }); + }; + + clock.clearInterval = function clearInterval(timerId) { + return clearTimer(clock, timerId, "Interval"); + }; + + clock.setImmediate = function setImmediate(func) { + return addTimer(clock, { + func: func, + args: Array.prototype.slice.call(arguments, 1), + immediate: true + }); + }; + + clock.clearImmediate = function clearImmediate(timerId) { + return clearTimer(clock, timerId, "Immediate"); + }; + + clock.tick = function tick(ms) { + ms = typeof ms === "number" ? ms : parseTime(ms); + var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now; + var timer = firstTimerInRange(clock, tickFrom, tickTo); + var oldNow; + + clock.duringTick = true; + + var firstException; + while (timer && tickFrom <= tickTo) { + if (clock.timers[timer.id]) { + tickFrom = clock.now = timer.callAt; + try { + oldNow = clock.now; + callTimer(clock, timer); + // compensate for any setSystemTime() call during timer callback + if (oldNow !== clock.now) { + tickFrom += clock.now - oldNow; + tickTo += clock.now - oldNow; + previous += clock.now - oldNow; + } + } catch (e) { + firstException = firstException || e; + } + } + + timer = firstTimerInRange(clock, previous, tickTo); + previous = tickFrom; + } + + clock.duringTick = false; + clock.now = tickTo; + + if (firstException) { + throw firstException; + } + + return clock.now; + }; + + clock.next = function next() { + var timer = firstTimer(clock); + if (!timer) { + return clock.now; + } + + clock.duringTick = true; + try { + clock.now = timer.callAt; + callTimer(clock, timer); + return clock.now; + } finally { + clock.duringTick = false; + } + }; + + clock.reset = function reset() { + clock.timers = {}; + }; + + clock.setSystemTime = function setSystemTime(now) { + // determine time difference + var newNow = getEpoch(now); + var difference = newNow - clock.now; + + // update 'system clock' + clock.now = newNow; + + // update timers and intervals to keep them stable + for (var id in clock.timers) { + if (clock.timers.hasOwnProperty(id)) { + var timer = clock.timers[id]; + timer.createdAt += difference; + timer.callAt += difference; + } + } + }; + + return clock; + } + exports.createClock = createClock; + + exports.install = function install(target, now, toFake) { + var i, + l; + + if (typeof target === "number") { + toFake = now; + now = target; + target = null; + } + + if (!target) { + target = global; + } + + var clock = createClock(now); + + clock.uninstall = function () { + uninstall(clock, target); + }; + + clock.methods = toFake || []; + + if (clock.methods.length === 0) { + clock.methods = keys(timers); + } + + for (i = 0, l = clock.methods.length; i < l; i++) { + hijackMethod(target, clock.methods[i], clock); + } + + return clock; }; - return clock; -}; - -exports.install = function install(target, now, toFake) { - if (typeof target === "number") { - toFake = now; - now = target; - target = null; - } - - if (!target) { - target = global; - } - - var clock = createClock(now); - - clock.uninstall = function () { - uninstall(clock, target); - }; - - clock.methods = toFake || []; - - if (clock.methods.length === 0) { - clock.methods = keys(timers); - } - - for (var i = 0, l = clock.methods.length; i < l; i++) { - hijackMethod(target, clock.methods[i], clock); - } - - return clock; -}; +}(global || this)); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}]},{},[1])(1) @@ -1104,17 +1235,18 @@ exports.install = function install(target, now, toFake) { * * Copyright (c) 2010-2013 Christian Johansen */ - var sinon = (function () { "use strict"; + // eslint-disable-line no-unused-vars - var sinon; + var sinonModule; var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { - sinon = module.exports = require("./sinon/util/core"); + sinonModule = module.exports = require("./sinon/util/core"); require("./sinon/extend"); + require("./sinon/walk"); require("./sinon/typeOf"); require("./sinon/times_in_words"); require("./sinon/spy"); @@ -1136,12 +1268,12 @@ var sinon = (function () { define(loadDependencies); } else if (isNode) { loadDependencies(require, module.exports, module); - sinon = module.exports; + sinonModule = module.exports; } else { - sinon = {}; + sinonModule = {}; } - return sinon; + return sinonModule; }()); /** @@ -1155,9 +1287,9 @@ var sinon = (function () { * * Copyright (c) 2010-2013 Christian Johansen */ +(function (sinonGlobal) { -(function (sinon) { - var div = typeof document != "undefined" && document.createElement("div"); + var div = typeof document !== "undefined" && document.createElement("div"); var hasOwn = Object.prototype.hasOwnProperty; function isDOMNode(obj) { @@ -1165,7 +1297,7 @@ var sinon = (function () { try { obj.appendChild(div); - success = div.parentNode == obj; + success = div.parentNode === obj; } catch (e) { return false; } finally { @@ -1212,18 +1344,20 @@ var sinon = (function () { throw new TypeError("Should wrap property of object"); } - if (typeof method != "function" && typeof method != "object") { + if (typeof method !== "function" && typeof method !== "object") { throw new TypeError("Method wrapper should be a function or a property descriptor"); } function checkWrappedMethod(wrappedMethod) { + var error; + if (!isFunction(wrappedMethod)) { error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " + property + " as function"); } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) { error = new TypeError("Attempted to wrap " + property + " which is already wrapped"); } else if (wrappedMethod.calledBefore) { - var verb = !!wrappedMethod.returns ? "stubbed" : "spied on"; + var verb = wrappedMethod.returns ? "stubbed" : "spied on"; error = new TypeError("Attempted to wrap " + property + " which is already " + verb); } @@ -1235,16 +1369,15 @@ var sinon = (function () { } } - var error, wrappedMethod; + var error, wrappedMethod, i; // 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); if (hasES5Support) { - var methodDesc = (typeof method == "function") ? {value: method} : method, - wrappedMethodDesc = sinon.getPropertyDescriptor(object, property), - i; + var methodDesc = (typeof method === "function") ? {value: method} : method; + var wrappedMethodDesc = sinon.getPropertyDescriptor(object, property); if (!wrappedMethodDesc) { error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " + @@ -1288,21 +1421,19 @@ var sinon = (function () { // If this fails (ex: localStorage on mobile safari) then force a reset // via direct assignment. if (!owned) { + // In some cases `delete` may throw an error try { delete object[property]; - } catch (e) {} + } catch (e) {} // eslint-disable-line no-empty // For native code functions `delete` fails without throwing an error // on Chrome < 43, PhantomJS, etc. - // Use strict equality comparison to check failures then force a reset - // via direct assignment. - if (object[property] === method) { - object[property] = wrappedMethod; - } } else if (hasES5Support) { Object.defineProperty(object, property, wrappedMethodDesc); } - if (!hasES5Support && object[property] === method) { + // Use strict equality comparison to check failures then force a reset + // via direct assignment. + if (object[property] === method) { object[property] = wrappedMethod; } }; @@ -1327,12 +1458,8 @@ var sinon = (function () { return a.test(b); } - if (typeof a != "object" || typeof b != "object") { - if (isReallyNaN(a) && isReallyNaN(b)) { - return true; - } else { - return a === b; - } + if (typeof a !== "object" || typeof b !== "object") { + return isReallyNaN(a) && isReallyNaN(b) || a === b; } if (isElement(a) || isElement(b)) { @@ -1353,37 +1480,43 @@ var sinon = (function () { } var aString = Object.prototype.toString.call(a); - if (aString != Object.prototype.toString.call(b)) { + if (aString !== Object.prototype.toString.call(b)) { return false; } - if (aString == "[object Date]") { + if (aString === "[object Date]") { return a.valueOf() === b.valueOf(); } - var prop, aLength = 0, bLength = 0; + var prop; + var aLength = 0; + var bLength = 0; - if (aString == "[object Array]" && a.length !== b.length) { + if (aString === "[object Array]" && a.length !== b.length) { return false; } for (prop in a) { - aLength += 1; + if (a.hasOwnProperty(prop)) { + aLength += 1; - if (!(prop in b)) { - return false; - } + if (!(prop in b)) { + return false; + } - if (!deepEqual(a[prop], b[prop])) { - return false; + if (!deepEqual(a[prop], b[prop])) { + return false; + } } } for (prop in b) { - bLength += 1; + if (b.hasOwnProperty(prop)) { + bLength += 1; + } } - return aLength == bLength; + return aLength === bLength; }; sinon.functionName = function functionName(func) { @@ -1403,7 +1536,9 @@ var sinon = (function () { sinon.functionToString = function toString() { if (this.getCall && this.callCount) { - var thisValue, prop, i = this.callCount; + var thisValue, + prop; + var i = this.callCount; while (i--) { thisValue = this.getCall(i).thisValue; @@ -1436,12 +1571,14 @@ var sinon = (function () { }; sinon.getPropertyDescriptor = function getPropertyDescriptor(object, property) { - var proto = object, descriptor; + var proto = object; + var descriptor; + while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) { proto = Object.getPrototypeOf(proto); } return descriptor; - } + }; sinon.getConfig = function (custom) { var config = {}; @@ -1466,9 +1603,9 @@ var sinon = (function () { }; sinon.timesInWords = function timesInWords(count) { - return count == 1 && "once" || - count == 2 && "twice" || - count == 3 && "thrice" || + return count === 1 && "once" || + count === 2 && "twice" || + count === 3 && "thrice" || (count || 0) + " times"; }; @@ -1516,7 +1653,7 @@ var sinon = (function () { return sinon; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports) { @@ -1525,20 +1662,26 @@ var sinon = (function () { if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend util/core.js */ +(function (sinonGlobal) { -(function (sinon) { function makeApi(sinon) { // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug @@ -1572,13 +1715,15 @@ var sinon = (function () { return "8"; }, unique: function () { - return "9" + return "9"; } }; var result = []; for (var prop in obj) { - result.push(obj[prop]()); + if (obj.hasOwnProperty(prop)) { + result.push(obj[prop]()); + } } return result.join("") !== "0123456789"; })(); @@ -1592,8 +1737,8 @@ var sinon = (function () { * Returns the extended target */ function extend(target /*, sources */) { - var sources = Array.prototype.slice.call(arguments, 1), - source, i, prop; + var sources = Array.prototype.slice.call(arguments, 1); + var source, i, prop; for (i = 0; i < sources.length; i++) { source = sources[i]; @@ -1612,7 +1757,7 @@ var sinon = (function () { } return target; - }; + } sinon.extend = extend; return sinon.extend; @@ -1623,25 +1768,31 @@ var sinon = (function () { module.exports = makeApi(sinon); } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend util/core.js */ +(function (sinonGlobal) { -(function (sinon) { function makeApi(sinon) { function timesInWords(count) { @@ -1662,23 +1813,29 @@ var sinon = (function () { } function loadDependencies(require, exports, module) { - var sinon = require("./util/core"); - module.exports = makeApi(sinon); + var core = require("./util/core"); + module.exports = makeApi(core); } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend util/core.js @@ -1691,8 +1848,8 @@ var sinon = (function () { * * Copyright (c) 2010-2014 Christian Johansen */ +(function (sinonGlobal) { -(function (sinon, formatio) { function makeApi(sinon) { function typeOf(value) { if (value === null) { @@ -1702,32 +1859,35 @@ var sinon = (function () { } var string = Object.prototype.toString.call(value); return string.substring(8, string.length - 1).toLowerCase(); - }; + } sinon.typeOf = typeOf; return sinon.typeOf; } function loadDependencies(require, exports, module) { - var sinon = require("./util/core"); - module.exports = makeApi(sinon); + var core = require("./util/core"); + module.exports = makeApi(core); } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); + } + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); } }( - (typeof sinon == "object" && sinon || null), - (typeof formatio == "object" && formatio) + typeof sinon === "object" && sinon // eslint-disable-line no-undef )); /** @@ -1744,8 +1904,8 @@ var sinon = (function () { * * Copyright (c) 2012 Maximilian Antoni */ +(function (sinonGlobal) { -(function (sinon) { function makeApi(sinon) { function assertType(value, type, name) { var actual = sinon.typeOf(value); @@ -1773,7 +1933,7 @@ var sinon = (function () { if (expectation.hasOwnProperty(key)) { var exp = expectation[key]; var act = actual[key]; - if (match.isMatcher(exp)) { + if (isMatcher(exp)) { if (!exp.test(act)) { return false; } @@ -1789,37 +1949,7 @@ var sinon = (function () { return true; } - matcher.or = function (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); - }; - or.message = m1.message + ".or(" + m2.message + ")"; - return or; - }; - - matcher.and = function (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); - }; - and.message = m1.message + ".and(" + m2.message + ")"; - return and; - }; - - var match = function (expectation, message) { + function match(expectation, message) { var m = sinon.create(matcher); var type = sinon.typeOf(expectation); switch (type) { @@ -1844,7 +1974,8 @@ var sinon = (function () { break; case "number": m.test = function (actual) { - return expectation == actual; + // we need type coercion here + return expectation == actual; // eslint-disable-line eqeqeq }; break; case "string": @@ -1881,6 +2012,36 @@ var sinon = (function () { m.message = "match(" + expectation + ")"; } return m; + } + + matcher.or = function (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); + }; + or.message = m1.message + ".or(" + m2.message + ")"; + return or; + }; + + matcher.and = function (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); + }; + and.message = m1.message + ".and(" + m2.message + ")"; + return and; }; match.isMatcher = isMatcher; @@ -1964,7 +2125,7 @@ var sinon = (function () { return match; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { @@ -1975,14 +2136,20 @@ var sinon = (function () { if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend util/core.js @@ -1995,8 +2162,8 @@ var sinon = (function () { * * Copyright (c) 2010-2014 Christian Johansen */ +(function (sinonGlobal, formatio) { -(function (sinon, formatio) { function makeApi(sinon) { function valueFormatter(value) { return "" + value; @@ -2010,36 +2177,38 @@ var sinon = (function () { function format() { return formatter.ascii.apply(formatter, arguments); - }; + } return format; } - function getNodeFormatter(value) { - function format(value) { - return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value; - }; - + function getNodeFormatter() { try { var util = require("util"); } catch (e) { /* Node, but no util module - would be very old, but better safe than sorry */ } + function format(v) { + var isObjectWithNativeToString = typeof v === "object" && v.toString === Object.prototype.toString; + return isObjectWithNativeToString ? util.inspect(v) : v; + } + return util ? format : valueFormatter; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function", - formatter; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; + var formatter; if (isNode) { try { formatio = require("formatio"); - } catch (e) {} + } + catch (e) {} // eslint-disable-line no-empty } if (formatio) { - formatter = getFormatioFormatter() + formatter = getFormatioFormatter(); } else if (isNode) { formatter = getNodeFormatter(); } else { @@ -2055,21 +2224,25 @@ var sinon = (function () { module.exports = makeApi(sinon); } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); + } + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); } }( - (typeof sinon == "object" && sinon || null), - (typeof formatio == "object" && formatio) + typeof sinon === "object" && sinon, // eslint-disable-line no-undef + typeof formatio === "object" && formatio // eslint-disable-line no-undef )); /** @@ -2087,8 +2260,10 @@ var sinon = (function () { * Copyright (c) 2010-2013 Christian Johansen * Copyright (c) 2013 Maximilian Antoni */ +(function (sinonGlobal) { + + var slice = Array.prototype.slice; -(function (sinon) { function makeApi(sinon) { function throwYieldError(proxy, text, args) { var msg = sinon.functionName(proxy) + text; @@ -2098,8 +2273,6 @@ var sinon = (function () { throw new Error(msg); } - var slice = Array.prototype.slice; - var callProto = { calledOn: function calledOn(thisValue) { if (sinon.match && sinon.match.isMatcher(thisValue)) { @@ -2138,7 +2311,7 @@ var sinon = (function () { }, calledWithExactly: function calledWithExactly() { - return arguments.length == this.args.length && + return arguments.length === this.args.length && this.calledWith.apply(this, arguments); }, @@ -2191,7 +2364,7 @@ var sinon = (function () { this.args[pos].apply(thisValue, args); }, - yield: function () { + "yield": function () { this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0))); }, @@ -2222,17 +2395,26 @@ var sinon = (function () { "' since no callback was passed.", args); }, + getStackFrames: function () { + // Omit the error message and the two top stack frames in sinon itself: + return this.stack && this.stack.split("\n").slice(3); + }, + toString: function () { - var callStr = this.proxy.toString() + "("; + var callStr = this.proxy ? this.proxy.toString() + "(" : ""; var args = []; + if (!this.args) { + return ":("; + } + for (var i = 0, l = this.args.length; i < l; ++i) { args.push(sinon.format(this.args[i])); } callStr = callStr + args.join(", ") + ")"; - if (typeof this.returnValue != "undefined") { + if (typeof this.returnValue !== "undefined") { callStr += " => " + sinon.format(this.returnValue); } @@ -2243,6 +2425,10 @@ var sinon = (function () { callStr += "(" + this.exception.message + ")"; } } + if (this.stack) { + callStr += this.getStackFrames()[0].replace(/^\s*(?:at\s+|@)?/, " at "); + + } return callStr; } @@ -2250,7 +2436,7 @@ var sinon = (function () { callProto.invokeCallback = callProto.yield; - function createSpyCall(spy, thisValue, args, returnValue, exception, id) { + function createSpyCall(spy, thisValue, args, returnValue, exception, id, stack) { if (typeof id !== "number") { throw new TypeError("Call id is not a number"); } @@ -2261,6 +2447,7 @@ var sinon = (function () { proxyCall.returnValue = returnValue; proxyCall.exception = exception; proxyCall.callId = id; + proxyCall.stack = stack; return proxyCall; } @@ -2270,7 +2457,7 @@ var sinon = (function () { return createSpyCall; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { @@ -2282,14 +2469,20 @@ var sinon = (function () { if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend times_in_words.js @@ -2306,8 +2499,7 @@ var sinon = (function () { * * Copyright (c) 2010-2013 Christian Johansen */ - -(function (sinon) { +(function (sinonGlobal) { function makeApi(sinon) { var push = Array.prototype.push; @@ -2315,7 +2507,7 @@ var sinon = (function () { var callId = 0; function spy(object, property, types) { - if (!property && typeof object == "function") { + if (!property && typeof object === "function") { return spy.create(object); } @@ -2329,15 +2521,14 @@ var sinon = (function () { methodDesc[types[i]] = spy.create(methodDesc[types[i]]); } return sinon.wrapMethod(object, property, methodDesc); - } else { - var method = object[property]; - return sinon.wrapMethod(object, property, spy.create(method)); } + + return sinon.wrapMethod(object, property, spy.create(object[property])); } function matchingFake(fakes, args, strict) { if (!fakes) { - return; + return undefined; } for (var i = 0, l = fakes.length; i < l; i++) { @@ -2351,9 +2542,9 @@ var sinon = (function () { this.called = true; this.callCount += 1; this.notCalled = false; - this.calledOnce = this.callCount == 1; - this.calledTwice = this.callCount == 2; - this.calledThrice = this.callCount == 3; + this.calledOnce = this.callCount === 1; + this.calledTwice = this.callCount === 2; + this.calledThrice = this.callCount === 3; } function createCallProperties() { @@ -2368,13 +2559,14 @@ var sinon = (function () { // Retain the function length: var p; if (proxyLength) { - eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) + + eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) + // eslint-disable-line no-eval ") { return p.invoke(func, this, slice.call(arguments)); });"); } else { p = function proxy() { return p.invoke(func, this, slice.call(arguments)); }; } + p.isSinonProxy = true; return p; } @@ -2405,6 +2597,7 @@ var sinon = (function () { this.thisValues = []; this.exceptions = []; this.callIds = []; + this.stacks = []; if (this.fakes) { for (var i = 0; i < this.fakes.length; i++) { this.fakes[i].reset(); @@ -2417,7 +2610,7 @@ var sinon = (function () { create: function create(func, spyLength) { var name; - if (typeof func != "function") { + if (typeof func !== "function") { func = function () { }; } else { name = sinon.functionName(func); @@ -2476,6 +2669,7 @@ var sinon = (function () { push.call(this.exceptions, exception); push.call(this.returnValues, returnValue); + push.call(this.stacks, new Error().stack); // Make return value and exception available in the calls: createCallProperties.call(this); @@ -2499,7 +2693,7 @@ var sinon = (function () { return sinon.spyCall(this, this.thisValues[i], this.args[i], this.returnValues[i], this.exceptions[i], - this.callIds[i]); + this.callIds[i], this.stacks[i]); }, getCalls: function () { @@ -2576,20 +2770,20 @@ var sinon = (function () { if (margs.length <= args.length && sinon.deepEqual(margs, args.slice(0, margs.length))) { - return !strict || margs.length == args.length; + return !strict || margs.length === args.length; } }, printf: function (format) { - var spy = this; + var spyInstance = this; var args = slice.call(arguments, 1); var formatter; return (format || "").replace(/%(.)/g, function (match, specifyer) { formatter = spyApi.formatters[specifyer]; - if (typeof formatter == "function") { - return formatter.call(null, spy, args); + if (typeof formatter === "function") { + return formatter.call(null, spyInstance, args); } else if (!isNaN(parseInt(specifyer, 10))) { return sinon.format(args[specifyer - 1]); } @@ -2635,10 +2829,12 @@ var sinon = (function () { delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch"); delegateToCalls("calledWithExactly", true); delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly"); - delegateToCalls("neverCalledWith", false, "notCalledWith", - function () { return true; }); - delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch", - function () { return true; }); + delegateToCalls("neverCalledWith", false, "notCalledWith", function () { + return true; + }); + delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch", function () { + return true; + }); delegateToCalls("threw", true); delegateToCalls("alwaysThrew", false, "threw"); delegateToCalls("returned", true); @@ -2671,19 +2867,19 @@ var sinon = (function () { }); spyApi.formatters = { - c: function (spy) { - return sinon.timesInWords(spy.callCount); + c: function (spyInstance) { + return sinon.timesInWords(spyInstance.callCount); }, - n: function (spy) { - return spy.toString(); + n: function (spyInstance) { + return spyInstance.toString(); }, - C: function (spy) { + C: function (spyInstance) { var calls = []; - for (var i = 0, l = spy.callCount; i < l; ++i) { - var stringifiedCall = " " + spy.getCall(i).toString(); + for (var i = 0, l = spyInstance.callCount; i < l; ++i) { + var stringifiedCall = " " + spyInstance.getCall(i).toString(); if (/\n/.test(calls[i - 1])) { stringifiedCall = "\n" + stringifiedCall; } @@ -2693,17 +2889,17 @@ var sinon = (function () { return calls.length > 0 ? "\n" + calls.join("\n") : ""; }, - t: function (spy) { + t: function (spyInstance) { var objects = []; - for (var i = 0, l = spy.callCount; i < l; ++i) { - push.call(objects, sinon.format(spy.thisValues[i])); + for (var i = 0, l = spyInstance.callCount; i < l; ++i) { + push.call(objects, sinon.format(spyInstance.thisValues[i])); } return objects.join(", "); }, - "*": function (spy, args) { + "*": function (spyInstance, args) { var formatted = []; for (var i = 0, l = args.length; i < l; ++i) { @@ -2722,28 +2918,34 @@ var sinon = (function () { return spy; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { - var sinon = require("./util/core"); + var core = require("./util/core"); require("./call"); require("./extend"); require("./times_in_words"); require("./format"); - module.exports = makeApi(sinon); + module.exports = makeApi(core); } if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend util/core.js @@ -2758,8 +2960,8 @@ var sinon = (function () { * * Copyright (c) 2010-2013 Christian Johansen */ +(function (sinonGlobal) { -(function (sinon) { var slice = Array.prototype.slice; var join = Array.prototype.join; var useLeftMostCallback = -1; @@ -2768,17 +2970,19 @@ var sinon = (function () { 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); - }; } + + if (typeof setImmediate === "function") { + return setImmediate; + } + + return function (callback) { + setTimeout(callback, 0); + }; })(); function throwsException(error, message) { - if (typeof error == "string") { + if (typeof error === "string") { this.exception = new Error(message || ""); this.exception.name = error; } else if (!error) { @@ -2810,12 +3014,12 @@ var sinon = (function () { var callArgProp = behavior.callArgProp; for (var i = 0, l = argumentList.length; i < l; ++i) { - if (!callArgProp && typeof argumentList[i] == "function") { + if (!callArgProp && typeof argumentList[i] === "function") { return argumentList[i]; } if (callArgProp && argumentList[i] && - typeof argumentList[i][callArgProp] == "function") { + typeof argumentList[i][callArgProp] === "function") { return argumentList[i][callArgProp]; } } @@ -2848,10 +3052,10 @@ var sinon = (function () { } function callCallback(behavior, args) { - if (typeof behavior.callArgAt == "number") { + if (typeof behavior.callArgAt === "number") { var func = getCallback(behavior, args); - if (typeof func != "function") { + if (typeof func !== "function") { throw new TypeError(getCallbackError(behavior, func, args)); } @@ -2875,9 +3079,9 @@ var sinon = (function () { }, isPresent: function isPresent() { - return (typeof this.callArgAt == "number" || + return (typeof this.callArgAt === "number" || this.exception || - typeof this.returnArgAt == "number" || + typeof this.returnArgAt === "number" || this.returnThis || this.returnValueDefined); }, @@ -2887,7 +3091,7 @@ var sinon = (function () { if (this.exception) { throw this.exception; - } else if (typeof this.returnArgAt == "number") { + } else if (typeof this.returnArgAt === "number") { return args[this.returnArgAt]; } else if (this.returnThis) { return context; @@ -2913,12 +3117,15 @@ var sinon = (function () { }, withArgs: function withArgs(/* 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."); + 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") { + if (typeof pos !== "number") { throw new TypeError("argument index is not number"); } @@ -2932,10 +3139,10 @@ var sinon = (function () { }, callsArgOn: function callsArgOn(pos, context) { - if (typeof pos != "number") { + if (typeof pos !== "number") { throw new TypeError("argument index is not number"); } - if (typeof context != "object") { + if (typeof context !== "object") { throw new TypeError("argument context is not an object"); } @@ -2949,7 +3156,7 @@ var sinon = (function () { }, callsArgWith: function callsArgWith(pos) { - if (typeof pos != "number") { + if (typeof pos !== "number") { throw new TypeError("argument index is not number"); } @@ -2963,10 +3170,10 @@ var sinon = (function () { }, callsArgOnWith: function callsArgWith(pos, context) { - if (typeof pos != "number") { + if (typeof pos !== "number") { throw new TypeError("argument index is not number"); } - if (typeof context != "object") { + if (typeof context !== "object") { throw new TypeError("argument context is not an object"); } @@ -3000,7 +3207,7 @@ var sinon = (function () { }, yieldsOn: function (context) { - if (typeof context != "object") { + if (typeof context !== "object") { throw new TypeError("argument context is not an object"); } @@ -3024,7 +3231,7 @@ var sinon = (function () { }, yieldsToOn: function (prop, context) { - if (typeof context != "object") { + if (typeof context !== "object") { throw new TypeError("argument context is not an object"); } @@ -3043,12 +3250,13 @@ var sinon = (function () { returns: function returns(value) { this.returnValue = value; this.returnValueDefined = true; + this.exception = undefined; return this; }, returnsArg: function returnsArg(pos) { - if (typeof pos != "number") { + if (typeof pos !== "number") { throw new TypeError("argument index is not number"); } @@ -3064,19 +3272,19 @@ var sinon = (function () { } }; + function createAsyncVersion(syncFnName) { + return function () { + var result = this[syncFnName].apply(this, arguments); + this.callbackAsync = true; + return result; + }; + } + // 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); + if (proto.hasOwnProperty(method) && method.match(/^(callsArg|yields)/) && !method.match(/Async/)) { + proto[method + "Async"] = createAsyncVersion(method); } } @@ -3084,7 +3292,7 @@ var sinon = (function () { return proto; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { @@ -3095,20 +3303,106 @@ var sinon = (function () { if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); + +/** + * @depend util/core.js + */ +(function (sinonGlobal) { + + function makeApi(sinon) { + function walkInternal(obj, iterator, context, originalObj, seen) { + var proto, prop; + + if (typeof Object.getOwnPropertyNames !== "function") { + // We explicitly want to enumerate through all of the prototype's properties + // in this case, therefore we deliberately leave out an own property check. + /* eslint-disable guard-for-in */ + for (prop in obj) { + iterator.call(context, obj[prop], prop, obj); + } + /* eslint-enable guard-for-in */ + + return; + } + + Object.getOwnPropertyNames(obj).forEach(function (k) { + if (!seen[k]) { + seen[k] = true; + var target = typeof Object.getOwnPropertyDescriptor(obj, k).get === "function" ? + originalObj : obj; + iterator.call(context, target[k], k, target); + } + }); + + proto = Object.getPrototypeOf(obj); + if (proto) { + walkInternal(proto, iterator, context, originalObj, seen); + } + } + + /* Public: walks the prototype chain of an object and iterates over every own property + * name encountered. The iterator is called in the same fashion that Array.prototype.forEach + * works, where it is passed the value, key, and own object as the 1st, 2nd, and 3rd positional + * argument, respectively. In cases where Object.getOwnPropertyNames is not available, walk will + * default to using a simple for..in loop. + * + * obj - The object to walk the prototype chain for. + * iterator - The function to be called on each pass of the walk. + * context - (Optional) When given, the iterator will be called with this object as the receiver. + */ + function walk(obj, iterator, context) { + return walkInternal(obj, iterator, context, obj, {}); + } + + sinon.walk = walk; + return sinon.walk; + } + + function loadDependencies(require, exports, module) { + var sinon = require("./util/core"); + module.exports = makeApi(sinon); + } + + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; + var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; + + if (isAMD) { + define(loadDependencies); + return; + } + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend util/core.js * @depend extend.js * @depend spy.js * @depend behavior.js + * @depend walk.js */ /** * Stub functions @@ -3118,18 +3412,18 @@ var sinon = (function () { * * Copyright (c) 2010-2013 Christian Johansen */ +(function (sinonGlobal) { -(function (sinon) { function makeApi(sinon) { function stub(object, property, func) { - if (!!func && typeof func != "function" && typeof func != "object") { + if (!!func && typeof func !== "function" && typeof func !== "object") { throw new TypeError("Custom stub should be a function or a property descriptor"); } var wrapper; if (func) { - if (typeof func == "function") { + if (typeof func === "function") { wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func; } else { wrapper = func; @@ -3142,7 +3436,7 @@ var sinon = (function () { } } else { var stubLength = 0; - if (typeof object == "object" && typeof object[property] == "function") { + if (typeof object === "object" && typeof object[property] === "function") { stubLength = object[property].length; } wrapper = stub.create(stubLength); @@ -3152,12 +3446,18 @@ var sinon = (function () { return sinon.stub.create(); } - if (typeof property === "undefined" && typeof object == "object") { - for (var prop in object) { - if (typeof object[prop] === "function") { + if (typeof property === "undefined" && typeof object === "object") { + sinon.walk(object || {}, function (value, prop, propOwner) { + // we don't want to stub things like toString(), valueOf(), etc. so we only stub if the object + // is not Object.prototype + if ( + propOwner !== Object.prototype && + prop !== "constructor" && + typeof sinon.getPropertyDescriptor(propOwner, prop).value === "function" + ) { stub(object, prop); } - } + }); return object; } @@ -3165,18 +3465,23 @@ var sinon = (function () { return sinon.wrapMethod(object, property, wrapper); } - function getDefaultBehavior(stub) { - return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub); + + /*eslint-disable no-use-before-define*/ + function getParentBehaviour(stubInstance) { + return (stubInstance.parent && getCurrentBehavior(stubInstance.parent)); } - function getParentBehaviour(stub) { - return (stub.parent && getCurrentBehavior(stub.parent)); + function getDefaultBehavior(stubInstance) { + return stubInstance.defaultBehavior || + getParentBehaviour(stubInstance) || + sinon.behavior.create(stubInstance); } - function getCurrentBehavior(stub) { - var behavior = stub.behaviors[stub.callCount - 1]; - return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub); + function getCurrentBehavior(stubInstance) { + var behavior = stubInstance.behaviors[stubInstance.callCount - 1]; + return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stubInstance); } + /*eslint-enable no-use-before-define*/ var uuid = 0; @@ -3240,19 +3545,21 @@ var sinon = (function () { } }; + function createBehavior(behaviorMethod) { + return function () { + this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this); + this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments); + return this; + }; + } + 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 !== "create" && + method !== "withArgs" && + method !== "invoke") { + proto[method] = createBehavior(method); } } @@ -3262,27 +3569,33 @@ var sinon = (function () { return stub; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { - var sinon = require("./util/core"); + var core = require("./util/core"); require("./behavior"); require("./spy"); require("./extend"); - module.exports = makeApi(sinon); + module.exports = makeApi(core); } if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend times_in_words.js @@ -3302,13 +3615,17 @@ var sinon = (function () { * * Copyright (c) 2010-2013 Christian Johansen */ +(function (sinonGlobal) { -(function (sinon) { function makeApi(sinon) { var push = [].push; var match = sinon.match; function mock(object) { + // if (typeof console !== undefined && console.warn) { + // console.warn("mock will be removed from Sinon.JS v2.0"); + // } + if (!object) { return sinon.expectation.create("Anonymous mock"); } @@ -3326,6 +3643,19 @@ var sinon = (function () { } } + function arrayEquals(arr1, arr2, compareLength) { + if (compareLength && (arr1.length !== arr2.length)) { + return false; + } + + for (var i = 0, l = arr1.length; i < l; i++) { + if (!sinon.deepEqual(arr1[i], arr2[i])) { + return false; + } + } + return true; + } + sinon.extend(mock, { create: function create(object) { if (!object) { @@ -3370,7 +3700,7 @@ var sinon = (function () { var object = this.object; each(this.proxies, function (proxy) { - if (typeof object[proxy].restore == "function") { + if (typeof object[proxy].restore === "function") { object[proxy].restore(); } }); @@ -3378,7 +3708,8 @@ var sinon = (function () { verify: function verify() { var expectations = this.expectations || {}; - var messages = [], met = []; + var messages = []; + var met = []; each(this.proxies, function (proxy) { each(expectations[proxy], function (expectation) { @@ -3402,31 +3733,44 @@ var sinon = (function () { }, invokeMethod: function invokeMethod(method, thisValue, args) { - var expectations = this.expectations && this.expectations[method]; - var length = expectations && expectations.length || 0, i; + var expectations = this.expectations && this.expectations[method] ? this.expectations[method] : []; + var expectationsWithMatchingArgs = []; + var currentArgs = args || []; + var i, available; - for (i = 0; i < length; i += 1) { - if (!expectations[i].met() && - expectations[i].allowsCall(thisValue, args)) { - return expectations[i].apply(thisValue, args); + for (i = 0; i < expectations.length; i += 1) { + var expectedArgs = expectations[i].expectedArguments || []; + if (arrayEquals(expectedArgs, currentArgs, expectations[i].expectsExactArgCount)) { + expectationsWithMatchingArgs.push(expectations[i]); } } - var messages = [], available, exhausted = 0; + for (i = 0; i < expectationsWithMatchingArgs.length; i += 1) { + if (!expectationsWithMatchingArgs[i].met() && + expectationsWithMatchingArgs[i].allowsCall(thisValue, args)) { + return expectationsWithMatchingArgs[i].apply(thisValue, args); + } + } - for (i = 0; i < length; i += 1) { - if (expectations[i].allowsCall(thisValue, args)) { - available = available || expectations[i]; + var messages = []; + var exhausted = 0; + + for (i = 0; i < expectationsWithMatchingArgs.length; i += 1) { + if (expectationsWithMatchingArgs[i].allowsCall(thisValue, args)) { + available = available || expectationsWithMatchingArgs[i]; } else { exhausted += 1; } - push.call(messages, " " + expectations[i].toString()); } - if (exhausted === 0) { + if (available && exhausted === 0) { return available.apply(thisValue, args); } + for (i = 0; i < expectations.length; i += 1) { + push.call(messages, " " + expectations[i].toString()); + } + messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({ proxy: method, args: args @@ -3440,28 +3784,28 @@ var sinon = (function () { var slice = Array.prototype.slice; function callCountInWords(callCount) { - if (callCount == 0) { + if (callCount === 0) { return "never called"; - } else { - return "called " + times(callCount); } + + return "called " + times(callCount); } function expectedCallCountInWords(expectation) { var min = expectation.minCalls; var max = expectation.maxCalls; - if (typeof min == "number" && typeof max == "number") { + if (typeof min === "number" && typeof max === "number") { var str = times(min); - if (min != max) { + if (min !== max) { str = "at least " + str + " and at most " + times(max); } return str; } - if (typeof min == "number") { + if (typeof min === "number") { return "at least " + times(min); } @@ -3469,24 +3813,22 @@ var sinon = (function () { } function receivedMinCalls(expectation) { - var hasMinLimit = typeof expectation.minCalls == "number"; + var hasMinLimit = typeof expectation.minCalls === "number"; return !hasMinLimit || expectation.callCount >= expectation.minCalls; } function receivedMaxCalls(expectation) { - if (typeof expectation.maxCalls != "number") { + if (typeof expectation.maxCalls !== "number") { return false; } - return expectation.callCount == expectation.maxCalls; + return expectation.callCount === expectation.maxCalls; } function verifyMatcher(possibleMatcher, arg) { - if (match && match.isMatcher(possibleMatcher)) { - return possibleMatcher.test(arg); - } else { - return true; - } + var isMatcher = match && match.isMatcher(possibleMatcher); + + return isMatcher && possibleMatcher.test(arg) || true; } sinon.expectation = { @@ -3508,7 +3850,7 @@ var sinon = (function () { }, atLeast: function atLeast(num) { - if (typeof num != "number") { + if (typeof num !== "number") { throw new TypeError("'" + num + "' is not number"); } @@ -3523,7 +3865,7 @@ var sinon = (function () { }, atMost: function atMost(num) { - if (typeof num != "number") { + if (typeof num !== "number") { throw new TypeError("'" + num + "' is not number"); } @@ -3554,7 +3896,7 @@ var sinon = (function () { }, exactly: function exactly(num) { - if (typeof num != "number") { + if (typeof num !== "number") { throw new TypeError("'" + num + "' is not a number"); } @@ -3592,7 +3934,7 @@ var sinon = (function () { } if (this.expectsExactArgCount && - args.length != this.expectedArguments.length) { + args.length !== this.expectedArguments.length) { sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) + "), expected " + sinon.format(this.expectedArguments)); } @@ -3631,7 +3973,7 @@ var sinon = (function () { } if (this.expectsExactArgCount && - args.length != this.expectedArguments.length) { + args.length !== this.expectedArguments.length) { return false; } @@ -3713,7 +4055,7 @@ var sinon = (function () { return mock; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { @@ -3731,14 +4073,20 @@ var sinon = (function () { if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend util/core.js @@ -3754,8 +4102,8 @@ var sinon = (function () { * * Copyright (c) 2010-2013 Christian Johansen */ +(function (sinonGlobal) { -(function (sinon) { var push = [].push; var hasOwnProperty = Object.prototype.hasOwnProperty; @@ -3771,7 +4119,7 @@ var sinon = (function () { var fakes = getFakes(fakeCollection); for (var i = 0, l = fakes.length; i < l; i += 1) { - if (typeof fakes[i][method] == "function") { + if (typeof fakes[i][method] === "function") { fakes[i][method](); } } @@ -3829,7 +4177,7 @@ var sinon = (function () { if (property) { var original = object[property]; - if (typeof original != "function") { + if (typeof original !== "function") { if (!hasOwnProperty.call(object, property)) { throw new TypeError("Cannot stub non-existent own property " + property); } @@ -3843,7 +4191,7 @@ var sinon = (function () { }); } } - if (!property && !!object && typeof object == "object") { + if (!property && !!object && typeof object === "object") { var stubbedObj = sinon.stub.apply(sinon, arguments); for (var prop in stubbedObj) { @@ -3885,7 +4233,7 @@ var sinon = (function () { return collection; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { @@ -3898,16 +4246,20 @@ var sinon = (function () { if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); -/*global lolex */ + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * Fake timer API @@ -3926,17 +4278,15 @@ var sinon = (function () { * * Copyright (c) 2010-2013 Christian Johansen */ +(function () { -if (typeof sinon == "undefined") { - var sinon = {}; -} - -(function (global) { - function makeApi(sinon, lol) { + function makeApi(s, lol) { + /*global lolex */ var llx = typeof lolex !== "undefined" ? lolex : lol; - sinon.useFakeTimers = function () { - var now, methods = Array.prototype.slice.call(arguments); + s.useFakeTimers = function () { + var now; + var methods = Array.prototype.slice.call(arguments); if (typeof methods[0] === "string") { now = 0; @@ -3949,13 +4299,13 @@ if (typeof sinon == "undefined") { return clock; }; - sinon.clock = { + s.clock = { create: function (now) { return llx.createClock(now); } }; - sinon.timers = { + s.timers = { setTimeout: setTimeout, clearTimeout: clearTimeout, setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined), @@ -3966,13 +4316,13 @@ if (typeof sinon == "undefined") { }; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, epxorts, module, lolex) { - var sinon = require("./core"); - makeApi(sinon, lolex); - module.exports = sinon; + var core = require("./core"); + makeApi(core, lolex); + module.exports = core; } if (isAMD) { @@ -3980,9 +4330,9 @@ if (typeof sinon == "undefined") { } else if (isNode) { loadDependencies(require, module.exports, module, require("lolex")); } else { - makeApi(sinon); + makeApi(sinon); // eslint-disable-line no-undef } -}(typeof global != "undefined" && typeof global !== "function" ? global : this)); +}()); /** * Minimal Event interface implementation @@ -3996,12 +4346,12 @@ if (typeof sinon == "undefined") { * * Copyright (c) 2011 Sven Fuchs, Christian Johansen */ - -if (typeof sinon == "undefined") { +if (typeof sinon === "undefined") { this.sinon = {}; } (function () { + var push = [].push; function makeApi(sinon) { @@ -4033,7 +4383,7 @@ if (typeof sinon == "undefined") { sinon.ProgressEvent.prototype = new sinon.Event(); - sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent; + sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent; sinon.CustomEvent = function CustomEvent(type, customData, target) { this.initEvent(type, false, false, target); @@ -4042,7 +4392,7 @@ if (typeof sinon == "undefined") { sinon.CustomEvent.prototype = new sinon.Event(); - sinon.CustomEvent.prototype.constructor = sinon.CustomEvent; + sinon.CustomEvent.prototype.constructor = sinon.CustomEvent; sinon.EventTarget = { addEventListener: function addEventListener(event, listener) { @@ -4055,7 +4405,7 @@ if (typeof sinon == "undefined") { var listeners = this.eventListeners && this.eventListeners[event] || []; for (var i = 0, l = listeners.length; i < l; ++i) { - if (listeners[i] == listener) { + if (listeners[i] === listener) { return listeners.splice(i, 1); } } @@ -4066,7 +4416,7 @@ if (typeof sinon == "undefined") { var listeners = this.eventListeners && this.eventListeners[type] || []; for (var i = 0; i < listeners.length; i++) { - if (typeof listeners[i] == "function") { + if (typeof listeners[i] === "function") { listeners[i].call(this, event); } else { listeners[i].handleEvent(event); @@ -4078,7 +4428,7 @@ if (typeof sinon == "undefined") { }; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require) { @@ -4091,7 +4441,7 @@ if (typeof sinon == "undefined") { } else if (isNode) { loadDependencies(require); } else { - makeApi(sinon); + makeApi(sinon); // eslint-disable-line no-undef } }()); @@ -4106,8 +4456,8 @@ if (typeof sinon == "undefined") { * * Copyright (c) 2010-2014 Christian Johansen */ +(function (sinonGlobal) { -(function (sinon) { // cache a reference to setTimeout, so that our reference won't be stubbed out // when using fake timers and errors will still get logged // https://github.com/cjohansen/Sinon.JS/issues/381 @@ -4120,22 +4470,32 @@ if (typeof sinon == "undefined") { function logError(label, err) { var msg = label + " threw exception: "; + function throwLoggedError() { + err.message = msg + err.message; + throw err; + } + sinon.log(msg + "[" + err.name + "] " + err.message); if (err.stack) { sinon.log(err.stack); } - logError.setTimeout(function () { - err.message = msg + err.message; - throw err; - }, 0); - }; + if (logError.useImmediateExceptions) { + throwLoggedError(); + } else { + logError.setTimeout(throwLoggedError, 0); + } + } + + // When set to true, any errors logged will be thrown immediately; + // If set to false, the errors will be thrown in separate execution frame. + logError.useImmediateExceptions = false; // wrap realSetTimeout with something we can stub in tests logError.setTimeout = function (func, timeout) { realSetTimeout(func, timeout); - } + }; var exports = {}; exports.log = sinon.log = log; @@ -4149,19 +4509,25 @@ if (typeof sinon == "undefined") { module.exports = makeApi(sinon); } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend core.js @@ -4173,16 +4539,31 @@ if (typeof sinon == "undefined") { * Fake XDomainRequest object */ -if (typeof sinon == "undefined") { - this.sinon = {}; +/** + * Returns the global to prevent assigning values to 'this' when this is undefined. + * This can occur when files are interpreted by node in strict mode. + * @private + */ +function getGlobal() { + + return typeof window !== "undefined" ? window : global; +} + +if (typeof sinon === "undefined") { + if (typeof this === "undefined") { + getGlobal().sinon = {}; + } else { + this.sinon = {}; + } } // wrapper for global (function (global) { + var xdr = { XDomainRequest: global.XDomainRequest }; xdr.GlobalXDomainRequest = global.XDomainRequest; - xdr.supportsXDR = typeof xdr.GlobalXDomainRequest != "undefined"; - xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false; + xdr.supportsXDR = typeof xdr.GlobalXDomainRequest !== "undefined"; + xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false; function makeApi(sinon) { sinon.xdr = xdr; @@ -4194,32 +4575,32 @@ if (typeof sinon == "undefined") { this.status = 0; this.timeout = null; - if (typeof FakeXDomainRequest.onCreate == "function") { + if (typeof FakeXDomainRequest.onCreate === "function") { FakeXDomainRequest.onCreate(this); } } - function verifyState(xdr) { - if (xdr.readyState !== FakeXDomainRequest.OPENED) { + function verifyState(x) { + if (x.readyState !== FakeXDomainRequest.OPENED) { throw new Error("INVALID_STATE_ERR"); } - if (xdr.sendFlag) { + if (x.sendFlag) { throw new Error("INVALID_STATE_ERR"); } } - function verifyRequestSent(xdr) { - if (xdr.readyState == FakeXDomainRequest.UNSENT) { + function verifyRequestSent(x) { + if (x.readyState === FakeXDomainRequest.UNSENT) { throw new Error("Request not sent"); } - if (xdr.readyState == FakeXDomainRequest.DONE) { + if (x.readyState === FakeXDomainRequest.DONE) { throw new Error("Request done"); } } function verifyResponseBodyType(body) { - if (typeof body != "string") { + if (typeof body !== "string") { var error = new Error("Attempted to respond to fake XDomainRequest with " + body + ", which is not a string."); error.name = "InvalidBodyException"; @@ -4254,18 +4635,18 @@ if (typeof sinon == "undefined") { break; case FakeXDomainRequest.DONE: if (this.isTimeout) { - eventName = "ontimeout" + eventName = "ontimeout"; } else if (this.errorFlag || (this.status < 200 || this.status > 299)) { eventName = "onerror"; } else { - eventName = "onload" + eventName = "onload"; } break; } // raising event (if defined) if (eventName) { - if (typeof this[eventName] == "function") { + if (typeof this[eventName] === "function") { try { this[eventName](); } catch (e) { @@ -4287,7 +4668,7 @@ if (typeof sinon == "undefined") { this.sendFlag = true; this.readyStateChange(FakeXDomainRequest.OPENED); - if (typeof this.onSend == "function") { + if (typeof this.onSend === "function") { this.onSend(this); } }, @@ -4324,7 +4705,7 @@ if (typeof sinon == "undefined") { // content-type ignored, since XDomainRequest does not carry this // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease // test integration across browsers - this.status = typeof status == "number" ? status : 200; + this.status = typeof status === "number" ? status : 200; this.setResponseBody(body || ""); }, @@ -4365,7 +4746,7 @@ if (typeof sinon == "undefined") { sinon.FakeXDomainRequest = FakeXDomainRequest; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { @@ -4382,9 +4763,9 @@ if (typeof sinon == "undefined") { } else if (isNode) { loadDependencies(require, module.exports, module); } else { - makeApi(sinon); + makeApi(sinon); // eslint-disable-line no-undef } -})(this); +})(typeof global !== "undefined" ? global : self); /** * @depend core.js @@ -4400,21 +4781,37 @@ if (typeof sinon == "undefined") { * * Copyright (c) 2010-2013 Christian Johansen */ +(function (sinonGlobal, global) { -(function (global) { + function getWorkingXHR(globalScope) { + var supportsXHR = typeof globalScope.XMLHttpRequest !== "undefined"; + if (supportsXHR) { + return globalScope.XMLHttpRequest; + } + + var supportsActiveX = typeof globalScope.ActiveXObject !== "undefined"; + if (supportsActiveX) { + return function () { + return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0"); + }; + } + + return false; + } var supportsProgress = typeof ProgressEvent !== "undefined"; var supportsCustomEvent = typeof CustomEvent !== "undefined"; + var supportsFormData = typeof FormData !== "undefined"; + var supportsArrayBuffer = typeof ArrayBuffer !== "undefined"; + var supportsBlob = typeof Blob === "function"; var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest }; sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest; sinonXhr.GlobalActiveXObject = global.ActiveXObject; - sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject != "undefined"; - sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest != "undefined"; - sinonXhr.workingXHR = sinonXhr.supportsXHR ? sinonXhr.GlobalXMLHttpRequest : sinonXhr.supportsActiveX - ? function () { return new sinonXhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false; + sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject !== "undefined"; + sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest !== "undefined"; + sinonXhr.workingXHR = getWorkingXHR(global); sinonXhr.supportsCORS = sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest()); - /*jsl:ignore*/ var unsafeHeaders = { "Accept-Charset": true, "Accept-Encoding": true, @@ -4435,40 +4832,6 @@ if (typeof sinon == "undefined") { "User-Agent": true, Via: true }; - /*jsl:end*/ - - function FakeXMLHttpRequest() { - this.readyState = FakeXMLHttpRequest.UNSENT; - this.requestHeaders = {}; - this.requestBody = null; - this.status = 0; - this.statusText = ""; - this.upload = new UploadProgress(); - if (sinonXhr.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.call(this, event); - } - }); - } - - for (var i = events.length - 1; i >= 0; i--) { - addEventListener(events[i]); - } - - if (typeof FakeXMLHttpRequest.onCreate == "function") { - FakeXMLHttpRequest.onCreate(this); - } - } // An upload object is created for each // FakeXMLHttpRequest and allows upload @@ -4480,7 +4843,7 @@ if (typeof sinon == "undefined") { load: [], abort: [], error: [] - } + }; } UploadProgress.prototype.addEventListener = function addEventListener(event, listener) { @@ -4491,7 +4854,7 @@ if (typeof sinon == "undefined") { var listeners = this.eventListeners[event] || []; for (var i = 0, l = listeners.length; i < l; ++i) { - if (listeners[i] == listener) { + if (listeners[i] === listener) { return listeners.splice(i, 1); } } @@ -4505,6 +4868,45 @@ if (typeof sinon == "undefined") { } }; + // Note that for FakeXMLHttpRequest to work pre ES5 + // we lose some of the alignment with the spec. + // To ensure as close a match as possible, + // set responseType before calling open, send or respond; + function FakeXMLHttpRequest() { + this.readyState = FakeXMLHttpRequest.UNSENT; + this.requestHeaders = {}; + this.requestBody = null; + this.status = 0; + this.statusText = ""; + this.upload = new UploadProgress(); + this.responseType = ""; + this.response = ""; + if (sinonXhr.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.call(this, event); + } + }); + } + + for (var i = events.length - 1; i >= 0; i--) { + addEventListener(events[i]); + } + + if (typeof FakeXMLHttpRequest.onCreate === "function") { + FakeXMLHttpRequest.onCreate(this); + } + } + function verifyState(xhr) { if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { throw new Error("INVALID_STATE_ERR"); @@ -4519,7 +4921,7 @@ if (typeof sinon == "undefined") { header = header.toLowerCase(); for (var h in headers) { - if (h.toLowerCase() == header) { + if (h.toLowerCase() === header) { return h; } } @@ -4560,11 +4962,12 @@ if (typeof sinon == "undefined") { FakeXMLHttpRequest.filters = []; FakeXMLHttpRequest.addFilter = function addFilter(fn) { - this.filters.push(fn) + this.filters.push(fn); }; var IE6Re = /MSIE 6/; FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) { - var xhr = new sinonXhr.workingXHR(); + var xhr = new sinonXhr.workingXHR(); // eslint-disable-line new-cap + each([ "open", "setRequestHeader", @@ -4584,7 +4987,7 @@ if (typeof sinon == "undefined") { var copyAttrs = function (args) { each(args, function (attr) { try { - fakeXhr[attr] = xhr[attr] + fakeXhr[attr] = xhr[attr]; } catch (e) { if (!IE6Re.test(navigator.userAgent)) { throw e; @@ -4612,9 +5015,12 @@ if (typeof sinon == "undefined") { if (xhr.addEventListener) { for (var event in fakeXhr.eventListeners) { if (fakeXhr.eventListeners.hasOwnProperty(event)) { + + /*eslint-disable no-loop-func*/ each(fakeXhr.eventListeners[event], function (handler) { xhr.addEventListener(event, handler); }); + /*eslint-enable no-loop-func*/ } } xhr.addEventListener("readystatechange", stateChange); @@ -4626,25 +5032,25 @@ if (typeof sinon == "undefined") { FakeXMLHttpRequest.useFilters = false; function verifyRequestOpened(xhr) { - if (xhr.readyState != FakeXMLHttpRequest.OPENED) { + if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { throw new Error("INVALID_STATE_ERR - " + xhr.readyState); } } function verifyRequestSent(xhr) { - if (xhr.readyState == FakeXMLHttpRequest.DONE) { + if (xhr.readyState === FakeXMLHttpRequest.DONE) { throw new Error("Request done"); } } function verifyHeadersReceived(xhr) { - if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) { + if (xhr.async && xhr.readyState !== FakeXMLHttpRequest.HEADERS_RECEIVED) { throw new Error("No headers received"); } } function verifyResponseBodyType(body) { - if (typeof body != "string") { + if (typeof body !== "string") { var error = new Error("Attempted to respond to fake XMLHttpRequest with " + body + ", which is not a string."); error.name = "InvalidBodyException"; @@ -4652,19 +5058,78 @@ if (typeof sinon == "undefined") { } } - FakeXMLHttpRequest.parseXML = function parseXML(text) { - var xmlDoc; + function convertToArrayBuffer(body) { + var buffer = new ArrayBuffer(body.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < body.length; i++) { + var charCode = body.charCodeAt(i); + if (charCode >= 256) { + throw new TypeError("arraybuffer or blob responseTypes require binary string, " + + "invalid character " + body[i] + " found."); + } + view[i] = charCode; + } + return buffer; + } - if (typeof DOMParser != "undefined") { - var parser = new DOMParser(); - xmlDoc = parser.parseFromString(text, "text/xml"); + function isXmlContentType(contentType) { + return !contentType || /(text\/xml)|(application\/xml)|(\+xml)/.test(contentType); + } + + function convertResponseBody(responseType, contentType, body) { + if (responseType === "" || responseType === "text") { + return body; + } else if (supportsArrayBuffer && responseType === "arraybuffer") { + return convertToArrayBuffer(body); + } else if (responseType === "json") { + try { + return JSON.parse(body); + } catch (e) { + // Return parsing failure as null + return null; + } + } else if (supportsBlob && responseType === "blob") { + var blobOptions = {}; + if (contentType) { + blobOptions.type = contentType; + } + return new Blob([convertToArrayBuffer(body)], blobOptions); + } else if (responseType === "document") { + if (isXmlContentType(contentType)) { + return FakeXMLHttpRequest.parseXML(body); + } + return null; + } + throw new Error("Invalid responseType " + responseType); + } + + function clearResponse(xhr) { + if (xhr.responseType === "" || xhr.responseType === "text") { + xhr.response = xhr.responseText = ""; } else { - xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); - xmlDoc.async = "false"; - xmlDoc.loadXML(text); + xhr.response = xhr.responseText = null; + } + xhr.responseXML = null; + } + + FakeXMLHttpRequest.parseXML = function parseXML(text) { + // Treat empty string as parsing failure + if (text !== "") { + try { + if (typeof DOMParser !== "undefined") { + var parser = new DOMParser(); + return parser.parseFromString(text, "text/xml"); + } + var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async = "false"; + xmlDoc.loadXML(text); + return xmlDoc; + } catch (e) { + // Unable to parse XML - no biggie + } } - return xmlDoc; + return null; }; FakeXMLHttpRequest.statusCodes = { @@ -4721,18 +5186,17 @@ if (typeof sinon == "undefined") { open: function open(method, url, async, username, password) { this.method = method; this.url = url; - this.async = typeof async == "boolean" ? async : true; + this.async = typeof async === "boolean" ? async : true; this.username = username; this.password = password; - this.responseText = null; - this.responseXML = null; + clearResponse(this); this.requestHeaders = {}; this.sendFlag = false; if (FakeXMLHttpRequest.useFilters === true) { var xhrArgs = arguments; var defake = some(FakeXMLHttpRequest.filters, function (filter) { - return filter.apply(this, xhrArgs) + return filter.apply(this, xhrArgs); }); if (defake) { return FakeXMLHttpRequest.defake(this, arguments); @@ -4744,27 +5208,29 @@ if (typeof sinon == "undefined") { readyStateChange: function readyStateChange(state) { this.readyState = state; - if (typeof this.onreadystatechange == "function") { + var readyStateChangeEvent = new sinon.Event("readystatechange", false, false, this); + + if (typeof this.onreadystatechange === "function") { try { - this.onreadystatechange(); + this.onreadystatechange(readyStateChangeEvent); } catch (e) { sinon.logError("Fake XHR onreadystatechange handler", e); } } - this.dispatchEvent(new sinon.Event("readystatechange")); - 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})); this.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100})); } + this.upload.dispatchEvent(new sinon.Event("load", false, false, this)); + this.dispatchEvent(new sinon.Event("load", false, false, this)); + this.dispatchEvent(new sinon.Event("loadend", false, false, this)); break; } + + this.dispatchEvent(readyStateChangeEvent); }, setRequestHeader: function setRequestHeader(header, value) { @@ -4808,7 +5274,7 @@ if (typeof sinon == "undefined") { if (this.requestHeaders[contentType]) { var value = this.requestHeaders[contentType].split(";"); this.requestHeaders[contentType] = value[0] + ";charset=utf-8"; - } else if (!(data instanceof FormData)) { + } else if (supportsFormData && !(data instanceof FormData)) { this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8"; } @@ -4817,9 +5283,10 @@ if (typeof sinon == "undefined") { this.errorFlag = false; this.sendFlag = this.async; + clearResponse(this); this.readyStateChange(FakeXMLHttpRequest.OPENED); - if (typeof this.onSend == "function") { + if (typeof this.onSend === "function") { this.onSend(this); } @@ -4828,9 +5295,10 @@ if (typeof sinon == "undefined") { abort: function abort() { this.aborted = true; - this.responseText = null; + clearResponse(this); this.errorFlag = true; this.requestHeaders = {}; + this.responseHeaders = {}; if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) { this.readyStateChange(FakeXMLHttpRequest.DONE); @@ -4883,36 +5351,39 @@ if (typeof sinon == "undefined") { verifyRequestSent(this); verifyHeadersReceived(this); verifyResponseBodyType(body); + var contentType = this.getResponseHeader("Content-Type"); - var chunkSize = this.chunkSize || 10; - var index = 0; - this.responseText = ""; + var isTextResponse = this.responseType === "" || this.responseType === "text"; + clearResponse(this); + if (this.async) { + var chunkSize = this.chunkSize || 10; + var index = 0; - do { - if (this.async) { + do { this.readyStateChange(FakeXMLHttpRequest.LOADING); - } - this.responseText += body.substring(index, index + chunkSize); - index += chunkSize; - } while (index < body.length); - - var type = this.getResponseHeader("Content-Type"); - - if (this.responseText && - (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) { - try { - this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText); - } catch (e) { - // Unable to parse XML - no biggie - } + if (isTextResponse) { + this.responseText = this.response += body.substring(index, index + chunkSize); + } + index += chunkSize; + } while (index < body.length); } + this.response = convertResponseBody(this.responseType, contentType, body); + if (isTextResponse) { + this.responseText = this.response; + } + + if (this.responseType === "document") { + this.responseXML = this.response; + } else if (this.responseType === "" && isXmlContentType(contentType)) { + this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText); + } this.readyStateChange(FakeXMLHttpRequest.DONE); }, respond: function respond(status, headers, body) { - this.status = typeof status == "number" ? status : 200; + this.status = typeof status === "number" ? status : 200; this.statusText = FakeXMLHttpRequest.statusCodes[this.status]; this.setResponseHeaders(headers || {}); this.setResponseBody(body || ""); @@ -4967,7 +5438,7 @@ if (typeof sinon == "undefined") { if (sinonXhr.supportsActiveX) { global.ActiveXObject = function ActiveXObject(objId) { - if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) { + if (objId === "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) { return new FakeXMLHttpRequest(); } @@ -4982,7 +5453,7 @@ if (typeof sinon == "undefined") { sinon.FakeXMLHttpRequest = FakeXMLHttpRequest; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { @@ -4996,15 +5467,21 @@ if (typeof sinon == "undefined") { if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (typeof sinon === "undefined") { return; - } else { - makeApi(sinon); } -})(typeof global !== "undefined" ? global : this); + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon, // eslint-disable-line no-undef + typeof global !== "undefined" ? global : self +)); /** * @depend fake_xdomain_request.js @@ -5023,28 +5500,18 @@ if (typeof sinon == "undefined") { * * Copyright (c) 2010-2013 Christian Johansen */ - -if (typeof sinon == "undefined") { - var sinon = {}; -} - (function () { - var push = [].push; - function F() {} - function create(proto) { - F.prototype = proto; - return new F(); - } + var push = [].push; function responseArray(handler) { var response = handler; - if (Object.prototype.toString.call(handler) != "[object Array]") { + if (Object.prototype.toString.call(handler) !== "[object Array]") { response = [200, {}, handler]; } - if (typeof response[2] != "string") { + if (typeof response[2] !== "string") { throw new TypeError("Fake server response body should be string, but was " + typeof response[2]); } @@ -5057,9 +5524,9 @@ if (typeof sinon == "undefined") { function matchOne(response, reqMethod, reqUrl) { var rmeth = response.method; - var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase(); + var matchMethod = !rmeth || rmeth.toLowerCase() === reqMethod.toLowerCase(); var url = response.url; - var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl)); + var matchUrl = !url || url === reqUrl || (typeof url.test === "function" && url.test(reqUrl)); return matchMethod && matchUrl; } @@ -5072,9 +5539,9 @@ if (typeof sinon == "undefined") { } if (matchOne(response, this.getHTTPMethod(request), requestUrl)) { - if (typeof response.response == "function") { + if (typeof response.response === "function") { var ru = response.url; - var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []); + var args = [request].concat(ru && typeof ru.exec === "function" ? ru.exec(requestUrl).slice(1) : []); return response.response.apply(response, args); } @@ -5086,8 +5553,9 @@ if (typeof sinon == "undefined") { function makeApi(sinon) { sinon.fakeServer = { - create: function () { - var server = create(this); + create: function (config) { + var server = sinon.create(this); + server.configure(config); if (!sinon.xhr.supportsCORS) { this.xhr = sinon.useFakeXDomainRequest(); } else { @@ -5101,7 +5569,22 @@ if (typeof sinon == "undefined") { return server; }, + configure: function (config) { + var whitelist = { + "autoRespond": true, + "autoRespondAfter": true, + "respondImmediately": true, + "fakeHTTPMethods": true + }; + var setting; + config = config || {}; + for (setting in config) { + if (whitelist.hasOwnProperty(setting) && config.hasOwnProperty(setting)) { + this[setting] = config[setting]; + } + } + }, addRequest: function addRequest(xhrObj) { var server = this; push.call(this.requests, xhrObj); @@ -5125,7 +5608,7 @@ if (typeof sinon == "undefined") { getHTTPMethod: function getHTTPMethod(request) { if (this.fakeHTTPMethods && /post/i.test(request.method)) { var matches = (request.requestBody || "").match(/_method=([^\b;]+)/); - return !!matches ? matches[1] : request.method; + return matches ? matches[1] : request.method; } return request.method; @@ -5146,26 +5629,28 @@ if (typeof sinon == "undefined") { log: function log(response, request) { var str; - str = "Request:\n" + sinon.format(request) + "\n\n"; + str = "Request:\n" + sinon.format(request) + "\n\n"; str += "Response:\n" + sinon.format(response) + "\n\n"; sinon.log(str); }, respondWith: function respondWith(method, url, body) { - if (arguments.length == 1 && typeof method != "function") { + if (arguments.length === 1 && typeof method !== "function") { this.response = responseArray(method); return; } - if (!this.responses) { this.responses = []; } + if (!this.responses) { + this.responses = []; + } - if (arguments.length == 1) { + if (arguments.length === 1) { body = method; url = method = null; } - if (arguments.length == 2) { + if (arguments.length === 2) { body = url; url = method; method = null; @@ -5174,7 +5659,7 @@ if (typeof sinon == "undefined") { push.call(this.responses, { method: method, url: url, - response: typeof body == "function" ? body : responseArray(body) + response: typeof body === "function" ? body : responseArray(body) }); }, @@ -5185,10 +5670,9 @@ if (typeof sinon == "undefined") { var queue = this.queue || []; var requests = queue.splice(0, queue.length); - var request; - while (request = requests.shift()) { - this.processRequest(request); + for (var i = 0; i < requests.length; i++) { + this.processRequest(requests[i]); } }, @@ -5209,7 +5693,7 @@ if (typeof sinon == "undefined") { } } - if (request.readyState != 4) { + if (request.readyState !== 4) { this.log(response, request); request.respond(response[0], response[1], response[2]); @@ -5225,7 +5709,7 @@ if (typeof sinon == "undefined") { }; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { @@ -5242,7 +5726,7 @@ if (typeof sinon == "undefined") { } else if (isNode) { loadDependencies(require, module.exports, module); } else { - makeApi(sinon); + makeApi(sinon); // eslint-disable-line no-undef } }()); @@ -5264,8 +5748,8 @@ if (typeof sinon == "undefined") { * * Copyright (c) 2010-2013 Christian Johansen */ - (function () { + function makeApi(sinon) { function Server() {} Server.prototype = sinon.fakeServer; @@ -5274,7 +5758,7 @@ if (typeof sinon == "undefined") { sinon.fakeServerWithClock.addRequest = function addRequest(xhr) { if (xhr.async) { - if (typeof setTimeout.clock == "object") { + if (typeof setTimeout.clock === "object") { this.clock = setTimeout.clock; } else { this.clock = sinon.useFakeTimers(); @@ -5328,7 +5812,7 @@ if (typeof sinon == "undefined") { }; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require) { @@ -5343,7 +5827,7 @@ if (typeof sinon == "undefined") { } else if (isNode) { loadDependencies(require); } else { - makeApi(sinon); + makeApi(sinon); // eslint-disable-line no-undef } }()); @@ -5363,8 +5847,8 @@ if (typeof sinon == "undefined") { * * Copyright (c) 2010-2013 Christian Johansen */ +(function (sinonGlobal) { -(function () { function makeApi(sinon) { var push = [].push; @@ -5385,7 +5869,7 @@ if (typeof sinon == "undefined") { var sandbox = sinon.create(sinon.sandbox); if (config.useFakeServer) { - if (typeof config.useFakeServer == "object") { + if (typeof config.useFakeServer === "object") { sandbox.serverPrototype = config.useFakeServer; } @@ -5393,7 +5877,7 @@ if (typeof sinon == "undefined") { } if (config.useFakeTimers) { - if (typeof config.useFakeTimers == "object") { + if (typeof config.useFakeTimers === "object") { sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers); } else { sandbox.useFakeTimers(); @@ -5463,12 +5947,14 @@ if (typeof sinon == "undefined") { sandbox.args = sandbox.args || []; sandbox.injectedKeys = []; sandbox.injectInto = config.injectInto; - var prop, value, exposed = sandbox.inject({}); + var prop, + value; + var exposed = sandbox.inject({}); if (config.properties) { for (var i = 0, l = config.properties.length; i < l; i++) { prop = config.properties[i]; - value = exposed[prop] || prop == "sandbox" && sandbox; + value = exposed[prop] || prop === "sandbox" && sandbox; exposeValue(sandbox, config, prop, value); } } else { @@ -5486,7 +5972,7 @@ if (typeof sinon == "undefined") { return sinon.sandbox; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { @@ -5500,14 +5986,20 @@ if (typeof sinon == "undefined") { if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}()); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend util/core.js @@ -5521,15 +6013,15 @@ if (typeof sinon == "undefined") { * * Copyright (c) 2010-2013 Christian Johansen */ +(function (sinonGlobal) { -(function (sinon) { function makeApi(sinon) { var slice = Array.prototype.slice; function test(callback) { var type = typeof callback; - if (type != "function") { + if (type !== "function") { throw new TypeError("sinon.test needs to wrap a test function, got " + type); } @@ -5541,15 +6033,14 @@ if (typeof sinon == "undefined") { var oldDone = args.length && args[args.length - 1]; var exception, result; - if (typeof oldDone == "function") { - args[args.length - 1] = function sinonDone(result) { - if (result) { + if (typeof oldDone === "function") { + args[args.length - 1] = function sinonDone(res) { + if (res) { sandbox.restore(); - throw exception; } else { sandbox.verifyAndRestore(); } - oldDone(result); + oldDone(res); }; } @@ -5559,7 +6050,7 @@ if (typeof sinon == "undefined") { exception = e; } - if (typeof oldDone != "function") { + if (typeof oldDone !== "function") { if (typeof exception !== "undefined") { sandbox.restore(); throw exception; @@ -5572,7 +6063,7 @@ if (typeof sinon == "undefined") { } if (callback.length) { - return function sinonAsyncSandboxedTest(callback) { + return function sinonAsyncSandboxedTest(done) { // eslint-disable-line no-unused-vars return sinonSandboxedTest.apply(this, arguments); }; } @@ -5592,23 +6083,23 @@ if (typeof sinon == "undefined") { return test; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { - var sinon = require("./util/core"); + var core = require("./util/core"); require("./sandbox"); - module.exports = makeApi(sinon); + module.exports = makeApi(core); } if (isAMD) { define(loadDependencies); } else if (isNode) { loadDependencies(require, module.exports, module); - } else if (sinon) { - makeApi(sinon); + } else if (sinonGlobal) { + makeApi(sinonGlobal); } -}(typeof sinon == "object" && sinon || null)); +}(typeof sinon === "object" && sinon || null)); // eslint-disable-line no-undef /** * @depend util/core.js @@ -5622,8 +6113,8 @@ if (typeof sinon == "undefined") { * * Copyright (c) 2010-2013 Christian Johansen */ +(function (sinonGlobal) { -(function (sinon) { function createTest(property, setUp, tearDown) { return function () { if (setUp) { @@ -5652,27 +6143,24 @@ if (typeof sinon == "undefined") { function makeApi(sinon) { function testCase(tests, prefix) { - /*jsl:ignore*/ - if (!tests || typeof tests != "object") { + if (!tests || typeof tests !== "object") { throw new TypeError("sinon.testCase needs an object with test functions"); } - /*jsl:end*/ prefix = prefix || "test"; var rPrefix = new RegExp("^" + prefix); - var methods = {}, testName, property, method; + var methods = {}; var setUp = tests.setUp; var tearDown = tests.tearDown; + var testName, + property, + method; for (testName in tests) { - if (tests.hasOwnProperty(testName)) { + if (tests.hasOwnProperty(testName) && !/^(setUp|tearDown)$/.test(testName)) { property = tests[testName]; - if (/^(setUp|tearDown)$/.test(testName)) { - continue; - } - - if (typeof property == "function" && rPrefix.test(testName)) { + if (typeof property === "function" && rPrefix.test(testName)) { method = property; if (setUp || tearDown) { @@ -5693,25 +6181,31 @@ if (typeof sinon == "undefined") { return testCase; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { - var sinon = require("./util/core"); + var core = require("./util/core"); require("./test"); - module.exports = makeApi(sinon); + module.exports = makeApi(core); } if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null)); + + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon // eslint-disable-line no-undef +)); /** * @depend times_in_words.js @@ -5727,8 +6221,8 @@ if (typeof sinon == "undefined") { * * Copyright (c) 2010-2013 Christian Johansen */ +(function (sinonGlobal, global) { -(function (sinon, global) { var slice = Array.prototype.slice; function makeApi(sinon) { @@ -5744,14 +6238,14 @@ if (typeof sinon == "undefined") { assert.fail("fake is not a spy"); } - if (method.proxy) { + if (method.proxy && method.proxy.isSinonProxy) { verifyIsStub(method.proxy); } else { - if (typeof method != "function") { + if (typeof method !== "function") { assert.fail(method + " is not a function"); } - if (typeof method.getCall != "function") { + if (typeof method.getCall !== "function") { assert.fail(method + " is not stubbed"); } } @@ -5766,7 +6260,7 @@ if (typeof sinon == "undefined") { } function mirrorPropAsAssertion(name, method, message) { - if (arguments.length == 2) { + if (arguments.length === 2) { message = method; method = name; } @@ -5777,10 +6271,10 @@ if (typeof sinon == "undefined") { var args = slice.call(arguments, 1); var failed = false; - if (typeof method == "function") { + if (typeof method === "function") { failed = !method(fake); } else { - failed = typeof fake[method] == "function" ? + failed = typeof fake[method] === "function" ? !fake[method].apply(fake, args) : !fake[method]; } @@ -5807,11 +6301,12 @@ if (typeof sinon == "undefined") { throw error; }, - pass: function pass(assertion) {}, + pass: function pass() {}, callOrder: function assertCallOrder() { verifyIsStub.apply(null, arguments); - var expected = "", actual = ""; + var expected = ""; + var actual = ""; if (!sinon.calledInOrder(arguments)) { try { @@ -5838,7 +6333,7 @@ if (typeof sinon == "undefined") { callCount: function assertCallCount(method, count) { verifyIsStub(method); - if (method.callCount != count) { + if (method.callCount !== count) { var msg = "expected %n to be called " + sinon.timesInWords(count) + " but was called %c%C"; failAssertion(this, method.printf(msg)); @@ -5853,11 +6348,11 @@ if (typeof sinon == "undefined") { } var o = options || {}; - var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix; - var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail; + var prefix = typeof o.prefix === "undefined" && "assert" || o.prefix; + var includeFail = typeof o.includeFail === "undefined" || !!o.includeFail; for (var method in this) { - if (method != "expose" && (includeFail || !/^(fail)/.test(method))) { + if (method !== "expose" && (includeFail || !/^(fail)/.test(method))) { target[exposedName(prefix, method)] = this[method]; } } @@ -5874,20 +6369,25 @@ if (typeof sinon == "undefined") { "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; }, - "expected %n to not have been called but was called %c%C"); + mirrorPropAsAssertion("notCalled", function (spy) { + return !spy.called; + }, "expected %n to not have been called but was called %c%C"); 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( + "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"); @@ -5905,7 +6405,7 @@ if (typeof sinon == "undefined") { return assert; } - var isNode = typeof module !== "undefined" && module.exports && typeof require == "function"; + var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; function loadDependencies(require, exports, module) { @@ -5917,15 +6417,21 @@ if (typeof sinon == "undefined") { if (isAMD) { define(loadDependencies); - } else if (isNode) { - loadDependencies(require, module.exports, module); - } else if (!sinon) { return; - } else { - makeApi(sinon); } -}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global)); + if (isNode) { + loadDependencies(require, module.exports, module); + return; + } + + if (sinonGlobal) { + makeApi(sinonGlobal); + } +}( + typeof sinon === "object" && sinon, // eslint-disable-line no-undef + typeof global !== "undefined" ? global : self +)); return sinon; }));