| 21627 |
kshitij.so |
1 |
/**
|
|
|
2 |
* Sinon.JS 1.5.0, 2012/10/19
|
|
|
3 |
*
|
|
|
4 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
5 |
* @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
|
|
|
6 |
*
|
|
|
7 |
* (The BSD License)
|
|
|
8 |
*
|
|
|
9 |
* Copyright (c) 2010-2012, Christian Johansen, christian@cjohansen.no
|
|
|
10 |
* All rights reserved.
|
|
|
11 |
*
|
|
|
12 |
* Redistribution and use in source and binary forms, with or without modification,
|
|
|
13 |
* are permitted provided that the following conditions are met:
|
|
|
14 |
*
|
|
|
15 |
* * Redistributions of source code must retain the above copyright notice,
|
|
|
16 |
* this list of conditions and the following disclaimer.
|
|
|
17 |
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
|
18 |
* this list of conditions and the following disclaimer in the documentation
|
|
|
19 |
* and/or other materials provided with the distribution.
|
|
|
20 |
* * Neither the name of Christian Johansen nor the names of his contributors
|
|
|
21 |
* may be used to endorse or promote products derived from this software
|
|
|
22 |
* without specific prior written permission.
|
|
|
23 |
*
|
|
|
24 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
25 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
26 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
27 |
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
|
28 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
29 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
30 |
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
31 |
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
32 |
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
33 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
34 |
*/
|
|
|
35 |
|
|
|
36 |
var sinon = (function () {
|
|
|
37 |
"use strict";
|
|
|
38 |
|
|
|
39 |
var buster = (function (setTimeout, B) {
|
|
|
40 |
var isNode = typeof require == "function" && typeof module == "object";
|
|
|
41 |
var div = typeof document != "undefined" && document.createElement("div");
|
|
|
42 |
var F = function () {};
|
|
|
43 |
|
|
|
44 |
var buster = {
|
|
|
45 |
bind: function bind(obj, methOrProp) {
|
|
|
46 |
var method = typeof methOrProp == "string" ? obj[methOrProp] : methOrProp;
|
|
|
47 |
var args = Array.prototype.slice.call(arguments, 2);
|
|
|
48 |
return function () {
|
|
|
49 |
var allArgs = args.concat(Array.prototype.slice.call(arguments));
|
|
|
50 |
return method.apply(obj, allArgs);
|
|
|
51 |
};
|
|
|
52 |
},
|
|
|
53 |
|
|
|
54 |
partial: function partial(fn) {
|
|
|
55 |
var args = [].slice.call(arguments, 1);
|
|
|
56 |
return function () {
|
|
|
57 |
return fn.apply(this, args.concat([].slice.call(arguments)));
|
|
|
58 |
};
|
|
|
59 |
},
|
|
|
60 |
|
|
|
61 |
create: function create(object) {
|
|
|
62 |
F.prototype = object;
|
|
|
63 |
return new F();
|
|
|
64 |
},
|
|
|
65 |
|
|
|
66 |
extend: function extend(target) {
|
|
|
67 |
if (!target) { return; }
|
|
|
68 |
for (var i = 1, l = arguments.length, prop; i < l; ++i) {
|
|
|
69 |
for (prop in arguments[i]) {
|
|
|
70 |
target[prop] = arguments[i][prop];
|
|
|
71 |
}
|
|
|
72 |
}
|
|
|
73 |
return target;
|
|
|
74 |
},
|
|
|
75 |
|
|
|
76 |
nextTick: function nextTick(callback) {
|
|
|
77 |
if (typeof process != "undefined" && process.nextTick) {
|
|
|
78 |
return process.nextTick(callback);
|
|
|
79 |
}
|
|
|
80 |
setTimeout(callback, 0);
|
|
|
81 |
},
|
|
|
82 |
|
|
|
83 |
functionName: function functionName(func) {
|
|
|
84 |
if (!func) return "";
|
|
|
85 |
if (func.displayName) return func.displayName;
|
|
|
86 |
if (func.name) return func.name;
|
|
|
87 |
var matches = func.toString().match(/function\s+([^\(]+)/m);
|
|
|
88 |
return matches && matches[1] || "";
|
|
|
89 |
},
|
|
|
90 |
|
|
|
91 |
isNode: function isNode(obj) {
|
|
|
92 |
if (!div) return false;
|
|
|
93 |
try {
|
|
|
94 |
obj.appendChild(div);
|
|
|
95 |
obj.removeChild(div);
|
|
|
96 |
} catch (e) {
|
|
|
97 |
return false;
|
|
|
98 |
}
|
|
|
99 |
return true;
|
|
|
100 |
},
|
|
|
101 |
|
|
|
102 |
isElement: function isElement(obj) {
|
|
|
103 |
return obj && obj.nodeType === 1 && buster.isNode(obj);
|
|
|
104 |
},
|
|
|
105 |
|
|
|
106 |
isArray: function isArray(arr) {
|
|
|
107 |
return Object.prototype.toString.call(arr) == "[object Array]";
|
|
|
108 |
},
|
|
|
109 |
|
|
|
110 |
flatten: function flatten(arr) {
|
|
|
111 |
var result = [], arr = arr || [];
|
|
|
112 |
for (var i = 0, l = arr.length; i < l; ++i) {
|
|
|
113 |
result = result.concat(buster.isArray(arr[i]) ? flatten(arr[i]) : arr[i]);
|
|
|
114 |
}
|
|
|
115 |
return result;
|
|
|
116 |
},
|
|
|
117 |
|
|
|
118 |
each: function each(arr, callback) {
|
|
|
119 |
for (var i = 0, l = arr.length; i < l; ++i) {
|
|
|
120 |
callback(arr[i]);
|
|
|
121 |
}
|
|
|
122 |
},
|
|
|
123 |
|
|
|
124 |
map: function map(arr, callback) {
|
|
|
125 |
var results = [];
|
|
|
126 |
for (var i = 0, l = arr.length; i < l; ++i) {
|
|
|
127 |
results.push(callback(arr[i]));
|
|
|
128 |
}
|
|
|
129 |
return results;
|
|
|
130 |
},
|
|
|
131 |
|
|
|
132 |
parallel: function parallel(fns, callback) {
|
|
|
133 |
function cb(err, res) {
|
|
|
134 |
if (typeof callback == "function") {
|
|
|
135 |
callback(err, res);
|
|
|
136 |
callback = null;
|
|
|
137 |
}
|
|
|
138 |
}
|
|
|
139 |
if (fns.length == 0) { return cb(null, []); }
|
|
|
140 |
var remaining = fns.length, results = [];
|
|
|
141 |
function makeDone(num) {
|
|
|
142 |
return function done(err, result) {
|
|
|
143 |
if (err) { return cb(err); }
|
|
|
144 |
results[num] = result;
|
|
|
145 |
if (--remaining == 0) { cb(null, results); }
|
|
|
146 |
};
|
|
|
147 |
}
|
|
|
148 |
for (var i = 0, l = fns.length; i < l; ++i) {
|
|
|
149 |
fns[i](makeDone(i));
|
|
|
150 |
}
|
|
|
151 |
},
|
|
|
152 |
|
|
|
153 |
series: function series(fns, callback) {
|
|
|
154 |
function cb(err, res) {
|
|
|
155 |
if (typeof callback == "function") {
|
|
|
156 |
callback(err, res);
|
|
|
157 |
}
|
|
|
158 |
}
|
|
|
159 |
var remaining = fns.slice();
|
|
|
160 |
var results = [];
|
|
|
161 |
function callNext() {
|
|
|
162 |
if (remaining.length == 0) return cb(null, results);
|
|
|
163 |
var promise = remaining.shift()(next);
|
|
|
164 |
if (promise && typeof promise.then == "function") {
|
|
|
165 |
promise.then(buster.partial(next, null), next);
|
|
|
166 |
}
|
|
|
167 |
}
|
|
|
168 |
function next(err, result) {
|
|
|
169 |
if (err) return cb(err);
|
|
|
170 |
results.push(result);
|
|
|
171 |
callNext();
|
|
|
172 |
}
|
|
|
173 |
callNext();
|
|
|
174 |
},
|
|
|
175 |
|
|
|
176 |
countdown: function countdown(num, done) {
|
|
|
177 |
return function () {
|
|
|
178 |
if (--num == 0) done();
|
|
|
179 |
};
|
|
|
180 |
}
|
|
|
181 |
};
|
|
|
182 |
|
|
|
183 |
if (typeof process === "object" &&
|
|
|
184 |
typeof require === "function" && typeof module === "object") {
|
|
|
185 |
var crypto = require("crypto");
|
|
|
186 |
var path = require("path");
|
|
|
187 |
|
|
|
188 |
buster.tmpFile = function (fileName) {
|
|
|
189 |
var hashed = crypto.createHash("sha1");
|
|
|
190 |
hashed.update(fileName);
|
|
|
191 |
var tmpfileName = hashed.digest("hex");
|
|
|
192 |
|
|
|
193 |
if (process.platform == "win32") {
|
|
|
194 |
return path.join(process.env["TEMP"], tmpfileName);
|
|
|
195 |
} else {
|
|
|
196 |
return path.join("/tmp", tmpfileName);
|
|
|
197 |
}
|
|
|
198 |
};
|
|
|
199 |
}
|
|
|
200 |
|
|
|
201 |
if (Array.prototype.some) {
|
|
|
202 |
buster.some = function (arr, fn, thisp) {
|
|
|
203 |
return arr.some(fn, thisp);
|
|
|
204 |
};
|
|
|
205 |
} else {
|
|
|
206 |
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
|
|
|
207 |
buster.some = function (arr, fun, thisp) {
|
|
|
208 |
if (arr == null) { throw new TypeError(); }
|
|
|
209 |
arr = Object(arr);
|
|
|
210 |
var len = arr.length >>> 0;
|
|
|
211 |
if (typeof fun !== "function") { throw new TypeError(); }
|
|
|
212 |
|
|
|
213 |
for (var i = 0; i < len; i++) {
|
|
|
214 |
if (arr.hasOwnProperty(i) && fun.call(thisp, arr[i], i, arr)) {
|
|
|
215 |
return true;
|
|
|
216 |
}
|
|
|
217 |
}
|
|
|
218 |
|
|
|
219 |
return false;
|
|
|
220 |
};
|
|
|
221 |
}
|
|
|
222 |
|
|
|
223 |
if (Array.prototype.filter) {
|
|
|
224 |
buster.filter = function (arr, fn, thisp) {
|
|
|
225 |
return arr.filter(fn, thisp);
|
|
|
226 |
};
|
|
|
227 |
} else {
|
|
|
228 |
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter
|
|
|
229 |
buster.filter = function (fn, thisp) {
|
|
|
230 |
if (this == null) { throw new TypeError(); }
|
|
|
231 |
|
|
|
232 |
var t = Object(this);
|
|
|
233 |
var len = t.length >>> 0;
|
|
|
234 |
if (typeof fn != "function") { throw new TypeError(); }
|
|
|
235 |
|
|
|
236 |
var res = [];
|
|
|
237 |
for (var i = 0; i < len; i++) {
|
|
|
238 |
if (i in t) {
|
|
|
239 |
var val = t[i]; // in case fun mutates this
|
|
|
240 |
if (fn.call(thisp, val, i, t)) { res.push(val); }
|
|
|
241 |
}
|
|
|
242 |
}
|
|
|
243 |
|
|
|
244 |
return res;
|
|
|
245 |
};
|
|
|
246 |
}
|
|
|
247 |
|
|
|
248 |
if (isNode) {
|
|
|
249 |
module.exports = buster;
|
|
|
250 |
buster.eventEmitter = require("./buster-event-emitter");
|
|
|
251 |
Object.defineProperty(buster, "defineVersionGetter", {
|
|
|
252 |
get: function () {
|
|
|
253 |
return require("./define-version-getter");
|
|
|
254 |
}
|
|
|
255 |
});
|
|
|
256 |
}
|
|
|
257 |
|
|
|
258 |
return buster.extend(B || {}, buster);
|
|
|
259 |
}(setTimeout, buster));
|
|
|
260 |
if (typeof buster === "undefined") {
|
|
|
261 |
var buster = {};
|
|
|
262 |
}
|
|
|
263 |
|
|
|
264 |
if (typeof module === "object" && typeof require === "function") {
|
|
|
265 |
buster = require("buster-core");
|
|
|
266 |
}
|
|
|
267 |
|
|
|
268 |
buster.format = buster.format || {};
|
|
|
269 |
buster.format.excludeConstructors = ["Object", /^.$/];
|
|
|
270 |
buster.format.quoteStrings = true;
|
|
|
271 |
|
|
|
272 |
buster.format.ascii = (function () {
|
|
|
273 |
|
|
|
274 |
var hasOwn = Object.prototype.hasOwnProperty;
|
|
|
275 |
|
|
|
276 |
var specialObjects = [];
|
|
|
277 |
if (typeof global != "undefined") {
|
|
|
278 |
specialObjects.push({ obj: global, value: "[object global]" });
|
|
|
279 |
}
|
|
|
280 |
if (typeof document != "undefined") {
|
|
|
281 |
specialObjects.push({ obj: document, value: "[object HTMLDocument]" });
|
|
|
282 |
}
|
|
|
283 |
if (typeof window != "undefined") {
|
|
|
284 |
specialObjects.push({ obj: window, value: "[object Window]" });
|
|
|
285 |
}
|
|
|
286 |
|
|
|
287 |
function keys(object) {
|
|
|
288 |
var k = Object.keys && Object.keys(object) || [];
|
|
|
289 |
|
|
|
290 |
if (k.length == 0) {
|
|
|
291 |
for (var prop in object) {
|
|
|
292 |
if (hasOwn.call(object, prop)) {
|
|
|
293 |
k.push(prop);
|
|
|
294 |
}
|
|
|
295 |
}
|
|
|
296 |
}
|
|
|
297 |
|
|
|
298 |
return k.sort();
|
|
|
299 |
}
|
|
|
300 |
|
|
|
301 |
function isCircular(object, objects) {
|
|
|
302 |
if (typeof object != "object") {
|
|
|
303 |
return false;
|
|
|
304 |
}
|
|
|
305 |
|
|
|
306 |
for (var i = 0, l = objects.length; i < l; ++i) {
|
|
|
307 |
if (objects[i] === object) {
|
|
|
308 |
return true;
|
|
|
309 |
}
|
|
|
310 |
}
|
|
|
311 |
|
|
|
312 |
return false;
|
|
|
313 |
}
|
|
|
314 |
|
|
|
315 |
function ascii(object, processed, indent) {
|
|
|
316 |
if (typeof object == "string") {
|
|
|
317 |
var quote = typeof this.quoteStrings != "boolean" || this.quoteStrings;
|
|
|
318 |
return processed || quote ? '"' + object + '"' : object;
|
|
|
319 |
}
|
|
|
320 |
|
|
|
321 |
if (typeof object == "function" && !(object instanceof RegExp)) {
|
|
|
322 |
return ascii.func(object);
|
|
|
323 |
}
|
|
|
324 |
|
|
|
325 |
processed = processed || [];
|
|
|
326 |
|
|
|
327 |
if (isCircular(object, processed)) {
|
|
|
328 |
return "[Circular]";
|
|
|
329 |
}
|
|
|
330 |
|
|
|
331 |
if (Object.prototype.toString.call(object) == "[object Array]") {
|
|
|
332 |
return ascii.array.call(this, object, processed);
|
|
|
333 |
}
|
|
|
334 |
|
|
|
335 |
if (!object) {
|
|
|
336 |
return "" + object;
|
|
|
337 |
}
|
|
|
338 |
|
|
|
339 |
if (buster.isElement(object)) {
|
|
|
340 |
return ascii.element(object);
|
|
|
341 |
}
|
|
|
342 |
|
|
|
343 |
if (typeof object.toString == "function" &&
|
|
|
344 |
object.toString !== Object.prototype.toString) {
|
|
|
345 |
return object.toString();
|
|
|
346 |
}
|
|
|
347 |
|
|
|
348 |
for (var i = 0, l = specialObjects.length; i < l; i++) {
|
|
|
349 |
if (object === specialObjects[i].obj) {
|
|
|
350 |
return specialObjects[i].value;
|
|
|
351 |
}
|
|
|
352 |
}
|
|
|
353 |
|
|
|
354 |
return ascii.object.call(this, object, processed, indent);
|
|
|
355 |
}
|
|
|
356 |
|
|
|
357 |
ascii.func = function (func) {
|
|
|
358 |
return "function " + buster.functionName(func) + "() {}";
|
|
|
359 |
};
|
|
|
360 |
|
|
|
361 |
ascii.array = function (array, processed) {
|
|
|
362 |
processed = processed || [];
|
|
|
363 |
processed.push(array);
|
|
|
364 |
var pieces = [];
|
|
|
365 |
|
|
|
366 |
for (var i = 0, l = array.length; i < l; ++i) {
|
|
|
367 |
pieces.push(ascii.call(this, array[i], processed));
|
|
|
368 |
}
|
|
|
369 |
|
|
|
370 |
return "[" + pieces.join(", ") + "]";
|
|
|
371 |
};
|
|
|
372 |
|
|
|
373 |
ascii.object = function (object, processed, indent) {
|
|
|
374 |
processed = processed || [];
|
|
|
375 |
processed.push(object);
|
|
|
376 |
indent = indent || 0;
|
|
|
377 |
var pieces = [], properties = keys(object), prop, str, obj;
|
|
|
378 |
var is = "";
|
|
|
379 |
var length = 3;
|
|
|
380 |
|
|
|
381 |
for (var i = 0, l = indent; i < l; ++i) {
|
|
|
382 |
is += " ";
|
|
|
383 |
}
|
|
|
384 |
|
|
|
385 |
for (i = 0, l = properties.length; i < l; ++i) {
|
|
|
386 |
prop = properties[i];
|
|
|
387 |
obj = object[prop];
|
|
|
388 |
|
|
|
389 |
if (isCircular(obj, processed)) {
|
|
|
390 |
str = "[Circular]";
|
|
|
391 |
} else {
|
|
|
392 |
str = ascii.call(this, obj, processed, indent + 2);
|
|
|
393 |
}
|
|
|
394 |
|
|
|
395 |
str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
|
|
|
396 |
length += str.length;
|
|
|
397 |
pieces.push(str);
|
|
|
398 |
}
|
|
|
399 |
|
|
|
400 |
var cons = ascii.constructorName.call(this, object);
|
|
|
401 |
var prefix = cons ? "[" + cons + "] " : ""
|
|
|
402 |
|
|
|
403 |
return (length + indent) > 80 ?
|
|
|
404 |
prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" + is + "}" :
|
|
|
405 |
prefix + "{ " + pieces.join(", ") + " }";
|
|
|
406 |
};
|
|
|
407 |
|
|
|
408 |
ascii.element = function (element) {
|
|
|
409 |
var tagName = element.tagName.toLowerCase();
|
|
|
410 |
var attrs = element.attributes, attribute, pairs = [], attrName;
|
|
|
411 |
|
|
|
412 |
for (var i = 0, l = attrs.length; i < l; ++i) {
|
|
|
413 |
attribute = attrs.item(i);
|
|
|
414 |
attrName = attribute.nodeName.toLowerCase().replace("html:", "");
|
|
|
415 |
|
|
|
416 |
if (attrName == "contenteditable" && attribute.nodeValue == "inherit") {
|
|
|
417 |
continue;
|
|
|
418 |
}
|
|
|
419 |
|
|
|
420 |
if (!!attribute.nodeValue) {
|
|
|
421 |
pairs.push(attrName + "=\"" + attribute.nodeValue + "\"");
|
|
|
422 |
}
|
|
|
423 |
}
|
|
|
424 |
|
|
|
425 |
var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
|
|
|
426 |
var content = element.innerHTML;
|
|
|
427 |
|
|
|
428 |
if (content.length > 20) {
|
|
|
429 |
content = content.substr(0, 20) + "[...]";
|
|
|
430 |
}
|
|
|
431 |
|
|
|
432 |
var res = formatted + pairs.join(" ") + ">" + content + "</" + tagName + ">";
|
|
|
433 |
|
|
|
434 |
return res.replace(/ contentEditable="inherit"/, "");
|
|
|
435 |
};
|
|
|
436 |
|
|
|
437 |
ascii.constructorName = function (object) {
|
|
|
438 |
var name = buster.functionName(object && object.constructor);
|
|
|
439 |
var excludes = this.excludeConstructors || buster.format.excludeConstructors || [];
|
|
|
440 |
|
|
|
441 |
for (var i = 0, l = excludes.length; i < l; ++i) {
|
|
|
442 |
if (typeof excludes[i] == "string" && excludes[i] == name) {
|
|
|
443 |
return "";
|
|
|
444 |
} else if (excludes[i].test && excludes[i].test(name)) {
|
|
|
445 |
return "";
|
|
|
446 |
}
|
|
|
447 |
}
|
|
|
448 |
|
|
|
449 |
return name;
|
|
|
450 |
};
|
|
|
451 |
|
|
|
452 |
return ascii;
|
|
|
453 |
}());
|
|
|
454 |
|
|
|
455 |
if (typeof module != "undefined") {
|
|
|
456 |
module.exports = buster.format;
|
|
|
457 |
}
|
|
|
458 |
/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
|
|
|
459 |
/*global module, require, __dirname, document*/
|
|
|
460 |
/**
|
|
|
461 |
* Sinon core utilities. For internal use only.
|
|
|
462 |
*
|
|
|
463 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
464 |
* @license BSD
|
|
|
465 |
*
|
|
|
466 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
467 |
*/
|
|
|
468 |
|
|
|
469 |
var sinon = (function (buster) {
|
|
|
470 |
var div = typeof document != "undefined" && document.createElement("div");
|
|
|
471 |
var hasOwn = Object.prototype.hasOwnProperty;
|
|
|
472 |
|
|
|
473 |
function isDOMNode(obj) {
|
|
|
474 |
var success = false;
|
|
|
475 |
|
|
|
476 |
try {
|
|
|
477 |
obj.appendChild(div);
|
|
|
478 |
success = div.parentNode == obj;
|
|
|
479 |
} catch (e) {
|
|
|
480 |
return false;
|
|
|
481 |
} finally {
|
|
|
482 |
try {
|
|
|
483 |
obj.removeChild(div);
|
|
|
484 |
} catch (e) {
|
|
|
485 |
// Remove failed, not much we can do about that
|
|
|
486 |
}
|
|
|
487 |
}
|
|
|
488 |
|
|
|
489 |
return success;
|
|
|
490 |
}
|
|
|
491 |
|
|
|
492 |
function isElement(obj) {
|
|
|
493 |
return div && obj && obj.nodeType === 1 && isDOMNode(obj);
|
|
|
494 |
}
|
|
|
495 |
|
|
|
496 |
function isFunction(obj) {
|
|
|
497 |
return !!(obj && obj.constructor && obj.call && obj.apply);
|
|
|
498 |
}
|
|
|
499 |
|
|
|
500 |
function mirrorProperties(target, source) {
|
|
|
501 |
for (var prop in source) {
|
|
|
502 |
if (!hasOwn.call(target, prop)) {
|
|
|
503 |
target[prop] = source[prop];
|
|
|
504 |
}
|
|
|
505 |
}
|
|
|
506 |
}
|
|
|
507 |
|
|
|
508 |
var sinon = {
|
|
|
509 |
wrapMethod: function wrapMethod(object, property, method) {
|
|
|
510 |
if (!object) {
|
|
|
511 |
throw new TypeError("Should wrap property of object");
|
|
|
512 |
}
|
|
|
513 |
|
|
|
514 |
if (typeof method != "function") {
|
|
|
515 |
throw new TypeError("Method wrapper should be function");
|
|
|
516 |
}
|
|
|
517 |
|
|
|
518 |
var wrappedMethod = object[property];
|
|
|
519 |
|
|
|
520 |
if (!isFunction(wrappedMethod)) {
|
|
|
521 |
throw new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
|
|
|
522 |
property + " as function");
|
|
|
523 |
}
|
|
|
524 |
|
|
|
525 |
if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
|
|
|
526 |
throw new TypeError("Attempted to wrap " + property + " which is already wrapped");
|
|
|
527 |
}
|
|
|
528 |
|
|
|
529 |
if (wrappedMethod.calledBefore) {
|
|
|
530 |
var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
|
|
|
531 |
throw new TypeError("Attempted to wrap " + property + " which is already " + verb);
|
|
|
532 |
}
|
|
|
533 |
|
|
|
534 |
// IE 8 does not support hasOwnProperty on the window object.
|
|
|
535 |
var owned = hasOwn.call(object, property);
|
|
|
536 |
object[property] = method;
|
|
|
537 |
method.displayName = property;
|
|
|
538 |
|
|
|
539 |
method.restore = function () {
|
|
|
540 |
// For prototype properties try to reset by delete first.
|
|
|
541 |
// If this fails (ex: localStorage on mobile safari) then force a reset
|
|
|
542 |
// via direct assignment.
|
|
|
543 |
if (!owned) {
|
|
|
544 |
delete object[property];
|
|
|
545 |
}
|
|
|
546 |
if (object[property] === method) {
|
|
|
547 |
object[property] = wrappedMethod;
|
|
|
548 |
}
|
|
|
549 |
};
|
|
|
550 |
|
|
|
551 |
method.restore.sinon = true;
|
|
|
552 |
mirrorProperties(method, wrappedMethod);
|
|
|
553 |
|
|
|
554 |
return method;
|
|
|
555 |
},
|
|
|
556 |
|
|
|
557 |
extend: function extend(target) {
|
|
|
558 |
for (var i = 1, l = arguments.length; i < l; i += 1) {
|
|
|
559 |
for (var prop in arguments[i]) {
|
|
|
560 |
if (arguments[i].hasOwnProperty(prop)) {
|
|
|
561 |
target[prop] = arguments[i][prop];
|
|
|
562 |
}
|
|
|
563 |
|
|
|
564 |
// DONT ENUM bug, only care about toString
|
|
|
565 |
if (arguments[i].hasOwnProperty("toString") &&
|
|
|
566 |
arguments[i].toString != target.toString) {
|
|
|
567 |
target.toString = arguments[i].toString;
|
|
|
568 |
}
|
|
|
569 |
}
|
|
|
570 |
}
|
|
|
571 |
|
|
|
572 |
return target;
|
|
|
573 |
},
|
|
|
574 |
|
|
|
575 |
create: function create(proto) {
|
|
|
576 |
var F = function () {};
|
|
|
577 |
F.prototype = proto;
|
|
|
578 |
return new F();
|
|
|
579 |
},
|
|
|
580 |
|
|
|
581 |
deepEqual: function deepEqual(a, b) {
|
|
|
582 |
if (sinon.match && sinon.match.isMatcher(a)) {
|
|
|
583 |
return a.test(b);
|
|
|
584 |
}
|
|
|
585 |
if (typeof a != "object" || typeof b != "object") {
|
|
|
586 |
return a === b;
|
|
|
587 |
}
|
|
|
588 |
|
|
|
589 |
if (isElement(a) || isElement(b)) {
|
|
|
590 |
return a === b;
|
|
|
591 |
}
|
|
|
592 |
|
|
|
593 |
if (a === b) {
|
|
|
594 |
return true;
|
|
|
595 |
}
|
|
|
596 |
|
|
|
597 |
var aString = Object.prototype.toString.call(a);
|
|
|
598 |
if (aString != Object.prototype.toString.call(b)) {
|
|
|
599 |
return false;
|
|
|
600 |
}
|
|
|
601 |
|
|
|
602 |
if (aString == "[object Array]") {
|
|
|
603 |
if (a.length !== b.length) {
|
|
|
604 |
return false;
|
|
|
605 |
}
|
|
|
606 |
|
|
|
607 |
for (var i = 0, l = a.length; i < l; i += 1) {
|
|
|
608 |
if (!deepEqual(a[i], b[i])) {
|
|
|
609 |
return false;
|
|
|
610 |
}
|
|
|
611 |
}
|
|
|
612 |
|
|
|
613 |
return true;
|
|
|
614 |
}
|
|
|
615 |
|
|
|
616 |
var prop, aLength = 0, bLength = 0;
|
|
|
617 |
|
|
|
618 |
for (prop in a) {
|
|
|
619 |
aLength += 1;
|
|
|
620 |
|
|
|
621 |
if (!deepEqual(a[prop], b[prop])) {
|
|
|
622 |
return false;
|
|
|
623 |
}
|
|
|
624 |
}
|
|
|
625 |
|
|
|
626 |
for (prop in b) {
|
|
|
627 |
bLength += 1;
|
|
|
628 |
}
|
|
|
629 |
|
|
|
630 |
if (aLength != bLength) {
|
|
|
631 |
return false;
|
|
|
632 |
}
|
|
|
633 |
|
|
|
634 |
return true;
|
|
|
635 |
},
|
|
|
636 |
|
|
|
637 |
functionName: function functionName(func) {
|
|
|
638 |
var name = func.displayName || func.name;
|
|
|
639 |
|
|
|
640 |
// Use function decomposition as a last resort to get function
|
|
|
641 |
// name. Does not rely on function decomposition to work - if it
|
|
|
642 |
// doesn't debugging will be slightly less informative
|
|
|
643 |
// (i.e. toString will say 'spy' rather than 'myFunc').
|
|
|
644 |
if (!name) {
|
|
|
645 |
var matches = func.toString().match(/function ([^\s\(]+)/);
|
|
|
646 |
name = matches && matches[1];
|
|
|
647 |
}
|
|
|
648 |
|
|
|
649 |
return name;
|
|
|
650 |
},
|
|
|
651 |
|
|
|
652 |
functionToString: function toString() {
|
|
|
653 |
if (this.getCall && this.callCount) {
|
|
|
654 |
var thisValue, prop, i = this.callCount;
|
|
|
655 |
|
|
|
656 |
while (i--) {
|
|
|
657 |
thisValue = this.getCall(i).thisValue;
|
|
|
658 |
|
|
|
659 |
for (prop in thisValue) {
|
|
|
660 |
if (thisValue[prop] === this) {
|
|
|
661 |
return prop;
|
|
|
662 |
}
|
|
|
663 |
}
|
|
|
664 |
}
|
|
|
665 |
}
|
|
|
666 |
|
|
|
667 |
return this.displayName || "sinon fake";
|
|
|
668 |
},
|
|
|
669 |
|
|
|
670 |
getConfig: function (custom) {
|
|
|
671 |
var config = {};
|
|
|
672 |
custom = custom || {};
|
|
|
673 |
var defaults = sinon.defaultConfig;
|
|
|
674 |
|
|
|
675 |
for (var prop in defaults) {
|
|
|
676 |
if (defaults.hasOwnProperty(prop)) {
|
|
|
677 |
config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
|
|
|
678 |
}
|
|
|
679 |
}
|
|
|
680 |
|
|
|
681 |
return config;
|
|
|
682 |
},
|
|
|
683 |
|
|
|
684 |
format: function (val) {
|
|
|
685 |
return "" + val;
|
|
|
686 |
},
|
|
|
687 |
|
|
|
688 |
defaultConfig: {
|
|
|
689 |
injectIntoThis: true,
|
|
|
690 |
injectInto: null,
|
|
|
691 |
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
|
|
|
692 |
useFakeTimers: true,
|
|
|
693 |
useFakeServer: true
|
|
|
694 |
},
|
|
|
695 |
|
|
|
696 |
timesInWords: function timesInWords(count) {
|
|
|
697 |
return count == 1 && "once" ||
|
|
|
698 |
count == 2 && "twice" ||
|
|
|
699 |
count == 3 && "thrice" ||
|
|
|
700 |
(count || 0) + " times";
|
|
|
701 |
},
|
|
|
702 |
|
|
|
703 |
calledInOrder: function (spies) {
|
|
|
704 |
for (var i = 1, l = spies.length; i < l; i++) {
|
|
|
705 |
if (!spies[i - 1].calledBefore(spies[i])) {
|
|
|
706 |
return false;
|
|
|
707 |
}
|
|
|
708 |
}
|
|
|
709 |
|
|
|
710 |
return true;
|
|
|
711 |
},
|
|
|
712 |
|
|
|
713 |
orderByFirstCall: function (spies) {
|
|
|
714 |
return spies.sort(function (a, b) {
|
|
|
715 |
// uuid, won't ever be equal
|
|
|
716 |
var aCall = a.getCall(0);
|
|
|
717 |
var bCall = b.getCall(0);
|
|
|
718 |
var aId = aCall && aCall.callId || -1;
|
|
|
719 |
var bId = bCall && bCall.callId || -1;
|
|
|
720 |
|
|
|
721 |
return aId < bId ? -1 : 1;
|
|
|
722 |
});
|
|
|
723 |
},
|
|
|
724 |
|
|
|
725 |
log: function () {},
|
|
|
726 |
|
|
|
727 |
logError: function (label, err) {
|
|
|
728 |
var msg = label + " threw exception: "
|
|
|
729 |
sinon.log(msg + "[" + err.name + "] " + err.message);
|
|
|
730 |
if (err.stack) { sinon.log(err.stack); }
|
|
|
731 |
|
|
|
732 |
setTimeout(function () {
|
|
|
733 |
err.message = msg + err.message;
|
|
|
734 |
throw err;
|
|
|
735 |
}, 0);
|
|
|
736 |
},
|
|
|
737 |
|
|
|
738 |
typeOf: function (value) {
|
|
|
739 |
if (value === null) {
|
|
|
740 |
return "null";
|
|
|
741 |
}
|
|
|
742 |
var string = Object.prototype.toString.call(value);
|
|
|
743 |
return string.substring(8, string.length - 1).toLowerCase();
|
|
|
744 |
}
|
|
|
745 |
};
|
|
|
746 |
|
|
|
747 |
var isNode = typeof module == "object" && typeof require == "function";
|
|
|
748 |
|
|
|
749 |
if (isNode) {
|
|
|
750 |
try {
|
|
|
751 |
buster = { format: require("buster-format") };
|
|
|
752 |
} catch (e) {}
|
|
|
753 |
module.exports = sinon;
|
|
|
754 |
module.exports.spy = require("./sinon/spy");
|
|
|
755 |
module.exports.stub = require("./sinon/stub");
|
|
|
756 |
module.exports.mock = require("./sinon/mock");
|
|
|
757 |
module.exports.collection = require("./sinon/collection");
|
|
|
758 |
module.exports.assert = require("./sinon/assert");
|
|
|
759 |
module.exports.sandbox = require("./sinon/sandbox");
|
|
|
760 |
module.exports.test = require("./sinon/test");
|
|
|
761 |
module.exports.testCase = require("./sinon/test_case");
|
|
|
762 |
module.exports.assert = require("./sinon/assert");
|
|
|
763 |
module.exports.match = require("./sinon/match");
|
|
|
764 |
}
|
|
|
765 |
|
|
|
766 |
if (buster) {
|
|
|
767 |
var formatter = sinon.create(buster.format);
|
|
|
768 |
formatter.quoteStrings = false;
|
|
|
769 |
sinon.format = function () {
|
|
|
770 |
return formatter.ascii.apply(formatter, arguments);
|
|
|
771 |
};
|
|
|
772 |
} else if (isNode) {
|
|
|
773 |
try {
|
|
|
774 |
var util = require("util");
|
|
|
775 |
sinon.format = function (value) {
|
|
|
776 |
return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
|
|
|
777 |
};
|
|
|
778 |
} catch (e) {
|
|
|
779 |
/* Node, but no util module - would be very old, but better safe than
|
|
|
780 |
sorry */
|
|
|
781 |
}
|
|
|
782 |
}
|
|
|
783 |
|
|
|
784 |
return sinon;
|
|
|
785 |
}(typeof buster == "object" && buster));
|
|
|
786 |
|
|
|
787 |
/* @depend ../sinon.js */
|
|
|
788 |
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
|
|
|
789 |
/*global module, require, sinon*/
|
|
|
790 |
/**
|
|
|
791 |
* Match functions
|
|
|
792 |
*
|
|
|
793 |
* @author Maximilian Antoni (mail@maxantoni.de)
|
|
|
794 |
* @license BSD
|
|
|
795 |
*
|
|
|
796 |
* Copyright (c) 2012 Maximilian Antoni
|
|
|
797 |
*/
|
|
|
798 |
|
|
|
799 |
(function (sinon) {
|
|
|
800 |
var commonJSModule = typeof module == "object" && typeof require == "function";
|
|
|
801 |
|
|
|
802 |
if (!sinon && commonJSModule) {
|
|
|
803 |
sinon = require("../sinon");
|
|
|
804 |
}
|
|
|
805 |
|
|
|
806 |
if (!sinon) {
|
|
|
807 |
return;
|
|
|
808 |
}
|
|
|
809 |
|
|
|
810 |
function assertType(value, type, name) {
|
|
|
811 |
var actual = sinon.typeOf(value);
|
|
|
812 |
if (actual !== type) {
|
|
|
813 |
throw new TypeError("Expected type of " + name + " to be " +
|
|
|
814 |
type + ", but was " + actual);
|
|
|
815 |
}
|
|
|
816 |
}
|
|
|
817 |
|
|
|
818 |
var matcher = {
|
|
|
819 |
toString: function () {
|
|
|
820 |
return this.message;
|
|
|
821 |
}
|
|
|
822 |
};
|
|
|
823 |
|
|
|
824 |
function isMatcher(object) {
|
|
|
825 |
return matcher.isPrototypeOf(object);
|
|
|
826 |
}
|
|
|
827 |
|
|
|
828 |
function matchObject(expectation, actual) {
|
|
|
829 |
if (actual === null || actual === undefined) {
|
|
|
830 |
return false;
|
|
|
831 |
}
|
|
|
832 |
for (var key in expectation) {
|
|
|
833 |
if (expectation.hasOwnProperty(key)) {
|
|
|
834 |
var exp = expectation[key];
|
|
|
835 |
var act = actual[key];
|
|
|
836 |
if (match.isMatcher(exp)) {
|
|
|
837 |
if (!exp.test(act)) {
|
|
|
838 |
return false;
|
|
|
839 |
}
|
|
|
840 |
} else if (sinon.typeOf(exp) === "object") {
|
|
|
841 |
if (!matchObject(exp, act)) {
|
|
|
842 |
return false;
|
|
|
843 |
}
|
|
|
844 |
} else if (!sinon.deepEqual(exp, act)) {
|
|
|
845 |
return false;
|
|
|
846 |
}
|
|
|
847 |
}
|
|
|
848 |
}
|
|
|
849 |
return true;
|
|
|
850 |
}
|
|
|
851 |
|
|
|
852 |
matcher.or = function (m2) {
|
|
|
853 |
if (!isMatcher(m2)) {
|
|
|
854 |
throw new TypeError("Matcher expected");
|
|
|
855 |
}
|
|
|
856 |
var m1 = this;
|
|
|
857 |
var or = sinon.create(matcher);
|
|
|
858 |
or.test = function (actual) {
|
|
|
859 |
return m1.test(actual) || m2.test(actual);
|
|
|
860 |
};
|
|
|
861 |
or.message = m1.message + ".or(" + m2.message + ")";
|
|
|
862 |
return or;
|
|
|
863 |
};
|
|
|
864 |
|
|
|
865 |
matcher.and = function (m2) {
|
|
|
866 |
if (!isMatcher(m2)) {
|
|
|
867 |
throw new TypeError("Matcher expected");
|
|
|
868 |
}
|
|
|
869 |
var m1 = this;
|
|
|
870 |
var and = sinon.create(matcher);
|
|
|
871 |
and.test = function (actual) {
|
|
|
872 |
return m1.test(actual) && m2.test(actual);
|
|
|
873 |
};
|
|
|
874 |
and.message = m1.message + ".and(" + m2.message + ")";
|
|
|
875 |
return and;
|
|
|
876 |
};
|
|
|
877 |
|
|
|
878 |
var match = function (expectation, message) {
|
|
|
879 |
var m = sinon.create(matcher);
|
|
|
880 |
var type = sinon.typeOf(expectation);
|
|
|
881 |
switch (type) {
|
|
|
882 |
case "object":
|
|
|
883 |
if (typeof expectation.test === "function") {
|
|
|
884 |
m.test = function (actual) {
|
|
|
885 |
return expectation.test(actual) === true;
|
|
|
886 |
};
|
|
|
887 |
m.message = "match(" + sinon.functionName(expectation.test) + ")";
|
|
|
888 |
return m;
|
|
|
889 |
}
|
|
|
890 |
var str = [];
|
|
|
891 |
for (var key in expectation) {
|
|
|
892 |
if (expectation.hasOwnProperty(key)) {
|
|
|
893 |
str.push(key + ": " + expectation[key]);
|
|
|
894 |
}
|
|
|
895 |
}
|
|
|
896 |
m.test = function (actual) {
|
|
|
897 |
return matchObject(expectation, actual);
|
|
|
898 |
};
|
|
|
899 |
m.message = "match(" + str.join(", ") + ")";
|
|
|
900 |
break;
|
|
|
901 |
case "number":
|
|
|
902 |
m.test = function (actual) {
|
|
|
903 |
return expectation == actual;
|
|
|
904 |
};
|
|
|
905 |
break;
|
|
|
906 |
case "string":
|
|
|
907 |
m.test = function (actual) {
|
|
|
908 |
if (typeof actual !== "string") {
|
|
|
909 |
return false;
|
|
|
910 |
}
|
|
|
911 |
return actual.indexOf(expectation) !== -1;
|
|
|
912 |
};
|
|
|
913 |
m.message = "match(\"" + expectation + "\")";
|
|
|
914 |
break;
|
|
|
915 |
case "regexp":
|
|
|
916 |
m.test = function (actual) {
|
|
|
917 |
if (typeof actual !== "string") {
|
|
|
918 |
return false;
|
|
|
919 |
}
|
|
|
920 |
return expectation.test(actual);
|
|
|
921 |
};
|
|
|
922 |
break;
|
|
|
923 |
case "function":
|
|
|
924 |
m.test = expectation;
|
|
|
925 |
if (message) {
|
|
|
926 |
m.message = message;
|
|
|
927 |
} else {
|
|
|
928 |
m.message = "match(" + sinon.functionName(expectation) + ")";
|
|
|
929 |
}
|
|
|
930 |
break;
|
|
|
931 |
default:
|
|
|
932 |
m.test = function (actual) {
|
|
|
933 |
return sinon.deepEqual(expectation, actual);
|
|
|
934 |
};
|
|
|
935 |
}
|
|
|
936 |
if (!m.message) {
|
|
|
937 |
m.message = "match(" + expectation + ")";
|
|
|
938 |
}
|
|
|
939 |
return m;
|
|
|
940 |
};
|
|
|
941 |
|
|
|
942 |
match.isMatcher = isMatcher;
|
|
|
943 |
|
|
|
944 |
match.any = match(function () {
|
|
|
945 |
return true;
|
|
|
946 |
}, "any");
|
|
|
947 |
|
|
|
948 |
match.defined = match(function (actual) {
|
|
|
949 |
return actual !== null && actual !== undefined;
|
|
|
950 |
}, "defined");
|
|
|
951 |
|
|
|
952 |
match.truthy = match(function (actual) {
|
|
|
953 |
return !!actual;
|
|
|
954 |
}, "truthy");
|
|
|
955 |
|
|
|
956 |
match.falsy = match(function (actual) {
|
|
|
957 |
return !actual;
|
|
|
958 |
}, "falsy");
|
|
|
959 |
|
|
|
960 |
match.same = function (expectation) {
|
|
|
961 |
return match(function (actual) {
|
|
|
962 |
return expectation === actual;
|
|
|
963 |
}, "same(" + expectation + ")");
|
|
|
964 |
};
|
|
|
965 |
|
|
|
966 |
match.typeOf = function (type) {
|
|
|
967 |
assertType(type, "string", "type");
|
|
|
968 |
return match(function (actual) {
|
|
|
969 |
return sinon.typeOf(actual) === type;
|
|
|
970 |
}, "typeOf(\"" + type + "\")");
|
|
|
971 |
};
|
|
|
972 |
|
|
|
973 |
match.instanceOf = function (type) {
|
|
|
974 |
assertType(type, "function", "type");
|
|
|
975 |
return match(function (actual) {
|
|
|
976 |
return actual instanceof type;
|
|
|
977 |
}, "instanceOf(" + sinon.functionName(type) + ")");
|
|
|
978 |
};
|
|
|
979 |
|
|
|
980 |
function createPropertyMatcher(propertyTest, messagePrefix) {
|
|
|
981 |
return function (property, value) {
|
|
|
982 |
assertType(property, "string", "property");
|
|
|
983 |
var onlyProperty = arguments.length === 1;
|
|
|
984 |
var message = messagePrefix + "(\"" + property + "\"";
|
|
|
985 |
if (!onlyProperty) {
|
|
|
986 |
message += ", " + value;
|
|
|
987 |
}
|
|
|
988 |
message += ")";
|
|
|
989 |
return match(function (actual) {
|
|
|
990 |
if (actual === undefined || actual === null ||
|
|
|
991 |
!propertyTest(actual, property)) {
|
|
|
992 |
return false;
|
|
|
993 |
}
|
|
|
994 |
return onlyProperty || sinon.deepEqual(value, actual[property]);
|
|
|
995 |
}, message);
|
|
|
996 |
};
|
|
|
997 |
}
|
|
|
998 |
|
|
|
999 |
match.has = createPropertyMatcher(function (actual, property) {
|
|
|
1000 |
if (typeof actual === "object") {
|
|
|
1001 |
return property in actual;
|
|
|
1002 |
}
|
|
|
1003 |
return actual[property] !== undefined;
|
|
|
1004 |
}, "has");
|
|
|
1005 |
|
|
|
1006 |
match.hasOwn = createPropertyMatcher(function (actual, property) {
|
|
|
1007 |
return actual.hasOwnProperty(property);
|
|
|
1008 |
}, "hasOwn");
|
|
|
1009 |
|
|
|
1010 |
match.bool = match.typeOf("boolean");
|
|
|
1011 |
match.number = match.typeOf("number");
|
|
|
1012 |
match.string = match.typeOf("string");
|
|
|
1013 |
match.object = match.typeOf("object");
|
|
|
1014 |
match.func = match.typeOf("function");
|
|
|
1015 |
match.array = match.typeOf("array");
|
|
|
1016 |
match.regexp = match.typeOf("regexp");
|
|
|
1017 |
match.date = match.typeOf("date");
|
|
|
1018 |
|
|
|
1019 |
if (commonJSModule) {
|
|
|
1020 |
module.exports = match;
|
|
|
1021 |
} else {
|
|
|
1022 |
sinon.match = match;
|
|
|
1023 |
}
|
|
|
1024 |
}(typeof sinon == "object" && sinon || null));
|
|
|
1025 |
|
|
|
1026 |
/**
|
|
|
1027 |
* @depend ../sinon.js
|
|
|
1028 |
* @depend match.js
|
|
|
1029 |
*/
|
|
|
1030 |
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
|
|
|
1031 |
/*global module, require, sinon*/
|
|
|
1032 |
/**
|
|
|
1033 |
* Spy functions
|
|
|
1034 |
*
|
|
|
1035 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
1036 |
* @license BSD
|
|
|
1037 |
*
|
|
|
1038 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
1039 |
*/
|
|
|
1040 |
|
|
|
1041 |
(function (sinon) {
|
|
|
1042 |
var commonJSModule = typeof module == "object" && typeof require == "function";
|
|
|
1043 |
var spyCall;
|
|
|
1044 |
var callId = 0;
|
|
|
1045 |
var push = [].push;
|
|
|
1046 |
var slice = Array.prototype.slice;
|
|
|
1047 |
|
|
|
1048 |
if (!sinon && commonJSModule) {
|
|
|
1049 |
sinon = require("../sinon");
|
|
|
1050 |
}
|
|
|
1051 |
|
|
|
1052 |
if (!sinon) {
|
|
|
1053 |
return;
|
|
|
1054 |
}
|
|
|
1055 |
|
|
|
1056 |
function spy(object, property) {
|
|
|
1057 |
if (!property && typeof object == "function") {
|
|
|
1058 |
return spy.create(object);
|
|
|
1059 |
}
|
|
|
1060 |
|
|
|
1061 |
if (!object && !property) {
|
|
|
1062 |
return spy.create(function () {});
|
|
|
1063 |
}
|
|
|
1064 |
|
|
|
1065 |
var method = object[property];
|
|
|
1066 |
return sinon.wrapMethod(object, property, spy.create(method));
|
|
|
1067 |
}
|
|
|
1068 |
|
|
|
1069 |
sinon.extend(spy, (function () {
|
|
|
1070 |
|
|
|
1071 |
function delegateToCalls(api, method, matchAny, actual, notCalled) {
|
|
|
1072 |
api[method] = function () {
|
|
|
1073 |
if (!this.called) {
|
|
|
1074 |
if (notCalled) {
|
|
|
1075 |
return notCalled.apply(this, arguments);
|
|
|
1076 |
}
|
|
|
1077 |
return false;
|
|
|
1078 |
}
|
|
|
1079 |
|
|
|
1080 |
var currentCall;
|
|
|
1081 |
var matches = 0;
|
|
|
1082 |
|
|
|
1083 |
for (var i = 0, l = this.callCount; i < l; i += 1) {
|
|
|
1084 |
currentCall = this.getCall(i);
|
|
|
1085 |
|
|
|
1086 |
if (currentCall[actual || method].apply(currentCall, arguments)) {
|
|
|
1087 |
matches += 1;
|
|
|
1088 |
|
|
|
1089 |
if (matchAny) {
|
|
|
1090 |
return true;
|
|
|
1091 |
}
|
|
|
1092 |
}
|
|
|
1093 |
}
|
|
|
1094 |
|
|
|
1095 |
return matches === this.callCount;
|
|
|
1096 |
};
|
|
|
1097 |
}
|
|
|
1098 |
|
|
|
1099 |
function matchingFake(fakes, args, strict) {
|
|
|
1100 |
if (!fakes) {
|
|
|
1101 |
return;
|
|
|
1102 |
}
|
|
|
1103 |
|
|
|
1104 |
var alen = args.length;
|
|
|
1105 |
|
|
|
1106 |
for (var i = 0, l = fakes.length; i < l; i++) {
|
|
|
1107 |
if (fakes[i].matches(args, strict)) {
|
|
|
1108 |
return fakes[i];
|
|
|
1109 |
}
|
|
|
1110 |
}
|
|
|
1111 |
}
|
|
|
1112 |
|
|
|
1113 |
function incrementCallCount() {
|
|
|
1114 |
this.called = true;
|
|
|
1115 |
this.callCount += 1;
|
|
|
1116 |
this.notCalled = false;
|
|
|
1117 |
this.calledOnce = this.callCount == 1;
|
|
|
1118 |
this.calledTwice = this.callCount == 2;
|
|
|
1119 |
this.calledThrice = this.callCount == 3;
|
|
|
1120 |
}
|
|
|
1121 |
|
|
|
1122 |
function createCallProperties() {
|
|
|
1123 |
this.firstCall = this.getCall(0);
|
|
|
1124 |
this.secondCall = this.getCall(1);
|
|
|
1125 |
this.thirdCall = this.getCall(2);
|
|
|
1126 |
this.lastCall = this.getCall(this.callCount - 1);
|
|
|
1127 |
}
|
|
|
1128 |
|
|
|
1129 |
var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
|
|
|
1130 |
function createProxy(func) {
|
|
|
1131 |
// Retain the function length:
|
|
|
1132 |
if (func.length) {
|
|
|
1133 |
return eval("(function proxy(" + vars.substring(0, func.length * 2 - 1) +
|
|
|
1134 |
") { return proxy.invoke(func, this, slice.call(arguments)); })");
|
|
|
1135 |
}
|
|
|
1136 |
return function proxy() {
|
|
|
1137 |
return proxy.invoke(func, this, slice.call(arguments));
|
|
|
1138 |
};
|
|
|
1139 |
}
|
|
|
1140 |
|
|
|
1141 |
var uuid = 0;
|
|
|
1142 |
|
|
|
1143 |
// Public API
|
|
|
1144 |
var spyApi = {
|
|
|
1145 |
reset: function () {
|
|
|
1146 |
this.called = false;
|
|
|
1147 |
this.notCalled = true;
|
|
|
1148 |
this.calledOnce = false;
|
|
|
1149 |
this.calledTwice = false;
|
|
|
1150 |
this.calledThrice = false;
|
|
|
1151 |
this.callCount = 0;
|
|
|
1152 |
this.firstCall = null;
|
|
|
1153 |
this.secondCall = null;
|
|
|
1154 |
this.thirdCall = null;
|
|
|
1155 |
this.lastCall = null;
|
|
|
1156 |
this.args = [];
|
|
|
1157 |
this.returnValues = [];
|
|
|
1158 |
this.thisValues = [];
|
|
|
1159 |
this.exceptions = [];
|
|
|
1160 |
this.callIds = [];
|
|
|
1161 |
if (this.fakes) {
|
|
|
1162 |
for (var i = 0; i < this.fakes.length; i++) {
|
|
|
1163 |
this.fakes[i].reset();
|
|
|
1164 |
}
|
|
|
1165 |
}
|
|
|
1166 |
},
|
|
|
1167 |
|
|
|
1168 |
create: function create(func) {
|
|
|
1169 |
var name;
|
|
|
1170 |
|
|
|
1171 |
if (typeof func != "function") {
|
|
|
1172 |
func = function () {};
|
|
|
1173 |
} else {
|
|
|
1174 |
name = sinon.functionName(func);
|
|
|
1175 |
}
|
|
|
1176 |
|
|
|
1177 |
var proxy = createProxy(func);
|
|
|
1178 |
|
|
|
1179 |
sinon.extend(proxy, spy);
|
|
|
1180 |
delete proxy.create;
|
|
|
1181 |
sinon.extend(proxy, func);
|
|
|
1182 |
|
|
|
1183 |
proxy.reset();
|
|
|
1184 |
proxy.prototype = func.prototype;
|
|
|
1185 |
proxy.displayName = name || "spy";
|
|
|
1186 |
proxy.toString = sinon.functionToString;
|
|
|
1187 |
proxy._create = sinon.spy.create;
|
|
|
1188 |
proxy.id = "spy#" + uuid++;
|
|
|
1189 |
|
|
|
1190 |
return proxy;
|
|
|
1191 |
},
|
|
|
1192 |
|
|
|
1193 |
invoke: function invoke(func, thisValue, args) {
|
|
|
1194 |
var matching = matchingFake(this.fakes, args);
|
|
|
1195 |
var exception, returnValue;
|
|
|
1196 |
|
|
|
1197 |
incrementCallCount.call(this);
|
|
|
1198 |
push.call(this.thisValues, thisValue);
|
|
|
1199 |
push.call(this.args, args);
|
|
|
1200 |
push.call(this.callIds, callId++);
|
|
|
1201 |
|
|
|
1202 |
try {
|
|
|
1203 |
if (matching) {
|
|
|
1204 |
returnValue = matching.invoke(func, thisValue, args);
|
|
|
1205 |
} else {
|
|
|
1206 |
returnValue = (this.func || func).apply(thisValue, args);
|
|
|
1207 |
}
|
|
|
1208 |
} catch (e) {
|
|
|
1209 |
push.call(this.returnValues, undefined);
|
|
|
1210 |
exception = e;
|
|
|
1211 |
throw e;
|
|
|
1212 |
} finally {
|
|
|
1213 |
push.call(this.exceptions, exception);
|
|
|
1214 |
}
|
|
|
1215 |
|
|
|
1216 |
push.call(this.returnValues, returnValue);
|
|
|
1217 |
|
|
|
1218 |
createCallProperties.call(this);
|
|
|
1219 |
|
|
|
1220 |
return returnValue;
|
|
|
1221 |
},
|
|
|
1222 |
|
|
|
1223 |
getCall: function getCall(i) {
|
|
|
1224 |
if (i < 0 || i >= this.callCount) {
|
|
|
1225 |
return null;
|
|
|
1226 |
}
|
|
|
1227 |
|
|
|
1228 |
return spyCall.create(this, this.thisValues[i], this.args[i],
|
|
|
1229 |
this.returnValues[i], this.exceptions[i],
|
|
|
1230 |
this.callIds[i]);
|
|
|
1231 |
},
|
|
|
1232 |
|
|
|
1233 |
calledBefore: function calledBefore(spyFn) {
|
|
|
1234 |
if (!this.called) {
|
|
|
1235 |
return false;
|
|
|
1236 |
}
|
|
|
1237 |
|
|
|
1238 |
if (!spyFn.called) {
|
|
|
1239 |
return true;
|
|
|
1240 |
}
|
|
|
1241 |
|
|
|
1242 |
return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
|
|
|
1243 |
},
|
|
|
1244 |
|
|
|
1245 |
calledAfter: function calledAfter(spyFn) {
|
|
|
1246 |
if (!this.called || !spyFn.called) {
|
|
|
1247 |
return false;
|
|
|
1248 |
}
|
|
|
1249 |
|
|
|
1250 |
return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
|
|
|
1251 |
},
|
|
|
1252 |
|
|
|
1253 |
withArgs: function () {
|
|
|
1254 |
var args = slice.call(arguments);
|
|
|
1255 |
|
|
|
1256 |
if (this.fakes) {
|
|
|
1257 |
var match = matchingFake(this.fakes, args, true);
|
|
|
1258 |
|
|
|
1259 |
if (match) {
|
|
|
1260 |
return match;
|
|
|
1261 |
}
|
|
|
1262 |
} else {
|
|
|
1263 |
this.fakes = [];
|
|
|
1264 |
}
|
|
|
1265 |
|
|
|
1266 |
var original = this;
|
|
|
1267 |
var fake = this._create();
|
|
|
1268 |
fake.matchingAguments = args;
|
|
|
1269 |
push.call(this.fakes, fake);
|
|
|
1270 |
|
|
|
1271 |
fake.withArgs = function () {
|
|
|
1272 |
return original.withArgs.apply(original, arguments);
|
|
|
1273 |
};
|
|
|
1274 |
|
|
|
1275 |
for (var i = 0; i < this.args.length; i++) {
|
|
|
1276 |
if (fake.matches(this.args[i])) {
|
|
|
1277 |
incrementCallCount.call(fake);
|
|
|
1278 |
push.call(fake.thisValues, this.thisValues[i]);
|
|
|
1279 |
push.call(fake.args, this.args[i]);
|
|
|
1280 |
push.call(fake.returnValues, this.returnValues[i]);
|
|
|
1281 |
push.call(fake.exceptions, this.exceptions[i]);
|
|
|
1282 |
push.call(fake.callIds, this.callIds[i]);
|
|
|
1283 |
}
|
|
|
1284 |
}
|
|
|
1285 |
createCallProperties.call(fake);
|
|
|
1286 |
|
|
|
1287 |
return fake;
|
|
|
1288 |
},
|
|
|
1289 |
|
|
|
1290 |
matches: function (args, strict) {
|
|
|
1291 |
var margs = this.matchingAguments;
|
|
|
1292 |
|
|
|
1293 |
if (margs.length <= args.length &&
|
|
|
1294 |
sinon.deepEqual(margs, args.slice(0, margs.length))) {
|
|
|
1295 |
return !strict || margs.length == args.length;
|
|
|
1296 |
}
|
|
|
1297 |
},
|
|
|
1298 |
|
|
|
1299 |
printf: function (format) {
|
|
|
1300 |
var spy = this;
|
|
|
1301 |
var args = slice.call(arguments, 1);
|
|
|
1302 |
var formatter;
|
|
|
1303 |
|
|
|
1304 |
return (format || "").replace(/%(.)/g, function (match, specifyer) {
|
|
|
1305 |
formatter = spyApi.formatters[specifyer];
|
|
|
1306 |
|
|
|
1307 |
if (typeof formatter == "function") {
|
|
|
1308 |
return formatter.call(null, spy, args);
|
|
|
1309 |
} else if (!isNaN(parseInt(specifyer), 10)) {
|
|
|
1310 |
return sinon.format(args[specifyer - 1]);
|
|
|
1311 |
}
|
|
|
1312 |
|
|
|
1313 |
return "%" + specifyer;
|
|
|
1314 |
});
|
|
|
1315 |
}
|
|
|
1316 |
};
|
|
|
1317 |
|
|
|
1318 |
delegateToCalls(spyApi, "calledOn", true);
|
|
|
1319 |
delegateToCalls(spyApi, "alwaysCalledOn", false, "calledOn");
|
|
|
1320 |
delegateToCalls(spyApi, "calledWith", true);
|
|
|
1321 |
delegateToCalls(spyApi, "calledWithMatch", true);
|
|
|
1322 |
delegateToCalls(spyApi, "alwaysCalledWith", false, "calledWith");
|
|
|
1323 |
delegateToCalls(spyApi, "alwaysCalledWithMatch", false, "calledWithMatch");
|
|
|
1324 |
delegateToCalls(spyApi, "calledWithExactly", true);
|
|
|
1325 |
delegateToCalls(spyApi, "alwaysCalledWithExactly", false, "calledWithExactly");
|
|
|
1326 |
delegateToCalls(spyApi, "neverCalledWith", false, "notCalledWith",
|
|
|
1327 |
function () { return true; });
|
|
|
1328 |
delegateToCalls(spyApi, "neverCalledWithMatch", false, "notCalledWithMatch",
|
|
|
1329 |
function () { return true; });
|
|
|
1330 |
delegateToCalls(spyApi, "threw", true);
|
|
|
1331 |
delegateToCalls(spyApi, "alwaysThrew", false, "threw");
|
|
|
1332 |
delegateToCalls(spyApi, "returned", true);
|
|
|
1333 |
delegateToCalls(spyApi, "alwaysReturned", false, "returned");
|
|
|
1334 |
delegateToCalls(spyApi, "calledWithNew", true);
|
|
|
1335 |
delegateToCalls(spyApi, "alwaysCalledWithNew", false, "calledWithNew");
|
|
|
1336 |
delegateToCalls(spyApi, "callArg", false, "callArgWith", function () {
|
|
|
1337 |
throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
|
|
|
1338 |
});
|
|
|
1339 |
spyApi.callArgWith = spyApi.callArg;
|
|
|
1340 |
delegateToCalls(spyApi, "yield", false, "yield", function () {
|
|
|
1341 |
throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
|
|
|
1342 |
});
|
|
|
1343 |
// "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
|
|
|
1344 |
spyApi.invokeCallback = spyApi.yield;
|
|
|
1345 |
delegateToCalls(spyApi, "yieldTo", false, "yieldTo", function (property) {
|
|
|
1346 |
throw new Error(this.toString() + " cannot yield to '" + property +
|
|
|
1347 |
"' since it was not yet invoked.");
|
|
|
1348 |
});
|
|
|
1349 |
|
|
|
1350 |
spyApi.formatters = {
|
|
|
1351 |
"c": function (spy) {
|
|
|
1352 |
return sinon.timesInWords(spy.callCount);
|
|
|
1353 |
},
|
|
|
1354 |
|
|
|
1355 |
"n": function (spy) {
|
|
|
1356 |
return spy.toString();
|
|
|
1357 |
},
|
|
|
1358 |
|
|
|
1359 |
"C": function (spy) {
|
|
|
1360 |
var calls = [];
|
|
|
1361 |
|
|
|
1362 |
for (var i = 0, l = spy.callCount; i < l; ++i) {
|
|
|
1363 |
push.call(calls, " " + spy.getCall(i).toString());
|
|
|
1364 |
}
|
|
|
1365 |
|
|
|
1366 |
return calls.length > 0 ? "\n" + calls.join("\n") : "";
|
|
|
1367 |
},
|
|
|
1368 |
|
|
|
1369 |
"t": function (spy) {
|
|
|
1370 |
var objects = [];
|
|
|
1371 |
|
|
|
1372 |
for (var i = 0, l = spy.callCount; i < l; ++i) {
|
|
|
1373 |
push.call(objects, sinon.format(spy.thisValues[i]));
|
|
|
1374 |
}
|
|
|
1375 |
|
|
|
1376 |
return objects.join(", ");
|
|
|
1377 |
},
|
|
|
1378 |
|
|
|
1379 |
"*": function (spy, args) {
|
|
|
1380 |
var formatted = [];
|
|
|
1381 |
|
|
|
1382 |
for (var i = 0, l = args.length; i < l; ++i) {
|
|
|
1383 |
push.call(formatted, sinon.format(args[i]));
|
|
|
1384 |
}
|
|
|
1385 |
|
|
|
1386 |
return formatted.join(", ");
|
|
|
1387 |
}
|
|
|
1388 |
};
|
|
|
1389 |
|
|
|
1390 |
return spyApi;
|
|
|
1391 |
}()));
|
|
|
1392 |
|
|
|
1393 |
spyCall = (function () {
|
|
|
1394 |
|
|
|
1395 |
function throwYieldError(proxy, text, args) {
|
|
|
1396 |
var msg = sinon.functionName(proxy) + text;
|
|
|
1397 |
if (args.length) {
|
|
|
1398 |
msg += " Received [" + slice.call(args).join(", ") + "]";
|
|
|
1399 |
}
|
|
|
1400 |
throw new Error(msg);
|
|
|
1401 |
}
|
|
|
1402 |
|
|
|
1403 |
var callApi = {
|
|
|
1404 |
create: function create(spy, thisValue, args, returnValue, exception, id) {
|
|
|
1405 |
var proxyCall = sinon.create(spyCall);
|
|
|
1406 |
delete proxyCall.create;
|
|
|
1407 |
proxyCall.proxy = spy;
|
|
|
1408 |
proxyCall.thisValue = thisValue;
|
|
|
1409 |
proxyCall.args = args;
|
|
|
1410 |
proxyCall.returnValue = returnValue;
|
|
|
1411 |
proxyCall.exception = exception;
|
|
|
1412 |
proxyCall.callId = typeof id == "number" && id || callId++;
|
|
|
1413 |
|
|
|
1414 |
return proxyCall;
|
|
|
1415 |
},
|
|
|
1416 |
|
|
|
1417 |
calledOn: function calledOn(thisValue) {
|
|
|
1418 |
if (sinon.match && sinon.match.isMatcher(thisValue)) {
|
|
|
1419 |
return thisValue.test(this.thisValue);
|
|
|
1420 |
}
|
|
|
1421 |
return this.thisValue === thisValue;
|
|
|
1422 |
},
|
|
|
1423 |
|
|
|
1424 |
calledWith: function calledWith() {
|
|
|
1425 |
for (var i = 0, l = arguments.length; i < l; i += 1) {
|
|
|
1426 |
if (!sinon.deepEqual(arguments[i], this.args[i])) {
|
|
|
1427 |
return false;
|
|
|
1428 |
}
|
|
|
1429 |
}
|
|
|
1430 |
|
|
|
1431 |
return true;
|
|
|
1432 |
},
|
|
|
1433 |
|
|
|
1434 |
calledWithMatch: function calledWithMatch() {
|
|
|
1435 |
for (var i = 0, l = arguments.length; i < l; i += 1) {
|
|
|
1436 |
var actual = this.args[i];
|
|
|
1437 |
var expectation = arguments[i];
|
|
|
1438 |
if (!sinon.match || !sinon.match(expectation).test(actual)) {
|
|
|
1439 |
return false;
|
|
|
1440 |
}
|
|
|
1441 |
}
|
|
|
1442 |
return true;
|
|
|
1443 |
},
|
|
|
1444 |
|
|
|
1445 |
calledWithExactly: function calledWithExactly() {
|
|
|
1446 |
return arguments.length == this.args.length &&
|
|
|
1447 |
this.calledWith.apply(this, arguments);
|
|
|
1448 |
},
|
|
|
1449 |
|
|
|
1450 |
notCalledWith: function notCalledWith() {
|
|
|
1451 |
return !this.calledWith.apply(this, arguments);
|
|
|
1452 |
},
|
|
|
1453 |
|
|
|
1454 |
notCalledWithMatch: function notCalledWithMatch() {
|
|
|
1455 |
return !this.calledWithMatch.apply(this, arguments);
|
|
|
1456 |
},
|
|
|
1457 |
|
|
|
1458 |
returned: function returned(value) {
|
|
|
1459 |
return sinon.deepEqual(value, this.returnValue);
|
|
|
1460 |
},
|
|
|
1461 |
|
|
|
1462 |
threw: function threw(error) {
|
|
|
1463 |
if (typeof error == "undefined" || !this.exception) {
|
|
|
1464 |
return !!this.exception;
|
|
|
1465 |
}
|
|
|
1466 |
|
|
|
1467 |
if (typeof error == "string") {
|
|
|
1468 |
return this.exception.name == error;
|
|
|
1469 |
}
|
|
|
1470 |
|
|
|
1471 |
return this.exception === error;
|
|
|
1472 |
},
|
|
|
1473 |
|
|
|
1474 |
calledWithNew: function calledWithNew(thisValue) {
|
|
|
1475 |
return this.thisValue instanceof this.proxy;
|
|
|
1476 |
},
|
|
|
1477 |
|
|
|
1478 |
calledBefore: function (other) {
|
|
|
1479 |
return this.callId < other.callId;
|
|
|
1480 |
},
|
|
|
1481 |
|
|
|
1482 |
calledAfter: function (other) {
|
|
|
1483 |
return this.callId > other.callId;
|
|
|
1484 |
},
|
|
|
1485 |
|
|
|
1486 |
callArg: function (pos) {
|
|
|
1487 |
this.args[pos]();
|
|
|
1488 |
},
|
|
|
1489 |
|
|
|
1490 |
callArgWith: function (pos) {
|
|
|
1491 |
var args = slice.call(arguments, 1);
|
|
|
1492 |
this.args[pos].apply(null, args);
|
|
|
1493 |
},
|
|
|
1494 |
|
|
|
1495 |
"yield": function () {
|
|
|
1496 |
var args = this.args;
|
|
|
1497 |
for (var i = 0, l = args.length; i < l; ++i) {
|
|
|
1498 |
if (typeof args[i] === "function") {
|
|
|
1499 |
args[i].apply(null, slice.call(arguments));
|
|
|
1500 |
return;
|
|
|
1501 |
}
|
|
|
1502 |
}
|
|
|
1503 |
throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
|
|
|
1504 |
},
|
|
|
1505 |
|
|
|
1506 |
yieldTo: function (prop) {
|
|
|
1507 |
var args = this.args;
|
|
|
1508 |
for (var i = 0, l = args.length; i < l; ++i) {
|
|
|
1509 |
if (args[i] && typeof args[i][prop] === "function") {
|
|
|
1510 |
args[i][prop].apply(null, slice.call(arguments, 1));
|
|
|
1511 |
return;
|
|
|
1512 |
}
|
|
|
1513 |
}
|
|
|
1514 |
throwYieldError(this.proxy, " cannot yield to '" + prop +
|
|
|
1515 |
"' since no callback was passed.", args);
|
|
|
1516 |
},
|
|
|
1517 |
|
|
|
1518 |
toString: function () {
|
|
|
1519 |
var callStr = this.proxy.toString() + "(";
|
|
|
1520 |
var args = [];
|
|
|
1521 |
|
|
|
1522 |
for (var i = 0, l = this.args.length; i < l; ++i) {
|
|
|
1523 |
push.call(args, sinon.format(this.args[i]));
|
|
|
1524 |
}
|
|
|
1525 |
|
|
|
1526 |
callStr = callStr + args.join(", ") + ")";
|
|
|
1527 |
|
|
|
1528 |
if (typeof this.returnValue != "undefined") {
|
|
|
1529 |
callStr += " => " + sinon.format(this.returnValue);
|
|
|
1530 |
}
|
|
|
1531 |
|
|
|
1532 |
if (this.exception) {
|
|
|
1533 |
callStr += " !" + this.exception.name;
|
|
|
1534 |
|
|
|
1535 |
if (this.exception.message) {
|
|
|
1536 |
callStr += "(" + this.exception.message + ")";
|
|
|
1537 |
}
|
|
|
1538 |
}
|
|
|
1539 |
|
|
|
1540 |
return callStr;
|
|
|
1541 |
}
|
|
|
1542 |
};
|
|
|
1543 |
callApi.invokeCallback = callApi.yield;
|
|
|
1544 |
return callApi;
|
|
|
1545 |
}());
|
|
|
1546 |
|
|
|
1547 |
spy.spyCall = spyCall;
|
|
|
1548 |
|
|
|
1549 |
// This steps outside the module sandbox and will be removed
|
|
|
1550 |
sinon.spyCall = spyCall;
|
|
|
1551 |
|
|
|
1552 |
if (commonJSModule) {
|
|
|
1553 |
module.exports = spy;
|
|
|
1554 |
} else {
|
|
|
1555 |
sinon.spy = spy;
|
|
|
1556 |
}
|
|
|
1557 |
}(typeof sinon == "object" && sinon || null));
|
|
|
1558 |
|
|
|
1559 |
/**
|
|
|
1560 |
* @depend ../sinon.js
|
|
|
1561 |
* @depend spy.js
|
|
|
1562 |
*/
|
|
|
1563 |
/*jslint eqeqeq: false, onevar: false*/
|
|
|
1564 |
/*global module, require, sinon*/
|
|
|
1565 |
/**
|
|
|
1566 |
* Stub functions
|
|
|
1567 |
*
|
|
|
1568 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
1569 |
* @license BSD
|
|
|
1570 |
*
|
|
|
1571 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
1572 |
*/
|
|
|
1573 |
|
|
|
1574 |
(function (sinon) {
|
|
|
1575 |
var commonJSModule = typeof module == "object" && typeof require == "function";
|
|
|
1576 |
|
|
|
1577 |
if (!sinon && commonJSModule) {
|
|
|
1578 |
sinon = require("../sinon");
|
|
|
1579 |
}
|
|
|
1580 |
|
|
|
1581 |
if (!sinon) {
|
|
|
1582 |
return;
|
|
|
1583 |
}
|
|
|
1584 |
|
|
|
1585 |
function stub(object, property, func) {
|
|
|
1586 |
if (!!func && typeof func != "function") {
|
|
|
1587 |
throw new TypeError("Custom stub should be function");
|
|
|
1588 |
}
|
|
|
1589 |
|
|
|
1590 |
var wrapper;
|
|
|
1591 |
|
|
|
1592 |
if (func) {
|
|
|
1593 |
wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
|
|
|
1594 |
} else {
|
|
|
1595 |
wrapper = stub.create();
|
|
|
1596 |
}
|
|
|
1597 |
|
|
|
1598 |
if (!object && !property) {
|
|
|
1599 |
return sinon.stub.create();
|
|
|
1600 |
}
|
|
|
1601 |
|
|
|
1602 |
if (!property && !!object && typeof object == "object") {
|
|
|
1603 |
for (var prop in object) {
|
|
|
1604 |
if (typeof object[prop] === "function") {
|
|
|
1605 |
stub(object, prop);
|
|
|
1606 |
}
|
|
|
1607 |
}
|
|
|
1608 |
|
|
|
1609 |
return object;
|
|
|
1610 |
}
|
|
|
1611 |
|
|
|
1612 |
return sinon.wrapMethod(object, property, wrapper);
|
|
|
1613 |
}
|
|
|
1614 |
|
|
|
1615 |
function getChangingValue(stub, property) {
|
|
|
1616 |
var index = stub.callCount - 1;
|
|
|
1617 |
var prop = index in stub[property] ? stub[property][index] : stub[property + "Last"];
|
|
|
1618 |
stub[property + "Last"] = prop;
|
|
|
1619 |
|
|
|
1620 |
return prop;
|
|
|
1621 |
}
|
|
|
1622 |
|
|
|
1623 |
function getCallback(stub, args) {
|
|
|
1624 |
var callArgAt = getChangingValue(stub, "callArgAts");
|
|
|
1625 |
|
|
|
1626 |
if (callArgAt < 0) {
|
|
|
1627 |
var callArgProp = getChangingValue(stub, "callArgProps");
|
|
|
1628 |
|
|
|
1629 |
for (var i = 0, l = args.length; i < l; ++i) {
|
|
|
1630 |
if (!callArgProp && typeof args[i] == "function") {
|
|
|
1631 |
return args[i];
|
|
|
1632 |
}
|
|
|
1633 |
|
|
|
1634 |
if (callArgProp && args[i] &&
|
|
|
1635 |
typeof args[i][callArgProp] == "function") {
|
|
|
1636 |
return args[i][callArgProp];
|
|
|
1637 |
}
|
|
|
1638 |
}
|
|
|
1639 |
|
|
|
1640 |
return null;
|
|
|
1641 |
}
|
|
|
1642 |
|
|
|
1643 |
return args[callArgAt];
|
|
|
1644 |
}
|
|
|
1645 |
|
|
|
1646 |
var join = Array.prototype.join;
|
|
|
1647 |
|
|
|
1648 |
function getCallbackError(stub, func, args) {
|
|
|
1649 |
if (stub.callArgAtsLast < 0) {
|
|
|
1650 |
var msg;
|
|
|
1651 |
|
|
|
1652 |
if (stub.callArgPropsLast) {
|
|
|
1653 |
msg = sinon.functionName(stub) +
|
|
|
1654 |
" expected to yield to '" + stub.callArgPropsLast +
|
|
|
1655 |
"', but no object with such a property was passed."
|
|
|
1656 |
} else {
|
|
|
1657 |
msg = sinon.functionName(stub) +
|
|
|
1658 |
" expected to yield, but no callback was passed."
|
|
|
1659 |
}
|
|
|
1660 |
|
|
|
1661 |
if (args.length > 0) {
|
|
|
1662 |
msg += " Received [" + join.call(args, ", ") + "]";
|
|
|
1663 |
}
|
|
|
1664 |
|
|
|
1665 |
return msg;
|
|
|
1666 |
}
|
|
|
1667 |
|
|
|
1668 |
return "argument at index " + stub.callArgAtsLast + " is not a function: " + func;
|
|
|
1669 |
}
|
|
|
1670 |
|
|
|
1671 |
var nextTick = (function () {
|
|
|
1672 |
if (typeof process === "object" && typeof process.nextTick === "function") {
|
|
|
1673 |
return process.nextTick;
|
|
|
1674 |
} else if (typeof msSetImmediate === "function") {
|
|
|
1675 |
return msSetImmediate.bind(window);
|
|
|
1676 |
} else if (typeof setImmediate === "function") {
|
|
|
1677 |
return setImmediate;
|
|
|
1678 |
} else {
|
|
|
1679 |
return function (callback) {
|
|
|
1680 |
setTimeout(callback, 0);
|
|
|
1681 |
};
|
|
|
1682 |
}
|
|
|
1683 |
})();
|
|
|
1684 |
|
|
|
1685 |
function callCallback(stub, args) {
|
|
|
1686 |
if (stub.callArgAts.length > 0) {
|
|
|
1687 |
var func = getCallback(stub, args);
|
|
|
1688 |
|
|
|
1689 |
if (typeof func != "function") {
|
|
|
1690 |
throw new TypeError(getCallbackError(stub, func, args));
|
|
|
1691 |
}
|
|
|
1692 |
|
|
|
1693 |
var index = stub.callCount - 1;
|
|
|
1694 |
|
|
|
1695 |
var callbackArguments = getChangingValue(stub, "callbackArguments");
|
|
|
1696 |
var callbackContext = getChangingValue(stub, "callbackContexts");
|
|
|
1697 |
|
|
|
1698 |
if (stub.callbackAsync) {
|
|
|
1699 |
nextTick(function() {
|
|
|
1700 |
func.apply(callbackContext, callbackArguments);
|
|
|
1701 |
});
|
|
|
1702 |
} else {
|
|
|
1703 |
func.apply(callbackContext, callbackArguments);
|
|
|
1704 |
}
|
|
|
1705 |
}
|
|
|
1706 |
}
|
|
|
1707 |
|
|
|
1708 |
var uuid = 0;
|
|
|
1709 |
|
|
|
1710 |
sinon.extend(stub, (function () {
|
|
|
1711 |
var slice = Array.prototype.slice, proto;
|
|
|
1712 |
|
|
|
1713 |
function throwsException(error, message) {
|
|
|
1714 |
if (typeof error == "string") {
|
|
|
1715 |
this.exception = new Error(message || "");
|
|
|
1716 |
this.exception.name = error;
|
|
|
1717 |
} else if (!error) {
|
|
|
1718 |
this.exception = new Error("Error");
|
|
|
1719 |
} else {
|
|
|
1720 |
this.exception = error;
|
|
|
1721 |
}
|
|
|
1722 |
|
|
|
1723 |
return this;
|
|
|
1724 |
}
|
|
|
1725 |
|
|
|
1726 |
proto = {
|
|
|
1727 |
create: function create() {
|
|
|
1728 |
var functionStub = function () {
|
|
|
1729 |
|
|
|
1730 |
callCallback(functionStub, arguments);
|
|
|
1731 |
|
|
|
1732 |
if (functionStub.exception) {
|
|
|
1733 |
throw functionStub.exception;
|
|
|
1734 |
} else if (typeof functionStub.returnArgAt == 'number') {
|
|
|
1735 |
return arguments[functionStub.returnArgAt];
|
|
|
1736 |
} else if (functionStub.returnThis) {
|
|
|
1737 |
return this;
|
|
|
1738 |
}
|
|
|
1739 |
return functionStub.returnValue;
|
|
|
1740 |
};
|
|
|
1741 |
|
|
|
1742 |
functionStub.id = "stub#" + uuid++;
|
|
|
1743 |
var orig = functionStub;
|
|
|
1744 |
functionStub = sinon.spy.create(functionStub);
|
|
|
1745 |
functionStub.func = orig;
|
|
|
1746 |
|
|
|
1747 |
functionStub.callArgAts = [];
|
|
|
1748 |
functionStub.callbackArguments = [];
|
|
|
1749 |
functionStub.callbackContexts = [];
|
|
|
1750 |
functionStub.callArgProps = [];
|
|
|
1751 |
|
|
|
1752 |
sinon.extend(functionStub, stub);
|
|
|
1753 |
functionStub._create = sinon.stub.create;
|
|
|
1754 |
functionStub.displayName = "stub";
|
|
|
1755 |
functionStub.toString = sinon.functionToString;
|
|
|
1756 |
|
|
|
1757 |
return functionStub;
|
|
|
1758 |
},
|
|
|
1759 |
|
|
|
1760 |
returns: function returns(value) {
|
|
|
1761 |
this.returnValue = value;
|
|
|
1762 |
|
|
|
1763 |
return this;
|
|
|
1764 |
},
|
|
|
1765 |
|
|
|
1766 |
returnsArg: function returnsArg(pos) {
|
|
|
1767 |
if (typeof pos != "number") {
|
|
|
1768 |
throw new TypeError("argument index is not number");
|
|
|
1769 |
}
|
|
|
1770 |
|
|
|
1771 |
this.returnArgAt = pos;
|
|
|
1772 |
|
|
|
1773 |
return this;
|
|
|
1774 |
},
|
|
|
1775 |
|
|
|
1776 |
returnsThis: function returnsThis() {
|
|
|
1777 |
this.returnThis = true;
|
|
|
1778 |
|
|
|
1779 |
return this;
|
|
|
1780 |
},
|
|
|
1781 |
|
|
|
1782 |
"throws": throwsException,
|
|
|
1783 |
throwsException: throwsException,
|
|
|
1784 |
|
|
|
1785 |
callsArg: function callsArg(pos) {
|
|
|
1786 |
if (typeof pos != "number") {
|
|
|
1787 |
throw new TypeError("argument index is not number");
|
|
|
1788 |
}
|
|
|
1789 |
|
|
|
1790 |
this.callArgAts.push(pos);
|
|
|
1791 |
this.callbackArguments.push([]);
|
|
|
1792 |
this.callbackContexts.push(undefined);
|
|
|
1793 |
this.callArgProps.push(undefined);
|
|
|
1794 |
|
|
|
1795 |
return this;
|
|
|
1796 |
},
|
|
|
1797 |
|
|
|
1798 |
callsArgOn: function callsArgOn(pos, context) {
|
|
|
1799 |
if (typeof pos != "number") {
|
|
|
1800 |
throw new TypeError("argument index is not number");
|
|
|
1801 |
}
|
|
|
1802 |
if (typeof context != "object") {
|
|
|
1803 |
throw new TypeError("argument context is not an object");
|
|
|
1804 |
}
|
|
|
1805 |
|
|
|
1806 |
this.callArgAts.push(pos);
|
|
|
1807 |
this.callbackArguments.push([]);
|
|
|
1808 |
this.callbackContexts.push(context);
|
|
|
1809 |
this.callArgProps.push(undefined);
|
|
|
1810 |
|
|
|
1811 |
return this;
|
|
|
1812 |
},
|
|
|
1813 |
|
|
|
1814 |
callsArgWith: function callsArgWith(pos) {
|
|
|
1815 |
if (typeof pos != "number") {
|
|
|
1816 |
throw new TypeError("argument index is not number");
|
|
|
1817 |
}
|
|
|
1818 |
|
|
|
1819 |
this.callArgAts.push(pos);
|
|
|
1820 |
this.callbackArguments.push(slice.call(arguments, 1));
|
|
|
1821 |
this.callbackContexts.push(undefined);
|
|
|
1822 |
this.callArgProps.push(undefined);
|
|
|
1823 |
|
|
|
1824 |
return this;
|
|
|
1825 |
},
|
|
|
1826 |
|
|
|
1827 |
callsArgOnWith: function callsArgWith(pos, context) {
|
|
|
1828 |
if (typeof pos != "number") {
|
|
|
1829 |
throw new TypeError("argument index is not number");
|
|
|
1830 |
}
|
|
|
1831 |
if (typeof context != "object") {
|
|
|
1832 |
throw new TypeError("argument context is not an object");
|
|
|
1833 |
}
|
|
|
1834 |
|
|
|
1835 |
this.callArgAts.push(pos);
|
|
|
1836 |
this.callbackArguments.push(slice.call(arguments, 2));
|
|
|
1837 |
this.callbackContexts.push(context);
|
|
|
1838 |
this.callArgProps.push(undefined);
|
|
|
1839 |
|
|
|
1840 |
return this;
|
|
|
1841 |
},
|
|
|
1842 |
|
|
|
1843 |
yields: function () {
|
|
|
1844 |
this.callArgAts.push(-1);
|
|
|
1845 |
this.callbackArguments.push(slice.call(arguments, 0));
|
|
|
1846 |
this.callbackContexts.push(undefined);
|
|
|
1847 |
this.callArgProps.push(undefined);
|
|
|
1848 |
|
|
|
1849 |
return this;
|
|
|
1850 |
},
|
|
|
1851 |
|
|
|
1852 |
yieldsOn: function (context) {
|
|
|
1853 |
if (typeof context != "object") {
|
|
|
1854 |
throw new TypeError("argument context is not an object");
|
|
|
1855 |
}
|
|
|
1856 |
|
|
|
1857 |
this.callArgAts.push(-1);
|
|
|
1858 |
this.callbackArguments.push(slice.call(arguments, 1));
|
|
|
1859 |
this.callbackContexts.push(context);
|
|
|
1860 |
this.callArgProps.push(undefined);
|
|
|
1861 |
|
|
|
1862 |
return this;
|
|
|
1863 |
},
|
|
|
1864 |
|
|
|
1865 |
yieldsTo: function (prop) {
|
|
|
1866 |
this.callArgAts.push(-1);
|
|
|
1867 |
this.callbackArguments.push(slice.call(arguments, 1));
|
|
|
1868 |
this.callbackContexts.push(undefined);
|
|
|
1869 |
this.callArgProps.push(prop);
|
|
|
1870 |
|
|
|
1871 |
return this;
|
|
|
1872 |
},
|
|
|
1873 |
|
|
|
1874 |
yieldsToOn: function (prop, context) {
|
|
|
1875 |
if (typeof context != "object") {
|
|
|
1876 |
throw new TypeError("argument context is not an object");
|
|
|
1877 |
}
|
|
|
1878 |
|
|
|
1879 |
this.callArgAts.push(-1);
|
|
|
1880 |
this.callbackArguments.push(slice.call(arguments, 2));
|
|
|
1881 |
this.callbackContexts.push(context);
|
|
|
1882 |
this.callArgProps.push(prop);
|
|
|
1883 |
|
|
|
1884 |
return this;
|
|
|
1885 |
}
|
|
|
1886 |
};
|
|
|
1887 |
|
|
|
1888 |
// create asynchronous versions of callsArg* and yields* methods
|
|
|
1889 |
for (var method in proto) {
|
|
|
1890 |
// need to avoid creating anotherasync versions of the newly added async methods
|
|
|
1891 |
if (proto.hasOwnProperty(method) &&
|
|
|
1892 |
method.match(/^(callsArg|yields|thenYields$)/) &&
|
|
|
1893 |
!method.match(/Async/)) {
|
|
|
1894 |
proto[method + 'Async'] = (function (syncFnName) {
|
|
|
1895 |
return function () {
|
|
|
1896 |
this.callbackAsync = true;
|
|
|
1897 |
return this[syncFnName].apply(this, arguments);
|
|
|
1898 |
};
|
|
|
1899 |
})(method);
|
|
|
1900 |
}
|
|
|
1901 |
}
|
|
|
1902 |
|
|
|
1903 |
return proto;
|
|
|
1904 |
|
|
|
1905 |
}()));
|
|
|
1906 |
|
|
|
1907 |
if (commonJSModule) {
|
|
|
1908 |
module.exports = stub;
|
|
|
1909 |
} else {
|
|
|
1910 |
sinon.stub = stub;
|
|
|
1911 |
}
|
|
|
1912 |
}(typeof sinon == "object" && sinon || null));
|
|
|
1913 |
|
|
|
1914 |
/**
|
|
|
1915 |
* @depend ../sinon.js
|
|
|
1916 |
* @depend stub.js
|
|
|
1917 |
*/
|
|
|
1918 |
/*jslint eqeqeq: false, onevar: false, nomen: false*/
|
|
|
1919 |
/*global module, require, sinon*/
|
|
|
1920 |
/**
|
|
|
1921 |
* Mock functions.
|
|
|
1922 |
*
|
|
|
1923 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
1924 |
* @license BSD
|
|
|
1925 |
*
|
|
|
1926 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
1927 |
*/
|
|
|
1928 |
|
|
|
1929 |
(function (sinon) {
|
|
|
1930 |
var commonJSModule = typeof module == "object" && typeof require == "function";
|
|
|
1931 |
var push = [].push;
|
|
|
1932 |
|
|
|
1933 |
if (!sinon && commonJSModule) {
|
|
|
1934 |
sinon = require("../sinon");
|
|
|
1935 |
}
|
|
|
1936 |
|
|
|
1937 |
if (!sinon) {
|
|
|
1938 |
return;
|
|
|
1939 |
}
|
|
|
1940 |
|
|
|
1941 |
function mock(object) {
|
|
|
1942 |
if (!object) {
|
|
|
1943 |
return sinon.expectation.create("Anonymous mock");
|
|
|
1944 |
}
|
|
|
1945 |
|
|
|
1946 |
return mock.create(object);
|
|
|
1947 |
}
|
|
|
1948 |
|
|
|
1949 |
sinon.mock = mock;
|
|
|
1950 |
|
|
|
1951 |
sinon.extend(mock, (function () {
|
|
|
1952 |
function each(collection, callback) {
|
|
|
1953 |
if (!collection) {
|
|
|
1954 |
return;
|
|
|
1955 |
}
|
|
|
1956 |
|
|
|
1957 |
for (var i = 0, l = collection.length; i < l; i += 1) {
|
|
|
1958 |
callback(collection[i]);
|
|
|
1959 |
}
|
|
|
1960 |
}
|
|
|
1961 |
|
|
|
1962 |
return {
|
|
|
1963 |
create: function create(object) {
|
|
|
1964 |
if (!object) {
|
|
|
1965 |
throw new TypeError("object is null");
|
|
|
1966 |
}
|
|
|
1967 |
|
|
|
1968 |
var mockObject = sinon.extend({}, mock);
|
|
|
1969 |
mockObject.object = object;
|
|
|
1970 |
delete mockObject.create;
|
|
|
1971 |
|
|
|
1972 |
return mockObject;
|
|
|
1973 |
},
|
|
|
1974 |
|
|
|
1975 |
expects: function expects(method) {
|
|
|
1976 |
if (!method) {
|
|
|
1977 |
throw new TypeError("method is falsy");
|
|
|
1978 |
}
|
|
|
1979 |
|
|
|
1980 |
if (!this.expectations) {
|
|
|
1981 |
this.expectations = {};
|
|
|
1982 |
this.proxies = [];
|
|
|
1983 |
}
|
|
|
1984 |
|
|
|
1985 |
if (!this.expectations[method]) {
|
|
|
1986 |
this.expectations[method] = [];
|
|
|
1987 |
var mockObject = this;
|
|
|
1988 |
|
|
|
1989 |
sinon.wrapMethod(this.object, method, function () {
|
|
|
1990 |
return mockObject.invokeMethod(method, this, arguments);
|
|
|
1991 |
});
|
|
|
1992 |
|
|
|
1993 |
push.call(this.proxies, method);
|
|
|
1994 |
}
|
|
|
1995 |
|
|
|
1996 |
var expectation = sinon.expectation.create(method);
|
|
|
1997 |
push.call(this.expectations[method], expectation);
|
|
|
1998 |
|
|
|
1999 |
return expectation;
|
|
|
2000 |
},
|
|
|
2001 |
|
|
|
2002 |
restore: function restore() {
|
|
|
2003 |
var object = this.object;
|
|
|
2004 |
|
|
|
2005 |
each(this.proxies, function (proxy) {
|
|
|
2006 |
if (typeof object[proxy].restore == "function") {
|
|
|
2007 |
object[proxy].restore();
|
|
|
2008 |
}
|
|
|
2009 |
});
|
|
|
2010 |
},
|
|
|
2011 |
|
|
|
2012 |
verify: function verify() {
|
|
|
2013 |
var expectations = this.expectations || {};
|
|
|
2014 |
var messages = [], met = [];
|
|
|
2015 |
|
|
|
2016 |
each(this.proxies, function (proxy) {
|
|
|
2017 |
each(expectations[proxy], function (expectation) {
|
|
|
2018 |
if (!expectation.met()) {
|
|
|
2019 |
push.call(messages, expectation.toString());
|
|
|
2020 |
} else {
|
|
|
2021 |
push.call(met, expectation.toString());
|
|
|
2022 |
}
|
|
|
2023 |
});
|
|
|
2024 |
});
|
|
|
2025 |
|
|
|
2026 |
this.restore();
|
|
|
2027 |
|
|
|
2028 |
if (messages.length > 0) {
|
|
|
2029 |
sinon.expectation.fail(messages.concat(met).join("\n"));
|
|
|
2030 |
} else {
|
|
|
2031 |
sinon.expectation.pass(messages.concat(met).join("\n"));
|
|
|
2032 |
}
|
|
|
2033 |
|
|
|
2034 |
return true;
|
|
|
2035 |
},
|
|
|
2036 |
|
|
|
2037 |
invokeMethod: function invokeMethod(method, thisValue, args) {
|
|
|
2038 |
var expectations = this.expectations && this.expectations[method];
|
|
|
2039 |
var length = expectations && expectations.length || 0, i;
|
|
|
2040 |
|
|
|
2041 |
for (i = 0; i < length; i += 1) {
|
|
|
2042 |
if (!expectations[i].met() &&
|
|
|
2043 |
expectations[i].allowsCall(thisValue, args)) {
|
|
|
2044 |
return expectations[i].apply(thisValue, args);
|
|
|
2045 |
}
|
|
|
2046 |
}
|
|
|
2047 |
|
|
|
2048 |
var messages = [], available, exhausted = 0;
|
|
|
2049 |
|
|
|
2050 |
for (i = 0; i < length; i += 1) {
|
|
|
2051 |
if (expectations[i].allowsCall(thisValue, args)) {
|
|
|
2052 |
available = available || expectations[i];
|
|
|
2053 |
} else {
|
|
|
2054 |
exhausted += 1;
|
|
|
2055 |
}
|
|
|
2056 |
push.call(messages, " " + expectations[i].toString());
|
|
|
2057 |
}
|
|
|
2058 |
|
|
|
2059 |
if (exhausted === 0) {
|
|
|
2060 |
return available.apply(thisValue, args);
|
|
|
2061 |
}
|
|
|
2062 |
|
|
|
2063 |
messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
|
|
|
2064 |
proxy: method,
|
|
|
2065 |
args: args
|
|
|
2066 |
}));
|
|
|
2067 |
|
|
|
2068 |
sinon.expectation.fail(messages.join("\n"));
|
|
|
2069 |
}
|
|
|
2070 |
};
|
|
|
2071 |
}()));
|
|
|
2072 |
|
|
|
2073 |
var times = sinon.timesInWords;
|
|
|
2074 |
|
|
|
2075 |
sinon.expectation = (function () {
|
|
|
2076 |
var slice = Array.prototype.slice;
|
|
|
2077 |
var _invoke = sinon.spy.invoke;
|
|
|
2078 |
|
|
|
2079 |
function callCountInWords(callCount) {
|
|
|
2080 |
if (callCount == 0) {
|
|
|
2081 |
return "never called";
|
|
|
2082 |
} else {
|
|
|
2083 |
return "called " + times(callCount);
|
|
|
2084 |
}
|
|
|
2085 |
}
|
|
|
2086 |
|
|
|
2087 |
function expectedCallCountInWords(expectation) {
|
|
|
2088 |
var min = expectation.minCalls;
|
|
|
2089 |
var max = expectation.maxCalls;
|
|
|
2090 |
|
|
|
2091 |
if (typeof min == "number" && typeof max == "number") {
|
|
|
2092 |
var str = times(min);
|
|
|
2093 |
|
|
|
2094 |
if (min != max) {
|
|
|
2095 |
str = "at least " + str + " and at most " + times(max);
|
|
|
2096 |
}
|
|
|
2097 |
|
|
|
2098 |
return str;
|
|
|
2099 |
}
|
|
|
2100 |
|
|
|
2101 |
if (typeof min == "number") {
|
|
|
2102 |
return "at least " + times(min);
|
|
|
2103 |
}
|
|
|
2104 |
|
|
|
2105 |
return "at most " + times(max);
|
|
|
2106 |
}
|
|
|
2107 |
|
|
|
2108 |
function receivedMinCalls(expectation) {
|
|
|
2109 |
var hasMinLimit = typeof expectation.minCalls == "number";
|
|
|
2110 |
return !hasMinLimit || expectation.callCount >= expectation.minCalls;
|
|
|
2111 |
}
|
|
|
2112 |
|
|
|
2113 |
function receivedMaxCalls(expectation) {
|
|
|
2114 |
if (typeof expectation.maxCalls != "number") {
|
|
|
2115 |
return false;
|
|
|
2116 |
}
|
|
|
2117 |
|
|
|
2118 |
return expectation.callCount == expectation.maxCalls;
|
|
|
2119 |
}
|
|
|
2120 |
|
|
|
2121 |
return {
|
|
|
2122 |
minCalls: 1,
|
|
|
2123 |
maxCalls: 1,
|
|
|
2124 |
|
|
|
2125 |
create: function create(methodName) {
|
|
|
2126 |
var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
|
|
|
2127 |
delete expectation.create;
|
|
|
2128 |
expectation.method = methodName;
|
|
|
2129 |
|
|
|
2130 |
return expectation;
|
|
|
2131 |
},
|
|
|
2132 |
|
|
|
2133 |
invoke: function invoke(func, thisValue, args) {
|
|
|
2134 |
this.verifyCallAllowed(thisValue, args);
|
|
|
2135 |
|
|
|
2136 |
return _invoke.apply(this, arguments);
|
|
|
2137 |
},
|
|
|
2138 |
|
|
|
2139 |
atLeast: function atLeast(num) {
|
|
|
2140 |
if (typeof num != "number") {
|
|
|
2141 |
throw new TypeError("'" + num + "' is not number");
|
|
|
2142 |
}
|
|
|
2143 |
|
|
|
2144 |
if (!this.limitsSet) {
|
|
|
2145 |
this.maxCalls = null;
|
|
|
2146 |
this.limitsSet = true;
|
|
|
2147 |
}
|
|
|
2148 |
|
|
|
2149 |
this.minCalls = num;
|
|
|
2150 |
|
|
|
2151 |
return this;
|
|
|
2152 |
},
|
|
|
2153 |
|
|
|
2154 |
atMost: function atMost(num) {
|
|
|
2155 |
if (typeof num != "number") {
|
|
|
2156 |
throw new TypeError("'" + num + "' is not number");
|
|
|
2157 |
}
|
|
|
2158 |
|
|
|
2159 |
if (!this.limitsSet) {
|
|
|
2160 |
this.minCalls = null;
|
|
|
2161 |
this.limitsSet = true;
|
|
|
2162 |
}
|
|
|
2163 |
|
|
|
2164 |
this.maxCalls = num;
|
|
|
2165 |
|
|
|
2166 |
return this;
|
|
|
2167 |
},
|
|
|
2168 |
|
|
|
2169 |
never: function never() {
|
|
|
2170 |
return this.exactly(0);
|
|
|
2171 |
},
|
|
|
2172 |
|
|
|
2173 |
once: function once() {
|
|
|
2174 |
return this.exactly(1);
|
|
|
2175 |
},
|
|
|
2176 |
|
|
|
2177 |
twice: function twice() {
|
|
|
2178 |
return this.exactly(2);
|
|
|
2179 |
},
|
|
|
2180 |
|
|
|
2181 |
thrice: function thrice() {
|
|
|
2182 |
return this.exactly(3);
|
|
|
2183 |
},
|
|
|
2184 |
|
|
|
2185 |
exactly: function exactly(num) {
|
|
|
2186 |
if (typeof num != "number") {
|
|
|
2187 |
throw new TypeError("'" + num + "' is not a number");
|
|
|
2188 |
}
|
|
|
2189 |
|
|
|
2190 |
this.atLeast(num);
|
|
|
2191 |
return this.atMost(num);
|
|
|
2192 |
},
|
|
|
2193 |
|
|
|
2194 |
met: function met() {
|
|
|
2195 |
return !this.failed && receivedMinCalls(this);
|
|
|
2196 |
},
|
|
|
2197 |
|
|
|
2198 |
verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
|
|
|
2199 |
if (receivedMaxCalls(this)) {
|
|
|
2200 |
this.failed = true;
|
|
|
2201 |
sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
|
|
|
2202 |
}
|
|
|
2203 |
|
|
|
2204 |
if ("expectedThis" in this && this.expectedThis !== thisValue) {
|
|
|
2205 |
sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
|
|
|
2206 |
this.expectedThis);
|
|
|
2207 |
}
|
|
|
2208 |
|
|
|
2209 |
if (!("expectedArguments" in this)) {
|
|
|
2210 |
return;
|
|
|
2211 |
}
|
|
|
2212 |
|
|
|
2213 |
if (!args) {
|
|
|
2214 |
sinon.expectation.fail(this.method + " received no arguments, expected " +
|
|
|
2215 |
this.expectedArguments.join());
|
|
|
2216 |
}
|
|
|
2217 |
|
|
|
2218 |
if (args.length < this.expectedArguments.length) {
|
|
|
2219 |
sinon.expectation.fail(this.method + " received too few arguments (" + args.join() +
|
|
|
2220 |
"), expected " + this.expectedArguments.join());
|
|
|
2221 |
}
|
|
|
2222 |
|
|
|
2223 |
if (this.expectsExactArgCount &&
|
|
|
2224 |
args.length != this.expectedArguments.length) {
|
|
|
2225 |
sinon.expectation.fail(this.method + " received too many arguments (" + args.join() +
|
|
|
2226 |
"), expected " + this.expectedArguments.join());
|
|
|
2227 |
}
|
|
|
2228 |
|
|
|
2229 |
for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
|
|
|
2230 |
if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
|
|
|
2231 |
sinon.expectation.fail(this.method + " received wrong arguments (" + args.join() +
|
|
|
2232 |
"), expected " + this.expectedArguments.join());
|
|
|
2233 |
}
|
|
|
2234 |
}
|
|
|
2235 |
},
|
|
|
2236 |
|
|
|
2237 |
allowsCall: function allowsCall(thisValue, args) {
|
|
|
2238 |
if (this.met() && receivedMaxCalls(this)) {
|
|
|
2239 |
return false;
|
|
|
2240 |
}
|
|
|
2241 |
|
|
|
2242 |
if ("expectedThis" in this && this.expectedThis !== thisValue) {
|
|
|
2243 |
return false;
|
|
|
2244 |
}
|
|
|
2245 |
|
|
|
2246 |
if (!("expectedArguments" in this)) {
|
|
|
2247 |
return true;
|
|
|
2248 |
}
|
|
|
2249 |
|
|
|
2250 |
args = args || [];
|
|
|
2251 |
|
|
|
2252 |
if (args.length < this.expectedArguments.length) {
|
|
|
2253 |
return false;
|
|
|
2254 |
}
|
|
|
2255 |
|
|
|
2256 |
if (this.expectsExactArgCount &&
|
|
|
2257 |
args.length != this.expectedArguments.length) {
|
|
|
2258 |
return false;
|
|
|
2259 |
}
|
|
|
2260 |
|
|
|
2261 |
for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
|
|
|
2262 |
if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
|
|
|
2263 |
return false;
|
|
|
2264 |
}
|
|
|
2265 |
}
|
|
|
2266 |
|
|
|
2267 |
return true;
|
|
|
2268 |
},
|
|
|
2269 |
|
|
|
2270 |
withArgs: function withArgs() {
|
|
|
2271 |
this.expectedArguments = slice.call(arguments);
|
|
|
2272 |
return this;
|
|
|
2273 |
},
|
|
|
2274 |
|
|
|
2275 |
withExactArgs: function withExactArgs() {
|
|
|
2276 |
this.withArgs.apply(this, arguments);
|
|
|
2277 |
this.expectsExactArgCount = true;
|
|
|
2278 |
return this;
|
|
|
2279 |
},
|
|
|
2280 |
|
|
|
2281 |
on: function on(thisValue) {
|
|
|
2282 |
this.expectedThis = thisValue;
|
|
|
2283 |
return this;
|
|
|
2284 |
},
|
|
|
2285 |
|
|
|
2286 |
toString: function () {
|
|
|
2287 |
var args = (this.expectedArguments || []).slice();
|
|
|
2288 |
|
|
|
2289 |
if (!this.expectsExactArgCount) {
|
|
|
2290 |
push.call(args, "[...]");
|
|
|
2291 |
}
|
|
|
2292 |
|
|
|
2293 |
var callStr = sinon.spyCall.toString.call({
|
|
|
2294 |
proxy: this.method, args: args
|
|
|
2295 |
});
|
|
|
2296 |
|
|
|
2297 |
var message = callStr.replace(", [...", "[, ...") + " " +
|
|
|
2298 |
expectedCallCountInWords(this);
|
|
|
2299 |
|
|
|
2300 |
if (this.met()) {
|
|
|
2301 |
return "Expectation met: " + message;
|
|
|
2302 |
}
|
|
|
2303 |
|
|
|
2304 |
return "Expected " + message + " (" +
|
|
|
2305 |
callCountInWords(this.callCount) + ")";
|
|
|
2306 |
},
|
|
|
2307 |
|
|
|
2308 |
verify: function verify() {
|
|
|
2309 |
if (!this.met()) {
|
|
|
2310 |
sinon.expectation.fail(this.toString());
|
|
|
2311 |
} else {
|
|
|
2312 |
sinon.expectation.pass(this.toString());
|
|
|
2313 |
}
|
|
|
2314 |
|
|
|
2315 |
return true;
|
|
|
2316 |
},
|
|
|
2317 |
|
|
|
2318 |
pass: function(message) {
|
|
|
2319 |
sinon.assert.pass(message);
|
|
|
2320 |
},
|
|
|
2321 |
fail: function (message) {
|
|
|
2322 |
var exception = new Error(message);
|
|
|
2323 |
exception.name = "ExpectationError";
|
|
|
2324 |
|
|
|
2325 |
throw exception;
|
|
|
2326 |
}
|
|
|
2327 |
};
|
|
|
2328 |
}());
|
|
|
2329 |
|
|
|
2330 |
if (commonJSModule) {
|
|
|
2331 |
module.exports = mock;
|
|
|
2332 |
} else {
|
|
|
2333 |
sinon.mock = mock;
|
|
|
2334 |
}
|
|
|
2335 |
}(typeof sinon == "object" && sinon || null));
|
|
|
2336 |
|
|
|
2337 |
/**
|
|
|
2338 |
* @depend ../sinon.js
|
|
|
2339 |
* @depend stub.js
|
|
|
2340 |
* @depend mock.js
|
|
|
2341 |
*/
|
|
|
2342 |
/*jslint eqeqeq: false, onevar: false, forin: true*/
|
|
|
2343 |
/*global module, require, sinon*/
|
|
|
2344 |
/**
|
|
|
2345 |
* Collections of stubs, spies and mocks.
|
|
|
2346 |
*
|
|
|
2347 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
2348 |
* @license BSD
|
|
|
2349 |
*
|
|
|
2350 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
2351 |
*/
|
|
|
2352 |
|
|
|
2353 |
(function (sinon) {
|
|
|
2354 |
var commonJSModule = typeof module == "object" && typeof require == "function";
|
|
|
2355 |
var push = [].push;
|
|
|
2356 |
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
|
2357 |
|
|
|
2358 |
if (!sinon && commonJSModule) {
|
|
|
2359 |
sinon = require("../sinon");
|
|
|
2360 |
}
|
|
|
2361 |
|
|
|
2362 |
if (!sinon) {
|
|
|
2363 |
return;
|
|
|
2364 |
}
|
|
|
2365 |
|
|
|
2366 |
function getFakes(fakeCollection) {
|
|
|
2367 |
if (!fakeCollection.fakes) {
|
|
|
2368 |
fakeCollection.fakes = [];
|
|
|
2369 |
}
|
|
|
2370 |
|
|
|
2371 |
return fakeCollection.fakes;
|
|
|
2372 |
}
|
|
|
2373 |
|
|
|
2374 |
function each(fakeCollection, method) {
|
|
|
2375 |
var fakes = getFakes(fakeCollection);
|
|
|
2376 |
|
|
|
2377 |
for (var i = 0, l = fakes.length; i < l; i += 1) {
|
|
|
2378 |
if (typeof fakes[i][method] == "function") {
|
|
|
2379 |
fakes[i][method]();
|
|
|
2380 |
}
|
|
|
2381 |
}
|
|
|
2382 |
}
|
|
|
2383 |
|
|
|
2384 |
function compact(fakeCollection) {
|
|
|
2385 |
var fakes = getFakes(fakeCollection);
|
|
|
2386 |
var i = 0;
|
|
|
2387 |
while (i < fakes.length) {
|
|
|
2388 |
fakes.splice(i, 1);
|
|
|
2389 |
}
|
|
|
2390 |
}
|
|
|
2391 |
|
|
|
2392 |
var collection = {
|
|
|
2393 |
verify: function resolve() {
|
|
|
2394 |
each(this, "verify");
|
|
|
2395 |
},
|
|
|
2396 |
|
|
|
2397 |
restore: function restore() {
|
|
|
2398 |
each(this, "restore");
|
|
|
2399 |
compact(this);
|
|
|
2400 |
},
|
|
|
2401 |
|
|
|
2402 |
verifyAndRestore: function verifyAndRestore() {
|
|
|
2403 |
var exception;
|
|
|
2404 |
|
|
|
2405 |
try {
|
|
|
2406 |
this.verify();
|
|
|
2407 |
} catch (e) {
|
|
|
2408 |
exception = e;
|
|
|
2409 |
}
|
|
|
2410 |
|
|
|
2411 |
this.restore();
|
|
|
2412 |
|
|
|
2413 |
if (exception) {
|
|
|
2414 |
throw exception;
|
|
|
2415 |
}
|
|
|
2416 |
},
|
|
|
2417 |
|
|
|
2418 |
add: function add(fake) {
|
|
|
2419 |
push.call(getFakes(this), fake);
|
|
|
2420 |
return fake;
|
|
|
2421 |
},
|
|
|
2422 |
|
|
|
2423 |
spy: function spy() {
|
|
|
2424 |
return this.add(sinon.spy.apply(sinon, arguments));
|
|
|
2425 |
},
|
|
|
2426 |
|
|
|
2427 |
stub: function stub(object, property, value) {
|
|
|
2428 |
if (property) {
|
|
|
2429 |
var original = object[property];
|
|
|
2430 |
|
|
|
2431 |
if (typeof original != "function") {
|
|
|
2432 |
if (!hasOwnProperty.call(object, property)) {
|
|
|
2433 |
throw new TypeError("Cannot stub non-existent own property " + property);
|
|
|
2434 |
}
|
|
|
2435 |
|
|
|
2436 |
object[property] = value;
|
|
|
2437 |
|
|
|
2438 |
return this.add({
|
|
|
2439 |
restore: function () {
|
|
|
2440 |
object[property] = original;
|
|
|
2441 |
}
|
|
|
2442 |
});
|
|
|
2443 |
}
|
|
|
2444 |
}
|
|
|
2445 |
if (!property && !!object && typeof object == "object") {
|
|
|
2446 |
var stubbedObj = sinon.stub.apply(sinon, arguments);
|
|
|
2447 |
|
|
|
2448 |
for (var prop in stubbedObj) {
|
|
|
2449 |
if (typeof stubbedObj[prop] === "function") {
|
|
|
2450 |
this.add(stubbedObj[prop]);
|
|
|
2451 |
}
|
|
|
2452 |
}
|
|
|
2453 |
|
|
|
2454 |
return stubbedObj;
|
|
|
2455 |
}
|
|
|
2456 |
|
|
|
2457 |
return this.add(sinon.stub.apply(sinon, arguments));
|
|
|
2458 |
},
|
|
|
2459 |
|
|
|
2460 |
mock: function mock() {
|
|
|
2461 |
return this.add(sinon.mock.apply(sinon, arguments));
|
|
|
2462 |
},
|
|
|
2463 |
|
|
|
2464 |
inject: function inject(obj) {
|
|
|
2465 |
var col = this;
|
|
|
2466 |
|
|
|
2467 |
obj.spy = function () {
|
|
|
2468 |
return col.spy.apply(col, arguments);
|
|
|
2469 |
};
|
|
|
2470 |
|
|
|
2471 |
obj.stub = function () {
|
|
|
2472 |
return col.stub.apply(col, arguments);
|
|
|
2473 |
};
|
|
|
2474 |
|
|
|
2475 |
obj.mock = function () {
|
|
|
2476 |
return col.mock.apply(col, arguments);
|
|
|
2477 |
};
|
|
|
2478 |
|
|
|
2479 |
return obj;
|
|
|
2480 |
}
|
|
|
2481 |
};
|
|
|
2482 |
|
|
|
2483 |
if (commonJSModule) {
|
|
|
2484 |
module.exports = collection;
|
|
|
2485 |
} else {
|
|
|
2486 |
sinon.collection = collection;
|
|
|
2487 |
}
|
|
|
2488 |
}(typeof sinon == "object" && sinon || null));
|
|
|
2489 |
|
|
|
2490 |
/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
|
|
|
2491 |
/*global module, require, window*/
|
|
|
2492 |
/**
|
|
|
2493 |
* Fake timer API
|
|
|
2494 |
* setTimeout
|
|
|
2495 |
* setInterval
|
|
|
2496 |
* clearTimeout
|
|
|
2497 |
* clearInterval
|
|
|
2498 |
* tick
|
|
|
2499 |
* reset
|
|
|
2500 |
* Date
|
|
|
2501 |
*
|
|
|
2502 |
* Inspired by jsUnitMockTimeOut from JsUnit
|
|
|
2503 |
*
|
|
|
2504 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
2505 |
* @license BSD
|
|
|
2506 |
*
|
|
|
2507 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
2508 |
*/
|
|
|
2509 |
|
|
|
2510 |
if (typeof sinon == "undefined") {
|
|
|
2511 |
var sinon = {};
|
|
|
2512 |
}
|
|
|
2513 |
|
|
|
2514 |
(function (global) {
|
|
|
2515 |
var id = 1;
|
|
|
2516 |
|
|
|
2517 |
function addTimer(args, recurring) {
|
|
|
2518 |
if (args.length === 0) {
|
|
|
2519 |
throw new Error("Function requires at least 1 parameter");
|
|
|
2520 |
}
|
|
|
2521 |
|
|
|
2522 |
var toId = id++;
|
|
|
2523 |
var delay = args[1] || 0;
|
|
|
2524 |
|
|
|
2525 |
if (!this.timeouts) {
|
|
|
2526 |
this.timeouts = {};
|
|
|
2527 |
}
|
|
|
2528 |
|
|
|
2529 |
this.timeouts[toId] = {
|
|
|
2530 |
id: toId,
|
|
|
2531 |
func: args[0],
|
|
|
2532 |
callAt: this.now + delay,
|
|
|
2533 |
invokeArgs: Array.prototype.slice.call(args, 2)
|
|
|
2534 |
};
|
|
|
2535 |
|
|
|
2536 |
if (recurring === true) {
|
|
|
2537 |
this.timeouts[toId].interval = delay;
|
|
|
2538 |
}
|
|
|
2539 |
|
|
|
2540 |
return toId;
|
|
|
2541 |
}
|
|
|
2542 |
|
|
|
2543 |
function parseTime(str) {
|
|
|
2544 |
if (!str) {
|
|
|
2545 |
return 0;
|
|
|
2546 |
}
|
|
|
2547 |
|
|
|
2548 |
var strings = str.split(":");
|
|
|
2549 |
var l = strings.length, i = l;
|
|
|
2550 |
var ms = 0, parsed;
|
|
|
2551 |
|
|
|
2552 |
if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
|
|
|
2553 |
throw new Error("tick only understands numbers and 'h:m:s'");
|
|
|
2554 |
}
|
|
|
2555 |
|
|
|
2556 |
while (i--) {
|
|
|
2557 |
parsed = parseInt(strings[i], 10);
|
|
|
2558 |
|
|
|
2559 |
if (parsed >= 60) {
|
|
|
2560 |
throw new Error("Invalid time " + str);
|
|
|
2561 |
}
|
|
|
2562 |
|
|
|
2563 |
ms += parsed * Math.pow(60, (l - i - 1));
|
|
|
2564 |
}
|
|
|
2565 |
|
|
|
2566 |
return ms * 1000;
|
|
|
2567 |
}
|
|
|
2568 |
|
|
|
2569 |
function createObject(object) {
|
|
|
2570 |
var newObject;
|
|
|
2571 |
|
|
|
2572 |
if (Object.create) {
|
|
|
2573 |
newObject = Object.create(object);
|
|
|
2574 |
} else {
|
|
|
2575 |
var F = function () {};
|
|
|
2576 |
F.prototype = object;
|
|
|
2577 |
newObject = new F();
|
|
|
2578 |
}
|
|
|
2579 |
|
|
|
2580 |
newObject.Date.clock = newObject;
|
|
|
2581 |
return newObject;
|
|
|
2582 |
}
|
|
|
2583 |
|
|
|
2584 |
sinon.clock = {
|
|
|
2585 |
now: 0,
|
|
|
2586 |
|
|
|
2587 |
create: function create(now) {
|
|
|
2588 |
var clock = createObject(this);
|
|
|
2589 |
|
|
|
2590 |
if (typeof now == "number") {
|
|
|
2591 |
clock.now = now;
|
|
|
2592 |
}
|
|
|
2593 |
|
|
|
2594 |
if (!!now && typeof now == "object") {
|
|
|
2595 |
throw new TypeError("now should be milliseconds since UNIX epoch");
|
|
|
2596 |
}
|
|
|
2597 |
|
|
|
2598 |
return clock;
|
|
|
2599 |
},
|
|
|
2600 |
|
|
|
2601 |
setTimeout: function setTimeout(callback, timeout) {
|
|
|
2602 |
return addTimer.call(this, arguments, false);
|
|
|
2603 |
},
|
|
|
2604 |
|
|
|
2605 |
clearTimeout: function clearTimeout(timerId) {
|
|
|
2606 |
if (!this.timeouts) {
|
|
|
2607 |
this.timeouts = [];
|
|
|
2608 |
}
|
|
|
2609 |
|
|
|
2610 |
if (timerId in this.timeouts) {
|
|
|
2611 |
delete this.timeouts[timerId];
|
|
|
2612 |
}
|
|
|
2613 |
},
|
|
|
2614 |
|
|
|
2615 |
setInterval: function setInterval(callback, timeout) {
|
|
|
2616 |
return addTimer.call(this, arguments, true);
|
|
|
2617 |
},
|
|
|
2618 |
|
|
|
2619 |
clearInterval: function clearInterval(timerId) {
|
|
|
2620 |
this.clearTimeout(timerId);
|
|
|
2621 |
},
|
|
|
2622 |
|
|
|
2623 |
tick: function tick(ms) {
|
|
|
2624 |
ms = typeof ms == "number" ? ms : parseTime(ms);
|
|
|
2625 |
var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
|
|
|
2626 |
var timer = this.firstTimerInRange(tickFrom, tickTo);
|
|
|
2627 |
|
|
|
2628 |
var firstException;
|
|
|
2629 |
while (timer && tickFrom <= tickTo) {
|
|
|
2630 |
if (this.timeouts[timer.id]) {
|
|
|
2631 |
tickFrom = this.now = timer.callAt;
|
|
|
2632 |
try {
|
|
|
2633 |
this.callTimer(timer);
|
|
|
2634 |
} catch (e) {
|
|
|
2635 |
firstException = firstException || e;
|
|
|
2636 |
}
|
|
|
2637 |
}
|
|
|
2638 |
|
|
|
2639 |
timer = this.firstTimerInRange(previous, tickTo);
|
|
|
2640 |
previous = tickFrom;
|
|
|
2641 |
}
|
|
|
2642 |
|
|
|
2643 |
this.now = tickTo;
|
|
|
2644 |
|
|
|
2645 |
if (firstException) {
|
|
|
2646 |
throw firstException;
|
|
|
2647 |
}
|
|
|
2648 |
},
|
|
|
2649 |
|
|
|
2650 |
firstTimerInRange: function (from, to) {
|
|
|
2651 |
var timer, smallest, originalTimer;
|
|
|
2652 |
|
|
|
2653 |
for (var id in this.timeouts) {
|
|
|
2654 |
if (this.timeouts.hasOwnProperty(id)) {
|
|
|
2655 |
if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
|
|
|
2656 |
continue;
|
|
|
2657 |
}
|
|
|
2658 |
|
|
|
2659 |
if (!smallest || this.timeouts[id].callAt < smallest) {
|
|
|
2660 |
originalTimer = this.timeouts[id];
|
|
|
2661 |
smallest = this.timeouts[id].callAt;
|
|
|
2662 |
|
|
|
2663 |
timer = {
|
|
|
2664 |
func: this.timeouts[id].func,
|
|
|
2665 |
callAt: this.timeouts[id].callAt,
|
|
|
2666 |
interval: this.timeouts[id].interval,
|
|
|
2667 |
id: this.timeouts[id].id,
|
|
|
2668 |
invokeArgs: this.timeouts[id].invokeArgs
|
|
|
2669 |
};
|
|
|
2670 |
}
|
|
|
2671 |
}
|
|
|
2672 |
}
|
|
|
2673 |
|
|
|
2674 |
return timer || null;
|
|
|
2675 |
},
|
|
|
2676 |
|
|
|
2677 |
callTimer: function (timer) {
|
|
|
2678 |
if (typeof timer.interval == "number") {
|
|
|
2679 |
this.timeouts[timer.id].callAt += timer.interval;
|
|
|
2680 |
} else {
|
|
|
2681 |
delete this.timeouts[timer.id];
|
|
|
2682 |
}
|
|
|
2683 |
|
|
|
2684 |
try {
|
|
|
2685 |
if (typeof timer.func == "function") {
|
|
|
2686 |
timer.func.apply(null, timer.invokeArgs);
|
|
|
2687 |
} else {
|
|
|
2688 |
eval(timer.func);
|
|
|
2689 |
}
|
|
|
2690 |
} catch (e) {
|
|
|
2691 |
var exception = e;
|
|
|
2692 |
}
|
|
|
2693 |
|
|
|
2694 |
if (!this.timeouts[timer.id]) {
|
|
|
2695 |
if (exception) {
|
|
|
2696 |
throw exception;
|
|
|
2697 |
}
|
|
|
2698 |
return;
|
|
|
2699 |
}
|
|
|
2700 |
|
|
|
2701 |
if (exception) {
|
|
|
2702 |
throw exception;
|
|
|
2703 |
}
|
|
|
2704 |
},
|
|
|
2705 |
|
|
|
2706 |
reset: function reset() {
|
|
|
2707 |
this.timeouts = {};
|
|
|
2708 |
},
|
|
|
2709 |
|
|
|
2710 |
Date: (function () {
|
|
|
2711 |
var NativeDate = Date;
|
|
|
2712 |
|
|
|
2713 |
function ClockDate(year, month, date, hour, minute, second, ms) {
|
|
|
2714 |
// Defensive and verbose to avoid potential harm in passing
|
|
|
2715 |
// explicit undefined when user does not pass argument
|
|
|
2716 |
switch (arguments.length) {
|
|
|
2717 |
case 0:
|
|
|
2718 |
return new NativeDate(ClockDate.clock.now);
|
|
|
2719 |
case 1:
|
|
|
2720 |
return new NativeDate(year);
|
|
|
2721 |
case 2:
|
|
|
2722 |
return new NativeDate(year, month);
|
|
|
2723 |
case 3:
|
|
|
2724 |
return new NativeDate(year, month, date);
|
|
|
2725 |
case 4:
|
|
|
2726 |
return new NativeDate(year, month, date, hour);
|
|
|
2727 |
case 5:
|
|
|
2728 |
return new NativeDate(year, month, date, hour, minute);
|
|
|
2729 |
case 6:
|
|
|
2730 |
return new NativeDate(year, month, date, hour, minute, second);
|
|
|
2731 |
default:
|
|
|
2732 |
return new NativeDate(year, month, date, hour, minute, second, ms);
|
|
|
2733 |
}
|
|
|
2734 |
}
|
|
|
2735 |
|
|
|
2736 |
return mirrorDateProperties(ClockDate, NativeDate);
|
|
|
2737 |
}())
|
|
|
2738 |
};
|
|
|
2739 |
|
|
|
2740 |
function mirrorDateProperties(target, source) {
|
|
|
2741 |
if (source.now) {
|
|
|
2742 |
target.now = function now() {
|
|
|
2743 |
return target.clock.now;
|
|
|
2744 |
};
|
|
|
2745 |
} else {
|
|
|
2746 |
delete target.now;
|
|
|
2747 |
}
|
|
|
2748 |
|
|
|
2749 |
if (source.toSource) {
|
|
|
2750 |
target.toSource = function toSource() {
|
|
|
2751 |
return source.toSource();
|
|
|
2752 |
};
|
|
|
2753 |
} else {
|
|
|
2754 |
delete target.toSource;
|
|
|
2755 |
}
|
|
|
2756 |
|
|
|
2757 |
target.toString = function toString() {
|
|
|
2758 |
return source.toString();
|
|
|
2759 |
};
|
|
|
2760 |
|
|
|
2761 |
target.prototype = source.prototype;
|
|
|
2762 |
target.parse = source.parse;
|
|
|
2763 |
target.UTC = source.UTC;
|
|
|
2764 |
target.prototype.toUTCString = source.prototype.toUTCString;
|
|
|
2765 |
return target;
|
|
|
2766 |
}
|
|
|
2767 |
|
|
|
2768 |
var methods = ["Date", "setTimeout", "setInterval",
|
|
|
2769 |
"clearTimeout", "clearInterval"];
|
|
|
2770 |
|
|
|
2771 |
function restore() {
|
|
|
2772 |
var method;
|
|
|
2773 |
|
|
|
2774 |
for (var i = 0, l = this.methods.length; i < l; i++) {
|
|
|
2775 |
method = this.methods[i];
|
|
|
2776 |
if (global[method].hadOwnProperty) {
|
|
|
2777 |
global[method] = this["_" + method];
|
|
|
2778 |
} else {
|
|
|
2779 |
delete global[method];
|
|
|
2780 |
}
|
|
|
2781 |
}
|
|
|
2782 |
|
|
|
2783 |
// Prevent multiple executions which will completely remove these props
|
|
|
2784 |
this.methods = [];
|
|
|
2785 |
}
|
|
|
2786 |
|
|
|
2787 |
function stubGlobal(method, clock) {
|
|
|
2788 |
clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
|
|
|
2789 |
clock["_" + method] = global[method];
|
|
|
2790 |
|
|
|
2791 |
if (method == "Date") {
|
|
|
2792 |
var date = mirrorDateProperties(clock[method], global[method]);
|
|
|
2793 |
global[method] = date;
|
|
|
2794 |
} else {
|
|
|
2795 |
global[method] = function () {
|
|
|
2796 |
return clock[method].apply(clock, arguments);
|
|
|
2797 |
};
|
|
|
2798 |
|
|
|
2799 |
for (var prop in clock[method]) {
|
|
|
2800 |
if (clock[method].hasOwnProperty(prop)) {
|
|
|
2801 |
global[method][prop] = clock[method][prop];
|
|
|
2802 |
}
|
|
|
2803 |
}
|
|
|
2804 |
}
|
|
|
2805 |
|
|
|
2806 |
global[method].clock = clock;
|
|
|
2807 |
}
|
|
|
2808 |
|
|
|
2809 |
sinon.useFakeTimers = function useFakeTimers(now) {
|
|
|
2810 |
var clock = sinon.clock.create(now);
|
|
|
2811 |
clock.restore = restore;
|
|
|
2812 |
clock.methods = Array.prototype.slice.call(arguments,
|
|
|
2813 |
typeof now == "number" ? 1 : 0);
|
|
|
2814 |
|
|
|
2815 |
if (clock.methods.length === 0) {
|
|
|
2816 |
clock.methods = methods;
|
|
|
2817 |
}
|
|
|
2818 |
|
|
|
2819 |
for (var i = 0, l = clock.methods.length; i < l; i++) {
|
|
|
2820 |
stubGlobal(clock.methods[i], clock);
|
|
|
2821 |
}
|
|
|
2822 |
|
|
|
2823 |
return clock;
|
|
|
2824 |
};
|
|
|
2825 |
}(typeof global != "undefined" && typeof global !== "function" ? global : this));
|
|
|
2826 |
|
|
|
2827 |
sinon.timers = {
|
|
|
2828 |
setTimeout: setTimeout,
|
|
|
2829 |
clearTimeout: clearTimeout,
|
|
|
2830 |
setInterval: setInterval,
|
|
|
2831 |
clearInterval: clearInterval,
|
|
|
2832 |
Date: Date
|
|
|
2833 |
};
|
|
|
2834 |
|
|
|
2835 |
if (typeof module == "object" && typeof require == "function") {
|
|
|
2836 |
module.exports = sinon;
|
|
|
2837 |
}
|
|
|
2838 |
|
|
|
2839 |
/*jslint eqeqeq: false, onevar: false*/
|
|
|
2840 |
/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
|
|
|
2841 |
/**
|
|
|
2842 |
* Minimal Event interface implementation
|
|
|
2843 |
*
|
|
|
2844 |
* Original implementation by Sven Fuchs: https://gist.github.com/995028
|
|
|
2845 |
* Modifications and tests by Christian Johansen.
|
|
|
2846 |
*
|
|
|
2847 |
* @author Sven Fuchs (svenfuchs@artweb-design.de)
|
|
|
2848 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
2849 |
* @license BSD
|
|
|
2850 |
*
|
|
|
2851 |
* Copyright (c) 2011 Sven Fuchs, Christian Johansen
|
|
|
2852 |
*/
|
|
|
2853 |
|
|
|
2854 |
if (typeof sinon == "undefined") {
|
|
|
2855 |
this.sinon = {};
|
|
|
2856 |
}
|
|
|
2857 |
|
|
|
2858 |
(function () {
|
|
|
2859 |
var push = [].push;
|
|
|
2860 |
|
|
|
2861 |
sinon.Event = function Event(type, bubbles, cancelable) {
|
|
|
2862 |
this.initEvent(type, bubbles, cancelable);
|
|
|
2863 |
};
|
|
|
2864 |
|
|
|
2865 |
sinon.Event.prototype = {
|
|
|
2866 |
initEvent: function(type, bubbles, cancelable) {
|
|
|
2867 |
this.type = type;
|
|
|
2868 |
this.bubbles = bubbles;
|
|
|
2869 |
this.cancelable = cancelable;
|
|
|
2870 |
},
|
|
|
2871 |
|
|
|
2872 |
stopPropagation: function () {},
|
|
|
2873 |
|
|
|
2874 |
preventDefault: function () {
|
|
|
2875 |
this.defaultPrevented = true;
|
|
|
2876 |
}
|
|
|
2877 |
};
|
|
|
2878 |
|
|
|
2879 |
sinon.EventTarget = {
|
|
|
2880 |
addEventListener: function addEventListener(event, listener, useCapture) {
|
|
|
2881 |
this.eventListeners = this.eventListeners || {};
|
|
|
2882 |
this.eventListeners[event] = this.eventListeners[event] || [];
|
|
|
2883 |
push.call(this.eventListeners[event], listener);
|
|
|
2884 |
},
|
|
|
2885 |
|
|
|
2886 |
removeEventListener: function removeEventListener(event, listener, useCapture) {
|
|
|
2887 |
var listeners = this.eventListeners && this.eventListeners[event] || [];
|
|
|
2888 |
|
|
|
2889 |
for (var i = 0, l = listeners.length; i < l; ++i) {
|
|
|
2890 |
if (listeners[i] == listener) {
|
|
|
2891 |
return listeners.splice(i, 1);
|
|
|
2892 |
}
|
|
|
2893 |
}
|
|
|
2894 |
},
|
|
|
2895 |
|
|
|
2896 |
dispatchEvent: function dispatchEvent(event) {
|
|
|
2897 |
var type = event.type;
|
|
|
2898 |
var listeners = this.eventListeners && this.eventListeners[type] || [];
|
|
|
2899 |
|
|
|
2900 |
for (var i = 0; i < listeners.length; i++) {
|
|
|
2901 |
if (typeof listeners[i] == "function") {
|
|
|
2902 |
listeners[i].call(this, event);
|
|
|
2903 |
} else {
|
|
|
2904 |
listeners[i].handleEvent(event);
|
|
|
2905 |
}
|
|
|
2906 |
}
|
|
|
2907 |
|
|
|
2908 |
return !!event.defaultPrevented;
|
|
|
2909 |
}
|
|
|
2910 |
};
|
|
|
2911 |
}());
|
|
|
2912 |
|
|
|
2913 |
/**
|
|
|
2914 |
* @depend ../../sinon.js
|
|
|
2915 |
* @depend event.js
|
|
|
2916 |
*/
|
|
|
2917 |
/*jslint eqeqeq: false, onevar: false*/
|
|
|
2918 |
/*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
|
|
|
2919 |
/**
|
|
|
2920 |
* Fake XMLHttpRequest object
|
|
|
2921 |
*
|
|
|
2922 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
2923 |
* @license BSD
|
|
|
2924 |
*
|
|
|
2925 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
2926 |
*/
|
|
|
2927 |
|
|
|
2928 |
if (typeof sinon == "undefined") {
|
|
|
2929 |
this.sinon = {};
|
|
|
2930 |
}
|
|
|
2931 |
sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
|
|
|
2932 |
|
|
|
2933 |
// wrapper for global
|
|
|
2934 |
(function(global) {
|
|
|
2935 |
var xhr = sinon.xhr;
|
|
|
2936 |
xhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
|
|
|
2937 |
xhr.GlobalActiveXObject = global.ActiveXObject;
|
|
|
2938 |
xhr.supportsActiveX = typeof xhr.GlobalActiveXObject != "undefined";
|
|
|
2939 |
xhr.supportsXHR = typeof xhr.GlobalXMLHttpRequest != "undefined";
|
|
|
2940 |
xhr.workingXHR = xhr.supportsXHR ? xhr.GlobalXMLHttpRequest : xhr.supportsActiveX
|
|
|
2941 |
? function() { return new xhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
|
|
|
2942 |
|
|
|
2943 |
/*jsl:ignore*/
|
|
|
2944 |
var unsafeHeaders = {
|
|
|
2945 |
"Accept-Charset": true,
|
|
|
2946 |
"Accept-Encoding": true,
|
|
|
2947 |
"Connection": true,
|
|
|
2948 |
"Content-Length": true,
|
|
|
2949 |
"Cookie": true,
|
|
|
2950 |
"Cookie2": true,
|
|
|
2951 |
"Content-Transfer-Encoding": true,
|
|
|
2952 |
"Date": true,
|
|
|
2953 |
"Expect": true,
|
|
|
2954 |
"Host": true,
|
|
|
2955 |
"Keep-Alive": true,
|
|
|
2956 |
"Referer": true,
|
|
|
2957 |
"TE": true,
|
|
|
2958 |
"Trailer": true,
|
|
|
2959 |
"Transfer-Encoding": true,
|
|
|
2960 |
"Upgrade": true,
|
|
|
2961 |
"User-Agent": true,
|
|
|
2962 |
"Via": true
|
|
|
2963 |
};
|
|
|
2964 |
/*jsl:end*/
|
|
|
2965 |
|
|
|
2966 |
function FakeXMLHttpRequest() {
|
|
|
2967 |
this.readyState = FakeXMLHttpRequest.UNSENT;
|
|
|
2968 |
this.requestHeaders = {};
|
|
|
2969 |
this.requestBody = null;
|
|
|
2970 |
this.status = 0;
|
|
|
2971 |
this.statusText = "";
|
|
|
2972 |
|
|
|
2973 |
if (typeof FakeXMLHttpRequest.onCreate == "function") {
|
|
|
2974 |
FakeXMLHttpRequest.onCreate(this);
|
|
|
2975 |
}
|
|
|
2976 |
}
|
|
|
2977 |
|
|
|
2978 |
function verifyState(xhr) {
|
|
|
2979 |
if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
|
|
|
2980 |
throw new Error("INVALID_STATE_ERR");
|
|
|
2981 |
}
|
|
|
2982 |
|
|
|
2983 |
if (xhr.sendFlag) {
|
|
|
2984 |
throw new Error("INVALID_STATE_ERR");
|
|
|
2985 |
}
|
|
|
2986 |
}
|
|
|
2987 |
|
|
|
2988 |
// filtering to enable a white-list version of Sinon FakeXhr,
|
|
|
2989 |
// where whitelisted requests are passed through to real XHR
|
|
|
2990 |
function each(collection, callback) {
|
|
|
2991 |
if (!collection) return;
|
|
|
2992 |
for (var i = 0, l = collection.length; i < l; i += 1) {
|
|
|
2993 |
callback(collection[i]);
|
|
|
2994 |
}
|
|
|
2995 |
}
|
|
|
2996 |
function some(collection, callback) {
|
|
|
2997 |
for (var index = 0; index < collection.length; index++) {
|
|
|
2998 |
if(callback(collection[index]) === true) return true;
|
|
|
2999 |
};
|
|
|
3000 |
return false;
|
|
|
3001 |
}
|
|
|
3002 |
// largest arity in XHR is 5 - XHR#open
|
|
|
3003 |
var apply = function(obj,method,args) {
|
|
|
3004 |
switch(args.length) {
|
|
|
3005 |
case 0: return obj[method]();
|
|
|
3006 |
case 1: return obj[method](args[0]);
|
|
|
3007 |
case 2: return obj[method](args[0],args[1]);
|
|
|
3008 |
case 3: return obj[method](args[0],args[1],args[2]);
|
|
|
3009 |
case 4: return obj[method](args[0],args[1],args[2],args[3]);
|
|
|
3010 |
case 5: return obj[method](args[0],args[1],args[2],args[3],args[4]);
|
|
|
3011 |
};
|
|
|
3012 |
};
|
|
|
3013 |
|
|
|
3014 |
FakeXMLHttpRequest.filters = [];
|
|
|
3015 |
FakeXMLHttpRequest.addFilter = function(fn) {
|
|
|
3016 |
this.filters.push(fn)
|
|
|
3017 |
};
|
|
|
3018 |
var IE6Re = /MSIE 6/;
|
|
|
3019 |
FakeXMLHttpRequest.defake = function(fakeXhr,xhrArgs) {
|
|
|
3020 |
var xhr = new sinon.xhr.workingXHR();
|
|
|
3021 |
each(["open","setRequestHeader","send","abort","getResponseHeader",
|
|
|
3022 |
"getAllResponseHeaders","addEventListener","overrideMimeType","removeEventListener"],
|
|
|
3023 |
function(method) {
|
|
|
3024 |
fakeXhr[method] = function() {
|
|
|
3025 |
return apply(xhr,method,arguments);
|
|
|
3026 |
};
|
|
|
3027 |
});
|
|
|
3028 |
|
|
|
3029 |
var copyAttrs = function(args) {
|
|
|
3030 |
each(args, function(attr) {
|
|
|
3031 |
try {
|
|
|
3032 |
fakeXhr[attr] = xhr[attr]
|
|
|
3033 |
} catch(e) {
|
|
|
3034 |
if(!IE6Re.test(navigator.userAgent)) throw e;
|
|
|
3035 |
}
|
|
|
3036 |
});
|
|
|
3037 |
};
|
|
|
3038 |
|
|
|
3039 |
var stateChange = function() {
|
|
|
3040 |
fakeXhr.readyState = xhr.readyState;
|
|
|
3041 |
if(xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
|
|
3042 |
copyAttrs(["status","statusText"]);
|
|
|
3043 |
}
|
|
|
3044 |
if(xhr.readyState >= FakeXMLHttpRequest.LOADING) {
|
|
|
3045 |
copyAttrs(["responseText"]);
|
|
|
3046 |
}
|
|
|
3047 |
if(xhr.readyState === FakeXMLHttpRequest.DONE) {
|
|
|
3048 |
copyAttrs(["responseXML"]);
|
|
|
3049 |
}
|
|
|
3050 |
if(fakeXhr.onreadystatechange) fakeXhr.onreadystatechange.call(fakeXhr);
|
|
|
3051 |
};
|
|
|
3052 |
if(xhr.addEventListener) {
|
|
|
3053 |
for(var event in fakeXhr.eventListeners) {
|
|
|
3054 |
if(fakeXhr.eventListeners.hasOwnProperty(event)) {
|
|
|
3055 |
each(fakeXhr.eventListeners[event],function(handler) {
|
|
|
3056 |
xhr.addEventListener(event, handler);
|
|
|
3057 |
});
|
|
|
3058 |
}
|
|
|
3059 |
}
|
|
|
3060 |
xhr.addEventListener("readystatechange",stateChange);
|
|
|
3061 |
} else {
|
|
|
3062 |
xhr.onreadystatechange = stateChange;
|
|
|
3063 |
}
|
|
|
3064 |
apply(xhr,"open",xhrArgs);
|
|
|
3065 |
};
|
|
|
3066 |
FakeXMLHttpRequest.useFilters = false;
|
|
|
3067 |
|
|
|
3068 |
function verifyRequestSent(xhr) {
|
|
|
3069 |
if (xhr.readyState == FakeXMLHttpRequest.DONE) {
|
|
|
3070 |
throw new Error("Request done");
|
|
|
3071 |
}
|
|
|
3072 |
}
|
|
|
3073 |
|
|
|
3074 |
function verifyHeadersReceived(xhr) {
|
|
|
3075 |
if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
|
|
3076 |
throw new Error("No headers received");
|
|
|
3077 |
}
|
|
|
3078 |
}
|
|
|
3079 |
|
|
|
3080 |
function verifyResponseBodyType(body) {
|
|
|
3081 |
if (typeof body != "string") {
|
|
|
3082 |
var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
|
|
|
3083 |
body + ", which is not a string.");
|
|
|
3084 |
error.name = "InvalidBodyException";
|
|
|
3085 |
throw error;
|
|
|
3086 |
}
|
|
|
3087 |
}
|
|
|
3088 |
|
|
|
3089 |
sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
|
|
|
3090 |
async: true,
|
|
|
3091 |
|
|
|
3092 |
open: function open(method, url, async, username, password) {
|
|
|
3093 |
this.method = method;
|
|
|
3094 |
this.url = url;
|
|
|
3095 |
this.async = typeof async == "boolean" ? async : true;
|
|
|
3096 |
this.username = username;
|
|
|
3097 |
this.password = password;
|
|
|
3098 |
this.responseText = null;
|
|
|
3099 |
this.responseXML = null;
|
|
|
3100 |
this.requestHeaders = {};
|
|
|
3101 |
this.sendFlag = false;
|
|
|
3102 |
if(sinon.FakeXMLHttpRequest.useFilters === true) {
|
|
|
3103 |
var xhrArgs = arguments;
|
|
|
3104 |
var defake = some(FakeXMLHttpRequest.filters,function(filter) {
|
|
|
3105 |
return filter.apply(this,xhrArgs)
|
|
|
3106 |
});
|
|
|
3107 |
if (defake) {
|
|
|
3108 |
return sinon.FakeXMLHttpRequest.defake(this,arguments);
|
|
|
3109 |
}
|
|
|
3110 |
}
|
|
|
3111 |
this.readyStateChange(FakeXMLHttpRequest.OPENED);
|
|
|
3112 |
},
|
|
|
3113 |
|
|
|
3114 |
readyStateChange: function readyStateChange(state) {
|
|
|
3115 |
this.readyState = state;
|
|
|
3116 |
|
|
|
3117 |
if (typeof this.onreadystatechange == "function") {
|
|
|
3118 |
try {
|
|
|
3119 |
this.onreadystatechange();
|
|
|
3120 |
} catch (e) {
|
|
|
3121 |
sinon.logError("Fake XHR onreadystatechange handler", e);
|
|
|
3122 |
}
|
|
|
3123 |
}
|
|
|
3124 |
|
|
|
3125 |
this.dispatchEvent(new sinon.Event("readystatechange"));
|
|
|
3126 |
},
|
|
|
3127 |
|
|
|
3128 |
setRequestHeader: function setRequestHeader(header, value) {
|
|
|
3129 |
verifyState(this);
|
|
|
3130 |
|
|
|
3131 |
if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
|
|
|
3132 |
throw new Error("Refused to set unsafe header \"" + header + "\"");
|
|
|
3133 |
}
|
|
|
3134 |
|
|
|
3135 |
if (this.requestHeaders[header]) {
|
|
|
3136 |
this.requestHeaders[header] += "," + value;
|
|
|
3137 |
} else {
|
|
|
3138 |
this.requestHeaders[header] = value;
|
|
|
3139 |
}
|
|
|
3140 |
},
|
|
|
3141 |
|
|
|
3142 |
// Helps testing
|
|
|
3143 |
setResponseHeaders: function setResponseHeaders(headers) {
|
|
|
3144 |
this.responseHeaders = {};
|
|
|
3145 |
|
|
|
3146 |
for (var header in headers) {
|
|
|
3147 |
if (headers.hasOwnProperty(header)) {
|
|
|
3148 |
this.responseHeaders[header] = headers[header];
|
|
|
3149 |
}
|
|
|
3150 |
}
|
|
|
3151 |
|
|
|
3152 |
if (this.async) {
|
|
|
3153 |
this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
|
|
|
3154 |
}
|
|
|
3155 |
},
|
|
|
3156 |
|
|
|
3157 |
// Currently treats ALL data as a DOMString (i.e. no Document)
|
|
|
3158 |
send: function send(data) {
|
|
|
3159 |
verifyState(this);
|
|
|
3160 |
|
|
|
3161 |
if (!/^(get|head)$/i.test(this.method)) {
|
|
|
3162 |
if (this.requestHeaders["Content-Type"]) {
|
|
|
3163 |
var value = this.requestHeaders["Content-Type"].split(";");
|
|
|
3164 |
this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
|
|
|
3165 |
} else {
|
|
|
3166 |
this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
|
|
|
3167 |
}
|
|
|
3168 |
|
|
|
3169 |
this.requestBody = data;
|
|
|
3170 |
}
|
|
|
3171 |
|
|
|
3172 |
this.errorFlag = false;
|
|
|
3173 |
this.sendFlag = this.async;
|
|
|
3174 |
this.readyStateChange(FakeXMLHttpRequest.OPENED);
|
|
|
3175 |
|
|
|
3176 |
if (typeof this.onSend == "function") {
|
|
|
3177 |
this.onSend(this);
|
|
|
3178 |
}
|
|
|
3179 |
},
|
|
|
3180 |
|
|
|
3181 |
abort: function abort() {
|
|
|
3182 |
this.aborted = true;
|
|
|
3183 |
this.responseText = null;
|
|
|
3184 |
this.errorFlag = true;
|
|
|
3185 |
this.requestHeaders = {};
|
|
|
3186 |
|
|
|
3187 |
if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
|
|
|
3188 |
this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
|
|
|
3189 |
this.sendFlag = false;
|
|
|
3190 |
}
|
|
|
3191 |
|
|
|
3192 |
this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
|
|
|
3193 |
},
|
|
|
3194 |
|
|
|
3195 |
getResponseHeader: function getResponseHeader(header) {
|
|
|
3196 |
if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
|
|
3197 |
return null;
|
|
|
3198 |
}
|
|
|
3199 |
|
|
|
3200 |
if (/^Set-Cookie2?$/i.test(header)) {
|
|
|
3201 |
return null;
|
|
|
3202 |
}
|
|
|
3203 |
|
|
|
3204 |
header = header.toLowerCase();
|
|
|
3205 |
|
|
|
3206 |
for (var h in this.responseHeaders) {
|
|
|
3207 |
if (h.toLowerCase() == header) {
|
|
|
3208 |
return this.responseHeaders[h];
|
|
|
3209 |
}
|
|
|
3210 |
}
|
|
|
3211 |
|
|
|
3212 |
return null;
|
|
|
3213 |
},
|
|
|
3214 |
|
|
|
3215 |
getAllResponseHeaders: function getAllResponseHeaders() {
|
|
|
3216 |
if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
|
|
3217 |
return "";
|
|
|
3218 |
}
|
|
|
3219 |
|
|
|
3220 |
var headers = "";
|
|
|
3221 |
|
|
|
3222 |
for (var header in this.responseHeaders) {
|
|
|
3223 |
if (this.responseHeaders.hasOwnProperty(header) &&
|
|
|
3224 |
!/^Set-Cookie2?$/i.test(header)) {
|
|
|
3225 |
headers += header + ": " + this.responseHeaders[header] + "\r\n";
|
|
|
3226 |
}
|
|
|
3227 |
}
|
|
|
3228 |
|
|
|
3229 |
return headers;
|
|
|
3230 |
},
|
|
|
3231 |
|
|
|
3232 |
setResponseBody: function setResponseBody(body) {
|
|
|
3233 |
verifyRequestSent(this);
|
|
|
3234 |
verifyHeadersReceived(this);
|
|
|
3235 |
verifyResponseBodyType(body);
|
|
|
3236 |
|
|
|
3237 |
var chunkSize = this.chunkSize || 10;
|
|
|
3238 |
var index = 0;
|
|
|
3239 |
this.responseText = "";
|
|
|
3240 |
|
|
|
3241 |
do {
|
|
|
3242 |
if (this.async) {
|
|
|
3243 |
this.readyStateChange(FakeXMLHttpRequest.LOADING);
|
|
|
3244 |
}
|
|
|
3245 |
|
|
|
3246 |
this.responseText += body.substring(index, index + chunkSize);
|
|
|
3247 |
index += chunkSize;
|
|
|
3248 |
} while (index < body.length);
|
|
|
3249 |
|
|
|
3250 |
var type = this.getResponseHeader("Content-Type");
|
|
|
3251 |
|
|
|
3252 |
if (this.responseText &&
|
|
|
3253 |
(!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
|
|
|
3254 |
try {
|
|
|
3255 |
this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
|
|
|
3256 |
} catch (e) {
|
|
|
3257 |
// Unable to parse XML - no biggie
|
|
|
3258 |
}
|
|
|
3259 |
}
|
|
|
3260 |
|
|
|
3261 |
if (this.async) {
|
|
|
3262 |
this.readyStateChange(FakeXMLHttpRequest.DONE);
|
|
|
3263 |
} else {
|
|
|
3264 |
this.readyState = FakeXMLHttpRequest.DONE;
|
|
|
3265 |
}
|
|
|
3266 |
},
|
|
|
3267 |
|
|
|
3268 |
respond: function respond(status, headers, body) {
|
|
|
3269 |
this.setResponseHeaders(headers || {});
|
|
|
3270 |
this.status = typeof status == "number" ? status : 200;
|
|
|
3271 |
this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
|
|
|
3272 |
this.setResponseBody(body || "");
|
|
|
3273 |
}
|
|
|
3274 |
});
|
|
|
3275 |
|
|
|
3276 |
sinon.extend(FakeXMLHttpRequest, {
|
|
|
3277 |
UNSENT: 0,
|
|
|
3278 |
OPENED: 1,
|
|
|
3279 |
HEADERS_RECEIVED: 2,
|
|
|
3280 |
LOADING: 3,
|
|
|
3281 |
DONE: 4
|
|
|
3282 |
});
|
|
|
3283 |
|
|
|
3284 |
// Borrowed from JSpec
|
|
|
3285 |
FakeXMLHttpRequest.parseXML = function parseXML(text) {
|
|
|
3286 |
var xmlDoc;
|
|
|
3287 |
|
|
|
3288 |
if (typeof DOMParser != "undefined") {
|
|
|
3289 |
var parser = new DOMParser();
|
|
|
3290 |
xmlDoc = parser.parseFromString(text, "text/xml");
|
|
|
3291 |
} else {
|
|
|
3292 |
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
|
|
|
3293 |
xmlDoc.async = "false";
|
|
|
3294 |
xmlDoc.loadXML(text);
|
|
|
3295 |
}
|
|
|
3296 |
|
|
|
3297 |
return xmlDoc;
|
|
|
3298 |
};
|
|
|
3299 |
|
|
|
3300 |
FakeXMLHttpRequest.statusCodes = {
|
|
|
3301 |
100: "Continue",
|
|
|
3302 |
101: "Switching Protocols",
|
|
|
3303 |
200: "OK",
|
|
|
3304 |
201: "Created",
|
|
|
3305 |
202: "Accepted",
|
|
|
3306 |
203: "Non-Authoritative Information",
|
|
|
3307 |
204: "No Content",
|
|
|
3308 |
205: "Reset Content",
|
|
|
3309 |
206: "Partial Content",
|
|
|
3310 |
300: "Multiple Choice",
|
|
|
3311 |
301: "Moved Permanently",
|
|
|
3312 |
302: "Found",
|
|
|
3313 |
303: "See Other",
|
|
|
3314 |
304: "Not Modified",
|
|
|
3315 |
305: "Use Proxy",
|
|
|
3316 |
307: "Temporary Redirect",
|
|
|
3317 |
400: "Bad Request",
|
|
|
3318 |
401: "Unauthorized",
|
|
|
3319 |
402: "Payment Required",
|
|
|
3320 |
403: "Forbidden",
|
|
|
3321 |
404: "Not Found",
|
|
|
3322 |
405: "Method Not Allowed",
|
|
|
3323 |
406: "Not Acceptable",
|
|
|
3324 |
407: "Proxy Authentication Required",
|
|
|
3325 |
408: "Request Timeout",
|
|
|
3326 |
409: "Conflict",
|
|
|
3327 |
410: "Gone",
|
|
|
3328 |
411: "Length Required",
|
|
|
3329 |
412: "Precondition Failed",
|
|
|
3330 |
413: "Request Entity Too Large",
|
|
|
3331 |
414: "Request-URI Too Long",
|
|
|
3332 |
415: "Unsupported Media Type",
|
|
|
3333 |
416: "Requested Range Not Satisfiable",
|
|
|
3334 |
417: "Expectation Failed",
|
|
|
3335 |
422: "Unprocessable Entity",
|
|
|
3336 |
500: "Internal Server Error",
|
|
|
3337 |
501: "Not Implemented",
|
|
|
3338 |
502: "Bad Gateway",
|
|
|
3339 |
503: "Service Unavailable",
|
|
|
3340 |
504: "Gateway Timeout",
|
|
|
3341 |
505: "HTTP Version Not Supported"
|
|
|
3342 |
};
|
|
|
3343 |
|
|
|
3344 |
sinon.useFakeXMLHttpRequest = function () {
|
|
|
3345 |
sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
|
|
|
3346 |
if (xhr.supportsXHR) {
|
|
|
3347 |
global.XMLHttpRequest = xhr.GlobalXMLHttpRequest;
|
|
|
3348 |
}
|
|
|
3349 |
|
|
|
3350 |
if (xhr.supportsActiveX) {
|
|
|
3351 |
global.ActiveXObject = xhr.GlobalActiveXObject;
|
|
|
3352 |
}
|
|
|
3353 |
|
|
|
3354 |
delete sinon.FakeXMLHttpRequest.restore;
|
|
|
3355 |
|
|
|
3356 |
if (keepOnCreate !== true) {
|
|
|
3357 |
delete sinon.FakeXMLHttpRequest.onCreate;
|
|
|
3358 |
}
|
|
|
3359 |
};
|
|
|
3360 |
if (xhr.supportsXHR) {
|
|
|
3361 |
global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
|
|
|
3362 |
}
|
|
|
3363 |
|
|
|
3364 |
if (xhr.supportsActiveX) {
|
|
|
3365 |
global.ActiveXObject = function ActiveXObject(objId) {
|
|
|
3366 |
if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
|
|
|
3367 |
|
|
|
3368 |
return new sinon.FakeXMLHttpRequest();
|
|
|
3369 |
}
|
|
|
3370 |
|
|
|
3371 |
return new xhr.GlobalActiveXObject(objId);
|
|
|
3372 |
};
|
|
|
3373 |
}
|
|
|
3374 |
|
|
|
3375 |
return sinon.FakeXMLHttpRequest;
|
|
|
3376 |
};
|
|
|
3377 |
|
|
|
3378 |
sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
|
|
|
3379 |
})(this);
|
|
|
3380 |
|
|
|
3381 |
if (typeof module == "object" && typeof require == "function") {
|
|
|
3382 |
module.exports = sinon;
|
|
|
3383 |
}
|
|
|
3384 |
|
|
|
3385 |
/**
|
|
|
3386 |
* @depend fake_xml_http_request.js
|
|
|
3387 |
*/
|
|
|
3388 |
/*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
|
|
|
3389 |
/*global module, require, window*/
|
|
|
3390 |
/**
|
|
|
3391 |
* The Sinon "server" mimics a web server that receives requests from
|
|
|
3392 |
* sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
|
|
|
3393 |
* both synchronously and asynchronously. To respond synchronuously, canned
|
|
|
3394 |
* answers have to be provided upfront.
|
|
|
3395 |
*
|
|
|
3396 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
3397 |
* @license BSD
|
|
|
3398 |
*
|
|
|
3399 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
3400 |
*/
|
|
|
3401 |
|
|
|
3402 |
if (typeof sinon == "undefined") {
|
|
|
3403 |
var sinon = {};
|
|
|
3404 |
}
|
|
|
3405 |
|
|
|
3406 |
sinon.fakeServer = (function () {
|
|
|
3407 |
var push = [].push;
|
|
|
3408 |
function F() {}
|
|
|
3409 |
|
|
|
3410 |
function create(proto) {
|
|
|
3411 |
F.prototype = proto;
|
|
|
3412 |
return new F();
|
|
|
3413 |
}
|
|
|
3414 |
|
|
|
3415 |
function responseArray(handler) {
|
|
|
3416 |
var response = handler;
|
|
|
3417 |
|
|
|
3418 |
if (Object.prototype.toString.call(handler) != "[object Array]") {
|
|
|
3419 |
response = [200, {}, handler];
|
|
|
3420 |
}
|
|
|
3421 |
|
|
|
3422 |
if (typeof response[2] != "string") {
|
|
|
3423 |
throw new TypeError("Fake server response body should be string, but was " +
|
|
|
3424 |
typeof response[2]);
|
|
|
3425 |
}
|
|
|
3426 |
|
|
|
3427 |
return response;
|
|
|
3428 |
}
|
|
|
3429 |
|
|
|
3430 |
var wloc = typeof window !== "undefined" ? window.location : {};
|
|
|
3431 |
var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
|
|
|
3432 |
|
|
|
3433 |
function matchOne(response, reqMethod, reqUrl) {
|
|
|
3434 |
var rmeth = response.method;
|
|
|
3435 |
var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
|
|
|
3436 |
var url = response.url;
|
|
|
3437 |
var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
|
|
|
3438 |
|
|
|
3439 |
return matchMethod && matchUrl;
|
|
|
3440 |
}
|
|
|
3441 |
|
|
|
3442 |
function match(response, request) {
|
|
|
3443 |
var requestMethod = this.getHTTPMethod(request);
|
|
|
3444 |
var requestUrl = request.url;
|
|
|
3445 |
|
|
|
3446 |
if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
|
|
|
3447 |
requestUrl = requestUrl.replace(rCurrLoc, "");
|
|
|
3448 |
}
|
|
|
3449 |
|
|
|
3450 |
if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
|
|
|
3451 |
if (typeof response.response == "function") {
|
|
|
3452 |
var ru = response.url;
|
|
|
3453 |
var args = [request].concat(!ru ? [] : requestUrl.match(ru).slice(1));
|
|
|
3454 |
return response.response.apply(response, args);
|
|
|
3455 |
}
|
|
|
3456 |
|
|
|
3457 |
return true;
|
|
|
3458 |
}
|
|
|
3459 |
|
|
|
3460 |
return false;
|
|
|
3461 |
}
|
|
|
3462 |
|
|
|
3463 |
return {
|
|
|
3464 |
create: function () {
|
|
|
3465 |
var server = create(this);
|
|
|
3466 |
this.xhr = sinon.useFakeXMLHttpRequest();
|
|
|
3467 |
server.requests = [];
|
|
|
3468 |
|
|
|
3469 |
this.xhr.onCreate = function (xhrObj) {
|
|
|
3470 |
server.addRequest(xhrObj);
|
|
|
3471 |
};
|
|
|
3472 |
|
|
|
3473 |
return server;
|
|
|
3474 |
},
|
|
|
3475 |
|
|
|
3476 |
addRequest: function addRequest(xhrObj) {
|
|
|
3477 |
var server = this;
|
|
|
3478 |
push.call(this.requests, xhrObj);
|
|
|
3479 |
|
|
|
3480 |
xhrObj.onSend = function () {
|
|
|
3481 |
server.handleRequest(this);
|
|
|
3482 |
};
|
|
|
3483 |
|
|
|
3484 |
if (this.autoRespond && !this.responding) {
|
|
|
3485 |
setTimeout(function () {
|
|
|
3486 |
server.responding = false;
|
|
|
3487 |
server.respond();
|
|
|
3488 |
}, this.autoRespondAfter || 10);
|
|
|
3489 |
|
|
|
3490 |
this.responding = true;
|
|
|
3491 |
}
|
|
|
3492 |
},
|
|
|
3493 |
|
|
|
3494 |
getHTTPMethod: function getHTTPMethod(request) {
|
|
|
3495 |
if (this.fakeHTTPMethods && /post/i.test(request.method)) {
|
|
|
3496 |
var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
|
|
|
3497 |
return !!matches ? matches[1] : request.method;
|
|
|
3498 |
}
|
|
|
3499 |
|
|
|
3500 |
return request.method;
|
|
|
3501 |
},
|
|
|
3502 |
|
|
|
3503 |
handleRequest: function handleRequest(xhr) {
|
|
|
3504 |
if (xhr.async) {
|
|
|
3505 |
if (!this.queue) {
|
|
|
3506 |
this.queue = [];
|
|
|
3507 |
}
|
|
|
3508 |
|
|
|
3509 |
push.call(this.queue, xhr);
|
|
|
3510 |
} else {
|
|
|
3511 |
this.processRequest(xhr);
|
|
|
3512 |
}
|
|
|
3513 |
},
|
|
|
3514 |
|
|
|
3515 |
respondWith: function respondWith(method, url, body) {
|
|
|
3516 |
if (arguments.length == 1 && typeof method != "function") {
|
|
|
3517 |
this.response = responseArray(method);
|
|
|
3518 |
return;
|
|
|
3519 |
}
|
|
|
3520 |
|
|
|
3521 |
if (!this.responses) { this.responses = []; }
|
|
|
3522 |
|
|
|
3523 |
if (arguments.length == 1) {
|
|
|
3524 |
body = method;
|
|
|
3525 |
url = method = null;
|
|
|
3526 |
}
|
|
|
3527 |
|
|
|
3528 |
if (arguments.length == 2) {
|
|
|
3529 |
body = url;
|
|
|
3530 |
url = method;
|
|
|
3531 |
method = null;
|
|
|
3532 |
}
|
|
|
3533 |
|
|
|
3534 |
push.call(this.responses, {
|
|
|
3535 |
method: method,
|
|
|
3536 |
url: url,
|
|
|
3537 |
response: typeof body == "function" ? body : responseArray(body)
|
|
|
3538 |
});
|
|
|
3539 |
},
|
|
|
3540 |
|
|
|
3541 |
respond: function respond() {
|
|
|
3542 |
if (arguments.length > 0) this.respondWith.apply(this, arguments);
|
|
|
3543 |
var queue = this.queue || [];
|
|
|
3544 |
var request;
|
|
|
3545 |
|
|
|
3546 |
while(request = queue.shift()) {
|
|
|
3547 |
this.processRequest(request);
|
|
|
3548 |
}
|
|
|
3549 |
},
|
|
|
3550 |
|
|
|
3551 |
processRequest: function processRequest(request) {
|
|
|
3552 |
try {
|
|
|
3553 |
if (request.aborted) {
|
|
|
3554 |
return;
|
|
|
3555 |
}
|
|
|
3556 |
|
|
|
3557 |
var response = this.response || [404, {}, ""];
|
|
|
3558 |
|
|
|
3559 |
if (this.responses) {
|
|
|
3560 |
for (var i = 0, l = this.responses.length; i < l; i++) {
|
|
|
3561 |
if (match.call(this, this.responses[i], request)) {
|
|
|
3562 |
response = this.responses[i].response;
|
|
|
3563 |
break;
|
|
|
3564 |
}
|
|
|
3565 |
}
|
|
|
3566 |
}
|
|
|
3567 |
|
|
|
3568 |
if (request.readyState != 4) {
|
|
|
3569 |
request.respond(response[0], response[1], response[2]);
|
|
|
3570 |
}
|
|
|
3571 |
} catch (e) {
|
|
|
3572 |
sinon.logError("Fake server request processing", e);
|
|
|
3573 |
}
|
|
|
3574 |
},
|
|
|
3575 |
|
|
|
3576 |
restore: function restore() {
|
|
|
3577 |
return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
|
|
|
3578 |
}
|
|
|
3579 |
};
|
|
|
3580 |
}());
|
|
|
3581 |
|
|
|
3582 |
if (typeof module == "object" && typeof require == "function") {
|
|
|
3583 |
module.exports = sinon;
|
|
|
3584 |
}
|
|
|
3585 |
|
|
|
3586 |
/**
|
|
|
3587 |
* @depend fake_server.js
|
|
|
3588 |
* @depend fake_timers.js
|
|
|
3589 |
*/
|
|
|
3590 |
/*jslint browser: true, eqeqeq: false, onevar: false*/
|
|
|
3591 |
/*global sinon*/
|
|
|
3592 |
/**
|
|
|
3593 |
* Add-on for sinon.fakeServer that automatically handles a fake timer along with
|
|
|
3594 |
* the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
|
|
|
3595 |
* 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
|
|
|
3596 |
* it polls the object for completion with setInterval. Dispite the direct
|
|
|
3597 |
* motivation, there is nothing jQuery-specific in this file, so it can be used
|
|
|
3598 |
* in any environment where the ajax implementation depends on setInterval or
|
|
|
3599 |
* setTimeout.
|
|
|
3600 |
*
|
|
|
3601 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
3602 |
* @license BSD
|
|
|
3603 |
*
|
|
|
3604 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
3605 |
*/
|
|
|
3606 |
|
|
|
3607 |
(function () {
|
|
|
3608 |
function Server() {}
|
|
|
3609 |
Server.prototype = sinon.fakeServer;
|
|
|
3610 |
|
|
|
3611 |
sinon.fakeServerWithClock = new Server();
|
|
|
3612 |
|
|
|
3613 |
sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
|
|
|
3614 |
if (xhr.async) {
|
|
|
3615 |
if (typeof setTimeout.clock == "object") {
|
|
|
3616 |
this.clock = setTimeout.clock;
|
|
|
3617 |
} else {
|
|
|
3618 |
this.clock = sinon.useFakeTimers();
|
|
|
3619 |
this.resetClock = true;
|
|
|
3620 |
}
|
|
|
3621 |
|
|
|
3622 |
if (!this.longestTimeout) {
|
|
|
3623 |
var clockSetTimeout = this.clock.setTimeout;
|
|
|
3624 |
var clockSetInterval = this.clock.setInterval;
|
|
|
3625 |
var server = this;
|
|
|
3626 |
|
|
|
3627 |
this.clock.setTimeout = function (fn, timeout) {
|
|
|
3628 |
server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
|
|
|
3629 |
|
|
|
3630 |
return clockSetTimeout.apply(this, arguments);
|
|
|
3631 |
};
|
|
|
3632 |
|
|
|
3633 |
this.clock.setInterval = function (fn, timeout) {
|
|
|
3634 |
server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
|
|
|
3635 |
|
|
|
3636 |
return clockSetInterval.apply(this, arguments);
|
|
|
3637 |
};
|
|
|
3638 |
}
|
|
|
3639 |
}
|
|
|
3640 |
|
|
|
3641 |
return sinon.fakeServer.addRequest.call(this, xhr);
|
|
|
3642 |
};
|
|
|
3643 |
|
|
|
3644 |
sinon.fakeServerWithClock.respond = function respond() {
|
|
|
3645 |
var returnVal = sinon.fakeServer.respond.apply(this, arguments);
|
|
|
3646 |
|
|
|
3647 |
if (this.clock) {
|
|
|
3648 |
this.clock.tick(this.longestTimeout || 0);
|
|
|
3649 |
this.longestTimeout = 0;
|
|
|
3650 |
|
|
|
3651 |
if (this.resetClock) {
|
|
|
3652 |
this.clock.restore();
|
|
|
3653 |
this.resetClock = false;
|
|
|
3654 |
}
|
|
|
3655 |
}
|
|
|
3656 |
|
|
|
3657 |
return returnVal;
|
|
|
3658 |
};
|
|
|
3659 |
|
|
|
3660 |
sinon.fakeServerWithClock.restore = function restore() {
|
|
|
3661 |
if (this.clock) {
|
|
|
3662 |
this.clock.restore();
|
|
|
3663 |
}
|
|
|
3664 |
|
|
|
3665 |
return sinon.fakeServer.restore.apply(this, arguments);
|
|
|
3666 |
};
|
|
|
3667 |
}());
|
|
|
3668 |
|
|
|
3669 |
/**
|
|
|
3670 |
* @depend ../sinon.js
|
|
|
3671 |
* @depend collection.js
|
|
|
3672 |
* @depend util/fake_timers.js
|
|
|
3673 |
* @depend util/fake_server_with_clock.js
|
|
|
3674 |
*/
|
|
|
3675 |
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
|
|
|
3676 |
/*global require, module*/
|
|
|
3677 |
/**
|
|
|
3678 |
* Manages fake collections as well as fake utilities such as Sinon's
|
|
|
3679 |
* timers and fake XHR implementation in one convenient object.
|
|
|
3680 |
*
|
|
|
3681 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
3682 |
* @license BSD
|
|
|
3683 |
*
|
|
|
3684 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
3685 |
*/
|
|
|
3686 |
|
|
|
3687 |
if (typeof module == "object" && typeof require == "function") {
|
|
|
3688 |
var sinon = require("../sinon");
|
|
|
3689 |
sinon.extend(sinon, require("./util/fake_timers"));
|
|
|
3690 |
}
|
|
|
3691 |
|
|
|
3692 |
(function () {
|
|
|
3693 |
var push = [].push;
|
|
|
3694 |
|
|
|
3695 |
function exposeValue(sandbox, config, key, value) {
|
|
|
3696 |
if (!value) {
|
|
|
3697 |
return;
|
|
|
3698 |
}
|
|
|
3699 |
|
|
|
3700 |
if (config.injectInto) {
|
|
|
3701 |
config.injectInto[key] = value;
|
|
|
3702 |
} else {
|
|
|
3703 |
push.call(sandbox.args, value);
|
|
|
3704 |
}
|
|
|
3705 |
}
|
|
|
3706 |
|
|
|
3707 |
function prepareSandboxFromConfig(config) {
|
|
|
3708 |
var sandbox = sinon.create(sinon.sandbox);
|
|
|
3709 |
|
|
|
3710 |
if (config.useFakeServer) {
|
|
|
3711 |
if (typeof config.useFakeServer == "object") {
|
|
|
3712 |
sandbox.serverPrototype = config.useFakeServer;
|
|
|
3713 |
}
|
|
|
3714 |
|
|
|
3715 |
sandbox.useFakeServer();
|
|
|
3716 |
}
|
|
|
3717 |
|
|
|
3718 |
if (config.useFakeTimers) {
|
|
|
3719 |
if (typeof config.useFakeTimers == "object") {
|
|
|
3720 |
sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
|
|
|
3721 |
} else {
|
|
|
3722 |
sandbox.useFakeTimers();
|
|
|
3723 |
}
|
|
|
3724 |
}
|
|
|
3725 |
|
|
|
3726 |
return sandbox;
|
|
|
3727 |
}
|
|
|
3728 |
|
|
|
3729 |
sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
|
|
|
3730 |
useFakeTimers: function useFakeTimers() {
|
|
|
3731 |
this.clock = sinon.useFakeTimers.apply(sinon, arguments);
|
|
|
3732 |
|
|
|
3733 |
return this.add(this.clock);
|
|
|
3734 |
},
|
|
|
3735 |
|
|
|
3736 |
serverPrototype: sinon.fakeServer,
|
|
|
3737 |
|
|
|
3738 |
useFakeServer: function useFakeServer() {
|
|
|
3739 |
var proto = this.serverPrototype || sinon.fakeServer;
|
|
|
3740 |
|
|
|
3741 |
if (!proto || !proto.create) {
|
|
|
3742 |
return null;
|
|
|
3743 |
}
|
|
|
3744 |
|
|
|
3745 |
this.server = proto.create();
|
|
|
3746 |
return this.add(this.server);
|
|
|
3747 |
},
|
|
|
3748 |
|
|
|
3749 |
inject: function (obj) {
|
|
|
3750 |
sinon.collection.inject.call(this, obj);
|
|
|
3751 |
|
|
|
3752 |
if (this.clock) {
|
|
|
3753 |
obj.clock = this.clock;
|
|
|
3754 |
}
|
|
|
3755 |
|
|
|
3756 |
if (this.server) {
|
|
|
3757 |
obj.server = this.server;
|
|
|
3758 |
obj.requests = this.server.requests;
|
|
|
3759 |
}
|
|
|
3760 |
|
|
|
3761 |
return obj;
|
|
|
3762 |
},
|
|
|
3763 |
|
|
|
3764 |
create: function (config) {
|
|
|
3765 |
if (!config) {
|
|
|
3766 |
return sinon.create(sinon.sandbox);
|
|
|
3767 |
}
|
|
|
3768 |
|
|
|
3769 |
var sandbox = prepareSandboxFromConfig(config);
|
|
|
3770 |
sandbox.args = sandbox.args || [];
|
|
|
3771 |
var prop, value, exposed = sandbox.inject({});
|
|
|
3772 |
|
|
|
3773 |
if (config.properties) {
|
|
|
3774 |
for (var i = 0, l = config.properties.length; i < l; i++) {
|
|
|
3775 |
prop = config.properties[i];
|
|
|
3776 |
value = exposed[prop] || prop == "sandbox" && sandbox;
|
|
|
3777 |
exposeValue(sandbox, config, prop, value);
|
|
|
3778 |
}
|
|
|
3779 |
} else {
|
|
|
3780 |
exposeValue(sandbox, config, "sandbox", value);
|
|
|
3781 |
}
|
|
|
3782 |
|
|
|
3783 |
return sandbox;
|
|
|
3784 |
}
|
|
|
3785 |
});
|
|
|
3786 |
|
|
|
3787 |
sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
|
|
|
3788 |
|
|
|
3789 |
if (typeof module == "object" && typeof require == "function") {
|
|
|
3790 |
module.exports = sinon.sandbox;
|
|
|
3791 |
}
|
|
|
3792 |
}());
|
|
|
3793 |
|
|
|
3794 |
/**
|
|
|
3795 |
* @depend ../sinon.js
|
|
|
3796 |
* @depend stub.js
|
|
|
3797 |
* @depend mock.js
|
|
|
3798 |
* @depend sandbox.js
|
|
|
3799 |
*/
|
|
|
3800 |
/*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
|
|
|
3801 |
/*global module, require, sinon*/
|
|
|
3802 |
/**
|
|
|
3803 |
* Test function, sandboxes fakes
|
|
|
3804 |
*
|
|
|
3805 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
3806 |
* @license BSD
|
|
|
3807 |
*
|
|
|
3808 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
3809 |
*/
|
|
|
3810 |
|
|
|
3811 |
(function (sinon) {
|
|
|
3812 |
var commonJSModule = typeof module == "object" && typeof require == "function";
|
|
|
3813 |
|
|
|
3814 |
if (!sinon && commonJSModule) {
|
|
|
3815 |
sinon = require("../sinon");
|
|
|
3816 |
}
|
|
|
3817 |
|
|
|
3818 |
if (!sinon) {
|
|
|
3819 |
return;
|
|
|
3820 |
}
|
|
|
3821 |
|
|
|
3822 |
function test(callback) {
|
|
|
3823 |
var type = typeof callback;
|
|
|
3824 |
|
|
|
3825 |
if (type != "function") {
|
|
|
3826 |
throw new TypeError("sinon.test needs to wrap a test function, got " + type);
|
|
|
3827 |
}
|
|
|
3828 |
|
|
|
3829 |
return function () {
|
|
|
3830 |
var config = sinon.getConfig(sinon.config);
|
|
|
3831 |
config.injectInto = config.injectIntoThis && this || config.injectInto;
|
|
|
3832 |
var sandbox = sinon.sandbox.create(config);
|
|
|
3833 |
var exception, result;
|
|
|
3834 |
var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
|
|
|
3835 |
|
|
|
3836 |
try {
|
|
|
3837 |
result = callback.apply(this, args);
|
|
|
3838 |
} catch (e) {
|
|
|
3839 |
exception = e;
|
|
|
3840 |
}
|
|
|
3841 |
|
|
|
3842 |
if (typeof exception !== "undefined") {
|
|
|
3843 |
sandbox.restore();
|
|
|
3844 |
throw exception;
|
|
|
3845 |
}
|
|
|
3846 |
else {
|
|
|
3847 |
sandbox.verifyAndRestore();
|
|
|
3848 |
}
|
|
|
3849 |
|
|
|
3850 |
return result;
|
|
|
3851 |
};
|
|
|
3852 |
}
|
|
|
3853 |
|
|
|
3854 |
test.config = {
|
|
|
3855 |
injectIntoThis: true,
|
|
|
3856 |
injectInto: null,
|
|
|
3857 |
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
|
|
|
3858 |
useFakeTimers: true,
|
|
|
3859 |
useFakeServer: true
|
|
|
3860 |
};
|
|
|
3861 |
|
|
|
3862 |
if (commonJSModule) {
|
|
|
3863 |
module.exports = test;
|
|
|
3864 |
} else {
|
|
|
3865 |
sinon.test = test;
|
|
|
3866 |
}
|
|
|
3867 |
}(typeof sinon == "object" && sinon || null));
|
|
|
3868 |
|
|
|
3869 |
/**
|
|
|
3870 |
* @depend ../sinon.js
|
|
|
3871 |
* @depend test.js
|
|
|
3872 |
*/
|
|
|
3873 |
/*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
|
|
|
3874 |
/*global module, require, sinon*/
|
|
|
3875 |
/**
|
|
|
3876 |
* Test case, sandboxes all test functions
|
|
|
3877 |
*
|
|
|
3878 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
3879 |
* @license BSD
|
|
|
3880 |
*
|
|
|
3881 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
3882 |
*/
|
|
|
3883 |
|
|
|
3884 |
(function (sinon) {
|
|
|
3885 |
var commonJSModule = typeof module == "object" && typeof require == "function";
|
|
|
3886 |
|
|
|
3887 |
if (!sinon && commonJSModule) {
|
|
|
3888 |
sinon = require("../sinon");
|
|
|
3889 |
}
|
|
|
3890 |
|
|
|
3891 |
if (!sinon || !Object.prototype.hasOwnProperty) {
|
|
|
3892 |
return;
|
|
|
3893 |
}
|
|
|
3894 |
|
|
|
3895 |
function createTest(property, setUp, tearDown) {
|
|
|
3896 |
return function () {
|
|
|
3897 |
if (setUp) {
|
|
|
3898 |
setUp.apply(this, arguments);
|
|
|
3899 |
}
|
|
|
3900 |
|
|
|
3901 |
var exception, result;
|
|
|
3902 |
|
|
|
3903 |
try {
|
|
|
3904 |
result = property.apply(this, arguments);
|
|
|
3905 |
} catch (e) {
|
|
|
3906 |
exception = e;
|
|
|
3907 |
}
|
|
|
3908 |
|
|
|
3909 |
if (tearDown) {
|
|
|
3910 |
tearDown.apply(this, arguments);
|
|
|
3911 |
}
|
|
|
3912 |
|
|
|
3913 |
if (exception) {
|
|
|
3914 |
throw exception;
|
|
|
3915 |
}
|
|
|
3916 |
|
|
|
3917 |
return result;
|
|
|
3918 |
};
|
|
|
3919 |
}
|
|
|
3920 |
|
|
|
3921 |
function testCase(tests, prefix) {
|
|
|
3922 |
/*jsl:ignore*/
|
|
|
3923 |
if (!tests || typeof tests != "object") {
|
|
|
3924 |
throw new TypeError("sinon.testCase needs an object with test functions");
|
|
|
3925 |
}
|
|
|
3926 |
/*jsl:end*/
|
|
|
3927 |
|
|
|
3928 |
prefix = prefix || "test";
|
|
|
3929 |
var rPrefix = new RegExp("^" + prefix);
|
|
|
3930 |
var methods = {}, testName, property, method;
|
|
|
3931 |
var setUp = tests.setUp;
|
|
|
3932 |
var tearDown = tests.tearDown;
|
|
|
3933 |
|
|
|
3934 |
for (testName in tests) {
|
|
|
3935 |
if (tests.hasOwnProperty(testName)) {
|
|
|
3936 |
property = tests[testName];
|
|
|
3937 |
|
|
|
3938 |
if (/^(setUp|tearDown)$/.test(testName)) {
|
|
|
3939 |
continue;
|
|
|
3940 |
}
|
|
|
3941 |
|
|
|
3942 |
if (typeof property == "function" && rPrefix.test(testName)) {
|
|
|
3943 |
method = property;
|
|
|
3944 |
|
|
|
3945 |
if (setUp || tearDown) {
|
|
|
3946 |
method = createTest(property, setUp, tearDown);
|
|
|
3947 |
}
|
|
|
3948 |
|
|
|
3949 |
methods[testName] = sinon.test(method);
|
|
|
3950 |
} else {
|
|
|
3951 |
methods[testName] = tests[testName];
|
|
|
3952 |
}
|
|
|
3953 |
}
|
|
|
3954 |
}
|
|
|
3955 |
|
|
|
3956 |
return methods;
|
|
|
3957 |
}
|
|
|
3958 |
|
|
|
3959 |
if (commonJSModule) {
|
|
|
3960 |
module.exports = testCase;
|
|
|
3961 |
} else {
|
|
|
3962 |
sinon.testCase = testCase;
|
|
|
3963 |
}
|
|
|
3964 |
}(typeof sinon == "object" && sinon || null));
|
|
|
3965 |
|
|
|
3966 |
/**
|
|
|
3967 |
* @depend ../sinon.js
|
|
|
3968 |
* @depend stub.js
|
|
|
3969 |
*/
|
|
|
3970 |
/*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
|
|
|
3971 |
/*global module, require, sinon*/
|
|
|
3972 |
/**
|
|
|
3973 |
* Assertions matching the test spy retrieval interface.
|
|
|
3974 |
*
|
|
|
3975 |
* @author Christian Johansen (christian@cjohansen.no)
|
|
|
3976 |
* @license BSD
|
|
|
3977 |
*
|
|
|
3978 |
* Copyright (c) 2010-2011 Christian Johansen
|
|
|
3979 |
*/
|
|
|
3980 |
|
|
|
3981 |
(function (sinon, global) {
|
|
|
3982 |
var commonJSModule = typeof module == "object" && typeof require == "function";
|
|
|
3983 |
var slice = Array.prototype.slice;
|
|
|
3984 |
var assert;
|
|
|
3985 |
|
|
|
3986 |
if (!sinon && commonJSModule) {
|
|
|
3987 |
sinon = require("../sinon");
|
|
|
3988 |
}
|
|
|
3989 |
|
|
|
3990 |
if (!sinon) {
|
|
|
3991 |
return;
|
|
|
3992 |
}
|
|
|
3993 |
|
|
|
3994 |
function verifyIsStub() {
|
|
|
3995 |
var method;
|
|
|
3996 |
|
|
|
3997 |
for (var i = 0, l = arguments.length; i < l; ++i) {
|
|
|
3998 |
method = arguments[i];
|
|
|
3999 |
|
|
|
4000 |
if (!method) {
|
|
|
4001 |
assert.fail("fake is not a spy");
|
|
|
4002 |
}
|
|
|
4003 |
|
|
|
4004 |
if (typeof method != "function") {
|
|
|
4005 |
assert.fail(method + " is not a function");
|
|
|
4006 |
}
|
|
|
4007 |
|
|
|
4008 |
if (typeof method.getCall != "function") {
|
|
|
4009 |
assert.fail(method + " is not stubbed");
|
|
|
4010 |
}
|
|
|
4011 |
}
|
|
|
4012 |
}
|
|
|
4013 |
|
|
|
4014 |
function failAssertion(object, msg) {
|
|
|
4015 |
object = object || global;
|
|
|
4016 |
var failMethod = object.fail || assert.fail;
|
|
|
4017 |
failMethod.call(object, msg);
|
|
|
4018 |
}
|
|
|
4019 |
|
|
|
4020 |
function mirrorPropAsAssertion(name, method, message) {
|
|
|
4021 |
if (arguments.length == 2) {
|
|
|
4022 |
message = method;
|
|
|
4023 |
method = name;
|
|
|
4024 |
}
|
|
|
4025 |
|
|
|
4026 |
assert[name] = function (fake) {
|
|
|
4027 |
verifyIsStub(fake);
|
|
|
4028 |
|
|
|
4029 |
var args = slice.call(arguments, 1);
|
|
|
4030 |
var failed = false;
|
|
|
4031 |
|
|
|
4032 |
if (typeof method == "function") {
|
|
|
4033 |
failed = !method(fake);
|
|
|
4034 |
} else {
|
|
|
4035 |
failed = typeof fake[method] == "function" ?
|
|
|
4036 |
!fake[method].apply(fake, args) : !fake[method];
|
|
|
4037 |
}
|
|
|
4038 |
|
|
|
4039 |
if (failed) {
|
|
|
4040 |
failAssertion(this, fake.printf.apply(fake, [message].concat(args)));
|
|
|
4041 |
} else {
|
|
|
4042 |
assert.pass(name);
|
|
|
4043 |
}
|
|
|
4044 |
};
|
|
|
4045 |
}
|
|
|
4046 |
|
|
|
4047 |
function exposedName(prefix, prop) {
|
|
|
4048 |
return !prefix || /^fail/.test(prop) ? prop :
|
|
|
4049 |
prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
|
|
|
4050 |
};
|
|
|
4051 |
|
|
|
4052 |
assert = {
|
|
|
4053 |
failException: "AssertError",
|
|
|
4054 |
|
|
|
4055 |
fail: function fail(message) {
|
|
|
4056 |
var error = new Error(message);
|
|
|
4057 |
error.name = this.failException || assert.failException;
|
|
|
4058 |
|
|
|
4059 |
throw error;
|
|
|
4060 |
},
|
|
|
4061 |
|
|
|
4062 |
pass: function pass(assertion) {},
|
|
|
4063 |
|
|
|
4064 |
callOrder: function assertCallOrder() {
|
|
|
4065 |
verifyIsStub.apply(null, arguments);
|
|
|
4066 |
var expected = "", actual = "";
|
|
|
4067 |
|
|
|
4068 |
if (!sinon.calledInOrder(arguments)) {
|
|
|
4069 |
try {
|
|
|
4070 |
expected = [].join.call(arguments, ", ");
|
|
|
4071 |
actual = sinon.orderByFirstCall(slice.call(arguments)).join(", ");
|
|
|
4072 |
} catch (e) {
|
|
|
4073 |
// If this fails, we'll just fall back to the blank string
|
|
|
4074 |
}
|
|
|
4075 |
|
|
|
4076 |
failAssertion(this, "expected " + expected + " to be " +
|
|
|
4077 |
"called in order but were called as " + actual);
|
|
|
4078 |
} else {
|
|
|
4079 |
assert.pass("callOrder");
|
|
|
4080 |
}
|
|
|
4081 |
},
|
|
|
4082 |
|
|
|
4083 |
callCount: function assertCallCount(method, count) {
|
|
|
4084 |
verifyIsStub(method);
|
|
|
4085 |
|
|
|
4086 |
if (method.callCount != count) {
|
|
|
4087 |
var msg = "expected %n to be called " + sinon.timesInWords(count) +
|
|
|
4088 |
" but was called %c%C";
|
|
|
4089 |
failAssertion(this, method.printf(msg));
|
|
|
4090 |
} else {
|
|
|
4091 |
assert.pass("callCount");
|
|
|
4092 |
}
|
|
|
4093 |
},
|
|
|
4094 |
|
|
|
4095 |
expose: function expose(target, options) {
|
|
|
4096 |
if (!target) {
|
|
|
4097 |
throw new TypeError("target is null or undefined");
|
|
|
4098 |
}
|
|
|
4099 |
|
|
|
4100 |
var o = options || {};
|
|
|
4101 |
var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
|
|
|
4102 |
var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
|
|
|
4103 |
|
|
|
4104 |
for (var method in this) {
|
|
|
4105 |
if (method != "export" && (includeFail || !/^(fail)/.test(method))) {
|
|
|
4106 |
target[exposedName(prefix, method)] = this[method];
|
|
|
4107 |
}
|
|
|
4108 |
}
|
|
|
4109 |
|
|
|
4110 |
return target;
|
|
|
4111 |
}
|
|
|
4112 |
};
|
|
|
4113 |
|
|
|
4114 |
mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
|
|
|
4115 |
mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
|
|
|
4116 |
"expected %n to not have been called but was called %c%C");
|
|
|
4117 |
mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
|
|
|
4118 |
mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
|
|
|
4119 |
mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
|
|
|
4120 |
mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
|
|
|
4121 |
mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
|
|
|
4122 |
mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
|
|
|
4123 |
mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
|
|
|
4124 |
mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
|
|
|
4125 |
mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
|
|
|
4126 |
mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
|
|
|
4127 |
mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
|
|
|
4128 |
mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
|
|
|
4129 |
mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
|
|
|
4130 |
mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
|
|
|
4131 |
mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
|
|
|
4132 |
mirrorPropAsAssertion("threw", "%n did not throw exception%C");
|
|
|
4133 |
mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
|
|
|
4134 |
|
|
|
4135 |
if (commonJSModule) {
|
|
|
4136 |
module.exports = assert;
|
|
|
4137 |
} else {
|
|
|
4138 |
sinon.assert = assert;
|
|
|
4139 |
}
|
|
|
4140 |
}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : global));
|
|
|
4141 |
|
|
|
4142 |
return sinon;}.call(typeof window != 'undefined' && window || {}));
|