rails-backbone-generator 0.0.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +15 -0
  2. data/README.md +18 -15
  3. data/lib/generators/backbone_generator.rb +1 -1
  4. data/lib/generators/{backbone → backbone_generator}/collection_generator.rb +9 -9
  5. data/lib/generators/{backbone → backbone_generator}/model_generator.rb +10 -10
  6. data/lib/generators/{backbone → backbone_generator}/namespace_generator.rb +18 -21
  7. data/lib/generators/{backbone → backbone_generator}/setup_generator.rb +25 -24
  8. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/Guardfile +4 -4
  9. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/app/assets/javascripts/application.js +7 -7
  10. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/app/assets/javascripts/shared/core_extentions/collections_extentions.coffee +8 -8
  11. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/app/assets/javascripts/shared/helpers/.gitkeep +0 -0
  12. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/app/assets/javascripts/shared/utils/.gitkeep +0 -0
  13. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/spec/javascripts/fixtures/.gitkeep +0 -0
  14. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/spec/javascripts/helpers/association_helpers.coffee +0 -0
  15. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/spec/javascripts/helpers/common_helpers.coffee +2 -2
  16. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/spec/javascripts/helpers/fake_host.coffee +3 -3
  17. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/spec/javascripts/helpers/headless_webkit_helper.coffee +0 -0
  18. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/spec/javascripts/support/jasmine.yml +0 -0
  19. data/lib/generators/backbone_generator/setup_generator/templates/vendor/assets/javascripts/backbone/backbone-1.1.0.js +1581 -0
  20. data/lib/generators/{backbone/setup_generator/templates/vendor/assets/javascripts/backbone/backbone-bind-to-1.0.0.coffee → backbone_generator/setup_generator/templates/vendor/assets/javascripts/backbone/backbone-bind-to-1.1.0.coffee} +23 -12
  21. data/lib/generators/backbone_generator/setup_generator/templates/vendor/assets/javascripts/backbone/backbone-handlebars-1.0.0.coffee +89 -0
  22. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/vendor/assets/javascripts/backbone/backbone-query-0.2.3.coffee +0 -0
  23. data/lib/generators/backbone_generator/setup_generator/templates/vendor/assets/javascripts/backbone/backbone-relational-0.8.6.js +1943 -0
  24. data/lib/generators/backbone_generator/setup_generator/templates/vendor/assets/javascripts/backbone/handlebars-1.1.2.js +2595 -0
  25. data/lib/generators/{backbone/setup_generator/templates/vendor/assets/javascripts/backbone/underscore-1.3.3.js → backbone_generator/setup_generator/templates/vendor/assets/javascripts/backbone/underscore-1.5.2.js} +529 -312
  26. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/vendor/assets/javascripts/browser_compatibility/json2.js +5 -6
  27. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/vendor/assets/javascripts/browser_compatibility/localstorage-polyfill.js +12 -12
  28. data/lib/generators/{backbone/setup_generator/templates/vendor/assets/javascripts/jquery/jquery-1.8.0.js → backbone_generator/setup_generator/templates/vendor/assets/javascripts/jquery/jquery-1.10.2.js} +4633 -4071
  29. data/lib/generators/backbone_generator/setup_generator/templates/vendor/assets/javascripts/jquery/jquery-ui-1.10.3.js +15003 -0
  30. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/vendor/assets/javascripts/jquery/jquery.easing-1.3.js +33 -33
  31. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/vendor/assets/javascripts/jquery/jquery_ujs.js +162 -136
  32. data/lib/generators/{backbone → backbone_generator}/setup_generator/templates/vendor/assets/javascripts/testing/backbone-factory.js +4 -4
  33. data/lib/generators/backbone_generator/setup_generator/templates/vendor/assets/javascripts/testing/jasmine-jquery-1.5.93.js +700 -0
  34. data/lib/generators/backbone_generator/setup_generator/templates/vendor/assets/javascripts/testing/jasmine-sinon-0.2.1.js +43 -0
  35. data/lib/generators/backbone_generator/setup_generator/templates/vendor/assets/javascripts/testing/mock-ajax-2.0.0.js +264 -0
  36. data/lib/generators/{backbone/setup_generator/templates/vendor/assets/javascripts/testing/sinon-1.4.2.js → backbone_generator/setup_generator/templates/vendor/assets/javascripts/testing/sinon-1.7.3.js} +686 -477
  37. data/lib/generators/{backbone → backbone_generator}/templates/app/assets/javascripts/%namespace%.coffee.tt +0 -1
  38. data/lib/generators/{backbone → backbone_generator}/templates/app/assets/javascripts/%namespace%/collections/%collection_name%.coffee.tt +0 -0
  39. data/lib/generators/{backbone → backbone_generator}/templates/app/assets/javascripts/%namespace%/collections/.gitkeep +0 -0
  40. data/lib/generators/{backbone → backbone_generator}/templates/app/assets/javascripts/%namespace%/models/%model_name%.coffee.tt +2 -2
  41. data/lib/generators/{backbone → backbone_generator}/templates/app/assets/javascripts/%namespace%/models/.gitkeep +0 -0
  42. data/lib/generators/{backbone → backbone_generator}/templates/app/assets/javascripts/%namespace%/routes/.gitkeep +0 -0
  43. data/lib/generators/{backbone → backbone_generator}/templates/app/assets/javascripts/%namespace%/templates/.gitkeep +0 -0
  44. data/lib/generators/{backbone → backbone_generator}/templates/app/assets/javascripts/%namespace%/views/.gitkeep +0 -0
  45. data/lib/generators/{backbone → backbone_generator}/templates/spec/javascripts/%namespace%/collections/%collection_name%_spec.coffee.tt +1 -1
  46. data/lib/generators/{backbone → backbone_generator}/templates/spec/javascripts/%namespace%/collections/.gitkeep +0 -0
  47. data/lib/generators/{backbone → backbone_generator}/templates/spec/javascripts/%namespace%/factories/%model_name%_factory.coffee.tt +1 -1
  48. data/lib/generators/{backbone → backbone_generator}/templates/spec/javascripts/%namespace%/factories/.gitkeep +0 -0
  49. data/lib/generators/{backbone → backbone_generator}/templates/spec/javascripts/%namespace%/models/%model_name%_spec.coffee.tt +3 -4
  50. data/lib/generators/{backbone → backbone_generator}/templates/spec/javascripts/%namespace%/models/.gitkeep +0 -0
  51. data/lib/generators/{backbone → backbone_generator}/templates/spec/javascripts/%namespace%/views/.gitkeep +0 -0
  52. data/lib/rails_backbone_generator/version.rb +1 -1
  53. metadata +53 -59
  54. data/lib/generators/backbone/setup_generator/templates/vendor/assets/javascripts/backbone/backbone-0.9.2.js +0 -1431
  55. data/lib/generators/backbone/setup_generator/templates/vendor/assets/javascripts/backbone/backbone-handlebars-1.0.0.js +0 -121
  56. data/lib/generators/backbone/setup_generator/templates/vendor/assets/javascripts/backbone/backbone-relational-0.6.0.js +0 -1687
  57. data/lib/generators/backbone/setup_generator/templates/vendor/assets/javascripts/backbone/handlebars-1.0.rc.1.js +0 -1920
  58. data/lib/generators/backbone/setup_generator/templates/vendor/assets/javascripts/jquery/jquery-ui.min.js +0 -17
  59. data/lib/generators/backbone/setup_generator/templates/vendor/assets/javascripts/testing/jasmine-jquery-1.3.1.js +0 -288
  60. data/lib/generators/backbone/setup_generator/templates/vendor/assets/javascripts/testing/jasmine-sinon.js +0 -43
  61. data/lib/generators/backbone/setup_generator/templates/vendor/assets/javascripts/testing/mock-ajax.js +0 -207
@@ -0,0 +1,43 @@
1
+ /* global jasmine */
2
+
3
+ 'use strict';
4
+
5
+ (function(jasmine, beforeEach) {
6
+
7
+ var spyMatchers = 'called calledOnce calledTwice calledThrice calledBefore calledAfter calledOn alwaysCalledOn calledWith alwaysCalledWith calledWithExactly alwaysCalledWithExactly calledWithMatch alwaysCalledWithMatch'.split(' '),
8
+ i = spyMatchers.length,
9
+ spyMatcherHash = {},
10
+ unusualMatchers = {
11
+ "returned": "toHaveReturned",
12
+ "alwaysReturned": "toHaveAlwaysReturned",
13
+ "threw": "toHaveThrown",
14
+ "alwaysThrew": "toHaveAlwaysThrown"
15
+ },
16
+
17
+ getMatcherFunction = function(sinonName, matcherName) {
18
+ var original = jasmine.Matchers.prototype[matcherName];
19
+ return function () {
20
+ if (jasmine.isSpy(this.actual) && original) {
21
+ return original.apply(this, arguments);
22
+ }
23
+ var sinonProperty = this.actual[sinonName];
24
+ return (typeof sinonProperty === 'function') ? sinonProperty.apply(this.actual, arguments) : sinonProperty;
25
+ };
26
+ };
27
+
28
+ while(i--) {
29
+ var sinonName = spyMatchers[i],
30
+ matcherName = "toHaveBeen" + sinonName.charAt(0).toUpperCase() + sinonName.slice(1);
31
+
32
+ spyMatcherHash[matcherName] = getMatcherFunction(sinonName, matcherName);
33
+ }
34
+
35
+ for (var j in unusualMatchers) {
36
+ spyMatcherHash[unusualMatchers[j]] = getMatcherFunction(j, unusualMatchers[j]);
37
+ }
38
+
39
+ beforeEach(function() {
40
+ this.addMatchers(spyMatcherHash);
41
+ });
42
+
43
+ })(jasmine, beforeEach);
@@ -0,0 +1,264 @@
1
+ /*
2
+
3
+ Jasmine-Ajax : a set of helpers for testing AJAX requests under the Jasmine
4
+ BDD framework for JavaScript.
5
+
6
+ http://github.com/pivotal/jasmine-ajax
7
+
8
+ Jasmine Home page: http://pivotal.github.com/jasmine
9
+
10
+ Copyright (c) 2008-2013 Pivotal Labs
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining
13
+ a copy of this software and associated documentation files (the
14
+ "Software"), to deal in the Software without restriction, including
15
+ without limitation the rights to use, copy, modify, merge, publish,
16
+ distribute, sublicense, and/or sell copies of the Software, and to
17
+ permit persons to whom the Software is furnished to do so, subject to
18
+ the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be
21
+ included in all copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
+
31
+ */
32
+
33
+ (function() {
34
+ function extend(destination, source) {
35
+ for (var property in source) {
36
+ destination[property] = source[property];
37
+ }
38
+ return destination;
39
+ }
40
+
41
+ function MockAjax(global) {
42
+ var requestTracker = new RequestTracker(),
43
+ stubTracker = new StubTracker(),
44
+ realAjaxFunction = global.XMLHttpRequest,
45
+ mockAjaxFunction = fakeRequest(requestTracker, stubTracker);
46
+
47
+ this.install = function() {
48
+ global.XMLHttpRequest = mockAjaxFunction;
49
+ };
50
+
51
+ this.uninstall = function() {
52
+ global.XMLHttpRequest = realAjaxFunction;
53
+
54
+ this.stubs.reset();
55
+ this.requests.reset();
56
+ };
57
+
58
+ this.stubRequest = function(url) {
59
+ var stub = new RequestStub(url);
60
+ stubTracker.addStub(stub);
61
+ return stub;
62
+ };
63
+
64
+ this.withMock = function(closure) {
65
+ this.install();
66
+ try {
67
+ closure();
68
+ } finally {
69
+ this.uninstall();
70
+ }
71
+ };
72
+
73
+ this.requests = requestTracker;
74
+ this.stubs = stubTracker;
75
+ }
76
+
77
+ function StubTracker() {
78
+ var stubs = [];
79
+
80
+ this.addStub = function(stub) {
81
+ stubs.push(stub);
82
+ };
83
+
84
+ this.reset = function() {
85
+ stubs = [];
86
+ };
87
+
88
+ this.findStub = function(url) {
89
+ for (var i = stubs.length - 1; i >= 0; i--) {
90
+ var stub = stubs[i];
91
+ if (stub.url === url) {
92
+ return stub;
93
+ }
94
+ }
95
+ };
96
+ }
97
+
98
+ function fakeRequest(requestTracker, stubTracker) {
99
+ function FakeXMLHttpRequest() {
100
+ requestTracker.track(this);
101
+ this.requestHeaders = {};
102
+ }
103
+
104
+ extend(FakeXMLHttpRequest.prototype, window.XMLHttpRequest);
105
+ extend(FakeXMLHttpRequest.prototype, {
106
+ open: function() {
107
+ this.method = arguments[0];
108
+ this.url = arguments[1];
109
+ this.username = arguments[3];
110
+ this.password = arguments[4];
111
+ this.readyState = 1;
112
+ },
113
+
114
+ setRequestHeader: function(header, value) {
115
+ this.requestHeaders[header] = value;
116
+ },
117
+
118
+ abort: function() {
119
+ this.readyState = 0;
120
+ this.status = 0;
121
+ this.statusText = "abort";
122
+ },
123
+
124
+ readyState: 0,
125
+
126
+ onload: function() {
127
+ },
128
+
129
+ onreadystatechange: function(isTimeout) {
130
+ },
131
+
132
+ status: null,
133
+
134
+ send: function(data) {
135
+ this.params = data;
136
+ this.readyState = 2;
137
+
138
+ var stub = stubTracker.findStub(this.url);
139
+ if (stub) {
140
+ this.response(stub);
141
+ }
142
+ },
143
+
144
+ data: function() {
145
+ var data = {};
146
+ if (typeof this.params !== 'string') { return data; }
147
+ var params = this.params.split('&');
148
+
149
+ for (var i = 0; i < params.length; ++i) {
150
+ var kv = params[i].replace(/\+/g, ' ').split('=');
151
+ var key = decodeURIComponent(kv[0]);
152
+ data[key] = data[key] || [];
153
+ data[key].push(decodeURIComponent(kv[1]));
154
+ data[key].sort();
155
+ }
156
+ return data;
157
+ },
158
+
159
+ getResponseHeader: function(name) {
160
+ return this.responseHeaders[name];
161
+ },
162
+
163
+ getAllResponseHeaders: function() {
164
+ var responseHeaders = [];
165
+ for (var i in this.responseHeaders) {
166
+ if (this.responseHeaders.hasOwnProperty(i)) {
167
+ responseHeaders.push(i + ': ' + this.responseHeaders[i]);
168
+ }
169
+ }
170
+ return responseHeaders.join('\r\n');
171
+ },
172
+
173
+ responseText: null,
174
+
175
+ response: function(response) {
176
+ this.status = response.status;
177
+ this.statusText = response.statusText || "";
178
+ this.responseText = response.responseText || "";
179
+ this.readyState = 4;
180
+ this.responseHeaders = response.responseHeaders ||
181
+ {"Content-type": response.contentType || "application/json" };
182
+
183
+ this.onload();
184
+ this.onreadystatechange();
185
+ },
186
+
187
+ responseTimeout: function() {
188
+ this.readyState = 4;
189
+ jasmine.clock().tick(30000);
190
+ this.onreadystatechange('timeout');
191
+ }
192
+ });
193
+
194
+ return FakeXMLHttpRequest;
195
+ }
196
+
197
+ function RequestTracker() {
198
+ var requests = [];
199
+
200
+ this.track = function(request) {
201
+ requests.push(request);
202
+ };
203
+
204
+ this.first = function() {
205
+ return requests[0];
206
+ };
207
+
208
+ this.count = function() {
209
+ return requests.length;
210
+ };
211
+
212
+ this.reset = function() {
213
+ requests = [];
214
+ };
215
+
216
+ this.mostRecent = function() {
217
+ return requests[requests.length - 1];
218
+ };
219
+
220
+ this.at = function(index) {
221
+ return requests[index];
222
+ };
223
+
224
+ this.filter = function(url_to_match) {
225
+ if (requests.length == 0) return [];
226
+ var matching_requests = [];
227
+
228
+ for (var i = 0; i < requests.length; i++) {
229
+ if (url_to_match instanceof RegExp &&
230
+ url_to_match.test(requests[i].url)) {
231
+ matching_requests.push(requests[i]);
232
+ } else if (url_to_match instanceof Function &&
233
+ url_to_match(requests[i])) {
234
+ matching_requests.push(requests[i]);
235
+ } else {
236
+ if (requests[i].url == url_to_match) {
237
+ matching_requests.push(requests[i]);
238
+ }
239
+ }
240
+ }
241
+
242
+ return matching_requests;
243
+ };
244
+ }
245
+
246
+ function RequestStub(url) {
247
+ this.url = url;
248
+
249
+ this.andReturn = function(options) {
250
+ this.status = options.status || 200;
251
+
252
+ this.contentType = options.contentType;
253
+ this.responseText = options.responseText;
254
+ };
255
+ }
256
+
257
+ if (typeof window === "undefined" && typeof exports === "object") {
258
+ exports.MockAjax = MockAjax;
259
+ jasmine.Ajax = new MockAjax(exports);
260
+ } else {
261
+ window.MockAjax = MockAjax;
262
+ jasmine.Ajax = new MockAjax(window);
263
+ }
264
+ }());
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Sinon.JS 1.4.2, 2012/07/11
2
+ * Sinon.JS 1.7.3, 2013/06/20
3
3
  *
4
4
  * @author Christian Johansen (christian@cjohansen.no)
5
5
  * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
6
6
  *
7
7
  * (The BSD License)
8
8
  *
9
- * Copyright (c) 2010-2012, Christian Johansen, christian@cjohansen.no
9
+ * Copyright (c) 2010-2013, Christian Johansen, christian@cjohansen.no
10
10
  * All rights reserved.
11
11
  *
12
12
  * Redistribution and use in source and binary forms, with or without modification,
@@ -33,8 +33,7 @@
33
33
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
34
  */
35
35
 
36
- "use strict";
37
- var sinon = (function () {
36
+ this.sinon = (function () {
38
37
  var buster = (function (setTimeout, B) {
39
38
  var isNode = typeof require == "function" && typeof module == "object";
40
39
  var div = typeof document != "undefined" && document.createElement("div");
@@ -462,7 +461,7 @@ if (typeof module != "undefined") {
462
461
  * @author Christian Johansen (christian@cjohansen.no)
463
462
  * @license BSD
464
463
  *
465
- * Copyright (c) 2010-2011 Christian Johansen
464
+ * Copyright (c) 2010-2013 Christian Johansen
466
465
  */
467
466
 
468
467
  var sinon = (function (buster) {
@@ -493,7 +492,7 @@ var sinon = (function (buster) {
493
492
  }
494
493
 
495
494
  function isFunction(obj) {
496
- return !!(obj && obj.constructor && obj.call && obj.apply);
495
+ return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
497
496
  }
498
497
 
499
498
  function mirrorProperties(target, source) {
@@ -504,6 +503,10 @@ var sinon = (function (buster) {
504
503
  }
505
504
  }
506
505
 
506
+ function isRestorable (obj) {
507
+ return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
508
+ }
509
+
507
510
  var sinon = {
508
511
  wrapMethod: function wrapMethod(object, property, method) {
509
512
  if (!object) {
@@ -593,6 +596,10 @@ var sinon = (function (buster) {
593
596
  return true;
594
597
  }
595
598
 
599
+ if ((a === null && b !== null) || (a !== null && b === null)) {
600
+ return false;
601
+ }
602
+
596
603
  var aString = Object.prototype.toString.call(a);
597
604
  if (aString != Object.prototype.toString.call(b)) {
598
605
  return false;
@@ -612,6 +619,10 @@ var sinon = (function (buster) {
612
619
  return true;
613
620
  }
614
621
 
622
+ if (aString == "[object Date]") {
623
+ return a.valueOf() === b.valueOf();
624
+ }
625
+
615
626
  var prop, aLength = 0, bLength = 0;
616
627
 
617
628
  for (prop in a) {
@@ -626,11 +637,7 @@ var sinon = (function (buster) {
626
637
  bLength += 1;
627
638
  }
628
639
 
629
- if (aLength != bLength) {
630
- return false;
631
- }
632
-
633
- return true;
640
+ return aLength == bLength;
634
641
  },
635
642
 
636
643
  functionName: function functionName(func) {
@@ -701,7 +708,7 @@ var sinon = (function (buster) {
701
708
 
702
709
  calledInOrder: function (spies) {
703
710
  for (var i = 1, l = spies.length; i < l; i++) {
704
- if (!spies[i - 1].calledBefore(spies[i])) {
711
+ if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
705
712
  return false;
706
713
  }
707
714
  }
@@ -736,10 +743,33 @@ var sinon = (function (buster) {
736
743
 
737
744
  typeOf: function (value) {
738
745
  if (value === null) {
739
- return "null";
746
+ return "null";
747
+ }
748
+ else if (value === undefined) {
749
+ return "undefined";
740
750
  }
741
751
  var string = Object.prototype.toString.call(value);
742
752
  return string.substring(8, string.length - 1).toLowerCase();
753
+ },
754
+
755
+ createStubInstance: function (constructor) {
756
+ if (typeof constructor !== "function") {
757
+ throw new TypeError("The constructor should be a function.");
758
+ }
759
+ return sinon.stub(sinon.create(constructor.prototype));
760
+ },
761
+
762
+ restore: function (object) {
763
+ if (object !== null && typeof object === "object") {
764
+ for (var prop in object) {
765
+ if (isRestorable(object[prop])) {
766
+ object[prop].restore();
767
+ }
768
+ }
769
+ }
770
+ else if (isRestorable(object)) {
771
+ object.restore();
772
+ }
743
773
  }
744
774
  };
745
775
 
@@ -1023,515 +1053,574 @@ var sinon = (function (buster) {
1023
1053
  }(typeof sinon == "object" && sinon || null));
1024
1054
 
1025
1055
  /**
1026
- * @depend ../sinon.js
1027
- * @depend match.js
1028
- */
1056
+ * @depend ../sinon.js
1057
+ * @depend match.js
1058
+ */
1029
1059
  /*jslint eqeqeq: false, onevar: false, plusplus: false*/
1030
1060
  /*global module, require, sinon*/
1031
1061
  /**
1032
- * Spy functions
1033
- *
1034
- * @author Christian Johansen (christian@cjohansen.no)
1035
- * @license BSD
1036
- *
1037
- * Copyright (c) 2010-2011 Christian Johansen
1038
- */
1062
+ * Spy calls
1063
+ *
1064
+ * @author Christian Johansen (christian@cjohansen.no)
1065
+ * @author Maximilian Antoni (mail@maxantoni.de)
1066
+ * @license BSD
1067
+ *
1068
+ * Copyright (c) 2010-2013 Christian Johansen
1069
+ * Copyright (c) 2013 Maximilian Antoni
1070
+ */
1071
+
1072
+ var commonJSModule = typeof module == "object" && typeof require == "function";
1073
+
1074
+ if (!this.sinon && commonJSModule) {
1075
+ var sinon = require("../sinon");
1076
+ }
1039
1077
 
1040
1078
  (function (sinon) {
1041
- var commonJSModule = typeof module == "object" && typeof require == "function";
1042
- var spyCall;
1043
- var callId = 0;
1044
- var push = [].push;
1045
- var slice = Array.prototype.slice;
1046
-
1047
- if (!sinon && commonJSModule) {
1048
- sinon = require("../sinon");
1049
- }
1050
-
1051
- if (!sinon) {
1052
- return;
1079
+ function throwYieldError(proxy, text, args) {
1080
+ var msg = sinon.functionName(proxy) + text;
1081
+ if (args.length) {
1082
+ msg += " Received [" + slice.call(args).join(", ") + "]";
1083
+ }
1084
+ throw new Error(msg);
1053
1085
  }
1054
1086
 
1055
- function spy(object, property) {
1056
- if (!property && typeof object == "function") {
1057
- return spy.create(object);
1058
- }
1087
+ var slice = Array.prototype.slice;
1059
1088
 
1060
- if (!object && !property) {
1061
- return spy.create(function () {});
1062
- }
1089
+ var callProto = {
1090
+ calledOn: function calledOn(thisValue) {
1091
+ if (sinon.match && sinon.match.isMatcher(thisValue)) {
1092
+ return thisValue.test(this.thisValue);
1093
+ }
1094
+ return this.thisValue === thisValue;
1095
+ },
1063
1096
 
1064
- var method = object[property];
1065
- return sinon.wrapMethod(object, property, spy.create(method));
1066
- }
1097
+ calledWith: function calledWith() {
1098
+ for (var i = 0, l = arguments.length; i < l; i += 1) {
1099
+ if (!sinon.deepEqual(arguments[i], this.args[i])) {
1100
+ return false;
1101
+ }
1102
+ }
1067
1103
 
1068
- sinon.extend(spy, (function () {
1104
+ return true;
1105
+ },
1069
1106
 
1070
- function delegateToCalls(api, method, matchAny, actual, notCalled) {
1071
- api[method] = function () {
1072
- if (!this.called) {
1073
- if (notCalled) {
1074
- return notCalled.apply(this, arguments);
1075
- }
1107
+ calledWithMatch: function calledWithMatch() {
1108
+ for (var i = 0, l = arguments.length; i < l; i += 1) {
1109
+ var actual = this.args[i];
1110
+ var expectation = arguments[i];
1111
+ if (!sinon.match || !sinon.match(expectation).test(actual)) {
1076
1112
  return false;
1077
1113
  }
1114
+ }
1115
+ return true;
1116
+ },
1078
1117
 
1079
- var currentCall;
1080
- var matches = 0;
1081
-
1082
- for (var i = 0, l = this.callCount; i < l; i += 1) {
1083
- currentCall = this.getCall(i);
1118
+ calledWithExactly: function calledWithExactly() {
1119
+ return arguments.length == this.args.length &&
1120
+ this.calledWith.apply(this, arguments);
1121
+ },
1084
1122
 
1085
- if (currentCall[actual || method].apply(currentCall, arguments)) {
1086
- matches += 1;
1123
+ notCalledWith: function notCalledWith() {
1124
+ return !this.calledWith.apply(this, arguments);
1125
+ },
1087
1126
 
1088
- if (matchAny) {
1089
- return true;
1090
- }
1091
- }
1092
- }
1127
+ notCalledWithMatch: function notCalledWithMatch() {
1128
+ return !this.calledWithMatch.apply(this, arguments);
1129
+ },
1093
1130
 
1094
- return matches === this.callCount;
1095
- };
1096
- }
1131
+ returned: function returned(value) {
1132
+ return sinon.deepEqual(value, this.returnValue);
1133
+ },
1097
1134
 
1098
- function matchingFake(fakes, args, strict) {
1099
- if (!fakes) {
1100
- return;
1135
+ threw: function threw(error) {
1136
+ if (typeof error === "undefined" || !this.exception) {
1137
+ return !!this.exception;
1101
1138
  }
1102
1139
 
1103
- var alen = args.length;
1140
+ return this.exception === error || this.exception.name === error;
1141
+ },
1104
1142
 
1105
- for (var i = 0, l = fakes.length; i < l; i++) {
1106
- if (fakes[i].matches(args, strict)) {
1107
- return fakes[i];
1108
- }
1109
- }
1110
- }
1143
+ calledWithNew: function calledWithNew(thisValue) {
1144
+ return this.thisValue instanceof this.proxy;
1145
+ },
1111
1146
 
1112
- function incrementCallCount() {
1113
- this.called = true;
1114
- this.callCount += 1;
1115
- this.notCalled = false;
1116
- this.calledOnce = this.callCount == 1;
1117
- this.calledTwice = this.callCount == 2;
1118
- this.calledThrice = this.callCount == 3;
1119
- }
1147
+ calledBefore: function (other) {
1148
+ return this.callId < other.callId;
1149
+ },
1120
1150
 
1121
- function createCallProperties() {
1122
- this.firstCall = this.getCall(0);
1123
- this.secondCall = this.getCall(1);
1124
- this.thirdCall = this.getCall(2);
1125
- this.lastCall = this.getCall(this.callCount - 1);
1126
- }
1151
+ calledAfter: function (other) {
1152
+ return this.callId > other.callId;
1153
+ },
1127
1154
 
1128
- var uuid = 0;
1155
+ callArg: function (pos) {
1156
+ this.args[pos]();
1157
+ },
1129
1158
 
1130
- // Public API
1131
- var spyApi = {
1132
- reset: function () {
1133
- this.called = false;
1134
- this.notCalled = true;
1135
- this.calledOnce = false;
1136
- this.calledTwice = false;
1137
- this.calledThrice = false;
1138
- this.callCount = 0;
1139
- this.firstCall = null;
1140
- this.secondCall = null;
1141
- this.thirdCall = null;
1142
- this.lastCall = null;
1143
- this.args = [];
1144
- this.returnValues = [];
1145
- this.thisValues = [];
1146
- this.exceptions = [];
1147
- this.callIds = [];
1148
- if (this.fakes) {
1149
- for (var i = 0; i < this.fakes.length; i++) {
1150
- this.fakes[i].reset();
1151
- }
1152
- }
1153
- },
1159
+ callArgOn: function (pos, thisValue) {
1160
+ this.args[pos].apply(thisValue);
1161
+ },
1154
1162
 
1155
- create: function create(func) {
1156
- var name;
1163
+ callArgWith: function (pos) {
1164
+ this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
1165
+ },
1157
1166
 
1158
- if (typeof func != "function") {
1159
- func = function () {};
1160
- } else {
1161
- name = sinon.functionName(func);
1162
- }
1167
+ callArgOnWith: function (pos, thisValue) {
1168
+ var args = slice.call(arguments, 2);
1169
+ this.args[pos].apply(thisValue, args);
1170
+ },
1163
1171
 
1164
- function proxy() {
1165
- return proxy.invoke(func, this, slice.call(arguments));
1172
+ "yield": function () {
1173
+ this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
1174
+ },
1175
+
1176
+ yieldOn: function (thisValue) {
1177
+ var args = this.args;
1178
+ for (var i = 0, l = args.length; i < l; ++i) {
1179
+ if (typeof args[i] === "function") {
1180
+ args[i].apply(thisValue, slice.call(arguments, 1));
1181
+ return;
1166
1182
  }
1183
+ }
1184
+ throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
1185
+ },
1167
1186
 
1168
- sinon.extend(proxy, spy);
1169
- delete proxy.create;
1170
- sinon.extend(proxy, func);
1187
+ yieldTo: function (prop) {
1188
+ this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
1189
+ },
1171
1190
 
1172
- proxy.reset();
1173
- proxy.prototype = func.prototype;
1174
- proxy.displayName = name || "spy";
1175
- proxy.toString = sinon.functionToString;
1176
- proxy._create = sinon.spy.create;
1177
- proxy.id = "spy#" + uuid++;
1191
+ yieldToOn: function (prop, thisValue) {
1192
+ var args = this.args;
1193
+ for (var i = 0, l = args.length; i < l; ++i) {
1194
+ if (args[i] && typeof args[i][prop] === "function") {
1195
+ args[i][prop].apply(thisValue, slice.call(arguments, 2));
1196
+ return;
1197
+ }
1198
+ }
1199
+ throwYieldError(this.proxy, " cannot yield to '" + prop +
1200
+ "' since no callback was passed.", args);
1201
+ },
1178
1202
 
1179
- return proxy;
1180
- },
1203
+ toString: function () {
1204
+ var callStr = this.proxy.toString() + "(";
1205
+ var args = [];
1181
1206
 
1182
- invoke: function invoke(func, thisValue, args) {
1183
- var matching = matchingFake(this.fakes, args);
1184
- var exception, returnValue;
1207
+ for (var i = 0, l = this.args.length; i < l; ++i) {
1208
+ args.push(sinon.format(this.args[i]));
1209
+ }
1185
1210
 
1186
- incrementCallCount.call(this);
1187
- push.call(this.thisValues, thisValue);
1188
- push.call(this.args, args);
1189
- push.call(this.callIds, callId++);
1211
+ callStr = callStr + args.join(", ") + ")";
1190
1212
 
1191
- try {
1192
- if (matching) {
1193
- returnValue = matching.invoke(func, thisValue, args);
1194
- } else {
1195
- returnValue = (this.func || func).apply(thisValue, args);
1196
- }
1197
- } catch (e) {
1198
- push.call(this.returnValues, undefined);
1199
- exception = e;
1200
- throw e;
1201
- } finally {
1202
- push.call(this.exceptions, exception);
1203
- }
1213
+ if (typeof this.returnValue != "undefined") {
1214
+ callStr += " => " + sinon.format(this.returnValue);
1215
+ }
1204
1216
 
1205
- push.call(this.returnValues, returnValue);
1217
+ if (this.exception) {
1218
+ callStr += " !" + this.exception.name;
1206
1219
 
1207
- createCallProperties.call(this);
1220
+ if (this.exception.message) {
1221
+ callStr += "(" + this.exception.message + ")";
1222
+ }
1223
+ }
1208
1224
 
1209
- return returnValue;
1210
- },
1225
+ return callStr;
1226
+ }
1227
+ };
1211
1228
 
1212
- getCall: function getCall(i) {
1213
- if (i < 0 || i >= this.callCount) {
1214
- return null;
1215
- }
1229
+ callProto.invokeCallback = callProto.yield;
1216
1230
 
1217
- return spyCall.create(this, this.thisValues[i], this.args[i],
1218
- this.returnValues[i], this.exceptions[i],
1219
- this.callIds[i]);
1220
- },
1231
+ function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
1232
+ if (typeof id !== "number") {
1233
+ throw new TypeError("Call id is not a number");
1234
+ }
1235
+ var proxyCall = sinon.create(callProto);
1236
+ proxyCall.proxy = spy;
1237
+ proxyCall.thisValue = thisValue;
1238
+ proxyCall.args = args;
1239
+ proxyCall.returnValue = returnValue;
1240
+ proxyCall.exception = exception;
1241
+ proxyCall.callId = id;
1242
+
1243
+ return proxyCall;
1244
+ };
1245
+ createSpyCall.toString = callProto.toString; // used by mocks
1221
1246
 
1222
- calledBefore: function calledBefore(spyFn) {
1223
- if (!this.called) {
1224
- return false;
1225
- }
1247
+ sinon.spyCall = createSpyCall;
1248
+ }(typeof sinon == "object" && sinon || null));
1226
1249
 
1227
- if (!spyFn.called) {
1228
- return true;
1229
- }
1250
+ /**
1251
+ * @depend ../sinon.js
1252
+ */
1253
+ /*jslint eqeqeq: false, onevar: false, plusplus: false*/
1254
+ /*global module, require, sinon*/
1255
+ /**
1256
+ * Spy functions
1257
+ *
1258
+ * @author Christian Johansen (christian@cjohansen.no)
1259
+ * @license BSD
1260
+ *
1261
+ * Copyright (c) 2010-2013 Christian Johansen
1262
+ */
1230
1263
 
1231
- return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
1232
- },
1264
+ (function (sinon) {
1265
+ var commonJSModule = typeof module == "object" && typeof require == "function";
1266
+ var push = Array.prototype.push;
1267
+ var slice = Array.prototype.slice;
1268
+ var callId = 0;
1233
1269
 
1234
- calledAfter: function calledAfter(spyFn) {
1235
- if (!this.called || !spyFn.called) {
1236
- return false;
1237
- }
1270
+ function spy(object, property) {
1271
+ if (!property && typeof object == "function") {
1272
+ return spy.create(object);
1273
+ }
1238
1274
 
1239
- return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
1240
- },
1275
+ if (!object && !property) {
1276
+ return spy.create(function () { });
1277
+ }
1241
1278
 
1242
- withArgs: function () {
1243
- var args = slice.call(arguments);
1279
+ var method = object[property];
1280
+ return sinon.wrapMethod(object, property, spy.create(method));
1281
+ }
1244
1282
 
1245
- if (this.fakes) {
1246
- var match = matchingFake(this.fakes, args, true);
1283
+ function matchingFake(fakes, args, strict) {
1284
+ if (!fakes) {
1285
+ return;
1286
+ }
1247
1287
 
1248
- if (match) {
1249
- return match;
1250
- }
1251
- } else {
1252
- this.fakes = [];
1253
- }
1288
+ var alen = args.length;
1254
1289
 
1255
- var original = this;
1256
- var fake = this._create();
1257
- fake.matchingAguments = args;
1258
- push.call(this.fakes, fake);
1290
+ for (var i = 0, l = fakes.length; i < l; i++) {
1291
+ if (fakes[i].matches(args, strict)) {
1292
+ return fakes[i];
1293
+ }
1294
+ }
1295
+ }
1259
1296
 
1260
- fake.withArgs = function () {
1261
- return original.withArgs.apply(original, arguments);
1262
- };
1297
+ function incrementCallCount() {
1298
+ this.called = true;
1299
+ this.callCount += 1;
1300
+ this.notCalled = false;
1301
+ this.calledOnce = this.callCount == 1;
1302
+ this.calledTwice = this.callCount == 2;
1303
+ this.calledThrice = this.callCount == 3;
1304
+ }
1263
1305
 
1264
- for (var i = 0; i < this.args.length; i++) {
1265
- if (fake.matches(this.args[i])) {
1266
- incrementCallCount.call(fake);
1267
- push.call(fake.thisValues, this.thisValues[i]);
1268
- push.call(fake.args, this.args[i]);
1269
- push.call(fake.returnValues, this.returnValues[i]);
1270
- push.call(fake.exceptions, this.exceptions[i]);
1271
- push.call(fake.callIds, this.callIds[i]);
1272
- }
1273
- }
1274
- createCallProperties.call(fake);
1306
+ function createCallProperties() {
1307
+ this.firstCall = this.getCall(0);
1308
+ this.secondCall = this.getCall(1);
1309
+ this.thirdCall = this.getCall(2);
1310
+ this.lastCall = this.getCall(this.callCount - 1);
1311
+ }
1275
1312
 
1276
- return fake;
1277
- },
1313
+ var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
1314
+ function createProxy(func) {
1315
+ // Retain the function length:
1316
+ var p;
1317
+ if (func.length) {
1318
+ eval("p = (function proxy(" + vars.substring(0, func.length * 2 - 1) +
1319
+ ") { return p.invoke(func, this, slice.call(arguments)); });");
1320
+ }
1321
+ else {
1322
+ p = function proxy() {
1323
+ return p.invoke(func, this, slice.call(arguments));
1324
+ };
1325
+ }
1326
+ return p;
1327
+ }
1278
1328
 
1279
- matches: function (args, strict) {
1280
- var margs = this.matchingAguments;
1329
+ var uuid = 0;
1281
1330
 
1282
- if (margs.length <= args.length &&
1283
- sinon.deepEqual(margs, args.slice(0, margs.length))) {
1284
- return !strict || margs.length == args.length;
1331
+ // Public API
1332
+ var spyApi = {
1333
+ reset: function () {
1334
+ this.called = false;
1335
+ this.notCalled = true;
1336
+ this.calledOnce = false;
1337
+ this.calledTwice = false;
1338
+ this.calledThrice = false;
1339
+ this.callCount = 0;
1340
+ this.firstCall = null;
1341
+ this.secondCall = null;
1342
+ this.thirdCall = null;
1343
+ this.lastCall = null;
1344
+ this.args = [];
1345
+ this.returnValues = [];
1346
+ this.thisValues = [];
1347
+ this.exceptions = [];
1348
+ this.callIds = [];
1349
+ if (this.fakes) {
1350
+ for (var i = 0; i < this.fakes.length; i++) {
1351
+ this.fakes[i].reset();
1285
1352
  }
1286
- },
1353
+ }
1354
+ },
1287
1355
 
1288
- printf: function (format) {
1289
- var spy = this;
1290
- var args = slice.call(arguments, 1);
1291
- var formatter;
1356
+ create: function create(func) {
1357
+ var name;
1292
1358
 
1293
- return (format || "").replace(/%(.)/g, function (match, specifyer) {
1294
- formatter = spyApi.formatters[specifyer];
1359
+ if (typeof func != "function") {
1360
+ func = function () { };
1361
+ } else {
1362
+ name = sinon.functionName(func);
1363
+ }
1295
1364
 
1296
- if (typeof formatter == "function") {
1297
- return formatter.call(null, spy, args);
1298
- } else if (!isNaN(parseInt(specifyer), 10)) {
1299
- return sinon.format(args[specifyer - 1]);
1300
- }
1365
+ var proxy = createProxy(func);
1301
1366
 
1302
- return "%" + specifyer;
1303
- });
1304
- }
1305
- };
1367
+ sinon.extend(proxy, spy);
1368
+ delete proxy.create;
1369
+ sinon.extend(proxy, func);
1306
1370
 
1307
- delegateToCalls(spyApi, "calledOn", true);
1308
- delegateToCalls(spyApi, "alwaysCalledOn", false, "calledOn");
1309
- delegateToCalls(spyApi, "calledWith", true);
1310
- delegateToCalls(spyApi, "calledWithMatch", true);
1311
- delegateToCalls(spyApi, "alwaysCalledWith", false, "calledWith");
1312
- delegateToCalls(spyApi, "alwaysCalledWithMatch", false, "calledWithMatch");
1313
- delegateToCalls(spyApi, "calledWithExactly", true);
1314
- delegateToCalls(spyApi, "alwaysCalledWithExactly", false, "calledWithExactly");
1315
- delegateToCalls(spyApi, "neverCalledWith", false, "notCalledWith",
1316
- function () { return true; });
1317
- delegateToCalls(spyApi, "neverCalledWithMatch", false, "notCalledWithMatch",
1318
- function () { return true; });
1319
- delegateToCalls(spyApi, "threw", true);
1320
- delegateToCalls(spyApi, "alwaysThrew", false, "threw");
1321
- delegateToCalls(spyApi, "returned", true);
1322
- delegateToCalls(spyApi, "alwaysReturned", false, "returned");
1323
- delegateToCalls(spyApi, "calledWithNew", true);
1324
- delegateToCalls(spyApi, "alwaysCalledWithNew", false, "calledWithNew");
1325
- delegateToCalls(spyApi, "callArg", false, "callArgWith", function () {
1326
- throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
1327
- });
1328
- spyApi.callArgWith = spyApi.callArg;
1329
- delegateToCalls(spyApi, "yield", false, "yield", function () {
1330
- throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
1331
- });
1332
- // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
1333
- spyApi.invokeCallback = spyApi.yield;
1334
- delegateToCalls(spyApi, "yieldTo", false, "yieldTo", function (property) {
1335
- throw new Error(this.toString() + " cannot yield to '" + property +
1336
- "' since it was not yet invoked.");
1337
- });
1371
+ proxy.reset();
1372
+ proxy.prototype = func.prototype;
1373
+ proxy.displayName = name || "spy";
1374
+ proxy.toString = sinon.functionToString;
1375
+ proxy._create = sinon.spy.create;
1376
+ proxy.id = "spy#" + uuid++;
1338
1377
 
1339
- spyApi.formatters = {
1340
- "c": function (spy) {
1341
- return sinon.timesInWords(spy.callCount);
1342
- },
1378
+ return proxy;
1379
+ },
1343
1380
 
1344
- "n": function (spy) {
1345
- return spy.toString();
1346
- },
1381
+ invoke: function invoke(func, thisValue, args) {
1382
+ var matching = matchingFake(this.fakes, args);
1383
+ var exception, returnValue;
1347
1384
 
1348
- "C": function (spy) {
1349
- var calls = [];
1385
+ incrementCallCount.call(this);
1386
+ push.call(this.thisValues, thisValue);
1387
+ push.call(this.args, args);
1388
+ push.call(this.callIds, callId++);
1350
1389
 
1351
- for (var i = 0, l = spy.callCount; i < l; ++i) {
1352
- push.call(calls, " " + spy.getCall(i).toString());
1390
+ try {
1391
+ if (matching) {
1392
+ returnValue = matching.invoke(func, thisValue, args);
1393
+ } else {
1394
+ returnValue = (this.func || func).apply(thisValue, args);
1353
1395
  }
1396
+ } catch (e) {
1397
+ push.call(this.returnValues, undefined);
1398
+ exception = e;
1399
+ throw e;
1400
+ } finally {
1401
+ push.call(this.exceptions, exception);
1402
+ }
1354
1403
 
1355
- return calls.length > 0 ? "\n" + calls.join("\n") : "";
1356
- },
1357
-
1358
- "t": function (spy) {
1359
- var objects = [];
1404
+ push.call(this.returnValues, returnValue);
1360
1405
 
1361
- for (var i = 0, l = spy.callCount; i < l; ++i) {
1362
- push.call(objects, sinon.format(spy.thisValues[i]));
1363
- }
1406
+ createCallProperties.call(this);
1364
1407
 
1365
- return objects.join(", ");
1366
- },
1408
+ return returnValue;
1409
+ },
1367
1410
 
1368
- "*": function (spy, args) {
1369
- var formatted = [];
1411
+ getCall: function getCall(i) {
1412
+ if (i < 0 || i >= this.callCount) {
1413
+ return null;
1414
+ }
1370
1415
 
1371
- for (var i = 0, l = args.length; i < l; ++i) {
1372
- push.call(formatted, sinon.format(args[i]));
1373
- }
1416
+ return sinon.spyCall(this, this.thisValues[i], this.args[i],
1417
+ this.returnValues[i], this.exceptions[i],
1418
+ this.callIds[i]);
1419
+ },
1374
1420
 
1375
- return formatted.join(", ");
1421
+ calledBefore: function calledBefore(spyFn) {
1422
+ if (!this.called) {
1423
+ return false;
1376
1424
  }
1377
- };
1378
1425
 
1379
- return spyApi;
1380
- }()));
1426
+ if (!spyFn.called) {
1427
+ return true;
1428
+ }
1381
1429
 
1382
- spyCall = (function () {
1430
+ return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
1431
+ },
1383
1432
 
1384
- function throwYieldError(proxy, text, args) {
1385
- var msg = sinon.functionName(proxy) + text;
1386
- if (args.length) {
1387
- msg += " Received [" + slice.call(args).join(", ") + "]";
1433
+ calledAfter: function calledAfter(spyFn) {
1434
+ if (!this.called || !spyFn.called) {
1435
+ return false;
1388
1436
  }
1389
- throw new Error(msg);
1390
- }
1391
1437
 
1392
- return {
1393
- create: function create(spy, thisValue, args, returnValue, exception, id) {
1394
- var proxyCall = sinon.create(spyCall);
1395
- delete proxyCall.create;
1396
- proxyCall.proxy = spy;
1397
- proxyCall.thisValue = thisValue;
1398
- proxyCall.args = args;
1399
- proxyCall.returnValue = returnValue;
1400
- proxyCall.exception = exception;
1401
- proxyCall.callId = typeof id == "number" && id || callId++;
1402
-
1403
- return proxyCall;
1404
- },
1438
+ return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
1439
+ },
1405
1440
 
1406
- calledOn: function calledOn(thisValue) {
1407
- return this.thisValue === thisValue;
1408
- },
1441
+ withArgs: function () {
1442
+ var args = slice.call(arguments);
1409
1443
 
1410
- calledWith: function calledWith() {
1411
- for (var i = 0, l = arguments.length; i < l; i += 1) {
1412
- if (!sinon.deepEqual(arguments[i], this.args[i])) {
1413
- return false;
1414
- }
1444
+ if (this.fakes) {
1445
+ var match = matchingFake(this.fakes, args, true);
1446
+
1447
+ if (match) {
1448
+ return match;
1415
1449
  }
1450
+ } else {
1451
+ this.fakes = [];
1452
+ }
1416
1453
 
1417
- return true;
1418
- },
1454
+ var original = this;
1455
+ var fake = this._create();
1456
+ fake.matchingAguments = args;
1457
+ push.call(this.fakes, fake);
1419
1458
 
1420
- calledWithMatch: function calledWithMatch() {
1421
- for (var i = 0, l = arguments.length; i < l; i += 1) {
1422
- var actual = this.args[i];
1423
- var expectation = arguments[i];
1424
- if (!sinon.match || !sinon.match(expectation).test(actual)) {
1425
- return false;
1426
- }
1427
- }
1428
- return true;
1429
- },
1459
+ fake.withArgs = function () {
1460
+ return original.withArgs.apply(original, arguments);
1461
+ };
1430
1462
 
1431
- calledWithExactly: function calledWithExactly() {
1432
- return arguments.length == this.args.length &&
1433
- this.calledWith.apply(this, arguments);
1434
- },
1463
+ for (var i = 0; i < this.args.length; i++) {
1464
+ if (fake.matches(this.args[i])) {
1465
+ incrementCallCount.call(fake);
1466
+ push.call(fake.thisValues, this.thisValues[i]);
1467
+ push.call(fake.args, this.args[i]);
1468
+ push.call(fake.returnValues, this.returnValues[i]);
1469
+ push.call(fake.exceptions, this.exceptions[i]);
1470
+ push.call(fake.callIds, this.callIds[i]);
1471
+ }
1472
+ }
1473
+ createCallProperties.call(fake);
1435
1474
 
1436
- notCalledWith: function notCalledWith() {
1437
- return !this.calledWith.apply(this, arguments);
1438
- },
1475
+ return fake;
1476
+ },
1439
1477
 
1440
- notCalledWithMatch: function notCalledWithMatch() {
1441
- return !this.calledWithMatch.apply(this, arguments);
1442
- },
1478
+ matches: function (args, strict) {
1479
+ var margs = this.matchingAguments;
1443
1480
 
1444
- returned: function returned(value) {
1445
- return sinon.deepEqual(value, this.returnValue);
1446
- },
1481
+ if (margs.length <= args.length &&
1482
+ sinon.deepEqual(margs, args.slice(0, margs.length))) {
1483
+ return !strict || margs.length == args.length;
1484
+ }
1485
+ },
1447
1486
 
1448
- threw: function threw(error) {
1449
- if (typeof error == "undefined" || !this.exception) {
1450
- return !!this.exception;
1451
- }
1487
+ printf: function (format) {
1488
+ var spy = this;
1489
+ var args = slice.call(arguments, 1);
1490
+ var formatter;
1452
1491
 
1453
- if (typeof error == "string") {
1454
- return this.exception.name == error;
1455
- }
1492
+ return (format || "").replace(/%(.)/g, function (match, specifyer) {
1493
+ formatter = spyApi.formatters[specifyer];
1456
1494
 
1457
- return this.exception === error;
1458
- },
1495
+ if (typeof formatter == "function") {
1496
+ return formatter.call(null, spy, args);
1497
+ } else if (!isNaN(parseInt(specifyer), 10)) {
1498
+ return sinon.format(args[specifyer - 1]);
1499
+ }
1459
1500
 
1460
- calledWithNew: function calledWithNew(thisValue) {
1461
- return this.thisValue instanceof this.proxy;
1462
- },
1501
+ return "%" + specifyer;
1502
+ });
1503
+ }
1504
+ };
1463
1505
 
1464
- calledBefore: function (other) {
1465
- return this.callId < other.callId;
1466
- },
1506
+ function delegateToCalls(method, matchAny, actual, notCalled) {
1507
+ spyApi[method] = function () {
1508
+ if (!this.called) {
1509
+ if (notCalled) {
1510
+ return notCalled.apply(this, arguments);
1511
+ }
1512
+ return false;
1513
+ }
1467
1514
 
1468
- calledAfter: function (other) {
1469
- return this.callId > other.callId;
1470
- },
1515
+ var currentCall;
1516
+ var matches = 0;
1471
1517
 
1472
- callArg: function (pos) {
1473
- this.args[pos]();
1474
- },
1518
+ for (var i = 0, l = this.callCount; i < l; i += 1) {
1519
+ currentCall = this.getCall(i);
1475
1520
 
1476
- callArgWith: function (pos) {
1477
- var args = slice.call(arguments, 1);
1478
- this.args[pos].apply(null, args);
1479
- },
1521
+ if (currentCall[actual || method].apply(currentCall, arguments)) {
1522
+ matches += 1;
1480
1523
 
1481
- "yield": function () {
1482
- var args = this.args;
1483
- for (var i = 0, l = args.length; i < l; ++i) {
1484
- if (typeof args[i] === "function") {
1485
- args[i].apply(null, slice.call(arguments));
1486
- return;
1524
+ if (matchAny) {
1525
+ return true;
1487
1526
  }
1488
1527
  }
1489
- throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
1490
- },
1528
+ }
1491
1529
 
1492
- yieldTo: function (prop) {
1493
- var args = this.args;
1494
- for (var i = 0, l = args.length; i < l; ++i) {
1495
- if (args[i] && typeof args[i][prop] === "function") {
1496
- args[i][prop].apply(null, slice.call(arguments, 1));
1497
- return;
1498
- }
1499
- }
1500
- throwYieldError(this.proxy, " cannot yield to '" + prop +
1501
- "' since no callback was passed.", args);
1502
- },
1530
+ return matches === this.callCount;
1531
+ };
1532
+ }
1503
1533
 
1504
- toString: function () {
1505
- var callStr = this.proxy.toString() + "(";
1506
- var args = [];
1534
+ delegateToCalls("calledOn", true);
1535
+ delegateToCalls("alwaysCalledOn", false, "calledOn");
1536
+ delegateToCalls("calledWith", true);
1537
+ delegateToCalls("calledWithMatch", true);
1538
+ delegateToCalls("alwaysCalledWith", false, "calledWith");
1539
+ delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
1540
+ delegateToCalls("calledWithExactly", true);
1541
+ delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
1542
+ delegateToCalls("neverCalledWith", false, "notCalledWith",
1543
+ function () { return true; });
1544
+ delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch",
1545
+ function () { return true; });
1546
+ delegateToCalls("threw", true);
1547
+ delegateToCalls("alwaysThrew", false, "threw");
1548
+ delegateToCalls("returned", true);
1549
+ delegateToCalls("alwaysReturned", false, "returned");
1550
+ delegateToCalls("calledWithNew", true);
1551
+ delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
1552
+ delegateToCalls("callArg", false, "callArgWith", function () {
1553
+ throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
1554
+ });
1555
+ spyApi.callArgWith = spyApi.callArg;
1556
+ delegateToCalls("callArgOn", false, "callArgOnWith", function () {
1557
+ throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
1558
+ });
1559
+ spyApi.callArgOnWith = spyApi.callArgOn;
1560
+ delegateToCalls("yield", false, "yield", function () {
1561
+ throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
1562
+ });
1563
+ // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
1564
+ spyApi.invokeCallback = spyApi.yield;
1565
+ delegateToCalls("yieldOn", false, "yieldOn", function () {
1566
+ throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
1567
+ });
1568
+ delegateToCalls("yieldTo", false, "yieldTo", function (property) {
1569
+ throw new Error(this.toString() + " cannot yield to '" + property +
1570
+ "' since it was not yet invoked.");
1571
+ });
1572
+ delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
1573
+ throw new Error(this.toString() + " cannot yield to '" + property +
1574
+ "' since it was not yet invoked.");
1575
+ });
1507
1576
 
1508
- for (var i = 0, l = this.args.length; i < l; ++i) {
1509
- push.call(args, sinon.format(this.args[i]));
1510
- }
1577
+ spyApi.formatters = {
1578
+ "c": function (spy) {
1579
+ return sinon.timesInWords(spy.callCount);
1580
+ },
1511
1581
 
1512
- callStr = callStr + args.join(", ") + ")";
1582
+ "n": function (spy) {
1583
+ return spy.toString();
1584
+ },
1585
+
1586
+ "C": function (spy) {
1587
+ var calls = [];
1513
1588
 
1514
- if (typeof this.returnValue != "undefined") {
1515
- callStr += " => " + sinon.format(this.returnValue);
1589
+ for (var i = 0, l = spy.callCount; i < l; ++i) {
1590
+ var stringifiedCall = " " + spy.getCall(i).toString();
1591
+ if (/\n/.test(calls[i - 1])) {
1592
+ stringifiedCall = "\n" + stringifiedCall;
1516
1593
  }
1594
+ push.call(calls, stringifiedCall);
1595
+ }
1517
1596
 
1518
- if (this.exception) {
1519
- callStr += " !" + this.exception.name;
1597
+ return calls.length > 0 ? "\n" + calls.join("\n") : "";
1598
+ },
1520
1599
 
1521
- if (this.exception.message) {
1522
- callStr += "(" + this.exception.message + ")";
1523
- }
1524
- }
1600
+ "t": function (spy) {
1601
+ var objects = [];
1525
1602
 
1526
- return callStr;
1603
+ for (var i = 0, l = spy.callCount; i < l; ++i) {
1604
+ push.call(objects, sinon.format(spy.thisValues[i]));
1527
1605
  }
1528
- };
1529
- }());
1530
1606
 
1531
- spy.spyCall = spyCall;
1607
+ return objects.join(", ");
1608
+ },
1609
+
1610
+ "*": function (spy, args) {
1611
+ var formatted = [];
1612
+
1613
+ for (var i = 0, l = args.length; i < l; ++i) {
1614
+ push.call(formatted, sinon.format(args[i]));
1615
+ }
1616
+
1617
+ return formatted.join(", ");
1618
+ }
1619
+ };
1532
1620
 
1533
- // This steps outside the module sandbox and will be removed
1534
- sinon.spyCall = spyCall;
1621
+ sinon.extend(spy, spyApi);
1622
+
1623
+ spy.spyCall = sinon.spyCall;
1535
1624
 
1536
1625
  if (commonJSModule) {
1537
1626
  module.exports = spy;
@@ -1552,7 +1641,7 @@ var sinon = (function (buster) {
1552
1641
  * @author Christian Johansen (christian@cjohansen.no)
1553
1642
  * @license BSD
1554
1643
  *
1555
- * Copyright (c) 2010-2011 Christian Johansen
1644
+ * Copyright (c) 2010-2013 Christian Johansen
1556
1645
  */
1557
1646
 
1558
1647
  (function (sinon) {
@@ -1596,34 +1685,47 @@ var sinon = (function (buster) {
1596
1685
  return sinon.wrapMethod(object, property, wrapper);
1597
1686
  }
1598
1687
 
1688
+ function getChangingValue(stub, property) {
1689
+ var index = stub.callCount - 1;
1690
+ var values = stub[property];
1691
+ var prop = index in values ? values[index] : values[values.length - 1];
1692
+ stub[property + "Last"] = prop;
1693
+
1694
+ return prop;
1695
+ }
1696
+
1599
1697
  function getCallback(stub, args) {
1600
- if (stub.callArgAt < 0) {
1698
+ var callArgAt = getChangingValue(stub, "callArgAts");
1699
+
1700
+ if (callArgAt < 0) {
1701
+ var callArgProp = getChangingValue(stub, "callArgProps");
1702
+
1601
1703
  for (var i = 0, l = args.length; i < l; ++i) {
1602
- if (!stub.callArgProp && typeof args[i] == "function") {
1704
+ if (!callArgProp && typeof args[i] == "function") {
1603
1705
  return args[i];
1604
1706
  }
1605
1707
 
1606
- if (stub.callArgProp && args[i] &&
1607
- typeof args[i][stub.callArgProp] == "function") {
1608
- return args[i][stub.callArgProp];
1708
+ if (callArgProp && args[i] &&
1709
+ typeof args[i][callArgProp] == "function") {
1710
+ return args[i][callArgProp];
1609
1711
  }
1610
1712
  }
1611
1713
 
1612
1714
  return null;
1613
1715
  }
1614
1716
 
1615
- return args[stub.callArgAt];
1717
+ return args[callArgAt];
1616
1718
  }
1617
1719
 
1618
1720
  var join = Array.prototype.join;
1619
1721
 
1620
1722
  function getCallbackError(stub, func, args) {
1621
- if (stub.callArgAt < 0) {
1723
+ if (stub.callArgAtsLast < 0) {
1622
1724
  var msg;
1623
1725
 
1624
- if (stub.callArgProp) {
1726
+ if (stub.callArgPropsLast) {
1625
1727
  msg = sinon.functionName(stub) +
1626
- " expected to yield to '" + stub.callArgProp +
1728
+ " expected to yield to '" + stub.callArgPropsLast +
1627
1729
  "', but no object with such a property was passed."
1628
1730
  } else {
1629
1731
  msg = sinon.functionName(stub) +
@@ -1637,14 +1739,12 @@ var sinon = (function (buster) {
1637
1739
  return msg;
1638
1740
  }
1639
1741
 
1640
- return "argument at index " + stub.callArgAt + " is not a function: " + func;
1742
+ return "argument at index " + stub.callArgAtsLast + " is not a function: " + func;
1641
1743
  }
1642
1744
 
1643
1745
  var nextTick = (function () {
1644
1746
  if (typeof process === "object" && typeof process.nextTick === "function") {
1645
1747
  return process.nextTick;
1646
- } else if (typeof msSetImmediate === "function") {
1647
- return msSetImmediate.bind(window);
1648
1748
  } else if (typeof setImmediate === "function") {
1649
1749
  return setImmediate;
1650
1750
  } else {
@@ -1655,19 +1755,22 @@ var sinon = (function (buster) {
1655
1755
  })();
1656
1756
 
1657
1757
  function callCallback(stub, args) {
1658
- if (typeof stub.callArgAt == "number") {
1758
+ if (stub.callArgAts.length > 0) {
1659
1759
  var func = getCallback(stub, args);
1660
1760
 
1661
1761
  if (typeof func != "function") {
1662
1762
  throw new TypeError(getCallbackError(stub, func, args));
1663
1763
  }
1664
1764
 
1765
+ var callbackArguments = getChangingValue(stub, "callbackArguments");
1766
+ var callbackContext = getChangingValue(stub, "callbackContexts");
1767
+
1665
1768
  if (stub.callbackAsync) {
1666
1769
  nextTick(function() {
1667
- func.apply(stub.callbackContext, stub.callbackArguments);
1770
+ func.apply(callbackContext, callbackArguments);
1668
1771
  });
1669
1772
  } else {
1670
- func.apply(stub.callbackContext, stub.callbackArguments);
1773
+ func.apply(callbackContext, callbackArguments);
1671
1774
  }
1672
1775
  }
1673
1776
  }
@@ -1711,6 +1814,11 @@ var sinon = (function (buster) {
1711
1814
  functionStub = sinon.spy.create(functionStub);
1712
1815
  functionStub.func = orig;
1713
1816
 
1817
+ functionStub.callArgAts = [];
1818
+ functionStub.callbackArguments = [];
1819
+ functionStub.callbackContexts = [];
1820
+ functionStub.callArgProps = [];
1821
+
1714
1822
  sinon.extend(functionStub, stub);
1715
1823
  functionStub._create = sinon.stub.create;
1716
1824
  functionStub.displayName = "stub";
@@ -1719,6 +1827,25 @@ var sinon = (function (buster) {
1719
1827
  return functionStub;
1720
1828
  },
1721
1829
 
1830
+ resetBehavior: function () {
1831
+ var i;
1832
+
1833
+ this.callArgAts = [];
1834
+ this.callbackArguments = [];
1835
+ this.callbackContexts = [];
1836
+ this.callArgProps = [];
1837
+
1838
+ delete this.returnValue;
1839
+ delete this.returnArgAt;
1840
+ this.returnThis = false;
1841
+
1842
+ if (this.fakes) {
1843
+ for (i = 0; i < this.fakes.length; i++) {
1844
+ this.fakes[i].resetBehavior();
1845
+ }
1846
+ }
1847
+ },
1848
+
1722
1849
  returns: function returns(value) {
1723
1850
  this.returnValue = value;
1724
1851
 
@@ -1749,8 +1876,10 @@ var sinon = (function (buster) {
1749
1876
  throw new TypeError("argument index is not number");
1750
1877
  }
1751
1878
 
1752
- this.callArgAt = pos;
1753
- this.callbackArguments = [];
1879
+ this.callArgAts.push(pos);
1880
+ this.callbackArguments.push([]);
1881
+ this.callbackContexts.push(undefined);
1882
+ this.callArgProps.push(undefined);
1754
1883
 
1755
1884
  return this;
1756
1885
  },
@@ -1763,9 +1892,10 @@ var sinon = (function (buster) {
1763
1892
  throw new TypeError("argument context is not an object");
1764
1893
  }
1765
1894
 
1766
- this.callArgAt = pos;
1767
- this.callbackArguments = [];
1768
- this.callbackContext = context;
1895
+ this.callArgAts.push(pos);
1896
+ this.callbackArguments.push([]);
1897
+ this.callbackContexts.push(context);
1898
+ this.callArgProps.push(undefined);
1769
1899
 
1770
1900
  return this;
1771
1901
  },
@@ -1775,8 +1905,10 @@ var sinon = (function (buster) {
1775
1905
  throw new TypeError("argument index is not number");
1776
1906
  }
1777
1907
 
1778
- this.callArgAt = pos;
1779
- this.callbackArguments = slice.call(arguments, 1);
1908
+ this.callArgAts.push(pos);
1909
+ this.callbackArguments.push(slice.call(arguments, 1));
1910
+ this.callbackContexts.push(undefined);
1911
+ this.callArgProps.push(undefined);
1780
1912
 
1781
1913
  return this;
1782
1914
  },
@@ -1789,16 +1921,19 @@ var sinon = (function (buster) {
1789
1921
  throw new TypeError("argument context is not an object");
1790
1922
  }
1791
1923
 
1792
- this.callArgAt = pos;
1793
- this.callbackArguments = slice.call(arguments, 2);
1794
- this.callbackContext = context;
1924
+ this.callArgAts.push(pos);
1925
+ this.callbackArguments.push(slice.call(arguments, 2));
1926
+ this.callbackContexts.push(context);
1927
+ this.callArgProps.push(undefined);
1795
1928
 
1796
1929
  return this;
1797
1930
  },
1798
1931
 
1799
1932
  yields: function () {
1800
- this.callArgAt = -1;
1801
- this.callbackArguments = slice.call(arguments, 0);
1933
+ this.callArgAts.push(-1);
1934
+ this.callbackArguments.push(slice.call(arguments, 0));
1935
+ this.callbackContexts.push(undefined);
1936
+ this.callArgProps.push(undefined);
1802
1937
 
1803
1938
  return this;
1804
1939
  },
@@ -1808,17 +1943,19 @@ var sinon = (function (buster) {
1808
1943
  throw new TypeError("argument context is not an object");
1809
1944
  }
1810
1945
 
1811
- this.callArgAt = -1;
1812
- this.callbackArguments = slice.call(arguments, 1);
1813
- this.callbackContext = context;
1946
+ this.callArgAts.push(-1);
1947
+ this.callbackArguments.push(slice.call(arguments, 1));
1948
+ this.callbackContexts.push(context);
1949
+ this.callArgProps.push(undefined);
1814
1950
 
1815
1951
  return this;
1816
1952
  },
1817
1953
 
1818
1954
  yieldsTo: function (prop) {
1819
- this.callArgAt = -1;
1820
- this.callArgProp = prop;
1821
- this.callbackArguments = slice.call(arguments, 1);
1955
+ this.callArgAts.push(-1);
1956
+ this.callbackArguments.push(slice.call(arguments, 1));
1957
+ this.callbackContexts.push(undefined);
1958
+ this.callArgProps.push(prop);
1822
1959
 
1823
1960
  return this;
1824
1961
  },
@@ -1828,10 +1965,10 @@ var sinon = (function (buster) {
1828
1965
  throw new TypeError("argument context is not an object");
1829
1966
  }
1830
1967
 
1831
- this.callArgAt = -1;
1832
- this.callArgProp = prop;
1833
- this.callbackArguments = slice.call(arguments, 2);
1834
- this.callbackContext = context;
1968
+ this.callArgAts.push(-1);
1969
+ this.callbackArguments.push(slice.call(arguments, 2));
1970
+ this.callbackContexts.push(context);
1971
+ this.callArgProps.push(prop);
1835
1972
 
1836
1973
  return this;
1837
1974
  }
@@ -1839,7 +1976,10 @@ var sinon = (function (buster) {
1839
1976
 
1840
1977
  // create asynchronous versions of callsArg* and yields* methods
1841
1978
  for (var method in proto) {
1842
- if (proto.hasOwnProperty(method) && method.match(/^(callsArg|yields)/)) {
1979
+ // need to avoid creating anotherasync versions of the newly added async methods
1980
+ if (proto.hasOwnProperty(method) &&
1981
+ method.match(/^(callsArg|yields|thenYields$)/) &&
1982
+ !method.match(/Async/)) {
1843
1983
  proto[method + 'Async'] = (function (syncFnName) {
1844
1984
  return function () {
1845
1985
  this.callbackAsync = true;
@@ -1872,7 +2012,7 @@ var sinon = (function (buster) {
1872
2012
  * @author Christian Johansen (christian@cjohansen.no)
1873
2013
  * @license BSD
1874
2014
  *
1875
- * Copyright (c) 2010-2011 Christian Johansen
2015
+ * Copyright (c) 2010-2013 Christian Johansen
1876
2016
  */
1877
2017
 
1878
2018
  (function (sinon) {
@@ -2161,24 +2301,24 @@ var sinon = (function (buster) {
2161
2301
 
2162
2302
  if (!args) {
2163
2303
  sinon.expectation.fail(this.method + " received no arguments, expected " +
2164
- this.expectedArguments.join());
2304
+ sinon.format(this.expectedArguments));
2165
2305
  }
2166
2306
 
2167
2307
  if (args.length < this.expectedArguments.length) {
2168
- sinon.expectation.fail(this.method + " received too few arguments (" + args.join() +
2169
- "), expected " + this.expectedArguments.join());
2308
+ sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
2309
+ "), expected " + sinon.format(this.expectedArguments));
2170
2310
  }
2171
2311
 
2172
2312
  if (this.expectsExactArgCount &&
2173
2313
  args.length != this.expectedArguments.length) {
2174
- sinon.expectation.fail(this.method + " received too many arguments (" + args.join() +
2175
- "), expected " + this.expectedArguments.join());
2314
+ sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
2315
+ "), expected " + sinon.format(this.expectedArguments));
2176
2316
  }
2177
2317
 
2178
2318
  for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
2179
2319
  if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
2180
- sinon.expectation.fail(this.method + " received wrong arguments (" + args.join() +
2181
- "), expected " + this.expectedArguments.join());
2320
+ sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
2321
+ ", expected " + sinon.format(this.expectedArguments));
2182
2322
  }
2183
2323
  }
2184
2324
  },
@@ -2240,7 +2380,8 @@ var sinon = (function (buster) {
2240
2380
  }
2241
2381
 
2242
2382
  var callStr = sinon.spyCall.toString.call({
2243
- proxy: this.method, args: args
2383
+ proxy: this.method || "anonymous mock expectation",
2384
+ args: args
2244
2385
  });
2245
2386
 
2246
2387
  var message = callStr.replace(", [...", "[, ...") + " " +
@@ -2296,12 +2437,13 @@ var sinon = (function (buster) {
2296
2437
  * @author Christian Johansen (christian@cjohansen.no)
2297
2438
  * @license BSD
2298
2439
  *
2299
- * Copyright (c) 2010-2011 Christian Johansen
2440
+ * Copyright (c) 2010-2013 Christian Johansen
2300
2441
  */
2301
2442
 
2302
2443
  (function (sinon) {
2303
2444
  var commonJSModule = typeof module == "object" && typeof require == "function";
2304
2445
  var push = [].push;
2446
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
2305
2447
 
2306
2448
  if (!sinon && commonJSModule) {
2307
2449
  sinon = require("../sinon");
@@ -2377,7 +2519,7 @@ var sinon = (function (buster) {
2377
2519
  var original = object[property];
2378
2520
 
2379
2521
  if (typeof original != "function") {
2380
- if (!object.hasOwnProperty(property)) {
2522
+ if (!hasOwnProperty.call(object, property)) {
2381
2523
  throw new TypeError("Cannot stub non-existent own property " + property);
2382
2524
  }
2383
2525
 
@@ -2452,7 +2594,7 @@ var sinon = (function (buster) {
2452
2594
  * @author Christian Johansen (christian@cjohansen.no)
2453
2595
  * @license BSD
2454
2596
  *
2455
- * Copyright (c) 2010-2011 Christian Johansen
2597
+ * Copyright (c) 2010-2013 Christian Johansen
2456
2598
  */
2457
2599
 
2458
2600
  if (typeof sinon == "undefined") {
@@ -2593,6 +2735,8 @@ if (typeof sinon == "undefined") {
2593
2735
  if (firstException) {
2594
2736
  throw firstException;
2595
2737
  }
2738
+
2739
+ return this.now;
2596
2740
  },
2597
2741
 
2598
2742
  firstTimerInRange: function (from, to) {
@@ -2806,15 +2950,16 @@ if (typeof sinon == "undefined") {
2806
2950
  (function () {
2807
2951
  var push = [].push;
2808
2952
 
2809
- sinon.Event = function Event(type, bubbles, cancelable) {
2810
- this.initEvent(type, bubbles, cancelable);
2953
+ sinon.Event = function Event(type, bubbles, cancelable, target) {
2954
+ this.initEvent(type, bubbles, cancelable, target);
2811
2955
  };
2812
2956
 
2813
2957
  sinon.Event.prototype = {
2814
- initEvent: function(type, bubbles, cancelable) {
2958
+ initEvent: function(type, bubbles, cancelable, target) {
2815
2959
  this.type = type;
2816
2960
  this.bubbles = bubbles;
2817
2961
  this.cancelable = cancelable;
2962
+ this.target = target;
2818
2963
  },
2819
2964
 
2820
2965
  stopPropagation: function () {},
@@ -2859,6 +3004,7 @@ if (typeof sinon == "undefined") {
2859
3004
  }());
2860
3005
 
2861
3006
  /**
3007
+ * @depend ../../sinon.js
2862
3008
  * @depend event.js
2863
3009
  */
2864
3010
  /*jslint eqeqeq: false, onevar: false*/
@@ -2869,7 +3015,7 @@ if (typeof sinon == "undefined") {
2869
3015
  * @author Christian Johansen (christian@cjohansen.no)
2870
3016
  * @license BSD
2871
3017
  *
2872
- * Copyright (c) 2010-2011 Christian Johansen
3018
+ * Copyright (c) 2010-2013 Christian Johansen
2873
3019
  */
2874
3020
 
2875
3021
  if (typeof sinon == "undefined") {
@@ -2917,6 +3063,23 @@ sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
2917
3063
  this.status = 0;
2918
3064
  this.statusText = "";
2919
3065
 
3066
+ var xhr = this;
3067
+ var events = ["loadstart", "load", "abort", "loadend"];
3068
+
3069
+ function addEventListener(eventName) {
3070
+ xhr.addEventListener(eventName, function (event) {
3071
+ var listener = xhr["on" + eventName];
3072
+
3073
+ if (listener && typeof listener == "function") {
3074
+ listener(event);
3075
+ }
3076
+ });
3077
+ }
3078
+
3079
+ for (var i = events.length - 1; i >= 0; i--) {
3080
+ addEventListener(events[i]);
3081
+ }
3082
+
2920
3083
  if (typeof FakeXMLHttpRequest.onCreate == "function") {
2921
3084
  FakeXMLHttpRequest.onCreate(this);
2922
3085
  }
@@ -3070,6 +3233,13 @@ sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
3070
3233
  }
3071
3234
 
3072
3235
  this.dispatchEvent(new sinon.Event("readystatechange"));
3236
+
3237
+ switch (this.readyState) {
3238
+ case FakeXMLHttpRequest.DONE:
3239
+ this.dispatchEvent(new sinon.Event("load", false, false, this));
3240
+ this.dispatchEvent(new sinon.Event("loadend", false, false, this));
3241
+ break;
3242
+ }
3073
3243
  },
3074
3244
 
3075
3245
  setRequestHeader: function setRequestHeader(header, value) {
@@ -3098,6 +3268,8 @@ sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
3098
3268
 
3099
3269
  if (this.async) {
3100
3270
  this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
3271
+ } else {
3272
+ this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
3101
3273
  }
3102
3274
  },
3103
3275
 
@@ -3123,6 +3295,8 @@ sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
3123
3295
  if (typeof this.onSend == "function") {
3124
3296
  this.onSend(this);
3125
3297
  }
3298
+
3299
+ this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
3126
3300
  },
3127
3301
 
3128
3302
  abort: function abort() {
@@ -3137,6 +3311,11 @@ sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
3137
3311
  }
3138
3312
 
3139
3313
  this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
3314
+
3315
+ this.dispatchEvent(new sinon.Event("abort", false, false, this));
3316
+ if (typeof this.onerror === "function") {
3317
+ this.onerror();
3318
+ }
3140
3319
  },
3141
3320
 
3142
3321
  getResponseHeader: function getResponseHeader(header) {
@@ -3217,6 +3396,10 @@ sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
3217
3396
  this.status = typeof status == "number" ? status : 200;
3218
3397
  this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
3219
3398
  this.setResponseBody(body || "");
3399
+ if (typeof this.onload === "function"){
3400
+ this.onload();
3401
+ }
3402
+
3220
3403
  }
3221
3404
  });
3222
3405
 
@@ -3343,7 +3526,7 @@ if (typeof module == "object" && typeof require == "function") {
3343
3526
  * @author Christian Johansen (christian@cjohansen.no)
3344
3527
  * @license BSD
3345
3528
  *
3346
- * Copyright (c) 2010-2011 Christian Johansen
3529
+ * Copyright (c) 2010-2013 Christian Johansen
3347
3530
  */
3348
3531
 
3349
3532
  if (typeof sinon == "undefined") {
@@ -3407,6 +3590,15 @@ sinon.fakeServer = (function () {
3407
3590
  return false;
3408
3591
  }
3409
3592
 
3593
+ function log(response, request) {
3594
+ var str;
3595
+
3596
+ str = "Request:\n" + sinon.format(request) + "\n\n";
3597
+ str += "Response:\n" + sinon.format(response) + "\n\n";
3598
+
3599
+ sinon.log(str);
3600
+ }
3601
+
3410
3602
  return {
3411
3603
  create: function () {
3412
3604
  var server = create(this);
@@ -3513,6 +3705,8 @@ sinon.fakeServer = (function () {
3513
3705
  }
3514
3706
 
3515
3707
  if (request.readyState != 4) {
3708
+ log(response, request);
3709
+
3516
3710
  request.respond(response[0], response[1], response[2]);
3517
3711
  }
3518
3712
  } catch (e) {
@@ -3548,7 +3742,7 @@ if (typeof module == "object" && typeof require == "function") {
3548
3742
  * @author Christian Johansen (christian@cjohansen.no)
3549
3743
  * @license BSD
3550
3744
  *
3551
- * Copyright (c) 2010-2011 Christian Johansen
3745
+ * Copyright (c) 2010-2013 Christian Johansen
3552
3746
  */
3553
3747
 
3554
3748
  (function () {
@@ -3628,7 +3822,7 @@ if (typeof module == "object" && typeof require == "function") {
3628
3822
  * @author Christian Johansen (christian@cjohansen.no)
3629
3823
  * @license BSD
3630
3824
  *
3631
- * Copyright (c) 2010-2011 Christian Johansen
3825
+ * Copyright (c) 2010-2013 Christian Johansen
3632
3826
  */
3633
3827
 
3634
3828
  if (typeof module == "object" && typeof require == "function") {
@@ -3752,7 +3946,7 @@ if (typeof module == "object" && typeof require == "function") {
3752
3946
  * @author Christian Johansen (christian@cjohansen.no)
3753
3947
  * @license BSD
3754
3948
  *
3755
- * Copyright (c) 2010-2011 Christian Johansen
3949
+ * Copyright (c) 2010-2013 Christian Johansen
3756
3950
  */
3757
3951
 
3758
3952
  (function (sinon) {
@@ -3782,7 +3976,15 @@ if (typeof module == "object" && typeof require == "function") {
3782
3976
 
3783
3977
  try {
3784
3978
  result = callback.apply(this, args);
3785
- } finally {
3979
+ } catch (e) {
3980
+ exception = e;
3981
+ }
3982
+
3983
+ if (typeof exception !== "undefined") {
3984
+ sandbox.restore();
3985
+ throw exception;
3986
+ }
3987
+ else {
3786
3988
  sandbox.verifyAndRestore();
3787
3989
  }
3788
3990
 
@@ -3817,7 +4019,7 @@ if (typeof module == "object" && typeof require == "function") {
3817
4019
  * @author Christian Johansen (christian@cjohansen.no)
3818
4020
  * @license BSD
3819
4021
  *
3820
- * Copyright (c) 2010-2011 Christian Johansen
4022
+ * Copyright (c) 2010-2013 Christian Johansen
3821
4023
  */
3822
4024
 
3823
4025
  (function (sinon) {
@@ -3914,7 +4116,7 @@ if (typeof module == "object" && typeof require == "function") {
3914
4116
  * @author Christian Johansen (christian@cjohansen.no)
3915
4117
  * @license BSD
3916
4118
  *
3917
- * Copyright (c) 2010-2011 Christian Johansen
4119
+ * Copyright (c) 2010-2013 Christian Johansen
3918
4120
  */
3919
4121
 
3920
4122
  (function (sinon, global) {
@@ -4007,7 +4209,14 @@ if (typeof module == "object" && typeof require == "function") {
4007
4209
  if (!sinon.calledInOrder(arguments)) {
4008
4210
  try {
4009
4211
  expected = [].join.call(arguments, ", ");
4010
- actual = sinon.orderByFirstCall(slice.call(arguments)).join(", ");
4212
+ var calls = slice.call(arguments);
4213
+ var i = calls.length;
4214
+ while (i) {
4215
+ if (!calls[--i].called) {
4216
+ calls.splice(i, 1);
4217
+ }
4218
+ }
4219
+ actual = sinon.orderByFirstCall(calls).join(", ");
4011
4220
  } catch (e) {
4012
4221
  // If this fails, we'll just fall back to the blank string
4013
4222
  }
@@ -4076,6 +4285,6 @@ if (typeof module == "object" && typeof require == "function") {
4076
4285
  } else {
4077
4286
  sinon.assert = assert;
4078
4287
  }
4079
- }(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : global));
4288
+ }(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
4080
4289
 
4081
4290
  return sinon;}.call(typeof window != 'undefined' && window || {}));