snapdragon 0.1.1 → 0.1.2

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.
@@ -1,54 +1,82 @@
1
1
  body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
2
2
 
3
- .html-reporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
4
- .html-reporter a { text-decoration: none; }
5
- .html-reporter a:hover { text-decoration: underline; }
6
- .html-reporter p, .html-reporter h1, .html-reporter h2, .html-reporter h3, .html-reporter h4, .html-reporter h5, .html-reporter h6 { margin: 0; line-height: 14px; }
7
- .html-reporter .banner, .html-reporter .symbol-summary, .html-reporter .summary, .html-reporter .result-message, .html-reporter .spec .description, .html-reporter .spec-detail .description, .html-reporter .alert .bar, .html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; }
8
- .html-reporter .banner .version { margin-left: 14px; }
9
- .html-reporter #jasmine_content { position: fixed; right: 100%; }
10
- .html-reporter .version { color: #aaaaaa; }
11
- .html-reporter .banner { margin-top: 14px; }
12
- .html-reporter .duration { color: #aaaaaa; float: right; }
13
- .html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; }
14
- .html-reporter .symbol-summary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
15
- .html-reporter .symbol-summary li.passed { font-size: 14px; }
16
- .html-reporter .symbol-summary li.passed:before { color: #5e7d00; content: "\02022"; }
17
- .html-reporter .symbol-summary li.failed { line-height: 9px; }
18
- .html-reporter .symbol-summary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
19
- .html-reporter .symbol-summary li.disabled { font-size: 14px; }
20
- .html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; }
21
- .html-reporter .symbol-summary li.pending { line-height: 17px; }
22
- .html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; }
23
- .html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
24
- .html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
25
- .html-reporter .bar.failed { background-color: #b03911; }
26
- .html-reporter .bar.passed { background-color: #a6b779; }
27
- .html-reporter .bar.skipped { background-color: #bababa; }
28
- .html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; }
29
- .html-reporter .bar.menu a { color: #333333; }
30
- .html-reporter .bar a { color: white; }
31
- .html-reporter.spec-list .bar.menu.failure-list, .html-reporter.spec-list .results .failures { display: none; }
32
- .html-reporter.failure-list .bar.menu.spec-list, .html-reporter.failure-list .summary { display: none; }
33
- .html-reporter .running-alert { background-color: #666666; }
34
- .html-reporter .results { margin-top: 14px; }
35
- .html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
36
- .html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
37
- .html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
38
- .html-reporter.showDetails .summary { display: none; }
39
- .html-reporter.showDetails #details { display: block; }
40
- .html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
41
- .html-reporter .summary { margin-top: 14px; }
42
- .html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; }
43
- .html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; }
44
- .html-reporter .summary li.passed a { color: #5e7d00; }
45
- .html-reporter .summary li.failed a { color: #b03911; }
46
- .html-reporter .summary li.pending a { color: #ba9d37; }
47
- .html-reporter .description + .suite { margin-top: 0; }
48
- .html-reporter .suite { margin-top: 14px; }
49
- .html-reporter .suite a { color: #333333; }
50
- .html-reporter .failures .spec-detail { margin-bottom: 28px; }
51
- .html-reporter .failures .spec-detail .description { display: block; color: white; background-color: #b03911; }
52
- .html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; }
53
- .html-reporter .result-message span.result { display: block; }
54
- .html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #dddddd; background: white; white-space: pre; }
3
+ #HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
4
+ #HTMLReporter a { text-decoration: none; }
5
+ #HTMLReporter a:hover { text-decoration: underline; }
6
+ #HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
7
+ #HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
8
+ #HTMLReporter #jasmine_content { position: fixed; right: 100%; }
9
+ #HTMLReporter .version { color: #aaaaaa; }
10
+ #HTMLReporter .banner { margin-top: 14px; }
11
+ #HTMLReporter .duration { color: #aaaaaa; float: right; }
12
+ #HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
13
+ #HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
14
+ #HTMLReporter .symbolSummary li.passed { font-size: 14px; }
15
+ #HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
16
+ #HTMLReporter .symbolSummary li.failed { line-height: 9px; }
17
+ #HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
18
+ #HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
19
+ #HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
20
+ #HTMLReporter .symbolSummary li.pending { line-height: 11px; }
21
+ #HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
22
+ #HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
23
+ #HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
24
+ #HTMLReporter .runningAlert { background-color: #666666; }
25
+ #HTMLReporter .skippedAlert { background-color: #aaaaaa; }
26
+ #HTMLReporter .skippedAlert:first-child { background-color: #333333; }
27
+ #HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
28
+ #HTMLReporter .passingAlert { background-color: #a6b779; }
29
+ #HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
30
+ #HTMLReporter .failingAlert { background-color: #cf867e; }
31
+ #HTMLReporter .failingAlert:first-child { background-color: #b03911; }
32
+ #HTMLReporter .results { margin-top: 14px; }
33
+ #HTMLReporter #details { display: none; }
34
+ #HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
35
+ #HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
36
+ #HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
37
+ #HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
38
+ #HTMLReporter.showDetails .summary { display: none; }
39
+ #HTMLReporter.showDetails #details { display: block; }
40
+ #HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
41
+ #HTMLReporter .summary { margin-top: 14px; }
42
+ #HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
43
+ #HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
44
+ #HTMLReporter .summary .specSummary.failed a { color: #b03911; }
45
+ #HTMLReporter .description + .suite { margin-top: 0; }
46
+ #HTMLReporter .suite { margin-top: 14px; }
47
+ #HTMLReporter .suite a { color: #333333; }
48
+ #HTMLReporter #details .specDetail { margin-bottom: 28px; }
49
+ #HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
50
+ #HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
51
+ #HTMLReporter .resultMessage span.result { display: block; }
52
+ #HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
53
+
54
+ #TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
55
+ #TrivialReporter a:visited, #TrivialReporter a { color: #303; }
56
+ #TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
57
+ #TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
58
+ #TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
59
+ #TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
60
+ #TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
61
+ #TrivialReporter .runner.running { background-color: yellow; }
62
+ #TrivialReporter .options { text-align: right; font-size: .8em; }
63
+ #TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
64
+ #TrivialReporter .suite .suite { margin: 5px; }
65
+ #TrivialReporter .suite.passed { background-color: #dfd; }
66
+ #TrivialReporter .suite.failed { background-color: #fdd; }
67
+ #TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
68
+ #TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
69
+ #TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
70
+ #TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
71
+ #TrivialReporter .spec.skipped { background-color: #bbb; }
72
+ #TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
73
+ #TrivialReporter .passed { background-color: #cfc; display: none; }
74
+ #TrivialReporter .failed { background-color: #fbb; }
75
+ #TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
76
+ #TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
77
+ #TrivialReporter .resultMessage .mismatch { color: black; }
78
+ #TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
79
+ #TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
80
+ #TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
81
+ #TrivialReporter #jasmine_content { position: fixed; right: 100%; }
82
+ #TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
@@ -1,2200 +1,2600 @@
1
- /*
2
- Copyright (c) 2008-2013 Pivotal Labs
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining
5
- a copy of this software and associated documentation files (the
6
- "Software"), to deal in the Software without restriction, including
7
- without limitation the rights to use, copy, modify, merge, publish,
8
- distribute, sublicense, and/or sell copies of the Software, and to
9
- permit persons to whom the Software is furnished to do so, subject to
10
- the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be
13
- included in all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- */
23
- function getJasmineRequireObj() {
24
- if (typeof module !== "undefined" && module.exports) {
25
- return exports;
26
- } else {
27
- window.jasmineRequire = window.jasmineRequire || {};
28
- return window.jasmineRequire;
29
- }
30
- }
31
-
32
- getJasmineRequireObj().core = function(jRequire) {
33
- j$ = {};
34
-
35
- jRequire.base(j$);
36
- j$.util = jRequire.util();
37
- j$.Any = jRequire.Any();
38
- j$.Clock = jRequire.Clock();
39
- j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
40
- j$.Env = jRequire.Env(j$);
41
- j$.ExceptionFormatter = jRequire.ExceptionFormatter();
42
- j$.Expectation = jRequire.Expectation();
43
- j$.buildExpectationResult = jRequire.buildExpectationResult();
44
- j$.JsApiReporter = jRequire.JsApiReporter();
45
- j$.matchersUtil = jRequire.matchersUtil(j$);
46
- j$.ObjectContaining = jRequire.ObjectContaining(j$);
47
- j$.StringPrettyPrinter = jRequire.StringPrettyPrinter(j$);
48
- j$.QueueRunner = jRequire.QueueRunner();
49
- j$.ReportDispatcher = jRequire.ReportDispatcher();
50
- j$.Spec = jRequire.Spec();
51
- j$.Spy = jRequire.Spy(j$);
52
- j$.Suite = jRequire.Suite();
53
- j$.version = jRequire.version();
54
-
55
- j$.matchers = jRequire.requireMatchers(jRequire);
56
-
57
- return j$;
58
- };
59
-
60
- getJasmineRequireObj().requireMatchers = function(jRequire) {
61
- var availableMatchers = [
62
- "toBe",
63
- "toBeCloseTo",
64
- "toBeDefined",
65
- "toBeFalsy",
66
- "toBeGreaterThan",
67
- "toBeLessThan",
68
- "toBeNaN",
69
- "toBeNull",
70
- "toBeTruthy",
71
- "toBeUndefined",
72
- "toContain",
73
- "toEqual",
74
- "toHaveBeenCalled",
75
- "toHaveBeenCalledWith",
76
- "toMatch",
77
- "toThrow",
78
- "toThrowError"
79
- ],
80
- matchers = {};
81
-
82
- for (var i = 0; i < availableMatchers.length; i++) {
83
- var name = availableMatchers[i];
84
- matchers[name] = jRequire[name]();
85
- }
86
-
87
- return matchers;
88
- };
89
-
90
- getJasmineRequireObj().base = function(j$) {
91
- j$.unimplementedMethod_ = function() {
92
- throw new Error("unimplemented method");
93
- };
94
-
95
- j$.DEFAULT_UPDATE_INTERVAL = 250;
96
- j$.MAX_PRETTY_PRINT_DEPTH = 40;
97
- j$.DEFAULT_TIMEOUT_INTERVAL = 5000;
98
-
99
- j$.getGlobal = function() {
100
- function getGlobal() {
101
- return this;
102
- }
103
-
104
- return getGlobal();
105
- };
106
-
107
- j$.getEnv = function(options) {
108
- var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options);
109
- //jasmine. singletons in here (setTimeout blah blah).
110
- return env;
111
- };
112
-
113
- j$.isArray_ = function(value) {
114
- return j$.isA_("Array", value);
115
- };
116
-
117
- j$.isString_ = function(value) {
118
- return j$.isA_("String", value);
119
- };
120
-
121
- j$.isNumber_ = function(value) {
122
- return j$.isA_("Number", value);
123
- };
124
-
125
- j$.isA_ = function(typeName, value) {
126
- return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
127
- };
128
-
129
- j$.pp = function(value) {
130
- var stringPrettyPrinter = new j$.StringPrettyPrinter();
131
- stringPrettyPrinter.format(value);
132
- return stringPrettyPrinter.string;
133
- };
134
-
135
- j$.isDomNode = function(obj) {
136
- return obj.nodeType > 0;
137
- };
138
-
139
- j$.any = function(clazz) {
140
- return new j$.Any(clazz);
141
- };
142
-
143
- j$.objectContaining = function(sample) {
144
- return new j$.ObjectContaining(sample);
145
- };
146
- };
147
-
148
- getJasmineRequireObj().util = function() {
149
-
150
- var util = {};
151
-
152
- util.inherit = function(childClass, parentClass) {
153
- var subclass = function() {
154
- };
155
- subclass.prototype = parentClass.prototype;
156
- childClass.prototype = new subclass();
157
- };
158
-
159
- util.htmlEscape = function(str) {
160
- if (!str) return str;
161
- return str.replace(/&/g, '&amp;')
162
- .replace(/</g, '&lt;')
163
- .replace(/>/g, '&gt;');
164
- };
165
-
166
- util.argsToArray = function(args) {
167
- var arrayOfArgs = [];
168
- for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
169
- return arrayOfArgs;
170
- };
1
+ var isCommonJS = typeof window == "undefined" && typeof exports == "object";
2
+
3
+ /**
4
+ * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
5
+ *
6
+ * @namespace
7
+ */
8
+ var jasmine = {};
9
+ if (isCommonJS) exports.jasmine = jasmine;
10
+ /**
11
+ * @private
12
+ */
13
+ jasmine.unimplementedMethod_ = function() {
14
+ throw new Error("unimplemented method");
15
+ };
171
16
 
172
- util.isUndefined = function(obj) {
173
- return obj === void 0;
174
- };
17
+ /**
18
+ * Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
19
+ * a plain old variable and may be redefined by somebody else.
20
+ *
21
+ * @private
22
+ */
23
+ jasmine.undefined = jasmine.___undefined___;
24
+
25
+ /**
26
+ * Show diagnostic messages in the console if set to true
27
+ *
28
+ */
29
+ jasmine.VERBOSE = false;
30
+
31
+ /**
32
+ * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
33
+ *
34
+ */
35
+ jasmine.DEFAULT_UPDATE_INTERVAL = 250;
36
+
37
+ /**
38
+ * Maximum levels of nesting that will be included when an object is pretty-printed
39
+ */
40
+ jasmine.MAX_PRETTY_PRINT_DEPTH = 40;
41
+
42
+ /**
43
+ * Default timeout interval in milliseconds for waitsFor() blocks.
44
+ */
45
+ jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
46
+
47
+ /**
48
+ * By default exceptions thrown in the context of a test are caught by jasmine so that it can run the remaining tests in the suite.
49
+ * Set to false to let the exception bubble up in the browser.
50
+ *
51
+ */
52
+ jasmine.CATCH_EXCEPTIONS = true;
53
+
54
+ jasmine.getGlobal = function() {
55
+ function getGlobal() {
56
+ return this;
57
+ }
175
58
 
176
- return util;
177
- };
178
-
179
- getJasmineRequireObj().Spec = function() {
180
- function Spec(attrs) {
181
- this.encounteredExpectations = false;
182
- this.expectationFactory = attrs.expectationFactory;
183
- this.resultCallback = attrs.resultCallback || function() {};
184
- this.id = attrs.id;
185
- this.description = attrs.description || '';
186
- this.fn = attrs.fn;
187
- this.beforeFns = attrs.beforeFns || function() {};
188
- this.afterFns = attrs.afterFns || function() {};
189
- this.catchingExceptions = attrs.catchingExceptions;
190
- this.onStart = attrs.onStart || function() {};
191
- this.exceptionFormatter = attrs.exceptionFormatter || function() {};
192
- this.getSpecName = attrs.getSpecName || function() { return ''; };
193
- this.expectationResultFactory = attrs.expectationResultFactory || function() { };
194
- this.queueRunner = attrs.queueRunner || function() {};
195
- this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
196
-
197
- if (!this.fn) {
198
- this.pend();
199
- }
59
+ return getGlobal();
60
+ };
200
61
 
201
- this.result = {
202
- id: this.id,
203
- description: this.description,
204
- fullName: this.getFullName(),
205
- status: this.status(),
206
- failedExpectations: []
62
+ /**
63
+ * Allows for bound functions to be compared. Internal use only.
64
+ *
65
+ * @ignore
66
+ * @private
67
+ * @param base {Object} bound 'this' for the function
68
+ * @param name {Function} function to find
69
+ */
70
+ jasmine.bindOriginal_ = function(base, name) {
71
+ var original = base[name];
72
+ if (original.apply) {
73
+ return function() {
74
+ return original.apply(base, arguments);
207
75
  };
76
+ } else {
77
+ // IE support
78
+ return jasmine.getGlobal()[name];
208
79
  }
80
+ };
209
81
 
210
- Spec.prototype.addExpectationResult = function(passed, data) {
211
- this.encounteredExpectations = true;
212
- if (passed) {
213
- return;
214
- }
215
- this.result.failedExpectations.push(this.expectationResultFactory(data));
216
- };
217
-
218
- Spec.prototype.expect = function(actual) {
219
- return this.expectationFactory(actual, this);
220
- };
221
-
222
- Spec.prototype.execute = function(onComplete) {
223
- var self = this;
224
-
225
- this.onStart(this);
226
-
227
- if (this.markedPending || this.disabled) {
228
- complete();
229
- return;
230
- }
231
-
232
- var befores = this.beforeFns() || [],
233
- afters = this.afterFns() || [];
234
- var allFns = befores.concat(this.fn).concat(afters);
235
-
236
- this.queueRunner({
237
- fns: allFns,
238
- onException: function(e) {
239
- if (Spec.isPendingSpecException(e)) {
240
- self.pend();
241
- return;
242
- }
243
-
244
- self.addExpectationResult(false, {
245
- matcherName: "",
246
- passed: false,
247
- expected: "",
248
- actual: "",
249
- error: e
250
- });
251
- },
252
- onComplete: complete
253
- });
254
-
255
- function complete() {
256
- self.result.status = self.status();
257
- self.resultCallback(self.result);
258
-
259
- if (onComplete) {
260
- onComplete();
261
- }
262
- }
263
- };
264
-
265
- Spec.prototype.disable = function() {
266
- this.disabled = true;
267
- };
268
-
269
- Spec.prototype.pend = function() {
270
- this.markedPending = true;
271
- };
272
-
273
- Spec.prototype.status = function() {
274
- if (this.disabled) {
275
- return 'disabled';
276
- }
82
+ jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
83
+ jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
84
+ jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
85
+ jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
277
86
 
278
- if (this.markedPending || !this.encounteredExpectations) {
279
- return 'pending';
280
- }
87
+ jasmine.MessageResult = function(values) {
88
+ this.type = 'log';
89
+ this.values = values;
90
+ this.trace = new Error(); // todo: test better
91
+ };
281
92
 
282
- if (this.result.failedExpectations.length > 0) {
283
- return 'failed';
93
+ jasmine.MessageResult.prototype.toString = function() {
94
+ var text = "";
95
+ for (var i = 0; i < this.values.length; i++) {
96
+ if (i > 0) text += " ";
97
+ if (jasmine.isString_(this.values[i])) {
98
+ text += this.values[i];
284
99
  } else {
285
- return 'passed';
100
+ text += jasmine.pp(this.values[i]);
286
101
  }
287
- };
288
-
289
- Spec.prototype.getFullName = function() {
290
- return this.getSpecName(this);
291
- };
102
+ }
103
+ return text;
104
+ };
292
105
 
293
- Spec.pendingSpecExceptionMessage = "=> marked Pending";
106
+ jasmine.ExpectationResult = function(params) {
107
+ this.type = 'expect';
108
+ this.matcherName = params.matcherName;
109
+ this.passed_ = params.passed;
110
+ this.expected = params.expected;
111
+ this.actual = params.actual;
112
+ this.message = this.passed_ ? 'Passed.' : params.message;
294
113
 
295
- Spec.isPendingSpecException = function(e) {
296
- return e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1;
297
- };
114
+ var trace = (params.trace || new Error(this.message));
115
+ this.trace = this.passed_ ? '' : trace;
116
+ };
298
117
 
299
- return Spec;
118
+ jasmine.ExpectationResult.prototype.toString = function () {
119
+ return this.message;
300
120
  };
301
121
 
302
- if (typeof window == void 0 && typeof exports == "object") {
303
- exports.Spec = jasmineRequire.Spec;
304
- }
122
+ jasmine.ExpectationResult.prototype.passed = function () {
123
+ return this.passed_;
124
+ };
305
125
 
306
- getJasmineRequireObj().Env = function(j$) {
307
- function Env(options) {
308
- options = options || {};
309
- var self = this;
310
- var global = options.global || j$.getGlobal(),
311
- now = options.now || function() { return new Date().getTime(); };
126
+ /**
127
+ * Getter for the Jasmine environment. Ensures one gets created
128
+ */
129
+ jasmine.getEnv = function() {
130
+ var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
131
+ return env;
132
+ };
312
133
 
313
- var catchExceptions = true;
134
+ /**
135
+ * @ignore
136
+ * @private
137
+ * @param value
138
+ * @returns {Boolean}
139
+ */
140
+ jasmine.isArray_ = function(value) {
141
+ return jasmine.isA_("Array", value);
142
+ };
314
143
 
315
- this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler());
144
+ /**
145
+ * @ignore
146
+ * @private
147
+ * @param value
148
+ * @returns {Boolean}
149
+ */
150
+ jasmine.isString_ = function(value) {
151
+ return jasmine.isA_("String", value);
152
+ };
316
153
 
317
- this.spies_ = [];
318
- this.currentSpec = null;
154
+ /**
155
+ * @ignore
156
+ * @private
157
+ * @param value
158
+ * @returns {Boolean}
159
+ */
160
+ jasmine.isNumber_ = function(value) {
161
+ return jasmine.isA_("Number", value);
162
+ };
319
163
 
320
- this.reporter = new j$.ReportDispatcher([
321
- "jasmineStarted",
322
- "jasmineDone",
323
- "suiteStarted",
324
- "suiteDone",
325
- "specStarted",
326
- "specDone"
327
- ]);
164
+ /**
165
+ * @ignore
166
+ * @private
167
+ * @param {String} typeName
168
+ * @param value
169
+ * @returns {Boolean}
170
+ */
171
+ jasmine.isA_ = function(typeName, value) {
172
+ return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
173
+ };
328
174
 
329
- this.lastUpdate = 0;
330
- this.specFilter = function() {
331
- return true;
332
- };
175
+ /**
176
+ * Pretty printer for expecations. Takes any object and turns it into a human-readable string.
177
+ *
178
+ * @param value {Object} an object to be outputted
179
+ * @returns {String}
180
+ */
181
+ jasmine.pp = function(value) {
182
+ var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
183
+ stringPrettyPrinter.format(value);
184
+ return stringPrettyPrinter.string;
185
+ };
333
186
 
334
- this.nextSpecId_ = 0;
335
- this.nextSuiteId_ = 0;
336
- this.equalityTesters_ = [];
187
+ /**
188
+ * Returns true if the object is a DOM Node.
189
+ *
190
+ * @param {Object} obj object to check
191
+ * @returns {Boolean}
192
+ */
193
+ jasmine.isDomNode = function(obj) {
194
+ return obj.nodeType > 0;
195
+ };
337
196
 
338
- var customEqualityTesters = [];
339
- this.addCustomEqualityTester = function(tester) {
340
- customEqualityTesters.push(tester);
341
- };
197
+ /**
198
+ * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
199
+ *
200
+ * @example
201
+ * // don't care about which function is passed in, as long as it's a function
202
+ * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
203
+ *
204
+ * @param {Class} clazz
205
+ * @returns matchable object of the type clazz
206
+ */
207
+ jasmine.any = function(clazz) {
208
+ return new jasmine.Matchers.Any(clazz);
209
+ };
342
210
 
343
- j$.Expectation.addCoreMatchers(j$.matchers);
211
+ /**
212
+ * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
213
+ * attributes on the object.
214
+ *
215
+ * @example
216
+ * // don't care about any other attributes than foo.
217
+ * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
218
+ *
219
+ * @param sample {Object} sample
220
+ * @returns matchable object for the sample
221
+ */
222
+ jasmine.objectContaining = function (sample) {
223
+ return new jasmine.Matchers.ObjectContaining(sample);
224
+ };
344
225
 
345
- var expectationFactory = function(actual, spec) {
346
- return j$.Expectation.Factory({
347
- util: j$.matchersUtil,
348
- customEqualityTesters: customEqualityTesters,
349
- actual: actual,
350
- addExpectationResult: addExpectationResult
351
- });
226
+ /**
227
+ * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
228
+ *
229
+ * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
230
+ * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
231
+ *
232
+ * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
233
+ *
234
+ * Spies are torn down at the end of every spec.
235
+ *
236
+ * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
237
+ *
238
+ * @example
239
+ * // a stub
240
+ * var myStub = jasmine.createSpy('myStub'); // can be used anywhere
241
+ *
242
+ * // spy example
243
+ * var foo = {
244
+ * not: function(bool) { return !bool; }
245
+ * }
246
+ *
247
+ * // actual foo.not will not be called, execution stops
248
+ * spyOn(foo, 'not');
249
+
250
+ // foo.not spied upon, execution will continue to implementation
251
+ * spyOn(foo, 'not').andCallThrough();
252
+ *
253
+ * // fake example
254
+ * var foo = {
255
+ * not: function(bool) { return !bool; }
256
+ * }
257
+ *
258
+ * // foo.not(val) will return val
259
+ * spyOn(foo, 'not').andCallFake(function(value) {return value;});
260
+ *
261
+ * // mock example
262
+ * foo.not(7 == 7);
263
+ * expect(foo.not).toHaveBeenCalled();
264
+ * expect(foo.not).toHaveBeenCalledWith(true);
265
+ *
266
+ * @constructor
267
+ * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
268
+ * @param {String} name
269
+ */
270
+ jasmine.Spy = function(name) {
271
+ /**
272
+ * The name of the spy, if provided.
273
+ */
274
+ this.identity = name || 'unknown';
275
+ /**
276
+ * Is this Object a spy?
277
+ */
278
+ this.isSpy = true;
279
+ /**
280
+ * The actual function this spy stubs.
281
+ */
282
+ this.plan = function() {
283
+ };
284
+ /**
285
+ * Tracking of the most recent call to the spy.
286
+ * @example
287
+ * var mySpy = jasmine.createSpy('foo');
288
+ * mySpy(1, 2);
289
+ * mySpy.mostRecentCall.args = [1, 2];
290
+ */
291
+ this.mostRecentCall = {};
292
+
293
+ /**
294
+ * Holds arguments for each call to the spy, indexed by call count
295
+ * @example
296
+ * var mySpy = jasmine.createSpy('foo');
297
+ * mySpy(1, 2);
298
+ * mySpy(7, 8);
299
+ * mySpy.mostRecentCall.args = [7, 8];
300
+ * mySpy.argsForCall[0] = [1, 2];
301
+ * mySpy.argsForCall[1] = [7, 8];
302
+ */
303
+ this.argsForCall = [];
304
+ this.calls = [];
305
+ };
352
306
 
353
- function addExpectationResult(passed, result) {
354
- return spec.addExpectationResult(passed, result);
355
- }
356
- };
307
+ /**
308
+ * Tells a spy to call through to the actual implemenatation.
309
+ *
310
+ * @example
311
+ * var foo = {
312
+ * bar: function() { // do some stuff }
313
+ * }
314
+ *
315
+ * // defining a spy on an existing property: foo.bar
316
+ * spyOn(foo, 'bar').andCallThrough();
317
+ */
318
+ jasmine.Spy.prototype.andCallThrough = function() {
319
+ this.plan = this.originalValue;
320
+ return this;
321
+ };
357
322
 
358
- var specStarted = function(spec) {
359
- self.currentSpec = spec;
360
- self.reporter.specStarted(spec.result);
361
- };
323
+ /**
324
+ * For setting the return value of a spy.
325
+ *
326
+ * @example
327
+ * // defining a spy from scratch: foo() returns 'baz'
328
+ * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
329
+ *
330
+ * // defining a spy on an existing property: foo.bar() returns 'baz'
331
+ * spyOn(foo, 'bar').andReturn('baz');
332
+ *
333
+ * @param {Object} value
334
+ */
335
+ jasmine.Spy.prototype.andReturn = function(value) {
336
+ this.plan = function() {
337
+ return value;
338
+ };
339
+ return this;
340
+ };
362
341
 
363
- var beforeFns = function(currentSuite) {
364
- return function() {
365
- var befores = [];
366
- for (var suite = currentSuite; suite; suite = suite.parentSuite) {
367
- befores = befores.concat(suite.beforeFns);
368
- }
369
- return befores.reverse();
370
- };
371
- };
342
+ /**
343
+ * For throwing an exception when a spy is called.
344
+ *
345
+ * @example
346
+ * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
347
+ * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
348
+ *
349
+ * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
350
+ * spyOn(foo, 'bar').andThrow('baz');
351
+ *
352
+ * @param {String} exceptionMsg
353
+ */
354
+ jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
355
+ this.plan = function() {
356
+ throw exceptionMsg;
357
+ };
358
+ return this;
359
+ };
372
360
 
373
- var afterFns = function(currentSuite) {
374
- return function() {
375
- var afters = [];
376
- for (var suite = currentSuite; suite; suite = suite.parentSuite) {
377
- afters = afters.concat(suite.afterFns);
378
- }
379
- return afters;
380
- };
381
- };
361
+ /**
362
+ * Calls an alternate implementation when a spy is called.
363
+ *
364
+ * @example
365
+ * var baz = function() {
366
+ * // do some stuff, return something
367
+ * }
368
+ * // defining a spy from scratch: foo() calls the function baz
369
+ * var foo = jasmine.createSpy('spy on foo').andCall(baz);
370
+ *
371
+ * // defining a spy on an existing property: foo.bar() calls an anonymnous function
372
+ * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
373
+ *
374
+ * @param {Function} fakeFunc
375
+ */
376
+ jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
377
+ this.plan = fakeFunc;
378
+ return this;
379
+ };
382
380
 
383
- var specConstructor = j$.Spec; // TODO: inline this
381
+ /**
382
+ * Resets all of a spy's the tracking variables so that it can be used again.
383
+ *
384
+ * @example
385
+ * spyOn(foo, 'bar');
386
+ *
387
+ * foo.bar();
388
+ *
389
+ * expect(foo.bar.callCount).toEqual(1);
390
+ *
391
+ * foo.bar.reset();
392
+ *
393
+ * expect(foo.bar.callCount).toEqual(0);
394
+ */
395
+ jasmine.Spy.prototype.reset = function() {
396
+ this.wasCalled = false;
397
+ this.callCount = 0;
398
+ this.argsForCall = [];
399
+ this.calls = [];
400
+ this.mostRecentCall = {};
401
+ };
384
402
 
385
- var getSpecName = function(spec, currentSuite) {
386
- return currentSuite.getFullName() + ' ' + spec.description + '.';
387
- };
403
+ jasmine.createSpy = function(name) {
388
404
 
389
- // TODO: we may just be able to pass in the fn instead of wrapping here
390
- var buildExpectationResult = j$.buildExpectationResult,
391
- exceptionFormatter = new j$.ExceptionFormatter(),
392
- expectationResultFactory = function(attrs) {
393
- attrs.messageFormatter = exceptionFormatter.message;
394
- attrs.stackFormatter = exceptionFormatter.stack;
405
+ var spyObj = function() {
406
+ spyObj.wasCalled = true;
407
+ spyObj.callCount++;
408
+ var args = jasmine.util.argsToArray(arguments);
409
+ spyObj.mostRecentCall.object = this;
410
+ spyObj.mostRecentCall.args = args;
411
+ spyObj.argsForCall.push(args);
412
+ spyObj.calls.push({object: this, args: args});
413
+ return spyObj.plan.apply(this, arguments);
414
+ };
395
415
 
396
- return buildExpectationResult(attrs);
397
- };
416
+ var spy = new jasmine.Spy(name);
398
417
 
399
- // TODO: fix this naming, and here's where the value comes in
400
- this.catchExceptions = function(value) {
401
- catchExceptions = !!value;
402
- return catchExceptions;
403
- };
418
+ for (var prop in spy) {
419
+ spyObj[prop] = spy[prop];
420
+ }
404
421
 
405
- this.catchingExceptions = function() {
406
- return catchExceptions;
407
- };
422
+ spyObj.reset();
408
423
 
409
- this.catchException = function(e){
410
- return j$.Spec.isPendingSpecException(e) || catchExceptions;
411
- };
424
+ return spyObj;
425
+ };
412
426
 
413
- var maximumSpecCallbackDepth = 100;
414
- var currentSpecCallbackDepth = 0;
427
+ /**
428
+ * Determines whether an object is a spy.
429
+ *
430
+ * @param {jasmine.Spy|Object} putativeSpy
431
+ * @returns {Boolean}
432
+ */
433
+ jasmine.isSpy = function(putativeSpy) {
434
+ return putativeSpy && putativeSpy.isSpy;
435
+ };
415
436
 
416
- function encourageGarbageCollection(fn) {
417
- currentSpecCallbackDepth++;
418
- if (currentSpecCallbackDepth > maximumSpecCallbackDepth) {
419
- currentSpecCallbackDepth = 0;
420
- global.setTimeout(fn, 0);
421
- } else {
422
- fn();
423
- }
424
- }
437
+ /**
438
+ * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
439
+ * large in one call.
440
+ *
441
+ * @param {String} baseName name of spy class
442
+ * @param {Array} methodNames array of names of methods to make spies
443
+ */
444
+ jasmine.createSpyObj = function(baseName, methodNames) {
445
+ if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
446
+ throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
447
+ }
448
+ var obj = {};
449
+ for (var i = 0; i < methodNames.length; i++) {
450
+ obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
451
+ }
452
+ return obj;
453
+ };
425
454
 
426
- var queueRunnerFactory = function(options) {
427
- options.catchException = self.catchException;
428
- options.encourageGC = options.encourageGarbageCollection || encourageGarbageCollection;
455
+ /**
456
+ * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
457
+ *
458
+ * Be careful not to leave calls to <code>jasmine.log</code> in production code.
459
+ */
460
+ jasmine.log = function() {
461
+ var spec = jasmine.getEnv().currentSpec;
462
+ spec.log.apply(spec, arguments);
463
+ };
429
464
 
430
- new j$.QueueRunner(options).run(options.fns, 0);
431
- };
465
+ /**
466
+ * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
467
+ *
468
+ * @example
469
+ * // spy example
470
+ * var foo = {
471
+ * not: function(bool) { return !bool; }
472
+ * }
473
+ * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
474
+ *
475
+ * @see jasmine.createSpy
476
+ * @param obj
477
+ * @param methodName
478
+ * @return {jasmine.Spy} a Jasmine spy that can be chained with all spy methods
479
+ */
480
+ var spyOn = function(obj, methodName) {
481
+ return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
482
+ };
483
+ if (isCommonJS) exports.spyOn = spyOn;
484
+
485
+ /**
486
+ * Creates a Jasmine spec that will be added to the current suite.
487
+ *
488
+ * // TODO: pending tests
489
+ *
490
+ * @example
491
+ * it('should be true', function() {
492
+ * expect(true).toEqual(true);
493
+ * });
494
+ *
495
+ * @param {String} desc description of this specification
496
+ * @param {Function} func defines the preconditions and expectations of the spec
497
+ */
498
+ var it = function(desc, func) {
499
+ return jasmine.getEnv().it(desc, func);
500
+ };
501
+ if (isCommonJS) exports.it = it;
502
+
503
+ /**
504
+ * Creates a <em>disabled</em> Jasmine spec.
505
+ *
506
+ * A convenience method that allows existing specs to be disabled temporarily during development.
507
+ *
508
+ * @param {String} desc description of this specification
509
+ * @param {Function} func defines the preconditions and expectations of the spec
510
+ */
511
+ var xit = function(desc, func) {
512
+ return jasmine.getEnv().xit(desc, func);
513
+ };
514
+ if (isCommonJS) exports.xit = xit;
515
+
516
+ /**
517
+ * Starts a chain for a Jasmine expectation.
518
+ *
519
+ * It is passed an Object that is the actual value and should chain to one of the many
520
+ * jasmine.Matchers functions.
521
+ *
522
+ * @param {Object} actual Actual value to test against and expected value
523
+ * @return {jasmine.Matchers}
524
+ */
525
+ var expect = function(actual) {
526
+ return jasmine.getEnv().currentSpec.expect(actual);
527
+ };
528
+ if (isCommonJS) exports.expect = expect;
529
+
530
+ /**
531
+ * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
532
+ *
533
+ * @param {Function} func Function that defines part of a jasmine spec.
534
+ */
535
+ var runs = function(func) {
536
+ jasmine.getEnv().currentSpec.runs(func);
537
+ };
538
+ if (isCommonJS) exports.runs = runs;
539
+
540
+ /**
541
+ * Waits a fixed time period before moving to the next block.
542
+ *
543
+ * @deprecated Use waitsFor() instead
544
+ * @param {Number} timeout milliseconds to wait
545
+ */
546
+ var waits = function(timeout) {
547
+ jasmine.getEnv().currentSpec.waits(timeout);
548
+ };
549
+ if (isCommonJS) exports.waits = waits;
550
+
551
+ /**
552
+ * Waits for the latchFunction to return true before proceeding to the next block.
553
+ *
554
+ * @param {Function} latchFunction
555
+ * @param {String} optional_timeoutMessage
556
+ * @param {Number} optional_timeout
557
+ */
558
+ var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
559
+ jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
560
+ };
561
+ if (isCommonJS) exports.waitsFor = waitsFor;
562
+
563
+ /**
564
+ * A function that is called before each spec in a suite.
565
+ *
566
+ * Used for spec setup, including validating assumptions.
567
+ *
568
+ * @param {Function} beforeEachFunction
569
+ */
570
+ var beforeEach = function(beforeEachFunction) {
571
+ jasmine.getEnv().beforeEach(beforeEachFunction);
572
+ };
573
+ if (isCommonJS) exports.beforeEach = beforeEach;
574
+
575
+ /**
576
+ * A function that is called after each spec in a suite.
577
+ *
578
+ * Used for restoring any state that is hijacked during spec execution.
579
+ *
580
+ * @param {Function} afterEachFunction
581
+ */
582
+ var afterEach = function(afterEachFunction) {
583
+ jasmine.getEnv().afterEach(afterEachFunction);
584
+ };
585
+ if (isCommonJS) exports.afterEach = afterEach;
586
+
587
+ /**
588
+ * Defines a suite of specifications.
589
+ *
590
+ * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
591
+ * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
592
+ * of setup in some tests.
593
+ *
594
+ * @example
595
+ * // TODO: a simple suite
596
+ *
597
+ * // TODO: a simple suite with a nested describe block
598
+ *
599
+ * @param {String} description A string, usually the class under test.
600
+ * @param {Function} specDefinitions function that defines several specs.
601
+ */
602
+ var describe = function(description, specDefinitions) {
603
+ return jasmine.getEnv().describe(description, specDefinitions);
604
+ };
605
+ if (isCommonJS) exports.describe = describe;
606
+
607
+ /**
608
+ * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
609
+ *
610
+ * @param {String} description A string, usually the class under test.
611
+ * @param {Function} specDefinitions function that defines several specs.
612
+ */
613
+ var xdescribe = function(description, specDefinitions) {
614
+ return jasmine.getEnv().xdescribe(description, specDefinitions);
615
+ };
616
+ if (isCommonJS) exports.xdescribe = xdescribe;
432
617
 
433
- var totalSpecsDefined = 0;
434
- this.specFactory = function(description, fn, suite) {
435
- totalSpecsDefined++;
436
-
437
- var spec = new specConstructor({
438
- id: self.nextSpecId(),
439
- beforeFns: beforeFns(suite),
440
- afterFns: afterFns(suite),
441
- expectationFactory: expectationFactory,
442
- exceptionFormatter: exceptionFormatter,
443
- resultCallback: specResultCallback,
444
- getSpecName: function(spec) {
445
- return getSpecName(spec, suite);
446
- },
447
- onStart: specStarted,
448
- description: description,
449
- expectationResultFactory: expectationResultFactory,
450
- queueRunner: queueRunnerFactory,
451
- fn: fn
452
- });
453
-
454
- if (!self.specFilter(spec)) {
455
- spec.disable();
456
- }
457
618
 
458
- return spec;
619
+ // Provide the XMLHttpRequest class for IE 5.x-6.x:
620
+ jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
621
+ function tryIt(f) {
622
+ try {
623
+ return f();
624
+ } catch(e) {
625
+ }
626
+ return null;
627
+ }
459
628
 
460
- function specResultCallback(result) {
461
- self.removeAllSpies();
462
- j$.Expectation.resetMatchers();
463
- customEqualityTesters.length = 0;
464
- self.clock.uninstall();
465
- self.currentSpec = null;
466
- self.reporter.specDone(result);
467
- }
468
- };
629
+ var xhr = tryIt(function() {
630
+ return new ActiveXObject("Msxml2.XMLHTTP.6.0");
631
+ }) ||
632
+ tryIt(function() {
633
+ return new ActiveXObject("Msxml2.XMLHTTP.3.0");
634
+ }) ||
635
+ tryIt(function() {
636
+ return new ActiveXObject("Msxml2.XMLHTTP");
637
+ }) ||
638
+ tryIt(function() {
639
+ return new ActiveXObject("Microsoft.XMLHTTP");
640
+ });
469
641
 
470
- var suiteStarted = function(suite) {
471
- self.reporter.suiteStarted(suite.result);
472
- };
642
+ if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
643
+
644
+ return xhr;
645
+ } : XMLHttpRequest;
646
+ /**
647
+ * @namespace
648
+ */
649
+ jasmine.util = {};
650
+
651
+ /**
652
+ * Declare that a child class inherit it's prototype from the parent class.
653
+ *
654
+ * @private
655
+ * @param {Function} childClass
656
+ * @param {Function} parentClass
657
+ */
658
+ jasmine.util.inherit = function(childClass, parentClass) {
659
+ /**
660
+ * @private
661
+ */
662
+ var subclass = function() {
663
+ };
664
+ subclass.prototype = parentClass.prototype;
665
+ childClass.prototype = new subclass();
666
+ };
473
667
 
474
- var suiteConstructor = j$.Suite;
668
+ jasmine.util.formatException = function(e) {
669
+ var lineNumber;
670
+ if (e.line) {
671
+ lineNumber = e.line;
672
+ }
673
+ else if (e.lineNumber) {
674
+ lineNumber = e.lineNumber;
675
+ }
475
676
 
476
- this.topSuite = new j$.Suite({
477
- env: this,
478
- id: this.nextSuiteId(),
479
- description: 'Jasmine__TopLevel__Suite',
480
- queueRunner: queueRunnerFactory,
481
- completeCallback: function() {}, // TODO - hook this up
482
- resultCallback: function() {} // TODO - hook this up
483
- });
484
- this.currentSuite = this.topSuite;
485
-
486
- this.suiteFactory = function(description) {
487
- return new suiteConstructor({
488
- env: self,
489
- id: self.nextSuiteId(),
490
- description: description,
491
- parentSuite: self.currentSuite,
492
- queueRunner: queueRunnerFactory,
493
- onStart: suiteStarted,
494
- resultCallback: function(attrs) {
495
- self.reporter.suiteDone(attrs);
496
- }
497
- });
498
- };
677
+ var file;
499
678
 
500
- this.execute = function() {
501
- var startTime = now();
502
- this.reporter.jasmineStarted({
503
- totalSpecsDefined: totalSpecsDefined
504
- });
505
- this.topSuite.execute(function() {
506
- self.reporter.jasmineDone({executionTime: now() - startTime});
507
- });
508
- };
679
+ if (e.sourceURL) {
680
+ file = e.sourceURL;
681
+ }
682
+ else if (e.fileName) {
683
+ file = e.fileName;
509
684
  }
510
685
 
511
- Env.prototype.addMatchers = function(matchersToAdd) {
512
- j$.Expectation.addMatchers(matchersToAdd);
513
- };
514
-
515
- Env.prototype.version = function() {
516
- return j$.version;
517
- };
686
+ var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
518
687
 
519
- Env.prototype.expect = function(actual) {
520
- return this.currentSpec.expect(actual);
521
- };
688
+ if (file && lineNumber) {
689
+ message += ' in ' + file + ' (line ' + lineNumber + ')';
690
+ }
522
691
 
523
- Env.prototype.spyOn = function(obj, methodName) {
524
- if (j$.util.isUndefined(obj)) {
525
- throw "spyOn could not find an object to spy upon for " + methodName + "()";
526
- }
692
+ return message;
693
+ };
527
694
 
528
- if (j$.util.isUndefined(obj[methodName])) {
529
- throw methodName + '() method does not exist';
530
- }
695
+ jasmine.util.htmlEscape = function(str) {
696
+ if (!str) return str;
697
+ return str.replace(/&/g, '&amp;')
698
+ .replace(/</g, '&lt;')
699
+ .replace(/>/g, '&gt;');
700
+ };
531
701
 
532
- if (obj[methodName] && obj[methodName].isSpy) {
533
- //TODO?: should this return the current spy? Downside: may cause user confusion about spy state
534
- throw new Error(methodName + ' has already been spied upon');
535
- }
702
+ jasmine.util.argsToArray = function(args) {
703
+ var arrayOfArgs = [];
704
+ for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
705
+ return arrayOfArgs;
706
+ };
536
707
 
537
- var spyObj = j$.createSpy(methodName);
708
+ jasmine.util.extend = function(destination, source) {
709
+ for (var property in source) destination[property] = source[property];
710
+ return destination;
711
+ };
538
712
 
539
- this.spies_.push(spyObj);
540
- spyObj.baseObj = obj;
541
- spyObj.methodName = methodName;
542
- spyObj.originalValue = obj[methodName];
713
+ /**
714
+ * Environment for Jasmine
715
+ *
716
+ * @constructor
717
+ */
718
+ jasmine.Env = function() {
719
+ this.currentSpec = null;
720
+ this.currentSuite = null;
721
+ this.currentRunner_ = new jasmine.Runner(this);
543
722
 
544
- obj[methodName] = spyObj;
723
+ this.reporter = new jasmine.MultiReporter();
545
724
 
546
- return spyObj;
725
+ this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
726
+ this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
727
+ this.lastUpdate = 0;
728
+ this.specFilter = function() {
729
+ return true;
547
730
  };
548
731
 
549
- // TODO: move this to closure
550
- Env.prototype.removeAllSpies = function() {
551
- for (var i = 0; i < this.spies_.length; i++) {
552
- var spy = this.spies_[i];
553
- spy.baseObj[spy.methodName] = spy.originalValue;
554
- }
555
- this.spies_ = [];
556
- };
732
+ this.nextSpecId_ = 0;
733
+ this.nextSuiteId_ = 0;
734
+ this.equalityTesters_ = [];
557
735
 
558
- // TODO: move this to closure
559
- Env.prototype.versionString = function() {
560
- console.log("DEPRECATED == use j$.version");
561
- return j$.version;
736
+ // wrap matchers
737
+ this.matchersClass = function() {
738
+ jasmine.Matchers.apply(this, arguments);
562
739
  };
740
+ jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
563
741
 
564
- // TODO: move this to closure
565
- Env.prototype.nextSpecId = function() {
566
- return this.nextSpecId_++;
567
- };
742
+ jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
743
+ };
568
744
 
569
- // TODO: move this to closure
570
- Env.prototype.nextSuiteId = function() {
571
- return this.nextSuiteId_++;
572
- };
573
745
 
574
- // TODO: move this to closure
575
- Env.prototype.addReporter = function(reporter) {
576
- this.reporter.addReporter(reporter);
577
- };
746
+ jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
747
+ jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
748
+ jasmine.Env.prototype.setInterval = jasmine.setInterval;
749
+ jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
578
750
 
579
- // TODO: move this to closure
580
- Env.prototype.describe = function(description, specDefinitions) {
581
- var suite = this.suiteFactory(description, specDefinitions);
751
+ /**
752
+ * @returns an object containing jasmine version build info, if set.
753
+ */
754
+ jasmine.Env.prototype.version = function () {
755
+ if (jasmine.version_) {
756
+ return jasmine.version_;
757
+ } else {
758
+ throw new Error('Version not set');
759
+ }
760
+ };
582
761
 
583
- var parentSuite = this.currentSuite;
584
- parentSuite.addSuite(suite);
585
- this.currentSuite = suite;
762
+ /**
763
+ * @returns string containing jasmine version build info, if set.
764
+ */
765
+ jasmine.Env.prototype.versionString = function() {
766
+ if (!jasmine.version_) {
767
+ return "version unknown";
768
+ }
586
769
 
587
- var declarationError = null;
588
- try {
589
- specDefinitions.call(suite);
590
- } catch (e) {
591
- declarationError = e;
592
- }
770
+ var version = this.version();
771
+ var versionString = version.major + "." + version.minor + "." + version.build;
772
+ if (version.release_candidate) {
773
+ versionString += ".rc" + version.release_candidate;
774
+ }
775
+ versionString += " revision " + version.revision;
776
+ return versionString;
777
+ };
593
778
 
594
- if (declarationError) {
595
- this.it("encountered a declaration exception", function() {
596
- throw declarationError;
597
- });
598
- }
779
+ /**
780
+ * @returns a sequential integer starting at 0
781
+ */
782
+ jasmine.Env.prototype.nextSpecId = function () {
783
+ return this.nextSpecId_++;
784
+ };
599
785
 
600
- this.currentSuite = parentSuite;
786
+ /**
787
+ * @returns a sequential integer starting at 0
788
+ */
789
+ jasmine.Env.prototype.nextSuiteId = function () {
790
+ return this.nextSuiteId_++;
791
+ };
601
792
 
602
- return suite;
603
- };
793
+ /**
794
+ * Register a reporter to receive status updates from Jasmine.
795
+ * @param {jasmine.Reporter} reporter An object which will receive status updates.
796
+ */
797
+ jasmine.Env.prototype.addReporter = function(reporter) {
798
+ this.reporter.addReporter(reporter);
799
+ };
604
800
 
605
- // TODO: move this to closure
606
- Env.prototype.xdescribe = function(description, specDefinitions) {
607
- var suite = this.describe(description, specDefinitions);
608
- suite.disable();
609
- return suite;
610
- };
801
+ jasmine.Env.prototype.execute = function() {
802
+ this.currentRunner_.execute();
803
+ };
611
804
 
612
- // TODO: move this to closure
613
- Env.prototype.it = function(description, fn) {
614
- var spec = this.specFactory(description, fn, this.currentSuite);
615
- this.currentSuite.addSpec(spec);
616
- return spec;
617
- };
805
+ jasmine.Env.prototype.describe = function(description, specDefinitions) {
806
+ var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
618
807
 
619
- // TODO: move this to closure
620
- Env.prototype.xit = function(description, fn) {
621
- var spec = this.it(description, fn);
622
- spec.pend();
623
- return spec;
624
- };
808
+ var parentSuite = this.currentSuite;
809
+ if (parentSuite) {
810
+ parentSuite.add(suite);
811
+ } else {
812
+ this.currentRunner_.add(suite);
813
+ }
625
814
 
626
- // TODO: move this to closure
627
- Env.prototype.beforeEach = function(beforeEachFunction) {
628
- this.currentSuite.beforeEach(beforeEachFunction);
629
- };
815
+ this.currentSuite = suite;
630
816
 
631
- // TODO: move this to closure
632
- Env.prototype.afterEach = function(afterEachFunction) {
633
- this.currentSuite.afterEach(afterEachFunction);
634
- };
817
+ var declarationError = null;
818
+ try {
819
+ specDefinitions.call(suite);
820
+ } catch(e) {
821
+ declarationError = e;
822
+ }
635
823
 
636
- // TODO: move this to closure
637
- Env.prototype.pending = function() {
638
- throw j$.Spec.pendingSpecExceptionMessage;
639
- };
824
+ if (declarationError) {
825
+ this.it("encountered a declaration exception", function() {
826
+ throw declarationError;
827
+ });
828
+ }
640
829
 
641
- // TODO: Still needed?
642
- Env.prototype.currentRunner = function() {
643
- return this.topSuite;
644
- };
830
+ this.currentSuite = parentSuite;
645
831
 
646
- return Env;
832
+ return suite;
647
833
  };
648
834
 
649
- getJasmineRequireObj().JsApiReporter = function() {
650
- function JsApiReporter(jasmine) { // TODO: this doesn't appear to be used
651
- this.jasmine = jasmine || {};
652
- this.started = false;
653
- this.finished = false;
654
-
655
- var status = 'loaded';
835
+ jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
836
+ if (this.currentSuite) {
837
+ this.currentSuite.beforeEach(beforeEachFunction);
838
+ } else {
839
+ this.currentRunner_.beforeEach(beforeEachFunction);
840
+ }
841
+ };
656
842
 
657
- this.jasmineStarted = function() {
658
- this.started = true;
659
- status = 'started';
660
- };
843
+ jasmine.Env.prototype.currentRunner = function () {
844
+ return this.currentRunner_;
845
+ };
661
846
 
662
- var executionTime;
847
+ jasmine.Env.prototype.afterEach = function(afterEachFunction) {
848
+ if (this.currentSuite) {
849
+ this.currentSuite.afterEach(afterEachFunction);
850
+ } else {
851
+ this.currentRunner_.afterEach(afterEachFunction);
852
+ }
663
853
 
664
- this.jasmineDone = function(options) {
665
- this.finished = true;
666
- executionTime = options.executionTime;
667
- status = 'done';
668
- };
854
+ };
669
855
 
670
- this.status = function() {
671
- return status;
672
- };
856
+ jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
857
+ return {
858
+ execute: function() {
859
+ }
860
+ };
861
+ };
673
862
 
674
- var suites = {};
863
+ jasmine.Env.prototype.it = function(description, func) {
864
+ var spec = new jasmine.Spec(this, this.currentSuite, description);
865
+ this.currentSuite.add(spec);
866
+ this.currentSpec = spec;
675
867
 
676
- this.suiteStarted = function(result) {
677
- storeSuite(result);
678
- };
868
+ if (func) {
869
+ spec.runs(func);
870
+ }
679
871
 
680
- this.suiteDone = function(result) {
681
- storeSuite(result);
682
- };
872
+ return spec;
873
+ };
683
874
 
684
- function storeSuite(result) {
685
- suites[result.id] = result;
875
+ jasmine.Env.prototype.xit = function(desc, func) {
876
+ return {
877
+ id: this.nextSpecId(),
878
+ runs: function() {
686
879
  }
880
+ };
881
+ };
687
882
 
688
- this.suites = function() {
689
- return suites;
690
- };
883
+ jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) {
884
+ if (a.source != b.source)
885
+ mismatchValues.push("expected pattern /" + b.source + "/ is not equal to the pattern /" + a.source + "/");
691
886
 
692
- var specs = [];
693
- this.specStarted = function(result) { };
887
+ if (a.ignoreCase != b.ignoreCase)
888
+ mismatchValues.push("expected modifier i was" + (b.ignoreCase ? " " : " not ") + "set and does not equal the origin modifier");
694
889
 
695
- this.specDone = function(result) {
696
- specs.push(result);
697
- };
890
+ if (a.global != b.global)
891
+ mismatchValues.push("expected modifier g was" + (b.global ? " " : " not ") + "set and does not equal the origin modifier");
698
892
 
699
- this.specResults = function(index, length) {
700
- return specs.slice(index, index + length);
701
- };
893
+ if (a.multiline != b.multiline)
894
+ mismatchValues.push("expected modifier m was" + (b.multiline ? " " : " not ") + "set and does not equal the origin modifier");
702
895
 
703
- this.specs = function() {
704
- return specs;
705
- };
896
+ if (a.sticky != b.sticky)
897
+ mismatchValues.push("expected modifier y was" + (b.sticky ? " " : " not ") + "set and does not equal the origin modifier");
706
898
 
707
- this.executionTime = function() {
708
- return executionTime;
709
- };
899
+ return (mismatchValues.length === 0);
900
+ };
710
901
 
902
+ jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
903
+ if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
904
+ return true;
711
905
  }
712
906
 
713
- return JsApiReporter;
714
- };
907
+ a.__Jasmine_been_here_before__ = b;
908
+ b.__Jasmine_been_here_before__ = a;
715
909
 
716
- getJasmineRequireObj().Any = function() {
910
+ var hasKey = function(obj, keyName) {
911
+ return obj !== null && obj[keyName] !== jasmine.undefined;
912
+ };
717
913
 
718
- function Any(expectedObject) {
719
- this.expectedObject = expectedObject;
914
+ for (var property in b) {
915
+ if (!hasKey(a, property) && hasKey(b, property)) {
916
+ mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
917
+ }
720
918
  }
721
-
722
- Any.prototype.jasmineMatches = function(other) {
723
- if (this.expectedObject == String) {
724
- return typeof other == 'string' || other instanceof String;
919
+ for (property in a) {
920
+ if (!hasKey(b, property) && hasKey(a, property)) {
921
+ mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
725
922
  }
726
-
727
- if (this.expectedObject == Number) {
728
- return typeof other == 'number' || other instanceof Number;
923
+ }
924
+ for (property in b) {
925
+ if (property == '__Jasmine_been_here_before__') continue;
926
+ if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
927
+ mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
729
928
  }
929
+ }
730
930
 
731
- if (this.expectedObject == Function) {
732
- return typeof other == 'function' || other instanceof Function;
733
- }
931
+ if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
932
+ mismatchValues.push("arrays were not the same length");
933
+ }
734
934
 
735
- if (this.expectedObject == Object) {
736
- return typeof other == 'object';
737
- }
935
+ delete a.__Jasmine_been_here_before__;
936
+ delete b.__Jasmine_been_here_before__;
937
+ return (mismatchKeys.length === 0 && mismatchValues.length === 0);
938
+ };
738
939
 
739
- return other instanceof this.expectedObject;
740
- };
940
+ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
941
+ mismatchKeys = mismatchKeys || [];
942
+ mismatchValues = mismatchValues || [];
741
943
 
742
- Any.prototype.jasmineToString = function() {
743
- return '<jasmine.any(' + this.expectedClass + ')>';
744
- };
944
+ for (var i = 0; i < this.equalityTesters_.length; i++) {
945
+ var equalityTester = this.equalityTesters_[i];
946
+ var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
947
+ if (result !== jasmine.undefined) return result;
948
+ }
745
949
 
746
- return Any;
747
- };
748
- getJasmineRequireObj().Clock = function() {
749
- function Clock(global, delayedFunctionScheduler) {
750
- var self = this,
751
- realTimingFunctions = {
752
- setTimeout: global.setTimeout,
753
- clearTimeout: global.clearTimeout,
754
- setInterval: global.setInterval,
755
- clearInterval: global.clearInterval
756
- },
757
- fakeTimingFunctions = {
758
- setTimeout: setTimeout,
759
- clearTimeout: clearTimeout,
760
- setInterval: setInterval,
761
- clearInterval: clearInterval
762
- },
763
- timer = realTimingFunctions,
764
- installed = false;
765
-
766
- self.install = function() {
767
- installed = true;
768
- timer = fakeTimingFunctions;
769
- };
950
+ if (a === b) return true;
770
951
 
771
- self.uninstall = function() {
772
- delayedFunctionScheduler.reset();
773
- installed = false;
774
- timer = realTimingFunctions;
775
- };
952
+ if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
953
+ return (a == jasmine.undefined && b == jasmine.undefined);
954
+ }
776
955
 
777
- self.setTimeout = function(fn, delay, params) {
778
- if (legacyIE()) {
779
- if (arguments.length > 2) {
780
- throw new Error("IE < 9 cannot support extra params to setTimeout without a polyfill");
781
- }
782
- return timer.setTimeout(fn, delay);
783
- }
784
- return timer.setTimeout.apply(global, arguments);
785
- };
956
+ if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
957
+ return a === b;
958
+ }
786
959
 
787
- self.setInterval = function(fn, delay, params) {
788
- if (legacyIE()) {
789
- if (arguments.length > 2) {
790
- throw new Error("IE < 9 cannot support extra params to setInterval without a polyfill");
791
- }
792
- return timer.setInterval(fn, delay);
793
- }
794
- return timer.setInterval.apply(global, arguments);
795
- };
960
+ if (a instanceof Date && b instanceof Date) {
961
+ return a.getTime() == b.getTime();
962
+ }
796
963
 
797
- self.clearTimeout = function(id) {
798
- return timer.clearTimeout.call(global, id);
799
- };
964
+ if (a.jasmineMatches) {
965
+ return a.jasmineMatches(b);
966
+ }
800
967
 
801
- self.clearInterval = function(id) {
802
- return timer.clearInterval.call(global, id);
803
- };
968
+ if (b.jasmineMatches) {
969
+ return b.jasmineMatches(a);
970
+ }
804
971
 
805
- self.tick = function(millis) {
806
- if (installed) {
807
- delayedFunctionScheduler.tick(millis);
808
- } else {
809
- throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
810
- }
811
- };
972
+ if (a instanceof jasmine.Matchers.ObjectContaining) {
973
+ return a.matches(b);
974
+ }
812
975
 
813
- return self;
976
+ if (b instanceof jasmine.Matchers.ObjectContaining) {
977
+ return b.matches(a);
978
+ }
814
979
 
815
- function legacyIE() {
816
- //if these methods are polyfilled, apply will be present
817
- //TODO: it may be difficult to load the polyfill before jasmine loads
818
- //(env should be new-ed inside of onload)
819
- return !(global.setTimeout || global.setInterval).apply;
820
- }
980
+ if (jasmine.isString_(a) && jasmine.isString_(b)) {
981
+ return (a == b);
982
+ }
821
983
 
822
- function setTimeout(fn, delay) {
823
- return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2));
824
- }
984
+ if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
985
+ return (a == b);
986
+ }
825
987
 
826
- function clearTimeout(id) {
827
- return delayedFunctionScheduler.removeFunctionWithId(id);
828
- }
988
+ if (a instanceof RegExp && b instanceof RegExp) {
989
+ return this.compareRegExps_(a, b, mismatchKeys, mismatchValues);
990
+ }
829
991
 
830
- function setInterval(fn, interval) {
831
- return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
832
- }
992
+ if (typeof a === "object" && typeof b === "object") {
993
+ return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
994
+ }
833
995
 
834
- function clearInterval(id) {
835
- return delayedFunctionScheduler.removeFunctionWithId(id);
836
- }
996
+ //Straight check
997
+ return (a === b);
998
+ };
837
999
 
838
- function argSlice(argsObj, n) {
839
- return Array.prototype.slice.call(argsObj, 2);
1000
+ jasmine.Env.prototype.contains_ = function(haystack, needle) {
1001
+ if (jasmine.isArray_(haystack)) {
1002
+ for (var i = 0; i < haystack.length; i++) {
1003
+ if (this.equals_(haystack[i], needle)) return true;
840
1004
  }
1005
+ return false;
841
1006
  }
1007
+ return haystack.indexOf(needle) >= 0;
1008
+ };
842
1009
 
843
- return Clock;
1010
+ jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
1011
+ this.equalityTesters_.push(equalityTester);
1012
+ };
1013
+ /** No-op base class for Jasmine reporters.
1014
+ *
1015
+ * @constructor
1016
+ */
1017
+ jasmine.Reporter = function() {
844
1018
  };
845
1019
 
846
- getJasmineRequireObj().DelayedFunctionScheduler = function() {
847
- function DelayedFunctionScheduler() {
848
- var self = this;
849
- var scheduledFunctions = {};
850
- var currentTime = 0;
851
- var delayedFnCount = 0;
852
-
853
- self.tick = function(millis) {
854
- millis = millis || 0;
855
- runFunctionsWithinRange(currentTime, currentTime + millis);
856
- currentTime = currentTime + millis;
857
- };
1020
+ //noinspection JSUnusedLocalSymbols
1021
+ jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
1022
+ };
858
1023
 
859
- self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) {
860
- millis = millis || 0;
861
- timeoutKey = timeoutKey || ++delayedFnCount;
862
- runAtMillis = runAtMillis || (currentTime + millis);
863
- scheduledFunctions[timeoutKey] = {
864
- runAtMillis: runAtMillis,
865
- funcToCall: funcToCall,
866
- recurring: recurring,
867
- params: params,
868
- timeoutKey: timeoutKey,
869
- millis: millis
870
- };
871
- return timeoutKey;
872
- };
1024
+ //noinspection JSUnusedLocalSymbols
1025
+ jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
1026
+ };
873
1027
 
874
- self.removeFunctionWithId = function(timeoutKey) {
875
- delete scheduledFunctions[timeoutKey];
876
- };
1028
+ //noinspection JSUnusedLocalSymbols
1029
+ jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
1030
+ };
877
1031
 
878
- self.reset = function() {
879
- currentTime = 0;
880
- scheduledFunctions = {};
881
- delayedFnCount = 0;
882
- };
1032
+ //noinspection JSUnusedLocalSymbols
1033
+ jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
1034
+ };
883
1035
 
884
- return self;
885
-
886
- // finds/dupes functions within range and removes them.
887
- function functionsWithinRange(startMillis, endMillis) {
888
- var fnsToRun = [];
889
- for (var timeoutKey in scheduledFunctions) {
890
- var scheduledFunc = scheduledFunctions[timeoutKey];
891
- if (scheduledFunc &&
892
- scheduledFunc.runAtMillis >= startMillis &&
893
- scheduledFunc.runAtMillis <= endMillis) {
894
-
895
- // remove fn -- we'll reschedule later if it is recurring.
896
- self.removeFunctionWithId(timeoutKey);
897
- if (!scheduledFunc.recurring) {
898
- fnsToRun.push(scheduledFunc); // schedules each function only once
899
- } else {
900
- fnsToRun.push(buildNthInstanceOf(scheduledFunc, 0));
901
- var additionalTimesFnRunsInRange =
902
- Math.floor((endMillis - scheduledFunc.runAtMillis) / scheduledFunc.millis);
903
- for (var i = 0; i < additionalTimesFnRunsInRange; i++) {
904
- fnsToRun.push(buildNthInstanceOf(scheduledFunc, i + 1));
905
- }
906
- reschedule(buildNthInstanceOf(scheduledFunc, additionalTimesFnRunsInRange));
907
- }
908
- }
909
- }
1036
+ //noinspection JSUnusedLocalSymbols
1037
+ jasmine.Reporter.prototype.reportSpecResults = function(spec) {
1038
+ };
910
1039
 
911
- return fnsToRun;
912
- }
1040
+ //noinspection JSUnusedLocalSymbols
1041
+ jasmine.Reporter.prototype.log = function(str) {
1042
+ };
913
1043
 
914
- function buildNthInstanceOf(scheduledFunc, n) {
915
- return {
916
- runAtMillis: scheduledFunc.runAtMillis + (scheduledFunc.millis * n),
917
- funcToCall: scheduledFunc.funcToCall,
918
- params: scheduledFunc.params,
919
- millis: scheduledFunc.millis,
920
- recurring: scheduledFunc.recurring,
921
- timeoutKey: scheduledFunc.timeoutKey
922
- };
923
- }
1044
+ /**
1045
+ * Blocks are functions with executable code that make up a spec.
1046
+ *
1047
+ * @constructor
1048
+ * @param {jasmine.Env} env
1049
+ * @param {Function} func
1050
+ * @param {jasmine.Spec} spec
1051
+ */
1052
+ jasmine.Block = function(env, func, spec) {
1053
+ this.env = env;
1054
+ this.func = func;
1055
+ this.spec = spec;
1056
+ };
924
1057
 
925
- function reschedule(scheduledFn) {
926
- self.scheduleFunction(scheduledFn.funcToCall,
927
- scheduledFn.millis,
928
- scheduledFn.params,
929
- true,
930
- scheduledFn.timeoutKey,
931
- scheduledFn.runAtMillis + scheduledFn.millis);
1058
+ jasmine.Block.prototype.execute = function(onComplete) {
1059
+ if (!jasmine.CATCH_EXCEPTIONS) {
1060
+ this.func.apply(this.spec);
1061
+ }
1062
+ else {
1063
+ try {
1064
+ this.func.apply(this.spec);
1065
+ } catch (e) {
1066
+ this.spec.fail(e);
932
1067
  }
1068
+ }
1069
+ onComplete();
1070
+ };
1071
+ /** JavaScript API reporter.
1072
+ *
1073
+ * @constructor
1074
+ */
1075
+ jasmine.JsApiReporter = function() {
1076
+ this.started = false;
1077
+ this.finished = false;
1078
+ this.suites_ = [];
1079
+ this.results_ = {};
1080
+ };
933
1081
 
1082
+ jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
1083
+ this.started = true;
1084
+ var suites = runner.topLevelSuites();
1085
+ for (var i = 0; i < suites.length; i++) {
1086
+ var suite = suites[i];
1087
+ this.suites_.push(this.summarize_(suite));
1088
+ }
1089
+ };
934
1090
 
935
- function runFunctionsWithinRange(startMillis, endMillis) {
936
- var funcsToRun = functionsWithinRange(startMillis, endMillis);
937
- if (funcsToRun.length === 0) {
938
- return;
939
- }
940
-
941
- funcsToRun.sort(function(a, b) {
942
- return a.runAtMillis - b.runAtMillis;
943
- });
1091
+ jasmine.JsApiReporter.prototype.suites = function() {
1092
+ return this.suites_;
1093
+ };
944
1094
 
945
- for (var i = 0; i < funcsToRun.length; ++i) {
946
- var funcToRun = funcsToRun[i];
947
- funcToRun.funcToCall.apply(null, funcToRun.params);
948
- }
1095
+ jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
1096
+ var isSuite = suiteOrSpec instanceof jasmine.Suite;
1097
+ var summary = {
1098
+ id: suiteOrSpec.id,
1099
+ name: suiteOrSpec.description,
1100
+ type: isSuite ? 'suite' : 'spec',
1101
+ children: []
1102
+ };
1103
+
1104
+ if (isSuite) {
1105
+ var children = suiteOrSpec.children();
1106
+ for (var i = 0; i < children.length; i++) {
1107
+ summary.children.push(this.summarize_(children[i]));
949
1108
  }
950
1109
  }
1110
+ return summary;
1111
+ };
951
1112
 
952
- return DelayedFunctionScheduler;
1113
+ jasmine.JsApiReporter.prototype.results = function() {
1114
+ return this.results_;
953
1115
  };
954
1116
 
955
- getJasmineRequireObj().ExceptionFormatter = function() {
956
- function ExceptionFormatter() {
957
- this.message = function(error) {
958
- var message = error.name +
959
- ': ' +
960
- error.message;
1117
+ jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
1118
+ return this.results_[specId];
1119
+ };
961
1120
 
962
- if (error.fileName || error.sourceURL) {
963
- message += " in " + (error.fileName || error.sourceURL);
964
- }
1121
+ //noinspection JSUnusedLocalSymbols
1122
+ jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
1123
+ this.finished = true;
1124
+ };
965
1125
 
966
- if (error.line || error.lineNumber) {
967
- message += " (line " + (error.line || error.lineNumber) + ")";
968
- }
1126
+ //noinspection JSUnusedLocalSymbols
1127
+ jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
1128
+ };
969
1129
 
970
- return message;
971
- };
1130
+ //noinspection JSUnusedLocalSymbols
1131
+ jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
1132
+ this.results_[spec.id] = {
1133
+ messages: spec.results().getItems(),
1134
+ result: spec.results().failedCount > 0 ? "failed" : "passed"
1135
+ };
1136
+ };
972
1137
 
973
- this.stack = function(error) {
974
- return error ? error.stack : null;
975
- };
1138
+ //noinspection JSUnusedLocalSymbols
1139
+ jasmine.JsApiReporter.prototype.log = function(str) {
1140
+ };
1141
+
1142
+ jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
1143
+ var results = {};
1144
+ for (var i = 0; i < specIds.length; i++) {
1145
+ var specId = specIds[i];
1146
+ results[specId] = this.summarizeResult_(this.results_[specId]);
1147
+ }
1148
+ return results;
1149
+ };
1150
+
1151
+ jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
1152
+ var summaryMessages = [];
1153
+ var messagesLength = result.messages.length;
1154
+ for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
1155
+ var resultMessage = result.messages[messageIndex];
1156
+ summaryMessages.push({
1157
+ text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
1158
+ passed: resultMessage.passed ? resultMessage.passed() : true,
1159
+ type: resultMessage.type,
1160
+ message: resultMessage.message,
1161
+ trace: {
1162
+ stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
1163
+ }
1164
+ });
976
1165
  }
977
1166
 
978
- return ExceptionFormatter;
1167
+ return {
1168
+ result : result.result,
1169
+ messages : summaryMessages
1170
+ };
979
1171
  };
980
1172
 
981
- getJasmineRequireObj().Expectation = function() {
1173
+ /**
1174
+ * @constructor
1175
+ * @param {jasmine.Env} env
1176
+ * @param actual
1177
+ * @param {jasmine.Spec} spec
1178
+ */
1179
+ jasmine.Matchers = function(env, actual, spec, opt_isNot) {
1180
+ this.env = env;
1181
+ this.actual = actual;
1182
+ this.spec = spec;
1183
+ this.isNot = opt_isNot || false;
1184
+ this.reportWasCalled_ = false;
1185
+ };
982
1186
 
983
- var matchers = {};
1187
+ // todo: @deprecated as of Jasmine 0.11, remove soon [xw]
1188
+ jasmine.Matchers.pp = function(str) {
1189
+ throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
1190
+ };
984
1191
 
985
- function Expectation(options) {
986
- this.util = options.util || { buildFailureMessage: function() {} };
987
- this.customEqualityTesters = options.customEqualityTesters || [];
988
- this.actual = options.actual;
989
- this.addExpectationResult = options.addExpectationResult || function(){};
990
- this.isNot = options.isNot;
1192
+ // todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
1193
+ jasmine.Matchers.prototype.report = function(result, failing_message, details) {
1194
+ throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
1195
+ };
991
1196
 
992
- for (var matcherName in matchers) {
993
- this[matcherName] = matchers[matcherName];
994
- }
1197
+ jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
1198
+ for (var methodName in prototype) {
1199
+ if (methodName == 'report') continue;
1200
+ var orig = prototype[methodName];
1201
+ matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
995
1202
  }
1203
+ };
996
1204
 
997
- Expectation.prototype.wrapCompare = function(name, matcherFactory) {
998
- return function() {
999
- var args = Array.prototype.slice.call(arguments, 0),
1000
- expected = args.slice(0),
1001
- message = "";
1002
-
1003
- args.unshift(this.actual);
1205
+ jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
1206
+ return function() {
1207
+ var matcherArgs = jasmine.util.argsToArray(arguments);
1208
+ var result = matcherFunction.apply(this, arguments);
1004
1209
 
1005
- var result = matcherFactory(this.util, this.customEqualityTesters).compare.apply(null, args);
1210
+ if (this.isNot) {
1211
+ result = !result;
1212
+ }
1006
1213
 
1007
- if (this.isNot) {
1008
- result.pass = !result.pass;
1009
- }
1214
+ if (this.reportWasCalled_) return result;
1010
1215
 
1011
- if (!result.pass) {
1012
- if (!result.message) {
1013
- args.unshift(this.isNot);
1014
- args.unshift(name);
1015
- message = this.util.buildFailureMessage.apply(null, args);
1016
- } else {
1017
- message = result.message;
1216
+ var message;
1217
+ if (!result) {
1218
+ if (this.message) {
1219
+ message = this.message.apply(this, arguments);
1220
+ if (jasmine.isArray_(message)) {
1221
+ message = message[this.isNot ? 1 : 0];
1018
1222
  }
1019
- }
1020
-
1021
- if (expected.length == 1) {
1022
- expected = expected[0];
1023
- }
1024
-
1025
- // TODO: how many of these params are needed?
1026
- this.addExpectationResult(
1027
- result.pass,
1028
- {
1029
- matcherName: name,
1030
- passed: result.pass,
1031
- message: message,
1032
- actual: this.actual,
1033
- expected: expected // TODO: this may need to be arrayified/sliced
1223
+ } else {
1224
+ var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
1225
+ message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
1226
+ if (matcherArgs.length > 0) {
1227
+ for (var i = 0; i < matcherArgs.length; i++) {
1228
+ if (i > 0) message += ",";
1229
+ message += " " + jasmine.pp(matcherArgs[i]);
1230
+ }
1034
1231
  }
1035
- );
1036
- };
1037
- };
1038
-
1039
- Expectation.addCoreMatchers = function(matchers) {
1040
- var prototype = Expectation.prototype;
1041
- for (var matcherName in matchers) {
1042
- var matcher = matchers[matcherName];
1043
- prototype[matcherName] = prototype.wrapCompare(matcherName, matcher);
1232
+ message += ".";
1233
+ }
1044
1234
  }
1235
+ var expectationResult = new jasmine.ExpectationResult({
1236
+ matcherName: matcherName,
1237
+ passed: result,
1238
+ expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
1239
+ actual: this.actual,
1240
+ message: message
1241
+ });
1242
+ this.spec.addMatcherResult(expectationResult);
1243
+ return jasmine.undefined;
1045
1244
  };
1245
+ };
1046
1246
 
1047
- Expectation.addMatchers = function(matchersToAdd) {
1048
- for (var name in matchersToAdd) {
1049
- var matcher = matchersToAdd[name];
1050
- matchers[name] = Expectation.prototype.wrapCompare(name, matcher);
1051
- }
1052
- };
1053
1247
 
1054
- Expectation.resetMatchers = function() {
1055
- for (var name in matchers) {
1056
- delete matchers[name];
1057
- }
1058
- };
1059
1248
 
1060
- Expectation.Factory = function(options) {
1061
- options = options || {};
1062
1249
 
1063
- var expect = new Expectation(options);
1250
+ /**
1251
+ * toBe: compares the actual to the expected using ===
1252
+ * @param expected
1253
+ */
1254
+ jasmine.Matchers.prototype.toBe = function(expected) {
1255
+ return this.actual === expected;
1256
+ };
1064
1257
 
1065
- // TODO: this would be nice as its own Object - NegativeExpectation
1066
- // TODO: copy instead of mutate options
1067
- options.isNot = true;
1068
- expect.not = new Expectation(options);
1258
+ /**
1259
+ * toNotBe: compares the actual to the expected using !==
1260
+ * @param expected
1261
+ * @deprecated as of 1.0. Use not.toBe() instead.
1262
+ */
1263
+ jasmine.Matchers.prototype.toNotBe = function(expected) {
1264
+ return this.actual !== expected;
1265
+ };
1069
1266
 
1070
- return expect;
1071
- };
1267
+ /**
1268
+ * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
1269
+ *
1270
+ * @param expected
1271
+ */
1272
+ jasmine.Matchers.prototype.toEqual = function(expected) {
1273
+ return this.env.equals_(this.actual, expected);
1274
+ };
1072
1275
 
1073
- return Expectation;
1276
+ /**
1277
+ * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
1278
+ * @param expected
1279
+ * @deprecated as of 1.0. Use not.toEqual() instead.
1280
+ */
1281
+ jasmine.Matchers.prototype.toNotEqual = function(expected) {
1282
+ return !this.env.equals_(this.actual, expected);
1074
1283
  };
1075
1284
 
1076
- //TODO: expectation result may make more sense as a presentation of an expectation.
1077
- getJasmineRequireObj().buildExpectationResult = function() {
1078
- function buildExpectationResult(options) {
1079
- var messageFormatter = options.messageFormatter || function() {},
1080
- stackFormatter = options.stackFormatter || function() {};
1285
+ /**
1286
+ * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
1287
+ * a pattern or a String.
1288
+ *
1289
+ * @param expected
1290
+ */
1291
+ jasmine.Matchers.prototype.toMatch = function(expected) {
1292
+ return new RegExp(expected).test(this.actual);
1293
+ };
1081
1294
 
1082
- return {
1083
- matcherName: options.matcherName,
1084
- expected: options.expected,
1085
- actual: options.actual,
1086
- message: message(),
1087
- stack: stack(),
1088
- passed: options.passed
1089
- };
1295
+ /**
1296
+ * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
1297
+ * @param expected
1298
+ * @deprecated as of 1.0. Use not.toMatch() instead.
1299
+ */
1300
+ jasmine.Matchers.prototype.toNotMatch = function(expected) {
1301
+ return !(new RegExp(expected).test(this.actual));
1302
+ };
1090
1303
 
1091
- function message() {
1092
- if (options.passed) {
1093
- return "Passed.";
1094
- } else if (options.message) {
1095
- return options.message;
1096
- } else if (options.error) {
1097
- return messageFormatter(options.error);
1098
- }
1099
- return "";
1100
- }
1304
+ /**
1305
+ * Matcher that compares the actual to jasmine.undefined.
1306
+ */
1307
+ jasmine.Matchers.prototype.toBeDefined = function() {
1308
+ return (this.actual !== jasmine.undefined);
1309
+ };
1101
1310
 
1102
- function stack() {
1103
- if (options.passed) {
1104
- return "";
1105
- }
1311
+ /**
1312
+ * Matcher that compares the actual to jasmine.undefined.
1313
+ */
1314
+ jasmine.Matchers.prototype.toBeUndefined = function() {
1315
+ return (this.actual === jasmine.undefined);
1316
+ };
1106
1317
 
1107
- var error = options.error;
1108
- if (!error) {
1109
- try {
1110
- throw new Error(message());
1111
- } catch (e) {
1112
- error = e;
1113
- }
1114
- }
1115
- return stackFormatter(error);
1116
- }
1117
- }
1318
+ /**
1319
+ * Matcher that compares the actual to null.
1320
+ */
1321
+ jasmine.Matchers.prototype.toBeNull = function() {
1322
+ return (this.actual === null);
1323
+ };
1118
1324
 
1119
- return buildExpectationResult;
1325
+ /**
1326
+ * Matcher that compares the actual to NaN.
1327
+ */
1328
+ jasmine.Matchers.prototype.toBeNaN = function() {
1329
+ this.message = function() {
1330
+ return [ "Expected " + jasmine.pp(this.actual) + " to be NaN." ];
1331
+ };
1332
+
1333
+ return (this.actual !== this.actual);
1120
1334
  };
1121
1335
 
1122
- getJasmineRequireObj().ObjectContaining = function(j$) {
1336
+ /**
1337
+ * Matcher that boolean not-nots the actual.
1338
+ */
1339
+ jasmine.Matchers.prototype.toBeTruthy = function() {
1340
+ return !!this.actual;
1341
+ };
1123
1342
 
1124
- function ObjectContaining(sample) {
1125
- this.sample = sample;
1126
- }
1127
1343
 
1128
- ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
1129
- mismatchKeys = mismatchKeys || [];
1130
- mismatchValues = mismatchValues || [];
1344
+ /**
1345
+ * Matcher that boolean nots the actual.
1346
+ */
1347
+ jasmine.Matchers.prototype.toBeFalsy = function() {
1348
+ return !this.actual;
1349
+ };
1131
1350
 
1132
- var hasKey = function(obj, keyName) {
1133
- return obj !== null && !j$.util.isUndefined(obj[keyName]);
1134
- };
1135
1351
 
1136
- for (var property in this.sample) {
1137
- if (!hasKey(other, property) && hasKey(this.sample, property)) {
1138
- mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
1139
- }
1140
- else if (!j$.matchersUtil.equals(this.sample[property], other[property], mismatchKeys, mismatchValues)) {
1141
- mismatchValues.push("'" + property + "' was '" + (other[property] ? j$.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? j$.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual.");
1142
- }
1143
- }
1352
+ /**
1353
+ * Matcher that checks to see if the actual, a Jasmine spy, was called.
1354
+ */
1355
+ jasmine.Matchers.prototype.toHaveBeenCalled = function() {
1356
+ if (arguments.length > 0) {
1357
+ throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
1358
+ }
1144
1359
 
1145
- return (mismatchKeys.length === 0 && mismatchValues.length === 0);
1146
- };
1360
+ if (!jasmine.isSpy(this.actual)) {
1361
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1362
+ }
1147
1363
 
1148
- ObjectContaining.prototype.jasmineToString = function() {
1149
- return "<jasmine.objectContaining(" + j$.pp(this.sample) + ")>";
1364
+ this.message = function() {
1365
+ return [
1366
+ "Expected spy " + this.actual.identity + " to have been called.",
1367
+ "Expected spy " + this.actual.identity + " not to have been called."
1368
+ ];
1150
1369
  };
1151
1370
 
1152
- return ObjectContaining;
1371
+ return this.actual.wasCalled;
1153
1372
  };
1154
1373
 
1155
- getJasmineRequireObj().StringPrettyPrinter = function(j$) {
1374
+ /** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
1375
+ jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
1376
+
1377
+ /**
1378
+ * Matcher that checks to see if the actual, a Jasmine spy, was not called.
1379
+ *
1380
+ * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
1381
+ */
1382
+ jasmine.Matchers.prototype.wasNotCalled = function() {
1383
+ if (arguments.length > 0) {
1384
+ throw new Error('wasNotCalled does not take arguments');
1385
+ }
1156
1386
 
1157
- function PrettyPrinter() {
1158
- this.ppNestLevel_ = 0;
1387
+ if (!jasmine.isSpy(this.actual)) {
1388
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1159
1389
  }
1160
1390
 
1161
- PrettyPrinter.prototype.format = function(value) {
1162
- this.ppNestLevel_++;
1163
- try {
1164
- if (j$.util.isUndefined(value)) {
1165
- this.emitScalar('undefined');
1166
- } else if (value === null) {
1167
- this.emitScalar('null');
1168
- } else if (value === j$.getGlobal()) {
1169
- this.emitScalar('<global>');
1170
- } else if (value.jasmineToString) {
1171
- this.emitScalar(value.jasmineToString());
1172
- } else if (typeof value === 'string') {
1173
- this.emitString(value);
1174
- } else if (j$.isSpy(value)) {
1175
- this.emitScalar("spy on " + value.identity);
1176
- } else if (value instanceof RegExp) {
1177
- this.emitScalar(value.toString());
1178
- } else if (typeof value === 'function') {
1179
- this.emitScalar('Function');
1180
- } else if (typeof value.nodeType === 'number') {
1181
- this.emitScalar('HTMLNode');
1182
- } else if (value instanceof Date) {
1183
- this.emitScalar('Date(' + value + ')');
1184
- } else if (value.__Jasmine_been_here_before__) {
1185
- this.emitScalar('<circular reference: ' + (j$.isArray_(value) ? 'Array' : 'Object') + '>');
1186
- } else if (j$.isArray_(value) || typeof value == 'object') {
1187
- value.__Jasmine_been_here_before__ = true;
1188
- if (j$.isArray_(value)) {
1189
- this.emitArray(value);
1190
- } else {
1191
- this.emitObject(value);
1192
- }
1193
- delete value.__Jasmine_been_here_before__;
1194
- } else {
1195
- this.emitScalar(value.toString());
1196
- }
1197
- } finally {
1198
- this.ppNestLevel_--;
1199
- }
1391
+ this.message = function() {
1392
+ return [
1393
+ "Expected spy " + this.actual.identity + " to not have been called.",
1394
+ "Expected spy " + this.actual.identity + " to have been called."
1395
+ ];
1200
1396
  };
1201
1397
 
1202
- PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1203
- for (var property in obj) {
1204
- if (!obj.hasOwnProperty(property)) continue;
1205
- if (property == '__Jasmine_been_here_before__') continue;
1206
- fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) &&
1207
- obj.__lookupGetter__(property) !== null) : false);
1398
+ return !this.actual.wasCalled;
1399
+ };
1400
+
1401
+ /**
1402
+ * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
1403
+ *
1404
+ * @example
1405
+ *
1406
+ */
1407
+ jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
1408
+ var expectedArgs = jasmine.util.argsToArray(arguments);
1409
+ if (!jasmine.isSpy(this.actual)) {
1410
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1411
+ }
1412
+ this.message = function() {
1413
+ var invertedMessage = "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was.";
1414
+ var positiveMessage = "";
1415
+ if (this.actual.callCount === 0) {
1416
+ positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
1417
+ } else {
1418
+ positiveMessage = "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but actual calls were " + jasmine.pp(this.actual.argsForCall).replace(/^\[ | \]$/g, '')
1208
1419
  }
1420
+ return [positiveMessage, invertedMessage];
1209
1421
  };
1210
1422
 
1211
- PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_;
1212
- PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_;
1213
- PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_;
1214
- PrettyPrinter.prototype.emitString = j$.unimplementedMethod_;
1423
+ return this.env.contains_(this.actual.argsForCall, expectedArgs);
1424
+ };
1215
1425
 
1216
- function StringPrettyPrinter() {
1217
- PrettyPrinter.call(this);
1426
+ /** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
1427
+ jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
1218
1428
 
1219
- this.string = '';
1429
+ /** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
1430
+ jasmine.Matchers.prototype.wasNotCalledWith = function() {
1431
+ var expectedArgs = jasmine.util.argsToArray(arguments);
1432
+ if (!jasmine.isSpy(this.actual)) {
1433
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1220
1434
  }
1221
- j$.util.inherit(StringPrettyPrinter, PrettyPrinter);
1222
1435
 
1223
- StringPrettyPrinter.prototype.emitScalar = function(value) {
1224
- this.append(value);
1436
+ this.message = function() {
1437
+ return [
1438
+ "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
1439
+ "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
1440
+ ];
1225
1441
  };
1226
1442
 
1227
- StringPrettyPrinter.prototype.emitString = function(value) {
1228
- this.append("'" + value + "'");
1229
- };
1443
+ return !this.env.contains_(this.actual.argsForCall, expectedArgs);
1444
+ };
1230
1445
 
1231
- StringPrettyPrinter.prototype.emitArray = function(array) {
1232
- if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
1233
- this.append("Array");
1234
- return;
1235
- }
1446
+ /**
1447
+ * Matcher that checks that the expected item is an element in the actual Array.
1448
+ *
1449
+ * @param {Object} expected
1450
+ */
1451
+ jasmine.Matchers.prototype.toContain = function(expected) {
1452
+ return this.env.contains_(this.actual, expected);
1453
+ };
1236
1454
 
1237
- this.append('[ ');
1238
- for (var i = 0; i < array.length; i++) {
1239
- if (i > 0) {
1240
- this.append(', ');
1241
- }
1242
- this.format(array[i]);
1243
- }
1244
- this.append(' ]');
1245
- };
1455
+ /**
1456
+ * Matcher that checks that the expected item is NOT an element in the actual Array.
1457
+ *
1458
+ * @param {Object} expected
1459
+ * @deprecated as of 1.0. Use not.toContain() instead.
1460
+ */
1461
+ jasmine.Matchers.prototype.toNotContain = function(expected) {
1462
+ return !this.env.contains_(this.actual, expected);
1463
+ };
1246
1464
 
1247
- StringPrettyPrinter.prototype.emitObject = function(obj) {
1248
- if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) {
1249
- this.append("Object");
1250
- return;
1251
- }
1465
+ jasmine.Matchers.prototype.toBeLessThan = function(expected) {
1466
+ return this.actual < expected;
1467
+ };
1252
1468
 
1253
- var self = this;
1254
- this.append('{ ');
1255
- var first = true;
1469
+ jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
1470
+ return this.actual > expected;
1471
+ };
1256
1472
 
1257
- this.iterateObject(obj, function(property, isGetter) {
1258
- if (first) {
1259
- first = false;
1260
- } else {
1261
- self.append(', ');
1262
- }
1473
+ /**
1474
+ * Matcher that checks that the expected item is equal to the actual item
1475
+ * up to a given level of decimal precision (default 2).
1476
+ *
1477
+ * @param {Number} expected
1478
+ * @param {Number} precision, as number of decimal places
1479
+ */
1480
+ jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
1481
+ if (!(precision === 0)) {
1482
+ precision = precision || 2;
1483
+ }
1484
+ return Math.abs(expected - this.actual) < (Math.pow(10, -precision) / 2);
1485
+ };
1263
1486
 
1264
- self.append(property);
1265
- self.append(' : ');
1266
- if (isGetter) {
1267
- self.append('<getter>');
1268
- } else {
1269
- self.format(obj[property]);
1270
- }
1271
- });
1487
+ /**
1488
+ * Matcher that checks that the expected exception was thrown by the actual.
1489
+ *
1490
+ * @param {String} [expected]
1491
+ */
1492
+ jasmine.Matchers.prototype.toThrow = function(expected) {
1493
+ var result = false;
1494
+ var exception;
1495
+ if (typeof this.actual != 'function') {
1496
+ throw new Error('Actual is not a function');
1497
+ }
1498
+ try {
1499
+ this.actual();
1500
+ } catch (e) {
1501
+ exception = e;
1502
+ }
1503
+ if (exception) {
1504
+ result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
1505
+ }
1272
1506
 
1273
- this.append(' }');
1274
- };
1507
+ var not = this.isNot ? "not " : "";
1275
1508
 
1276
- StringPrettyPrinter.prototype.append = function(value) {
1277
- this.string += value;
1509
+ this.message = function() {
1510
+ if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
1511
+ return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
1512
+ } else {
1513
+ return "Expected function to throw an exception.";
1514
+ }
1278
1515
  };
1279
1516
 
1280
- return StringPrettyPrinter;
1517
+ return result;
1281
1518
  };
1282
1519
 
1283
- getJasmineRequireObj().QueueRunner = function() {
1520
+ jasmine.Matchers.Any = function(expectedClass) {
1521
+ this.expectedClass = expectedClass;
1522
+ };
1284
1523
 
1285
- function QueueRunner(attrs) {
1286
- this.fns = attrs.fns || [];
1287
- this.onComplete = attrs.onComplete || function() {};
1288
- this.encourageGC = attrs.encourageGC || function(fn) {fn();};
1289
- this.onException = attrs.onException || function() {};
1290
- this.catchException = attrs.catchException || function() { return true; };
1524
+ jasmine.Matchers.Any.prototype.jasmineMatches = function(other) {
1525
+ if (this.expectedClass == String) {
1526
+ return typeof other == 'string' || other instanceof String;
1291
1527
  }
1292
1528
 
1293
- QueueRunner.prototype.execute = function() {
1294
- this.run(this.fns, 0);
1295
- };
1296
-
1297
- QueueRunner.prototype.run = function(fns, index) {
1298
- if (index >= fns.length) {
1299
- this.encourageGC(this.onComplete);
1300
- return;
1301
- }
1529
+ if (this.expectedClass == Number) {
1530
+ return typeof other == 'number' || other instanceof Number;
1531
+ }
1302
1532
 
1303
- var fn = fns[index];
1304
- var self = this;
1305
- if (fn.length > 0) {
1306
- attempt(function() { fn.call(self, function() { self.run(fns, index + 1); }); });
1307
- } else {
1308
- attempt(function() { fn.call(self); });
1309
- self.run(fns, index + 1);
1310
- }
1533
+ if (this.expectedClass == Function) {
1534
+ return typeof other == 'function' || other instanceof Function;
1535
+ }
1311
1536
 
1312
- function attempt(fn) {
1313
- try {
1314
- fn();
1315
- } catch (e) {
1316
- self.onException(e);
1317
- if (!self.catchException(e)) {
1318
- //TODO: set a var when we catch an exception and
1319
- //use a finally block to close the loop in a nice way..
1320
- throw e;
1321
- }
1322
- }
1323
- }
1324
- };
1537
+ if (this.expectedClass == Object) {
1538
+ return typeof other == 'object';
1539
+ }
1325
1540
 
1326
- return QueueRunner;
1541
+ return other instanceof this.expectedClass;
1327
1542
  };
1328
1543
 
1329
- getJasmineRequireObj().ReportDispatcher = function() {
1330
- function ReportDispatcher(methods) {
1331
-
1332
- var dispatchedMethods = methods || [];
1544
+ jasmine.Matchers.Any.prototype.jasmineToString = function() {
1545
+ return '<jasmine.any(' + this.expectedClass + ')>';
1546
+ };
1333
1547
 
1334
- for (var i = 0; i < dispatchedMethods.length; i++) {
1335
- var method = dispatchedMethods[i];
1336
- this[method] = function(m) {
1337
- return function() {
1338
- dispatch(m, arguments);
1339
- };
1340
- }(method);
1341
- }
1548
+ jasmine.Matchers.ObjectContaining = function (sample) {
1549
+ this.sample = sample;
1550
+ };
1342
1551
 
1343
- var reporters = [];
1552
+ jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
1553
+ mismatchKeys = mismatchKeys || [];
1554
+ mismatchValues = mismatchValues || [];
1344
1555
 
1345
- this.addReporter = function(reporter) {
1346
- reporters.push(reporter);
1347
- };
1556
+ var env = jasmine.getEnv();
1348
1557
 
1349
- return this;
1558
+ var hasKey = function(obj, keyName) {
1559
+ return obj != null && obj[keyName] !== jasmine.undefined;
1560
+ };
1350
1561
 
1351
- function dispatch(method, args) {
1352
- for (var i = 0; i < reporters.length; i++) {
1353
- var reporter = reporters[i];
1354
- if (reporter[method]) {
1355
- reporter[method].apply(reporter, args);
1356
- }
1357
- }
1562
+ for (var property in this.sample) {
1563
+ if (!hasKey(other, property) && hasKey(this.sample, property)) {
1564
+ mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
1565
+ }
1566
+ else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) {
1567
+ mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual.");
1358
1568
  }
1359
1569
  }
1360
1570
 
1361
- return ReportDispatcher;
1571
+ return (mismatchKeys.length === 0 && mismatchValues.length === 0);
1362
1572
  };
1363
1573
 
1574
+ jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
1575
+ return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
1576
+ };
1577
+ // Mock setTimeout, clearTimeout
1578
+ // Contributed by Pivotal Computer Systems, www.pivotalsf.com
1364
1579
 
1365
- getJasmineRequireObj().Spy = function(j$) {
1366
-
1367
- function Spy(name) {
1368
- this.identity = name || 'unknown';
1369
- this.isSpy = true;
1370
- this.plan = function() {
1371
- };
1372
- this.mostRecentCall = {};
1373
-
1374
- this.argsForCall = [];
1375
- this.calls = [];
1376
- }
1580
+ jasmine.FakeTimer = function() {
1581
+ this.reset();
1377
1582
 
1378
- Spy.prototype.andCallThrough = function() {
1379
- this.plan = this.originalValue;
1380
- return this;
1381
- };
1382
-
1383
- Spy.prototype.andReturn = function(value) {
1384
- this.plan = function() {
1385
- return value;
1386
- };
1387
- return this;
1583
+ var self = this;
1584
+ self.setTimeout = function(funcToCall, millis) {
1585
+ self.timeoutsMade++;
1586
+ self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
1587
+ return self.timeoutsMade;
1388
1588
  };
1389
1589
 
1390
- Spy.prototype.andThrow = function(exceptionMsg) {
1391
- this.plan = function() {
1392
- throw exceptionMsg;
1393
- };
1394
- return this;
1590
+ self.setInterval = function(funcToCall, millis) {
1591
+ self.timeoutsMade++;
1592
+ self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
1593
+ return self.timeoutsMade;
1395
1594
  };
1396
1595
 
1397
- Spy.prototype.andCallFake = function(fakeFunc) {
1398
- this.plan = fakeFunc;
1399
- return this;
1596
+ self.clearTimeout = function(timeoutKey) {
1597
+ self.scheduledFunctions[timeoutKey] = jasmine.undefined;
1400
1598
  };
1401
1599
 
1402
- Spy.prototype.reset = function() {
1403
- this.wasCalled = false;
1404
- this.callCount = 0;
1405
- this.argsForCall = [];
1406
- this.calls = [];
1407
- this.mostRecentCall = {};
1600
+ self.clearInterval = function(timeoutKey) {
1601
+ self.scheduledFunctions[timeoutKey] = jasmine.undefined;
1408
1602
  };
1409
1603
 
1410
- j$.createSpy = function(name) {
1411
-
1412
- var spyObj = function() {
1413
- spyObj.wasCalled = true;
1414
- spyObj.callCount++;
1415
- var args = j$.util.argsToArray(arguments);
1416
- spyObj.mostRecentCall.object = this;
1417
- spyObj.mostRecentCall.args = args;
1418
- spyObj.argsForCall.push(args);
1419
- spyObj.calls.push({object: this, args: args});
1420
- return spyObj.plan.apply(this, arguments);
1421
- };
1422
-
1423
- var spy = new Spy(name);
1424
-
1425
- for (var prop in spy) {
1426
- spyObj[prop] = spy[prop];
1427
- }
1428
-
1429
- spyObj.reset();
1604
+ };
1430
1605
 
1431
- return spyObj;
1432
- };
1606
+ jasmine.FakeTimer.prototype.reset = function() {
1607
+ this.timeoutsMade = 0;
1608
+ this.scheduledFunctions = {};
1609
+ this.nowMillis = 0;
1610
+ };
1433
1611
 
1434
- j$.isSpy = function(putativeSpy) {
1435
- return putativeSpy && putativeSpy.isSpy;
1436
- };
1612
+ jasmine.FakeTimer.prototype.tick = function(millis) {
1613
+ var oldMillis = this.nowMillis;
1614
+ var newMillis = oldMillis + millis;
1615
+ this.runFunctionsWithinRange(oldMillis, newMillis);
1616
+ this.nowMillis = newMillis;
1617
+ };
1437
1618
 
1438
- j$.createSpyObj = function(baseName, methodNames) {
1439
- if (!j$.isArray_(methodNames) || methodNames.length === 0) {
1440
- throw "createSpyObj requires a non-empty array of method names to create spies for";
1441
- }
1442
- var obj = {};
1443
- for (var i = 0; i < methodNames.length; i++) {
1444
- obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]);
1619
+ jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
1620
+ var scheduledFunc;
1621
+ var funcsToRun = [];
1622
+ for (var timeoutKey in this.scheduledFunctions) {
1623
+ scheduledFunc = this.scheduledFunctions[timeoutKey];
1624
+ if (scheduledFunc != jasmine.undefined &&
1625
+ scheduledFunc.runAtMillis >= oldMillis &&
1626
+ scheduledFunc.runAtMillis <= nowMillis) {
1627
+ funcsToRun.push(scheduledFunc);
1628
+ this.scheduledFunctions[timeoutKey] = jasmine.undefined;
1445
1629
  }
1446
- return obj;
1447
- };
1448
-
1449
- return Spy;
1450
- };
1451
-
1452
- getJasmineRequireObj().Suite = function() {
1453
- function Suite(attrs) {
1454
- this.env = attrs.env;
1455
- this.id = attrs.id;
1456
- this.parentSuite = attrs.parentSuite;
1457
- this.description = attrs.description;
1458
- this.onStart = attrs.onStart || function() {};
1459
- this.completeCallback = attrs.completeCallback || function() {};
1460
- this.resultCallback = attrs.resultCallback || function() {};
1461
- this.encourageGC = attrs.encourageGC || function(fn) {fn();};
1462
-
1463
- this.beforeFns = [];
1464
- this.afterFns = [];
1465
- this.queueRunner = attrs.queueRunner || function() {};
1466
- this.disabled = false;
1467
-
1468
- this.children_ = []; // TODO: rename
1469
- this.suites = []; // TODO: needed?
1470
- this.specs = []; // TODO: needed?
1471
-
1472
- this.result = {
1473
- id: this.id,
1474
- status: this.disabled ? 'disabled' : '',
1475
- description: this.description,
1476
- fullName: this.getFullName()
1477
- };
1478
1630
  }
1479
1631
 
1480
- Suite.prototype.getFullName = function() {
1481
- var fullName = this.description;
1482
- for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
1483
- if (parentSuite.parentSuite) {
1484
- fullName = parentSuite.description + ' ' + fullName;
1632
+ if (funcsToRun.length > 0) {
1633
+ funcsToRun.sort(function(a, b) {
1634
+ return a.runAtMillis - b.runAtMillis;
1635
+ });
1636
+ for (var i = 0; i < funcsToRun.length; ++i) {
1637
+ try {
1638
+ var funcToRun = funcsToRun[i];
1639
+ this.nowMillis = funcToRun.runAtMillis;
1640
+ funcToRun.funcToCall();
1641
+ if (funcToRun.recurring) {
1642
+ this.scheduleFunction(funcToRun.timeoutKey,
1643
+ funcToRun.funcToCall,
1644
+ funcToRun.millis,
1645
+ true);
1646
+ }
1647
+ } catch(e) {
1485
1648
  }
1486
1649
  }
1487
- return fullName;
1488
- };
1489
-
1490
- Suite.prototype.disable = function() {
1491
- this.disabled = true;
1492
- };
1650
+ this.runFunctionsWithinRange(oldMillis, nowMillis);
1651
+ }
1652
+ };
1493
1653
 
1494
- Suite.prototype.beforeEach = function(fn) {
1495
- this.beforeFns.unshift(fn);
1654
+ jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
1655
+ this.scheduledFunctions[timeoutKey] = {
1656
+ runAtMillis: this.nowMillis + millis,
1657
+ funcToCall: funcToCall,
1658
+ recurring: recurring,
1659
+ timeoutKey: timeoutKey,
1660
+ millis: millis
1496
1661
  };
1662
+ };
1497
1663
 
1498
- Suite.prototype.afterEach = function(fn) {
1499
- this.afterFns.unshift(fn);
1500
- };
1664
+ /**
1665
+ * @namespace
1666
+ */
1667
+ jasmine.Clock = {
1668
+ defaultFakeTimer: new jasmine.FakeTimer(),
1501
1669
 
1502
- Suite.prototype.addSpec = function(spec) {
1503
- this.children_.push(spec);
1504
- this.specs.push(spec); // TODO: needed?
1505
- };
1670
+ reset: function() {
1671
+ jasmine.Clock.assertInstalled();
1672
+ jasmine.Clock.defaultFakeTimer.reset();
1673
+ },
1506
1674
 
1507
- Suite.prototype.addSuite = function(suite) {
1508
- suite.parentSuite = this;
1509
- this.children_.push(suite);
1510
- this.suites.push(suite); // TODO: needed?
1511
- };
1675
+ tick: function(millis) {
1676
+ jasmine.Clock.assertInstalled();
1677
+ jasmine.Clock.defaultFakeTimer.tick(millis);
1678
+ },
1512
1679
 
1513
- Suite.prototype.children = function() {
1514
- return this.children_;
1515
- };
1680
+ runFunctionsWithinRange: function(oldMillis, nowMillis) {
1681
+ jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
1682
+ },
1516
1683
 
1517
- Suite.prototype.execute = function(onComplete) {
1518
- var self = this;
1519
- if (this.disabled) {
1520
- complete();
1521
- return;
1522
- }
1684
+ scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
1685
+ jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
1686
+ },
1523
1687
 
1524
- var allFns = [],
1525
- children = this.children_;
1688
+ useMock: function() {
1689
+ if (!jasmine.Clock.isInstalled()) {
1690
+ var spec = jasmine.getEnv().currentSpec;
1691
+ spec.after(jasmine.Clock.uninstallMock);
1526
1692
 
1527
- for (var i = 0; i < children.length; i++) {
1528
- allFns.push(wrapChild(children[i]));
1693
+ jasmine.Clock.installMock();
1529
1694
  }
1695
+ },
1530
1696
 
1531
- this.onStart(this);
1697
+ installMock: function() {
1698
+ jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
1699
+ },
1532
1700
 
1533
- this.queueRunner({
1534
- fns: allFns,
1535
- onComplete: complete
1536
- });
1701
+ uninstallMock: function() {
1702
+ jasmine.Clock.assertInstalled();
1703
+ jasmine.Clock.installed = jasmine.Clock.real;
1704
+ },
1537
1705
 
1538
- function complete() {
1539
- self.resultCallback(self.result);
1706
+ real: {
1707
+ setTimeout: jasmine.getGlobal().setTimeout,
1708
+ clearTimeout: jasmine.getGlobal().clearTimeout,
1709
+ setInterval: jasmine.getGlobal().setInterval,
1710
+ clearInterval: jasmine.getGlobal().clearInterval
1711
+ },
1540
1712
 
1541
- if (onComplete) {
1542
- onComplete();
1543
- }
1713
+ assertInstalled: function() {
1714
+ if (!jasmine.Clock.isInstalled()) {
1715
+ throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
1544
1716
  }
1717
+ },
1545
1718
 
1546
- function wrapChild(child) {
1547
- return function(done) {
1548
- child.execute(done);
1549
- };
1550
- }
1551
- };
1552
-
1553
- return Suite;
1719
+ isInstalled: function() {
1720
+ return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
1721
+ },
1722
+
1723
+ installed: null
1724
+ };
1725
+ jasmine.Clock.installed = jasmine.Clock.real;
1726
+
1727
+ //else for IE support
1728
+ jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
1729
+ if (jasmine.Clock.installed.setTimeout.apply) {
1730
+ return jasmine.Clock.installed.setTimeout.apply(this, arguments);
1731
+ } else {
1732
+ return jasmine.Clock.installed.setTimeout(funcToCall, millis);
1733
+ }
1554
1734
  };
1555
1735
 
1556
- if (typeof window == void 0 && typeof exports == "object") {
1557
- exports.Suite = jasmineRequire.Suite;
1558
- }
1736
+ jasmine.getGlobal().setInterval = function(funcToCall, millis) {
1737
+ if (jasmine.Clock.installed.setInterval.apply) {
1738
+ return jasmine.Clock.installed.setInterval.apply(this, arguments);
1739
+ } else {
1740
+ return jasmine.Clock.installed.setInterval(funcToCall, millis);
1741
+ }
1742
+ };
1559
1743
 
1560
- getJasmineRequireObj().matchersUtil = function(j$) {
1561
- // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter?
1744
+ jasmine.getGlobal().clearTimeout = function(timeoutKey) {
1745
+ if (jasmine.Clock.installed.clearTimeout.apply) {
1746
+ return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
1747
+ } else {
1748
+ return jasmine.Clock.installed.clearTimeout(timeoutKey);
1749
+ }
1750
+ };
1562
1751
 
1563
- return {
1564
- equals: function(a, b, customTesters) {
1565
- customTesters = customTesters || [];
1752
+ jasmine.getGlobal().clearInterval = function(timeoutKey) {
1753
+ if (jasmine.Clock.installed.clearTimeout.apply) {
1754
+ return jasmine.Clock.installed.clearInterval.apply(this, arguments);
1755
+ } else {
1756
+ return jasmine.Clock.installed.clearInterval(timeoutKey);
1757
+ }
1758
+ };
1566
1759
 
1567
- return eq(a, b, [], [], customTesters);
1568
- },
1760
+ /**
1761
+ * @constructor
1762
+ */
1763
+ jasmine.MultiReporter = function() {
1764
+ this.subReporters_ = [];
1765
+ };
1766
+ jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
1569
1767
 
1570
- contains: function(haystack, needle, customTesters) {
1571
- customTesters = customTesters || [];
1768
+ jasmine.MultiReporter.prototype.addReporter = function(reporter) {
1769
+ this.subReporters_.push(reporter);
1770
+ };
1572
1771
 
1573
- if (Object.prototype.toString.apply(haystack) === "[object Array]") {
1574
- for (var i = 0; i < haystack.length; i++) {
1575
- if (eq(haystack[i], needle, [], [], customTesters)) {
1576
- return true;
1772
+ (function() {
1773
+ var functionNames = [
1774
+ "reportRunnerStarting",
1775
+ "reportRunnerResults",
1776
+ "reportSuiteResults",
1777
+ "reportSpecStarting",
1778
+ "reportSpecResults",
1779
+ "log"
1780
+ ];
1781
+ for (var i = 0; i < functionNames.length; i++) {
1782
+ var functionName = functionNames[i];
1783
+ jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
1784
+ return function() {
1785
+ for (var j = 0; j < this.subReporters_.length; j++) {
1786
+ var subReporter = this.subReporters_[j];
1787
+ if (subReporter[functionName]) {
1788
+ subReporter[functionName].apply(subReporter, arguments);
1577
1789
  }
1578
1790
  }
1579
- return false;
1580
- }
1581
- return haystack.indexOf(needle) >= 0;
1582
- },
1583
-
1584
- buildFailureMessage: function() {
1585
- var args = Array.prototype.slice.call(arguments, 0),
1586
- matcherName = args[0],
1587
- isNot = args[1],
1588
- actual = args[2],
1589
- expected = args.slice(3),
1590
- englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
1591
-
1592
- var message = "Expected " +
1593
- j$.pp(actual) +
1594
- (isNot ? " not " : " ") +
1595
- englishyPredicate;
1596
-
1597
- if (expected.length > 0) {
1598
- for (var i = 0; i < expected.length; i++) {
1599
- if (i > 0) message += ",";
1600
- message += " " + j$.pp(expected[i]);
1601
- }
1602
- }
1791
+ };
1792
+ })(functionName);
1793
+ }
1794
+ })();
1795
+ /**
1796
+ * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
1797
+ *
1798
+ * @constructor
1799
+ */
1800
+ jasmine.NestedResults = function() {
1801
+ /**
1802
+ * The total count of results
1803
+ */
1804
+ this.totalCount = 0;
1805
+ /**
1806
+ * Number of passed results
1807
+ */
1808
+ this.passedCount = 0;
1809
+ /**
1810
+ * Number of failed results
1811
+ */
1812
+ this.failedCount = 0;
1813
+ /**
1814
+ * Was this suite/spec skipped?
1815
+ */
1816
+ this.skipped = false;
1817
+ /**
1818
+ * @ignore
1819
+ */
1820
+ this.items_ = [];
1821
+ };
1603
1822
 
1604
- return message + ".";
1605
- }
1606
- };
1823
+ /**
1824
+ * Roll up the result counts.
1825
+ *
1826
+ * @param result
1827
+ */
1828
+ jasmine.NestedResults.prototype.rollupCounts = function(result) {
1829
+ this.totalCount += result.totalCount;
1830
+ this.passedCount += result.passedCount;
1831
+ this.failedCount += result.failedCount;
1832
+ };
1607
1833
 
1608
- // Equality function lovingly adapted from isEqual in
1609
- // [Underscore](http://underscorejs.org)
1610
- function eq(a, b, aStack, bStack, customTesters) {
1611
- var result = true;
1834
+ /**
1835
+ * Adds a log message.
1836
+ * @param values Array of message parts which will be concatenated later.
1837
+ */
1838
+ jasmine.NestedResults.prototype.log = function(values) {
1839
+ this.items_.push(new jasmine.MessageResult(values));
1840
+ };
1612
1841
 
1613
- for (var i = 0; i < customTesters.length; i++) {
1614
- result = customTesters[i](a, b);
1615
- if (result) {
1616
- return true;
1617
- }
1618
- }
1842
+ /**
1843
+ * Getter for the results: message & results.
1844
+ */
1845
+ jasmine.NestedResults.prototype.getItems = function() {
1846
+ return this.items_;
1847
+ };
1619
1848
 
1620
- if (a instanceof j$.Any) {
1621
- result = a.jasmineMatches(b);
1622
- if (result) {
1623
- return true;
1849
+ /**
1850
+ * Adds a result, tracking counts (total, passed, & failed)
1851
+ * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
1852
+ */
1853
+ jasmine.NestedResults.prototype.addResult = function(result) {
1854
+ if (result.type != 'log') {
1855
+ if (result.items_) {
1856
+ this.rollupCounts(result);
1857
+ } else {
1858
+ this.totalCount++;
1859
+ if (result.passed()) {
1860
+ this.passedCount++;
1861
+ } else {
1862
+ this.failedCount++;
1624
1863
  }
1625
1864
  }
1865
+ }
1866
+ this.items_.push(result);
1867
+ };
1626
1868
 
1627
- if (b instanceof j$.Any) {
1628
- result = b.jasmineMatches(a);
1629
- if (result) {
1630
- return true;
1631
- }
1632
- }
1869
+ /**
1870
+ * @returns {Boolean} True if <b>everything</b> below passed
1871
+ */
1872
+ jasmine.NestedResults.prototype.passed = function() {
1873
+ return this.passedCount === this.totalCount;
1874
+ };
1875
+ /**
1876
+ * Base class for pretty printing for expectation results.
1877
+ */
1878
+ jasmine.PrettyPrinter = function() {
1879
+ this.ppNestLevel_ = 0;
1880
+ };
1633
1881
 
1634
- if (b instanceof j$.ObjectContaining) {
1635
- result = b.jasmineMatches(a);
1636
- if (result) {
1637
- return true;
1882
+ /**
1883
+ * Formats a value in a nice, human-readable string.
1884
+ *
1885
+ * @param value
1886
+ */
1887
+ jasmine.PrettyPrinter.prototype.format = function(value) {
1888
+ this.ppNestLevel_++;
1889
+ try {
1890
+ if (value === jasmine.undefined) {
1891
+ this.emitScalar('undefined');
1892
+ } else if (value === null) {
1893
+ this.emitScalar('null');
1894
+ } else if (value === jasmine.getGlobal()) {
1895
+ this.emitScalar('<global>');
1896
+ } else if (value.jasmineToString) {
1897
+ this.emitScalar(value.jasmineToString());
1898
+ } else if (typeof value === 'string') {
1899
+ this.emitString(value);
1900
+ } else if (jasmine.isSpy(value)) {
1901
+ this.emitScalar("spy on " + value.identity);
1902
+ } else if (value instanceof RegExp) {
1903
+ this.emitScalar(value.toString());
1904
+ } else if (typeof value === 'function') {
1905
+ this.emitScalar('Function');
1906
+ } else if (typeof value.nodeType === 'number') {
1907
+ this.emitScalar('HTMLNode');
1908
+ } else if (value instanceof Date) {
1909
+ this.emitScalar('Date(' + value + ')');
1910
+ } else if (value.__Jasmine_been_here_before__) {
1911
+ this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
1912
+ } else if (jasmine.isArray_(value) || typeof value == 'object') {
1913
+ value.__Jasmine_been_here_before__ = true;
1914
+ if (jasmine.isArray_(value)) {
1915
+ this.emitArray(value);
1916
+ } else {
1917
+ this.emitObject(value);
1638
1918
  }
1919
+ delete value.__Jasmine_been_here_before__;
1920
+ } else {
1921
+ this.emitScalar(value.toString());
1639
1922
  }
1923
+ } finally {
1924
+ this.ppNestLevel_--;
1925
+ }
1926
+ };
1640
1927
 
1641
- if (a instanceof Error && b instanceof Error) {
1642
- return a.message == b.message;
1643
- }
1928
+ jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1929
+ for (var property in obj) {
1930
+ if (!obj.hasOwnProperty(property)) continue;
1931
+ if (property == '__Jasmine_been_here_before__') continue;
1932
+ fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
1933
+ obj.__lookupGetter__(property) !== null) : false);
1934
+ }
1935
+ };
1644
1936
 
1645
- // Identical objects are equal. `0 === -0`, but they aren't identical.
1646
- // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
1647
- if (a === b) return a !== 0 || 1 / a == 1 / b;
1648
- // A strict comparison is necessary because `null == undefined`.
1649
- if (a === null || b === null) return a === b;
1650
- var className = Object.prototype.toString.call(a);
1651
- if (className != Object.prototype.toString.call(b)) return false;
1652
- switch (className) {
1653
- // Strings, numbers, dates, and booleans are compared by value.
1654
- case '[object String]':
1655
- // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
1656
- // equivalent to `new String("5")`.
1657
- return a == String(b);
1658
- case '[object Number]':
1659
- // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
1660
- // other numeric values.
1661
- return a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b);
1662
- case '[object Date]':
1663
- case '[object Boolean]':
1664
- // Coerce dates and booleans to numeric primitive values. Dates are compared by their
1665
- // millisecond representations. Note that invalid dates with millisecond representations
1666
- // of `NaN` are not equivalent.
1667
- return +a == +b;
1668
- // RegExps are compared by their source patterns and flags.
1669
- case '[object RegExp]':
1670
- return a.source == b.source &&
1671
- a.global == b.global &&
1672
- a.multiline == b.multiline &&
1673
- a.ignoreCase == b.ignoreCase;
1674
- }
1675
- if (typeof a != 'object' || typeof b != 'object') return false;
1676
- // Assume equality for cyclic structures. The algorithm for detecting cyclic
1677
- // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
1678
- var length = aStack.length;
1679
- while (length--) {
1680
- // Linear search. Performance is inversely proportional to the number of
1681
- // unique nested structures.
1682
- if (aStack[length] == a) return bStack[length] == b;
1683
- }
1684
- // Add the first object to the stack of traversed objects.
1685
- aStack.push(a);
1686
- bStack.push(b);
1687
- var size = 0;
1688
- // Recursively compare objects and arrays.
1689
- if (className == '[object Array]') {
1690
- // Compare array lengths to determine if a deep comparison is necessary.
1691
- size = a.length;
1692
- result = size == b.length;
1693
- if (result) {
1694
- // Deep compare the contents, ignoring non-numeric properties.
1695
- while (size--) {
1696
- if (!(result = eq(a[size], b[size], aStack, bStack, customTesters))) break;
1697
- }
1698
- }
1699
- } else {
1700
- // Objects with different constructors are not equivalent, but `Object`s
1701
- // from different frames are.
1702
- var aCtor = a.constructor, bCtor = b.constructor;
1703
- if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) &&
1704
- isFunction(bCtor) && (bCtor instanceof bCtor))) {
1705
- return false;
1706
- }
1707
- // Deep compare objects.
1708
- for (var key in a) {
1709
- if (has(a, key)) {
1710
- // Count the expected number of properties.
1711
- size++;
1712
- // Deep compare each member.
1713
- if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) break;
1714
- }
1715
- }
1716
- // Ensure that both objects contain the same number of properties.
1717
- if (result) {
1718
- for (key in b) {
1719
- if (has(b, key) && !(size--)) break;
1720
- }
1721
- result = !size;
1722
- }
1723
- }
1724
- // Remove the first object from the stack of traversed objects.
1725
- aStack.pop();
1726
- bStack.pop();
1937
+ jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
1938
+ jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
1939
+ jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
1940
+ jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
1727
1941
 
1728
- return result;
1942
+ jasmine.StringPrettyPrinter = function() {
1943
+ jasmine.PrettyPrinter.call(this);
1729
1944
 
1730
- function has(obj, key) {
1731
- return obj.hasOwnProperty(key);
1732
- }
1945
+ this.string = '';
1946
+ };
1947
+ jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
1948
+
1949
+ jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
1950
+ this.append(value);
1951
+ };
1733
1952
 
1734
- function isFunction(obj) {
1735
- return typeof obj === 'function';
1953
+ jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
1954
+ this.append("'" + value + "'");
1955
+ };
1956
+
1957
+ jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
1958
+ if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
1959
+ this.append("Array");
1960
+ return;
1961
+ }
1962
+
1963
+ this.append('[ ');
1964
+ for (var i = 0; i < array.length; i++) {
1965
+ if (i > 0) {
1966
+ this.append(', ');
1736
1967
  }
1968
+ this.format(array[i]);
1737
1969
  }
1970
+ this.append(' ]');
1738
1971
  };
1739
- getJasmineRequireObj().toBe = function() {
1740
- function toBe() {
1741
- return {
1742
- compare: function(actual, expected) {
1743
- return {
1744
- pass: actual === expected
1745
- };
1746
- }
1747
- };
1972
+
1973
+ jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
1974
+ if (this.ppNestLevel_ > jasmine.MAX_PRETTY_PRINT_DEPTH) {
1975
+ this.append("Object");
1976
+ return;
1748
1977
  }
1749
1978
 
1750
- return toBe;
1751
- };
1979
+ var self = this;
1980
+ this.append('{ ');
1981
+ var first = true;
1752
1982
 
1753
- getJasmineRequireObj().toBeCloseTo = function() {
1983
+ this.iterateObject(obj, function(property, isGetter) {
1984
+ if (first) {
1985
+ first = false;
1986
+ } else {
1987
+ self.append(', ');
1988
+ }
1754
1989
 
1755
- function toBeCloseTo() {
1756
- return {
1757
- compare: function(actual, expected, precision) {
1758
- if (precision !== 0) {
1759
- precision = precision || 2;
1760
- }
1990
+ self.append(property);
1991
+ self.append(' : ');
1992
+ if (isGetter) {
1993
+ self.append('<getter>');
1994
+ } else {
1995
+ self.format(obj[property]);
1996
+ }
1997
+ });
1761
1998
 
1762
- return {
1763
- pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2)
1764
- };
1765
- }
1766
- };
1767
- }
1999
+ this.append(' }');
2000
+ };
1768
2001
 
1769
- return toBeCloseTo;
2002
+ jasmine.StringPrettyPrinter.prototype.append = function(value) {
2003
+ this.string += value;
2004
+ };
2005
+ jasmine.Queue = function(env) {
2006
+ this.env = env;
2007
+
2008
+ // parallel to blocks. each true value in this array means the block will
2009
+ // get executed even if we abort
2010
+ this.ensured = [];
2011
+ this.blocks = [];
2012
+ this.running = false;
2013
+ this.index = 0;
2014
+ this.offset = 0;
2015
+ this.abort = false;
1770
2016
  };
1771
2017
 
1772
- getJasmineRequireObj().toBeDefined = function() {
1773
- function toBeDefined() {
1774
- return {
1775
- compare: function(actual) {
1776
- return {
1777
- pass: (void 0 !== actual)
1778
- };
1779
- }
1780
- };
2018
+ jasmine.Queue.prototype.addBefore = function(block, ensure) {
2019
+ if (ensure === jasmine.undefined) {
2020
+ ensure = false;
1781
2021
  }
1782
2022
 
1783
- return toBeDefined;
2023
+ this.blocks.unshift(block);
2024
+ this.ensured.unshift(ensure);
1784
2025
  };
1785
2026
 
1786
- getJasmineRequireObj().toBeFalsy = function() {
1787
- function toBeFalsy() {
1788
- return {
1789
- compare: function(actual) {
1790
- return {
1791
- pass: !!!actual
1792
- };
1793
- }
1794
- };
2027
+ jasmine.Queue.prototype.add = function(block, ensure) {
2028
+ if (ensure === jasmine.undefined) {
2029
+ ensure = false;
1795
2030
  }
1796
2031
 
1797
- return toBeFalsy;
2032
+ this.blocks.push(block);
2033
+ this.ensured.push(ensure);
1798
2034
  };
1799
2035
 
1800
- getJasmineRequireObj().toBeGreaterThan = function() {
1801
-
1802
- function toBeGreaterThan() {
1803
- return {
1804
- compare: function(actual, expected) {
1805
- return {
1806
- pass: actual > expected
1807
- };
1808
- }
1809
- };
2036
+ jasmine.Queue.prototype.insertNext = function(block, ensure) {
2037
+ if (ensure === jasmine.undefined) {
2038
+ ensure = false;
1810
2039
  }
1811
2040
 
1812
- return toBeGreaterThan;
2041
+ this.ensured.splice((this.index + this.offset + 1), 0, ensure);
2042
+ this.blocks.splice((this.index + this.offset + 1), 0, block);
2043
+ this.offset++;
1813
2044
  };
1814
2045
 
2046
+ jasmine.Queue.prototype.start = function(onComplete) {
2047
+ this.running = true;
2048
+ this.onComplete = onComplete;
2049
+ this.next_();
2050
+ };
1815
2051
 
1816
- getJasmineRequireObj().toBeLessThan = function() {
1817
- function toBeLessThan() {
1818
- return {
2052
+ jasmine.Queue.prototype.isRunning = function() {
2053
+ return this.running;
2054
+ };
1819
2055
 
1820
- compare: function(actual, expected) {
1821
- return {
1822
- pass: actual < expected
1823
- };
1824
- }
1825
- };
1826
- }
2056
+ jasmine.Queue.LOOP_DONT_RECURSE = true;
1827
2057
 
1828
- return toBeLessThan;
1829
- };
1830
- getJasmineRequireObj().toBeNaN = function() {
2058
+ jasmine.Queue.prototype.next_ = function() {
2059
+ var self = this;
2060
+ var goAgain = true;
2061
+
2062
+ while (goAgain) {
2063
+ goAgain = false;
2064
+
2065
+ if (self.index < self.blocks.length && !(this.abort && !this.ensured[self.index])) {
2066
+ var calledSynchronously = true;
2067
+ var completedSynchronously = false;
1831
2068
 
1832
- function toBeNaN() {
1833
- return {
1834
- compare: function(actual) {
1835
- var result = {
1836
- pass: (actual !== actual)
1837
- };
2069
+ var onComplete = function () {
2070
+ if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
2071
+ completedSynchronously = true;
2072
+ return;
2073
+ }
2074
+
2075
+ if (self.blocks[self.index].abort) {
2076
+ self.abort = true;
2077
+ }
1838
2078
 
1839
- if (result.pass) {
1840
- result.message = "Expected actual not to be NaN.";
2079
+ self.offset = 0;
2080
+ self.index++;
2081
+
2082
+ var now = new Date().getTime();
2083
+ if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
2084
+ self.env.lastUpdate = now;
2085
+ self.env.setTimeout(function() {
2086
+ self.next_();
2087
+ }, 0);
1841
2088
  } else {
1842
- result.message = "Expected " + j$.pp(actual) + " to be NaN.";
2089
+ if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
2090
+ goAgain = true;
2091
+ } else {
2092
+ self.next_();
2093
+ }
1843
2094
  }
2095
+ };
2096
+ self.blocks[self.index].execute(onComplete);
1844
2097
 
1845
- return result;
2098
+ calledSynchronously = false;
2099
+ if (completedSynchronously) {
2100
+ onComplete();
1846
2101
  }
1847
- };
2102
+
2103
+ } else {
2104
+ self.running = false;
2105
+ if (self.onComplete) {
2106
+ self.onComplete();
2107
+ }
2108
+ }
1848
2109
  }
2110
+ };
1849
2111
 
1850
- return toBeNaN;
2112
+ jasmine.Queue.prototype.results = function() {
2113
+ var results = new jasmine.NestedResults();
2114
+ for (var i = 0; i < this.blocks.length; i++) {
2115
+ if (this.blocks[i].results) {
2116
+ results.addResult(this.blocks[i].results());
2117
+ }
2118
+ }
2119
+ return results;
1851
2120
  };
1852
2121
 
1853
- getJasmineRequireObj().toBeNull = function() {
1854
2122
 
1855
- function toBeNull() {
1856
- return {
1857
- compare: function(actual) {
1858
- return {
1859
- pass: actual === null
1860
- };
1861
- }
1862
- };
2123
+ /**
2124
+ * Runner
2125
+ *
2126
+ * @constructor
2127
+ * @param {jasmine.Env} env
2128
+ */
2129
+ jasmine.Runner = function(env) {
2130
+ var self = this;
2131
+ self.env = env;
2132
+ self.queue = new jasmine.Queue(env);
2133
+ self.before_ = [];
2134
+ self.after_ = [];
2135
+ self.suites_ = [];
2136
+ };
2137
+
2138
+ jasmine.Runner.prototype.execute = function() {
2139
+ var self = this;
2140
+ if (self.env.reporter.reportRunnerStarting) {
2141
+ self.env.reporter.reportRunnerStarting(this);
1863
2142
  }
2143
+ self.queue.start(function () {
2144
+ self.finishCallback();
2145
+ });
2146
+ };
1864
2147
 
1865
- return toBeNull;
2148
+ jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
2149
+ beforeEachFunction.typeName = 'beforeEach';
2150
+ this.before_.splice(0,0,beforeEachFunction);
1866
2151
  };
1867
2152
 
1868
- getJasmineRequireObj().toBeTruthy = function() {
2153
+ jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
2154
+ afterEachFunction.typeName = 'afterEach';
2155
+ this.after_.splice(0,0,afterEachFunction);
2156
+ };
1869
2157
 
1870
- function toBeTruthy() {
1871
- return {
1872
- compare: function(actual) {
1873
- return {
1874
- pass: !!actual
1875
- };
1876
- }
1877
- };
1878
- }
1879
2158
 
1880
- return toBeTruthy;
2159
+ jasmine.Runner.prototype.finishCallback = function() {
2160
+ this.env.reporter.reportRunnerResults(this);
1881
2161
  };
1882
2162
 
1883
- getJasmineRequireObj().toBeUndefined = function() {
2163
+ jasmine.Runner.prototype.addSuite = function(suite) {
2164
+ this.suites_.push(suite);
2165
+ };
1884
2166
 
1885
- function toBeUndefined() {
1886
- return {
1887
- compare: function(actual) {
1888
- return {
1889
- pass: void 0 === actual
1890
- };
1891
- }
1892
- };
2167
+ jasmine.Runner.prototype.add = function(block) {
2168
+ if (block instanceof jasmine.Suite) {
2169
+ this.addSuite(block);
1893
2170
  }
2171
+ this.queue.add(block);
2172
+ };
1894
2173
 
1895
- return toBeUndefined;
2174
+ jasmine.Runner.prototype.specs = function () {
2175
+ var suites = this.suites();
2176
+ var specs = [];
2177
+ for (var i = 0; i < suites.length; i++) {
2178
+ specs = specs.concat(suites[i].specs());
2179
+ }
2180
+ return specs;
1896
2181
  };
1897
2182
 
1898
- getJasmineRequireObj().toContain = function() {
1899
- function toContain(util, customEqualityTesters) {
1900
- customEqualityTesters = customEqualityTesters || [];
2183
+ jasmine.Runner.prototype.suites = function() {
2184
+ return this.suites_;
2185
+ };
1901
2186
 
1902
- return {
1903
- compare: function(actual, expected) {
2187
+ jasmine.Runner.prototype.topLevelSuites = function() {
2188
+ var topLevelSuites = [];
2189
+ for (var i = 0; i < this.suites_.length; i++) {
2190
+ if (!this.suites_[i].parentSuite) {
2191
+ topLevelSuites.push(this.suites_[i]);
2192
+ }
2193
+ }
2194
+ return topLevelSuites;
2195
+ };
1904
2196
 
1905
- return {
1906
- pass: util.contains(actual, expected, customEqualityTesters)
1907
- };
1908
- }
1909
- };
2197
+ jasmine.Runner.prototype.results = function() {
2198
+ return this.queue.results();
2199
+ };
2200
+ /**
2201
+ * Internal representation of a Jasmine specification, or test.
2202
+ *
2203
+ * @constructor
2204
+ * @param {jasmine.Env} env
2205
+ * @param {jasmine.Suite} suite
2206
+ * @param {String} description
2207
+ */
2208
+ jasmine.Spec = function(env, suite, description) {
2209
+ if (!env) {
2210
+ throw new Error('jasmine.Env() required');
2211
+ }
2212
+ if (!suite) {
2213
+ throw new Error('jasmine.Suite() required');
1910
2214
  }
2215
+ var spec = this;
2216
+ spec.id = env.nextSpecId ? env.nextSpecId() : null;
2217
+ spec.env = env;
2218
+ spec.suite = suite;
2219
+ spec.description = description;
2220
+ spec.queue = new jasmine.Queue(env);
2221
+
2222
+ spec.afterCallbacks = [];
2223
+ spec.spies_ = [];
2224
+
2225
+ spec.results_ = new jasmine.NestedResults();
2226
+ spec.results_.description = description;
2227
+ spec.matchersClass = null;
2228
+ };
1911
2229
 
1912
- return toContain;
2230
+ jasmine.Spec.prototype.getFullName = function() {
2231
+ return this.suite.getFullName() + ' ' + this.description + '.';
1913
2232
  };
1914
2233
 
1915
- getJasmineRequireObj().toEqual = function() {
1916
2234
 
1917
- function toEqual(util, customEqualityTesters) {
1918
- customEqualityTesters = customEqualityTesters || [];
2235
+ jasmine.Spec.prototype.results = function() {
2236
+ return this.results_;
2237
+ };
1919
2238
 
1920
- return {
1921
- compare: function(actual, expected) {
1922
- var result = {
1923
- pass: false
1924
- };
2239
+ /**
2240
+ * All parameters are pretty-printed and concatenated together, then written to the spec's output.
2241
+ *
2242
+ * Be careful not to leave calls to <code>jasmine.log</code> in production code.
2243
+ */
2244
+ jasmine.Spec.prototype.log = function() {
2245
+ return this.results_.log(arguments);
2246
+ };
1925
2247
 
1926
- result.pass = util.equals(actual, expected, customEqualityTesters);
2248
+ jasmine.Spec.prototype.runs = function (func) {
2249
+ var block = new jasmine.Block(this.env, func, this);
2250
+ this.addToQueue(block);
2251
+ return this;
2252
+ };
1927
2253
 
1928
- return result;
1929
- }
1930
- };
2254
+ jasmine.Spec.prototype.addToQueue = function (block) {
2255
+ if (this.queue.isRunning()) {
2256
+ this.queue.insertNext(block);
2257
+ } else {
2258
+ this.queue.add(block);
1931
2259
  }
2260
+ };
1932
2261
 
1933
- return toEqual;
2262
+ /**
2263
+ * @param {jasmine.ExpectationResult} result
2264
+ */
2265
+ jasmine.Spec.prototype.addMatcherResult = function(result) {
2266
+ this.results_.addResult(result);
1934
2267
  };
1935
2268
 
1936
- getJasmineRequireObj().toHaveBeenCalled = function() {
2269
+ jasmine.Spec.prototype.expect = function(actual) {
2270
+ var positive = new (this.getMatchersClass_())(this.env, actual, this);
2271
+ positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
2272
+ return positive;
2273
+ };
1937
2274
 
1938
- function toHaveBeenCalled() {
1939
- return {
1940
- compare: function(actual) {
1941
- var result = {};
2275
+ /**
2276
+ * Waits a fixed time period before moving to the next block.
2277
+ *
2278
+ * @deprecated Use waitsFor() instead
2279
+ * @param {Number} timeout milliseconds to wait
2280
+ */
2281
+ jasmine.Spec.prototype.waits = function(timeout) {
2282
+ var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
2283
+ this.addToQueue(waitsFunc);
2284
+ return this;
2285
+ };
1942
2286
 
1943
- if (!j$.isSpy(actual)) {
1944
- throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
1945
- }
2287
+ /**
2288
+ * Waits for the latchFunction to return true before proceeding to the next block.
2289
+ *
2290
+ * @param {Function} latchFunction
2291
+ * @param {String} optional_timeoutMessage
2292
+ * @param {Number} optional_timeout
2293
+ */
2294
+ jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
2295
+ var latchFunction_ = null;
2296
+ var optional_timeoutMessage_ = null;
2297
+ var optional_timeout_ = null;
2298
+
2299
+ for (var i = 0; i < arguments.length; i++) {
2300
+ var arg = arguments[i];
2301
+ switch (typeof arg) {
2302
+ case 'function':
2303
+ latchFunction_ = arg;
2304
+ break;
2305
+ case 'string':
2306
+ optional_timeoutMessage_ = arg;
2307
+ break;
2308
+ case 'number':
2309
+ optional_timeout_ = arg;
2310
+ break;
2311
+ }
2312
+ }
1946
2313
 
1947
- if (arguments.length > 1) {
1948
- throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
1949
- }
2314
+ var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
2315
+ this.addToQueue(waitsForFunc);
2316
+ return this;
2317
+ };
1950
2318
 
1951
- result.pass = actual.wasCalled;
2319
+ jasmine.Spec.prototype.fail = function (e) {
2320
+ var expectationResult = new jasmine.ExpectationResult({
2321
+ passed: false,
2322
+ message: e ? jasmine.util.formatException(e) : 'Exception',
2323
+ trace: { stack: e.stack }
2324
+ });
2325
+ this.results_.addResult(expectationResult);
2326
+ };
1952
2327
 
1953
- result.message = result.pass ?
1954
- "Expected spy " + actual.identity + " not to have been called." :
1955
- "Expected spy " + actual.identity + " to have been called.";
2328
+ jasmine.Spec.prototype.getMatchersClass_ = function() {
2329
+ return this.matchersClass || this.env.matchersClass;
2330
+ };
1956
2331
 
1957
- return result;
1958
- }
1959
- };
2332
+ jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
2333
+ var parent = this.getMatchersClass_();
2334
+ var newMatchersClass = function() {
2335
+ parent.apply(this, arguments);
2336
+ };
2337
+ jasmine.util.inherit(newMatchersClass, parent);
2338
+ jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
2339
+ this.matchersClass = newMatchersClass;
2340
+ };
2341
+
2342
+ jasmine.Spec.prototype.finishCallback = function() {
2343
+ this.env.reporter.reportSpecResults(this);
2344
+ };
2345
+
2346
+ jasmine.Spec.prototype.finish = function(onComplete) {
2347
+ this.removeAllSpies();
2348
+ this.finishCallback();
2349
+ if (onComplete) {
2350
+ onComplete();
1960
2351
  }
2352
+ };
1961
2353
 
1962
- return toHaveBeenCalled;
2354
+ jasmine.Spec.prototype.after = function(doAfter) {
2355
+ if (this.queue.isRunning()) {
2356
+ this.queue.add(new jasmine.Block(this.env, doAfter, this), true);
2357
+ } else {
2358
+ this.afterCallbacks.unshift(doAfter);
2359
+ }
1963
2360
  };
1964
2361
 
1965
- getJasmineRequireObj().toHaveBeenCalledWith = function() {
2362
+ jasmine.Spec.prototype.execute = function(onComplete) {
2363
+ var spec = this;
2364
+ if (!spec.env.specFilter(spec)) {
2365
+ spec.results_.skipped = true;
2366
+ spec.finish(onComplete);
2367
+ return;
2368
+ }
1966
2369
 
1967
- function toHaveBeenCalledWith(util) {
1968
- return {
1969
- compare: function() {
1970
- var args = Array.prototype.slice.call(arguments, 0),
1971
- actual = args[0],
1972
- expectedArgs = args.slice(1);
2370
+ this.env.reporter.reportSpecStarting(this);
1973
2371
 
1974
- if (!j$.isSpy(actual)) {
1975
- throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
1976
- }
2372
+ spec.env.currentSpec = spec;
1977
2373
 
1978
- return {
1979
- pass: util.contains(actual.argsForCall, expectedArgs)
1980
- };
1981
- },
1982
- message: function(actual) {
1983
- return {
1984
- affirmative: "Expected spy " + actual.identity + " to have been called.",
1985
- negative: "Expected spy " + actual.identity + " not to have been called."
1986
- };
1987
- }
1988
- };
1989
- }
2374
+ spec.addBeforesAndAftersToQueue();
1990
2375
 
1991
- return toHaveBeenCalledWith;
2376
+ spec.queue.start(function () {
2377
+ spec.finish(onComplete);
2378
+ });
1992
2379
  };
1993
2380
 
1994
- getJasmineRequireObj().toMatch = function() {
2381
+ jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
2382
+ var runner = this.env.currentRunner();
2383
+ var i;
1995
2384
 
1996
- function toMatch() {
1997
- return {
1998
- compare: function(actual, expected) {
1999
- var regexp = new RegExp(expected);
2000
-
2001
- return {
2002
- pass: regexp.test(actual)
2003
- };
2004
- }
2005
- };
2385
+ for (var suite = this.suite; suite; suite = suite.parentSuite) {
2386
+ for (i = 0; i < suite.before_.length; i++) {
2387
+ this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
2388
+ }
2389
+ }
2390
+ for (i = 0; i < runner.before_.length; i++) {
2391
+ this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
2392
+ }
2393
+ for (i = 0; i < this.afterCallbacks.length; i++) {
2394
+ this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this), true);
2395
+ }
2396
+ for (suite = this.suite; suite; suite = suite.parentSuite) {
2397
+ for (i = 0; i < suite.after_.length; i++) {
2398
+ this.queue.add(new jasmine.Block(this.env, suite.after_[i], this), true);
2399
+ }
2400
+ }
2401
+ for (i = 0; i < runner.after_.length; i++) {
2402
+ this.queue.add(new jasmine.Block(this.env, runner.after_[i], this), true);
2006
2403
  }
2007
-
2008
- return toMatch;
2009
2404
  };
2010
2405
 
2011
- getJasmineRequireObj().toThrow = function() {
2406
+ jasmine.Spec.prototype.explodes = function() {
2407
+ throw 'explodes function should not have been called';
2408
+ };
2012
2409
 
2013
- function toThrow(util) {
2014
- return {
2015
- compare: function(actual, expected) {
2016
- var result = { pass: false },
2017
- threw = false,
2018
- thrown;
2410
+ jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
2411
+ if (obj == jasmine.undefined) {
2412
+ throw "spyOn could not find an object to spy upon for " + methodName + "()";
2413
+ }
2019
2414
 
2020
- if (typeof actual != "function") {
2021
- throw new Error("Actual is not a Function");
2022
- }
2415
+ if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
2416
+ throw methodName + '() method does not exist';
2417
+ }
2023
2418
 
2024
- try {
2025
- actual();
2026
- } catch (e) {
2027
- threw = true;
2028
- thrown = e;
2029
- }
2419
+ if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
2420
+ throw new Error(methodName + ' has already been spied upon');
2421
+ }
2030
2422
 
2031
- if (!threw) {
2032
- result.message = "Expected function to throw an exception.";
2033
- return result;
2034
- }
2423
+ var spyObj = jasmine.createSpy(methodName);
2035
2424
 
2036
- if (arguments.length == 1) {
2037
- result.pass = true;
2038
- result.message = "Expected function not to throw.";
2425
+ this.spies_.push(spyObj);
2426
+ spyObj.baseObj = obj;
2427
+ spyObj.methodName = methodName;
2428
+ spyObj.originalValue = obj[methodName];
2039
2429
 
2040
- return result;
2041
- }
2430
+ obj[methodName] = spyObj;
2042
2431
 
2043
- if (util.equals(thrown, expected)) {
2044
- result.pass = true;
2045
- result.message = "Expected function not to throw " + j$.pp(expected) + ".";
2046
- } else {
2047
- result.message = "Expected function to throw " + j$.pp(expected) + ".";
2048
- }
2432
+ return spyObj;
2433
+ };
2049
2434
 
2050
- return result;
2051
- }
2052
- };
2435
+ jasmine.Spec.prototype.removeAllSpies = function() {
2436
+ for (var i = 0; i < this.spies_.length; i++) {
2437
+ var spy = this.spies_[i];
2438
+ spy.baseObj[spy.methodName] = spy.originalValue;
2053
2439
  }
2054
-
2055
- return toThrow;
2440
+ this.spies_ = [];
2056
2441
  };
2057
2442
 
2058
- getJasmineRequireObj().toThrowError = function() {
2059
- function toThrowError (util) {
2060
- return {
2061
- compare: function(actual) {
2062
- var threw = false,
2063
- thrown,
2064
- errorType,
2065
- message,
2066
- regexp;
2067
-
2068
- if (typeof actual != "function") {
2069
- throw new Error("Actual is not a Function");
2070
- }
2071
-
2072
- extractExpectedParams.apply(null, arguments);
2073
-
2074
- try {
2075
- actual();
2076
- } catch (e) {
2077
- threw = true;
2078
- thrown = e;
2079
- }
2443
+ /**
2444
+ * Internal representation of a Jasmine suite.
2445
+ *
2446
+ * @constructor
2447
+ * @param {jasmine.Env} env
2448
+ * @param {String} description
2449
+ * @param {Function} specDefinitions
2450
+ * @param {jasmine.Suite} parentSuite
2451
+ */
2452
+ jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
2453
+ var self = this;
2454
+ self.id = env.nextSuiteId ? env.nextSuiteId() : null;
2455
+ self.description = description;
2456
+ self.queue = new jasmine.Queue(env);
2457
+ self.parentSuite = parentSuite;
2458
+ self.env = env;
2459
+ self.before_ = [];
2460
+ self.after_ = [];
2461
+ self.children_ = [];
2462
+ self.suites_ = [];
2463
+ self.specs_ = [];
2464
+ };
2080
2465
 
2081
- if (!threw) {
2082
- return fail("Expected function to throw an Error.");
2083
- }
2466
+ jasmine.Suite.prototype.getFullName = function() {
2467
+ var fullName = this.description;
2468
+ for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
2469
+ fullName = parentSuite.description + ' ' + fullName;
2470
+ }
2471
+ return fullName;
2472
+ };
2084
2473
 
2085
- if (!(thrown instanceof Error)) {
2086
- return fail("Expected function to throw an Error, but it threw " + thrown + ".");
2087
- }
2474
+ jasmine.Suite.prototype.finish = function(onComplete) {
2475
+ this.env.reporter.reportSuiteResults(this);
2476
+ this.finished = true;
2477
+ if (typeof(onComplete) == 'function') {
2478
+ onComplete();
2479
+ }
2480
+ };
2088
2481
 
2089
- if (arguments.length == 1) {
2090
- return pass("Expected function not to throw an Error, but it threw " + thrown + ".");
2091
- }
2482
+ jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
2483
+ beforeEachFunction.typeName = 'beforeEach';
2484
+ this.before_.unshift(beforeEachFunction);
2485
+ };
2092
2486
 
2093
- if (errorType && message) {
2094
- if (thrown.constructor == errorType && util.equals(thrown.message, message)) {
2095
- return pass("Expected function not to throw Error with message \"" + message + "\".");
2096
- } else {
2097
- return fail("Expected function to throw Error with message \"" + message + "\".");
2098
- }
2099
- }
2487
+ jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
2488
+ afterEachFunction.typeName = 'afterEach';
2489
+ this.after_.unshift(afterEachFunction);
2490
+ };
2100
2491
 
2101
- if (errorType && regexp) {
2102
- if (thrown.constructor == errorType && regexp.test(thrown.message)) {
2103
- return pass("Expected function not to throw Error with message matching " + regexp + ".");
2104
- } else {
2105
- return fail("Expected function to throw Error with message matching " + regexp + ".");
2106
- }
2107
- }
2492
+ jasmine.Suite.prototype.results = function() {
2493
+ return this.queue.results();
2494
+ };
2108
2495
 
2109
- if (errorType) {
2110
- if (thrown.constructor == errorType) {
2111
- return pass("Expected function not to throw " + errorType.name + ".");
2112
- } else {
2113
- return fail("Expected function to throw " + errorType.name + ".");
2114
- }
2115
- }
2496
+ jasmine.Suite.prototype.add = function(suiteOrSpec) {
2497
+ this.children_.push(suiteOrSpec);
2498
+ if (suiteOrSpec instanceof jasmine.Suite) {
2499
+ this.suites_.push(suiteOrSpec);
2500
+ this.env.currentRunner().addSuite(suiteOrSpec);
2501
+ } else {
2502
+ this.specs_.push(suiteOrSpec);
2503
+ }
2504
+ this.queue.add(suiteOrSpec);
2505
+ };
2116
2506
 
2117
- if (message) {
2118
- if (thrown.message == message) {
2119
- return pass("Expected function not to throw an execption with message " + j$.pp(message) + ".");
2120
- } else {
2121
- return fail("Expected function to throw an execption with message " + j$.pp(message) + ".");
2122
- }
2123
- }
2507
+ jasmine.Suite.prototype.specs = function() {
2508
+ return this.specs_;
2509
+ };
2124
2510
 
2125
- if (regexp) {
2126
- if (regexp.test(thrown.message)) {
2127
- return pass("Expected function not to throw an execption with a message matching " + j$.pp(regexp) + ".");
2128
- } else {
2129
- return fail("Expected function to throw an execption with a message matching " + j$.pp(regexp) + ".");
2130
- }
2131
- }
2511
+ jasmine.Suite.prototype.suites = function() {
2512
+ return this.suites_;
2513
+ };
2132
2514
 
2133
- function pass(notMessage) {
2134
- return {
2135
- pass: true,
2136
- message: notMessage
2137
- };
2138
- }
2515
+ jasmine.Suite.prototype.children = function() {
2516
+ return this.children_;
2517
+ };
2139
2518
 
2140
- function fail(message) {
2141
- return {
2142
- pass: false,
2143
- message: message
2144
- };
2145
- }
2519
+ jasmine.Suite.prototype.execute = function(onComplete) {
2520
+ var self = this;
2521
+ this.queue.start(function () {
2522
+ self.finish(onComplete);
2523
+ });
2524
+ };
2525
+ jasmine.WaitsBlock = function(env, timeout, spec) {
2526
+ this.timeout = timeout;
2527
+ jasmine.Block.call(this, env, null, spec);
2528
+ };
2146
2529
 
2147
- function extractExpectedParams() {
2148
- if (arguments.length == 1) {
2149
- return;
2150
- }
2530
+ jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
2151
2531
 
2152
- if (arguments.length == 2) {
2153
- var expected = arguments[1];
2532
+ jasmine.WaitsBlock.prototype.execute = function (onComplete) {
2533
+ if (jasmine.VERBOSE) {
2534
+ this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
2535
+ }
2536
+ this.env.setTimeout(function () {
2537
+ onComplete();
2538
+ }, this.timeout);
2539
+ };
2540
+ /**
2541
+ * A block which waits for some condition to become true, with timeout.
2542
+ *
2543
+ * @constructor
2544
+ * @extends jasmine.Block
2545
+ * @param {jasmine.Env} env The Jasmine environment.
2546
+ * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
2547
+ * @param {Function} latchFunction A function which returns true when the desired condition has been met.
2548
+ * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
2549
+ * @param {jasmine.Spec} spec The Jasmine spec.
2550
+ */
2551
+ jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
2552
+ this.timeout = timeout || env.defaultTimeoutInterval;
2553
+ this.latchFunction = latchFunction;
2554
+ this.message = message;
2555
+ this.totalTimeSpentWaitingForLatch = 0;
2556
+ jasmine.Block.call(this, env, null, spec);
2557
+ };
2558
+ jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
2154
2559
 
2155
- if (expected instanceof RegExp) {
2156
- regexp = expected;
2157
- } else if (typeof expected == "string") {
2158
- message = expected;
2159
- } else if (checkForAnErrorType(expected)) {
2160
- errorType = expected;
2161
- }
2560
+ jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
2162
2561
 
2163
- if (!(errorType || message || regexp)) {
2164
- throw new Error("Expected is not an Error, string, or RegExp.");
2165
- }
2166
- } else {
2167
- if (checkForAnErrorType(arguments[1])) {
2168
- errorType = arguments[1];
2169
- } else {
2170
- throw new Error("Expected error type is not an Error.");
2171
- }
2172
-
2173
- if (arguments[2] instanceof RegExp) {
2174
- regexp = arguments[2];
2175
- } else if (typeof arguments[2] == "string") {
2176
- message = arguments[2];
2177
- } else {
2178
- throw new Error("Expected error message is not a string or RegExp.");
2179
- }
2180
- }
2181
- }
2562
+ jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
2563
+ if (jasmine.VERBOSE) {
2564
+ this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
2565
+ }
2566
+ var latchFunctionResult;
2567
+ try {
2568
+ latchFunctionResult = this.latchFunction.apply(this.spec);
2569
+ } catch (e) {
2570
+ this.spec.fail(e);
2571
+ onComplete();
2572
+ return;
2573
+ }
2182
2574
 
2183
- function checkForAnErrorType(type) {
2184
- if (typeof type !== "function") {
2185
- return false;
2186
- }
2575
+ if (latchFunctionResult) {
2576
+ onComplete();
2577
+ } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
2578
+ var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
2579
+ this.spec.fail({
2580
+ name: 'timeout',
2581
+ message: message
2582
+ });
2187
2583
 
2188
- var Surrogate = function() {};
2189
- Surrogate.prototype = type.prototype;
2190
- return (new Surrogate()) instanceof Error;
2191
- }
2192
- }
2193
- };
2584
+ this.abort = true;
2585
+ onComplete();
2586
+ } else {
2587
+ this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
2588
+ var self = this;
2589
+ this.env.setTimeout(function() {
2590
+ self.execute(onComplete);
2591
+ }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
2194
2592
  }
2593
+ };
2195
2594
 
2196
- return toThrowError;
2595
+ jasmine.version_= {
2596
+ "major": 1,
2597
+ "minor": 3,
2598
+ "build": 1,
2599
+ "revision": 1354556913
2197
2600
  };
2198
- getJasmineRequireObj().version = function() {
2199
- return "2.0.0-alpha";
2200
- };