Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

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