/agent/js/node_modules/sinon/lib/sinon/stub.js

http://webpagetest.googlecode.com/ · JavaScript · 320 lines · 237 code · 68 blank · 15 comment · 83 complexity · 5f2d593d01b0b428208832e921e5e4d3 MD5 · raw file

  1. /**
  2. * @depend ../sinon.js
  3. * @depend spy.js
  4. */
  5. /*jslint eqeqeq: false, onevar: false*/
  6. /*global module, require, sinon*/
  7. /**
  8. * Stub functions
  9. *
  10. * @author Christian Johansen (christian@cjohansen.no)
  11. * @license BSD
  12. *
  13. * Copyright (c) 2010-2011 Christian Johansen
  14. */
  15. "use strict";
  16. (function (sinon) {
  17. var commonJSModule = typeof module == "object" && typeof require == "function";
  18. if (!sinon && commonJSModule) {
  19. sinon = require("../sinon");
  20. }
  21. if (!sinon) {
  22. return;
  23. }
  24. function stub(object, property, func) {
  25. if (!!func && typeof func != "function") {
  26. throw new TypeError("Custom stub should be function");
  27. }
  28. var wrapper;
  29. if (func) {
  30. wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
  31. } else {
  32. wrapper = stub.create();
  33. }
  34. if (!object && !property) {
  35. return sinon.stub.create();
  36. }
  37. if (!property && !!object && typeof object == "object") {
  38. for (var prop in object) {
  39. if (typeof object[prop] === "function") {
  40. stub(object, prop);
  41. }
  42. }
  43. return object;
  44. }
  45. return sinon.wrapMethod(object, property, wrapper);
  46. }
  47. function getCallback(stub, args) {
  48. if (stub.callArgAt < 0) {
  49. for (var i = 0, l = args.length; i < l; ++i) {
  50. if (!stub.callArgProp && typeof args[i] == "function") {
  51. return args[i];
  52. }
  53. if (stub.callArgProp && args[i] &&
  54. typeof args[i][stub.callArgProp] == "function") {
  55. return args[i][stub.callArgProp];
  56. }
  57. }
  58. return null;
  59. }
  60. return args[stub.callArgAt];
  61. }
  62. var join = Array.prototype.join;
  63. function getCallbackError(stub, func, args) {
  64. if (stub.callArgAt < 0) {
  65. var msg;
  66. if (stub.callArgProp) {
  67. msg = sinon.functionName(stub) +
  68. " expected to yield to '" + stub.callArgProp +
  69. "', but no object with such a property was passed."
  70. } else {
  71. msg = sinon.functionName(stub) +
  72. " expected to yield, but no callback was passed."
  73. }
  74. if (args.length > 0) {
  75. msg += " Received [" + join.call(args, ", ") + "]";
  76. }
  77. return msg;
  78. }
  79. return "argument at index " + stub.callArgAt + " is not a function: " + func;
  80. }
  81. var nextTick = (function () {
  82. if (typeof process === "object" && typeof process.nextTick === "function") {
  83. return process.nextTick;
  84. } else if (typeof msSetImmediate === "function") {
  85. return msSetImmediate.bind(window);
  86. } else if (typeof setImmediate === "function") {
  87. return setImmediate;
  88. } else {
  89. return function (callback) {
  90. setTimeout(callback, 0);
  91. };
  92. }
  93. })();
  94. function callCallback(stub, args) {
  95. if (typeof stub.callArgAt == "number") {
  96. var func = getCallback(stub, args);
  97. if (typeof func != "function") {
  98. throw new TypeError(getCallbackError(stub, func, args));
  99. }
  100. if (stub.callbackAsync) {
  101. nextTick(function() {
  102. func.apply(stub.callbackContext, stub.callbackArguments);
  103. });
  104. } else {
  105. func.apply(stub.callbackContext, stub.callbackArguments);
  106. }
  107. }
  108. }
  109. var uuid = 0;
  110. sinon.extend(stub, (function () {
  111. var slice = Array.prototype.slice, proto;
  112. function throwsException(error, message) {
  113. if (typeof error == "string") {
  114. this.exception = new Error(message || "");
  115. this.exception.name = error;
  116. } else if (!error) {
  117. this.exception = new Error("Error");
  118. } else {
  119. this.exception = error;
  120. }
  121. return this;
  122. }
  123. proto = {
  124. create: function create() {
  125. var functionStub = function () {
  126. callCallback(functionStub, arguments);
  127. if (functionStub.exception) {
  128. throw functionStub.exception;
  129. } else if (typeof functionStub.returnArgAt == 'number') {
  130. return arguments[functionStub.returnArgAt];
  131. } else if (functionStub.returnThis) {
  132. return this;
  133. }
  134. return functionStub.returnValue;
  135. };
  136. functionStub.id = "stub#" + uuid++;
  137. var orig = functionStub;
  138. functionStub = sinon.spy.create(functionStub);
  139. functionStub.func = orig;
  140. sinon.extend(functionStub, stub);
  141. functionStub._create = sinon.stub.create;
  142. functionStub.displayName = "stub";
  143. functionStub.toString = sinon.functionToString;
  144. return functionStub;
  145. },
  146. returns: function returns(value) {
  147. this.returnValue = value;
  148. return this;
  149. },
  150. returnsArg: function returnsArg(pos) {
  151. if (typeof pos != "number") {
  152. throw new TypeError("argument index is not number");
  153. }
  154. this.returnArgAt = pos;
  155. return this;
  156. },
  157. returnsThis: function returnsThis() {
  158. this.returnThis = true;
  159. return this;
  160. },
  161. "throws": throwsException,
  162. throwsException: throwsException,
  163. callsArg: function callsArg(pos) {
  164. if (typeof pos != "number") {
  165. throw new TypeError("argument index is not number");
  166. }
  167. this.callArgAt = pos;
  168. this.callbackArguments = [];
  169. return this;
  170. },
  171. callsArgOn: function callsArgOn(pos, context) {
  172. if (typeof pos != "number") {
  173. throw new TypeError("argument index is not number");
  174. }
  175. if (typeof context != "object") {
  176. throw new TypeError("argument context is not an object");
  177. }
  178. this.callArgAt = pos;
  179. this.callbackArguments = [];
  180. this.callbackContext = context;
  181. return this;
  182. },
  183. callsArgWith: function callsArgWith(pos) {
  184. if (typeof pos != "number") {
  185. throw new TypeError("argument index is not number");
  186. }
  187. this.callArgAt = pos;
  188. this.callbackArguments = slice.call(arguments, 1);
  189. return this;
  190. },
  191. callsArgOnWith: function callsArgWith(pos, context) {
  192. if (typeof pos != "number") {
  193. throw new TypeError("argument index is not number");
  194. }
  195. if (typeof context != "object") {
  196. throw new TypeError("argument context is not an object");
  197. }
  198. this.callArgAt = pos;
  199. this.callbackArguments = slice.call(arguments, 2);
  200. this.callbackContext = context;
  201. return this;
  202. },
  203. yields: function () {
  204. this.callArgAt = -1;
  205. this.callbackArguments = slice.call(arguments, 0);
  206. return this;
  207. },
  208. yieldsOn: function (context) {
  209. if (typeof context != "object") {
  210. throw new TypeError("argument context is not an object");
  211. }
  212. this.callArgAt = -1;
  213. this.callbackArguments = slice.call(arguments, 1);
  214. this.callbackContext = context;
  215. return this;
  216. },
  217. yieldsTo: function (prop) {
  218. this.callArgAt = -1;
  219. this.callArgProp = prop;
  220. this.callbackArguments = slice.call(arguments, 1);
  221. return this;
  222. },
  223. yieldsToOn: function (prop, context) {
  224. if (typeof context != "object") {
  225. throw new TypeError("argument context is not an object");
  226. }
  227. this.callArgAt = -1;
  228. this.callArgProp = prop;
  229. this.callbackArguments = slice.call(arguments, 2);
  230. this.callbackContext = context;
  231. return this;
  232. }
  233. };
  234. // create asynchronous versions of callsArg* and yields* methods
  235. for (var method in proto) {
  236. if (proto.hasOwnProperty(method) && method.match(/^(callsArg|yields)/)) {
  237. proto[method + 'Async'] = (function (syncFnName) {
  238. return function () {
  239. this.callbackAsync = true;
  240. return this[syncFnName].apply(this, arguments);
  241. };
  242. })(method);
  243. }
  244. }
  245. return proto;
  246. }()));
  247. if (commonJSModule) {
  248. module.exports = stub;
  249. } else {
  250. sinon.stub = stub;
  251. }
  252. }(typeof sinon == "object" && sinon || null));