konacha-chai-matchers 0.1.8 → 0.2.0

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