UNPKG

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