sayso-js-test-driver-rails 0.4.3

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.
@@ -0,0 +1,70 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2
+
3
+ module JsTestDriver
4
+ class HtmlFixtureTest < Test::Unit::TestCase
5
+
6
+ def fixture_for_dir(dir)
7
+ JsTestDriver::HtmlFixture.new(dir)
8
+ end
9
+
10
+ def test_given_a_made_up_fixture_directory_should_return_an_empty_hash
11
+ # given
12
+ fixture = fixture_for_dir('/xxx/yyy/zzz')
13
+
14
+ # then
15
+ assert_equal({}, fixture.to_h)
16
+ end
17
+
18
+ def file_contents(fixture_name)
19
+ return File.read(File.join(fixture_dir, "#{fixture_name}.html"))
20
+ end
21
+
22
+ def known_fixtures
23
+ %w{ a b c foo/a foo/bar/a baz/a }
24
+ end
25
+
26
+ def test_should_return_all_of_the_html_files_in_fixture_directory
27
+ # given
28
+ fixture = fixture_for_dir(fixture_dir)
29
+
30
+ # then
31
+ assert_equal known_fixtures.sort, fixture.to_h.keys.sort
32
+ end
33
+
34
+ def test_should_have_the_right_contents_for_every_fixture_file
35
+ # given
36
+ fixture = fixture_for_dir(fixture_dir)
37
+
38
+ # then
39
+ known_fixtures.each do |name|
40
+ assert_equal file_contents(name), fixture.to_h[name], "The contents of the fixture '#{name}' differ"
41
+ end
42
+ end
43
+
44
+ def fixture_named(name, namespace)
45
+ JsTestDriver::HtmlFixture.new('/some/bogus/directory', name, namespace)
46
+ end
47
+
48
+ def assert_contains(expected, actual)
49
+ assert_not_nil actual
50
+ assert actual.include?(expected), "Expected:\n#{actual}\nto include:\n#{expected}"
51
+ end
52
+
53
+ def test_should_initialize_the_namespace
54
+ # given
55
+ fixture = fixture_named('foo', 'ns')
56
+
57
+ # then
58
+ assert_contains "if (typeof(ns) === 'undefined') { ns = {}; }", fixture.to_s
59
+ end
60
+
61
+ def test_should_set_the_fixture
62
+ # given
63
+ fixture = fixture_named('foo', 'ns')
64
+
65
+ # then
66
+ assert_contains "ns.foo = {};", fixture.to_s
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,107 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
2
+
3
+ module JsTestDriver
4
+ class RunnerTest < Test::Unit::TestCase
5
+
6
+ def given_a_runner(opts = {})
7
+ return JsTestDriver::Runner.new(opts)
8
+ end
9
+
10
+ def test_should_have_default_config_path
11
+ # given
12
+ runner = given_a_runner
13
+
14
+ # then
15
+ assert runner.config_path
16
+ end
17
+
18
+ def test_should_have_default_jar_path
19
+ # given
20
+ runner = given_a_runner
21
+
22
+ # then
23
+ assert runner.jar_path
24
+ end
25
+
26
+ def test_should_have_default_tmp_path
27
+ # given
28
+ runner = given_a_runner
29
+
30
+ # then
31
+ assert runner.config_yml_path
32
+ end
33
+
34
+ def expect_command_to_be_executed(cmd)
35
+ JsTestDriver::Runner::Command.any_instance.expects(:system).with(cmd)
36
+ end
37
+
38
+ def expect_spawn(cmd)
39
+ JsTestDriver::Runner.any_instance.expects(:spawn).with(cmd)
40
+ end
41
+
42
+ def test_should_run_server_with_given_port_number
43
+ config = JsTestDriver::Config.new(:port => 6666)
44
+ runner = given_a_runner(:config => config)
45
+
46
+ expect_command_to_be_executed("java -jar #{runner.jar_path} --port #{config.port}")
47
+
48
+ runner.start_server
49
+ end
50
+
51
+ def test_should_run_all_tests_by_default
52
+ runner = given_a_runner(:config => JsTestDriver::Config.new)
53
+
54
+ expect_command_to_be_executed("java -jar #{runner.jar_path} --config #{runner.config_yml_path} --tests all")
55
+
56
+ runner.run_tests
57
+ end
58
+
59
+ def test_should_run_selected_tests
60
+ runner = given_a_runner(:config => JsTestDriver::Config.new)
61
+
62
+ expect_command_to_be_executed("java -jar #{runner.jar_path} --config #{runner.config_yml_path} --tests MyTestCase.some_test")
63
+
64
+ runner.run_tests('MyTestCase.some_test')
65
+ end
66
+
67
+ def test_should_capture_default_browsers
68
+ runner = given_a_runner(:config => JsTestDriver::Config.new(:browsers => ['foo', 'bar', 'baz']))
69
+
70
+ ['foo', 'bar', 'baz'].each do |browser|
71
+ expect_spawn("#{browser} 'http://localhost:4224/capture'")
72
+ end
73
+
74
+ runner.capture_browsers
75
+ end
76
+
77
+ def test_should_capture_given_browsers
78
+ runner = given_a_runner(:config => JsTestDriver::Config.new(:browsers => ['foo', 'bar', 'baz']))
79
+
80
+ ['aaa', 'bbb'].each do |browser|
81
+ expect_spawn("#{browser} 'http://localhost:4224/capture'")
82
+ end
83
+
84
+ runner.capture_browsers('aaa,bbb')
85
+ end
86
+
87
+ def test_should_run_with_all_arguments_at_once
88
+ runner = given_a_runner(:config => JsTestDriver::Config.new(:browsers => ['foo', 'bar', 'baz']))
89
+
90
+ expect_command_to_be_executed("java -jar #{runner.jar_path} --port 4224 --config #{runner.config_yml_path} --browser aaa,bbb --tests TestCase --testOutput #{File.expand_path('.js_test_driver')} --captureConsole")
91
+
92
+ runner.start_server_capture_and_run('TestCase', 'aaa,bbb', '.js_test_driver', true)
93
+ end
94
+
95
+ def test_when_measuring_coverage
96
+ config = JsTestDriver::Config.new
97
+ config.measure_coverage
98
+ runner = given_a_runner(:config => config)
99
+
100
+ JsTestDriver::Runner::Command.any_instance.expects(:system)
101
+ runner.expects(:system).with("genhtml -o #{File.expand_path('.js_test_driver/coverage')} #{File.expand_path('.js_test_driver/jsTestDriver.conf-coverage.dat')}")
102
+
103
+ runner.start_server_capture_and_run(nil, 'aaa', '.js_test_driver')
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,179 @@
1
+ /**
2
+ * @fileoverview Jasmine JsTestDriver Adapter.
3
+ * @author misko@hevery.com (Misko Hevery)
4
+ * @author olmo.maldonado@gmail.com (Olmo Maldonado)
5
+ */
6
+ (function(){
7
+
8
+
9
+ var Env = function(onTestDone, onComplete){
10
+ jasmine.Env.call(this);
11
+
12
+ this.specFilter = function(spec){
13
+ if (!this.exclusive) return true;
14
+ var blocks = spec.queue.blocks, l = blocks.length;
15
+ for (var i = 0; i < l; i++) if (blocks[i].func.exclusive >= this.exclusive) return true;
16
+ return false;
17
+ };
18
+
19
+ this.reporter = new Reporter(onTestDone, onComplete);
20
+ };
21
+ jasmine.util.inherit(Env, jasmine.Env);
22
+
23
+ // Here we store:
24
+ // 0: everyone runs
25
+ // 1: run everything under ddescribe
26
+ // 2: run only iits (ignore ddescribe)
27
+ Env.prototype.exclusive = 0;
28
+
29
+
30
+ Env.prototype.execute = function(){
31
+ collectMode = false;
32
+ playback();
33
+ jasmine.Env.prototype.execute.call(this);
34
+ };
35
+
36
+
37
+ var Reporter = function(onTestDone, onComplete){
38
+ this.onTestDone = onTestDone;
39
+ this.onComplete = onComplete;
40
+ this.reset();
41
+ };
42
+ jasmine.util.inherit(Reporter, jasmine.Reporter);
43
+
44
+
45
+ Reporter.formatStack = function(stack) {
46
+ var line, lines = (stack || '').split(/\r?\n/), l = lines.length, frames = [];
47
+ for (var i = 0; i < l; i++){
48
+ line = lines[i];
49
+ if (line.match(/\/jasmine[\.-]/)) continue;
50
+ frames.push(line.replace(/https?:\/\/\w+(:\d+)?\/test\//, '').replace(/^\s*/, ' '));
51
+ }
52
+ return frames.join('\n');
53
+ };
54
+
55
+
56
+ Reporter.prototype.reset = function(){
57
+ this.specLog = jstestdriver.console.log_ = [];
58
+ };
59
+
60
+
61
+ Reporter.prototype.log = function(str){
62
+ this.specLog.push(str);
63
+ };
64
+
65
+
66
+ Reporter.prototype.reportSpecStarting = function(){
67
+ this.reset();
68
+ this.start = +new Date();
69
+ };
70
+
71
+
72
+ Reporter.prototype.reportSpecResults = function(spec){
73
+ var elapsed = +new Date() - this.start, results = spec.results();
74
+
75
+ if (results.skipped) return;
76
+
77
+ var item, state = 'passed', items = results.getItems(), l = items.length, messages = [];
78
+ for (var i = 0; i < l; i++){
79
+ item = items[i];
80
+ if (item.passed()) continue;
81
+ state = (item.message.indexOf('AssertionError:') != -1) ? 'error' : 'failed';
82
+ messages.push({
83
+ message: item + '',
84
+ name: item.trace.name,
85
+ stack: Reporter.formatStack(item.trace.stack)
86
+ });
87
+ }
88
+
89
+ this.onTestDone(new jstestdriver.TestResult(
90
+ spec.suite.getFullName(),
91
+ spec.description,
92
+ state,
93
+ jstestdriver.angular.toJson(messages),
94
+ this.specLog.join('\n'),
95
+ elapsed
96
+ ));
97
+ };
98
+
99
+
100
+ Reporter.prototype.reportRunnerResults = function(){
101
+ this.onComplete();
102
+ };
103
+
104
+
105
+ var collectMode = true, intercepted = {};
106
+
107
+ describe = intercept('describe');
108
+ beforeEach = intercept('beforeEach');
109
+ afterEach = intercept('afterEach');
110
+
111
+ var template = TestCase('Jasmine Adapter Tests', null, 'jasmine test case');
112
+
113
+ jstestdriver.pluginRegistrar.register({
114
+
115
+ name: 'jasmine',
116
+
117
+ runTestConfiguration: function(config, onTestDone, onComplete){
118
+ if (config.testCaseInfo_.template_ !== template) return;
119
+ (jasmine.currentEnv_ = new Env(onTestDone, onComplete)).execute();
120
+ return true;
121
+ },
122
+
123
+ onTestsFinish: function(){
124
+ jasmine.currentEnv_ = null;
125
+ collectMode = true;
126
+ }
127
+
128
+ });
129
+
130
+ function intercept(method){
131
+ var bucket = intercepted[method] = [], method = window[method];
132
+ return function(desc, fn){
133
+ if (collectMode) bucket.push(function(){ method(desc, fn); });
134
+ else method(desc, fn);
135
+ };
136
+ }
137
+
138
+ function playback(){
139
+ for (var method in intercepted){
140
+ var bucket = intercepted[method];
141
+ for (var i = 0, l = bucket.length; i < l; i++) bucket[i]();
142
+ }
143
+ }
144
+
145
+ })();
146
+
147
+ var ddescribe = function(name, fn){
148
+ var env = jasmine.getEnv();
149
+ if (!env.exclusive) env.exclusive = 1; // run ddescribe only
150
+ describe(name, function(){
151
+ var oldIt = it;
152
+ it = function(name, fn){
153
+ fn.exclusive = 1; // run anything under ddescribe
154
+ env.it(name, fn);
155
+ };
156
+
157
+ try {
158
+ fn.call(this);
159
+ } finally {
160
+ it = oldIt;
161
+ };
162
+ });
163
+ };
164
+
165
+ var iit = function(name, fn){
166
+ var env = jasmine.getEnv();
167
+ env.exclusive = fn.exclusive = 2; // run only iits
168
+ env.it(name, fn);
169
+ };
170
+
171
+ // Patch Jasmine for proper stack traces
172
+ jasmine.Spec.prototype.fail = function (e) {
173
+ var result = new jasmine.ExpectationResult({
174
+ passed: false,
175
+ message: e ? jasmine.util.formatException(e) : 'Exception'
176
+ });
177
+ if(e) result.trace = e;
178
+ this.results_.addResult(result);
179
+ };
data/vendor/VERSIONS ADDED
@@ -0,0 +1,3 @@
1
+ JsTestDriver: 1.3.2
2
+ Jasmine: 1.0.1
3
+ JasmineAdapter: http://github.com/mhevery/jasmine-jstd-adapter/commit/66fd298eac4364a02f80cc7d0714adcdffbe175e
Binary file
data/vendor/jasmine.js ADDED
@@ -0,0 +1,2435 @@
1
+ var isCommonJS = typeof window == "undefined";
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
+ };
16
+
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
+ * 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.
27
+ *
28
+ */
29
+ jasmine.DEFAULT_UPDATE_INTERVAL = 250;
30
+
31
+ /**
32
+ * Default timeout interval in milliseconds for waitsFor() blocks.
33
+ */
34
+ jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
35
+
36
+ jasmine.getGlobal = function() {
37
+ function getGlobal() {
38
+ return this;
39
+ }
40
+
41
+ return getGlobal();
42
+ };
43
+
44
+ /**
45
+ * Allows for bound functions to be compared. Internal use only.
46
+ *
47
+ * @ignore
48
+ * @private
49
+ * @param base {Object} bound 'this' for the function
50
+ * @param name {Function} function to find
51
+ */
52
+ jasmine.bindOriginal_ = function(base, name) {
53
+ var original = base[name];
54
+ if (original.apply) {
55
+ return function() {
56
+ return original.apply(base, arguments);
57
+ };
58
+ } else {
59
+ // IE support
60
+ return jasmine.getGlobal()[name];
61
+ }
62
+ };
63
+
64
+ jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
65
+ jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
66
+ jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
67
+ jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
68
+
69
+ jasmine.MessageResult = function(values) {
70
+ this.type = 'log';
71
+ this.values = values;
72
+ this.trace = new Error(); // todo: test better
73
+ };
74
+
75
+ jasmine.MessageResult.prototype.toString = function() {
76
+ var text = "";
77
+ for(var i = 0; i < this.values.length; i++) {
78
+ if (i > 0) text += " ";
79
+ if (jasmine.isString_(this.values[i])) {
80
+ text += this.values[i];
81
+ } else {
82
+ text += jasmine.pp(this.values[i]);
83
+ }
84
+ }
85
+ return text;
86
+ };
87
+
88
+ jasmine.ExpectationResult = function(params) {
89
+ this.type = 'expect';
90
+ this.matcherName = params.matcherName;
91
+ this.passed_ = params.passed;
92
+ this.expected = params.expected;
93
+ this.actual = params.actual;
94
+
95
+ this.message = this.passed_ ? 'Passed.' : params.message;
96
+ this.trace = this.passed_ ? '' : new Error(this.message);
97
+ };
98
+
99
+ jasmine.ExpectationResult.prototype.toString = function () {
100
+ return this.message;
101
+ };
102
+
103
+ jasmine.ExpectationResult.prototype.passed = function () {
104
+ return this.passed_;
105
+ };
106
+
107
+ /**
108
+ * Getter for the Jasmine environment. Ensures one gets created
109
+ */
110
+ jasmine.getEnv = function() {
111
+ var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
112
+ return env;
113
+ };
114
+
115
+ /**
116
+ * @ignore
117
+ * @private
118
+ * @param value
119
+ * @returns {Boolean}
120
+ */
121
+ jasmine.isArray_ = function(value) {
122
+ return jasmine.isA_("Array", value);
123
+ };
124
+
125
+ /**
126
+ * @ignore
127
+ * @private
128
+ * @param value
129
+ * @returns {Boolean}
130
+ */
131
+ jasmine.isString_ = function(value) {
132
+ return jasmine.isA_("String", value);
133
+ };
134
+
135
+ /**
136
+ * @ignore
137
+ * @private
138
+ * @param value
139
+ * @returns {Boolean}
140
+ */
141
+ jasmine.isNumber_ = function(value) {
142
+ return jasmine.isA_("Number", value);
143
+ };
144
+
145
+ /**
146
+ * @ignore
147
+ * @private
148
+ * @param {String} typeName
149
+ * @param value
150
+ * @returns {Boolean}
151
+ */
152
+ jasmine.isA_ = function(typeName, value) {
153
+ return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
154
+ };
155
+
156
+ /**
157
+ * Pretty printer for expecations. Takes any object and turns it into a human-readable string.
158
+ *
159
+ * @param value {Object} an object to be outputted
160
+ * @returns {String}
161
+ */
162
+ jasmine.pp = function(value) {
163
+ var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
164
+ stringPrettyPrinter.format(value);
165
+ return stringPrettyPrinter.string;
166
+ };
167
+
168
+ /**
169
+ * Returns true if the object is a DOM Node.
170
+ *
171
+ * @param {Object} obj object to check
172
+ * @returns {Boolean}
173
+ */
174
+ jasmine.isDomNode = function(obj) {
175
+ return obj.nodeType > 0;
176
+ };
177
+
178
+ /**
179
+ * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
180
+ *
181
+ * @example
182
+ * // don't care about which function is passed in, as long as it's a function
183
+ * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
184
+ *
185
+ * @param {Class} clazz
186
+ * @returns matchable object of the type clazz
187
+ */
188
+ jasmine.any = function(clazz) {
189
+ return new jasmine.Matchers.Any(clazz);
190
+ };
191
+
192
+ /**
193
+ * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
194
+ *
195
+ * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
196
+ * expectation syntax. Spies can be checked if they were called or not and what the calling params were.
197
+ *
198
+ * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
199
+ *
200
+ * Spies are torn down at the end of every spec.
201
+ *
202
+ * Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
203
+ *
204
+ * @example
205
+ * // a stub
206
+ * var myStub = jasmine.createSpy('myStub'); // can be used anywhere
207
+ *
208
+ * // spy example
209
+ * var foo = {
210
+ * not: function(bool) { return !bool; }
211
+ * }
212
+ *
213
+ * // actual foo.not will not be called, execution stops
214
+ * spyOn(foo, 'not');
215
+
216
+ // foo.not spied upon, execution will continue to implementation
217
+ * spyOn(foo, 'not').andCallThrough();
218
+ *
219
+ * // fake example
220
+ * var foo = {
221
+ * not: function(bool) { return !bool; }
222
+ * }
223
+ *
224
+ * // foo.not(val) will return val
225
+ * spyOn(foo, 'not').andCallFake(function(value) {return value;});
226
+ *
227
+ * // mock example
228
+ * foo.not(7 == 7);
229
+ * expect(foo.not).toHaveBeenCalled();
230
+ * expect(foo.not).toHaveBeenCalledWith(true);
231
+ *
232
+ * @constructor
233
+ * @see spyOn, jasmine.createSpy, jasmine.createSpyObj
234
+ * @param {String} name
235
+ */
236
+ jasmine.Spy = function(name) {
237
+ /**
238
+ * The name of the spy, if provided.
239
+ */
240
+ this.identity = name || 'unknown';
241
+ /**
242
+ * Is this Object a spy?
243
+ */
244
+ this.isSpy = true;
245
+ /**
246
+ * The actual function this spy stubs.
247
+ */
248
+ this.plan = function() {
249
+ };
250
+ /**
251
+ * Tracking of the most recent call to the spy.
252
+ * @example
253
+ * var mySpy = jasmine.createSpy('foo');
254
+ * mySpy(1, 2);
255
+ * mySpy.mostRecentCall.args = [1, 2];
256
+ */
257
+ this.mostRecentCall = {};
258
+
259
+ /**
260
+ * Holds arguments for each call to the spy, indexed by call count
261
+ * @example
262
+ * var mySpy = jasmine.createSpy('foo');
263
+ * mySpy(1, 2);
264
+ * mySpy(7, 8);
265
+ * mySpy.mostRecentCall.args = [7, 8];
266
+ * mySpy.argsForCall[0] = [1, 2];
267
+ * mySpy.argsForCall[1] = [7, 8];
268
+ */
269
+ this.argsForCall = [];
270
+ this.calls = [];
271
+ };
272
+
273
+ /**
274
+ * Tells a spy to call through to the actual implemenatation.
275
+ *
276
+ * @example
277
+ * var foo = {
278
+ * bar: function() { // do some stuff }
279
+ * }
280
+ *
281
+ * // defining a spy on an existing property: foo.bar
282
+ * spyOn(foo, 'bar').andCallThrough();
283
+ */
284
+ jasmine.Spy.prototype.andCallThrough = function() {
285
+ this.plan = this.originalValue;
286
+ return this;
287
+ };
288
+
289
+ /**
290
+ * For setting the return value of a spy.
291
+ *
292
+ * @example
293
+ * // defining a spy from scratch: foo() returns 'baz'
294
+ * var foo = jasmine.createSpy('spy on foo').andReturn('baz');
295
+ *
296
+ * // defining a spy on an existing property: foo.bar() returns 'baz'
297
+ * spyOn(foo, 'bar').andReturn('baz');
298
+ *
299
+ * @param {Object} value
300
+ */
301
+ jasmine.Spy.prototype.andReturn = function(value) {
302
+ this.plan = function() {
303
+ return value;
304
+ };
305
+ return this;
306
+ };
307
+
308
+ /**
309
+ * For throwing an exception when a spy is called.
310
+ *
311
+ * @example
312
+ * // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
313
+ * var foo = jasmine.createSpy('spy on foo').andThrow('baz');
314
+ *
315
+ * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
316
+ * spyOn(foo, 'bar').andThrow('baz');
317
+ *
318
+ * @param {String} exceptionMsg
319
+ */
320
+ jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
321
+ this.plan = function() {
322
+ throw exceptionMsg;
323
+ };
324
+ return this;
325
+ };
326
+
327
+ /**
328
+ * Calls an alternate implementation when a spy is called.
329
+ *
330
+ * @example
331
+ * var baz = function() {
332
+ * // do some stuff, return something
333
+ * }
334
+ * // defining a spy from scratch: foo() calls the function baz
335
+ * var foo = jasmine.createSpy('spy on foo').andCall(baz);
336
+ *
337
+ * // defining a spy on an existing property: foo.bar() calls an anonymnous function
338
+ * spyOn(foo, 'bar').andCall(function() { return 'baz';} );
339
+ *
340
+ * @param {Function} fakeFunc
341
+ */
342
+ jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
343
+ this.plan = fakeFunc;
344
+ return this;
345
+ };
346
+
347
+ /**
348
+ * Resets all of a spy's the tracking variables so that it can be used again.
349
+ *
350
+ * @example
351
+ * spyOn(foo, 'bar');
352
+ *
353
+ * foo.bar();
354
+ *
355
+ * expect(foo.bar.callCount).toEqual(1);
356
+ *
357
+ * foo.bar.reset();
358
+ *
359
+ * expect(foo.bar.callCount).toEqual(0);
360
+ */
361
+ jasmine.Spy.prototype.reset = function() {
362
+ this.wasCalled = false;
363
+ this.callCount = 0;
364
+ this.argsForCall = [];
365
+ this.calls = [];
366
+ this.mostRecentCall = {};
367
+ };
368
+
369
+ jasmine.createSpy = function(name) {
370
+
371
+ var spyObj = function() {
372
+ spyObj.wasCalled = true;
373
+ spyObj.callCount++;
374
+ var args = jasmine.util.argsToArray(arguments);
375
+ spyObj.mostRecentCall.object = this;
376
+ spyObj.mostRecentCall.args = args;
377
+ spyObj.argsForCall.push(args);
378
+ spyObj.calls.push({object: this, args: args});
379
+ return spyObj.plan.apply(this, arguments);
380
+ };
381
+
382
+ var spy = new jasmine.Spy(name);
383
+
384
+ for (var prop in spy) {
385
+ spyObj[prop] = spy[prop];
386
+ }
387
+
388
+ spyObj.reset();
389
+
390
+ return spyObj;
391
+ };
392
+
393
+ /**
394
+ * Determines whether an object is a spy.
395
+ *
396
+ * @param {jasmine.Spy|Object} putativeSpy
397
+ * @returns {Boolean}
398
+ */
399
+ jasmine.isSpy = function(putativeSpy) {
400
+ return putativeSpy && putativeSpy.isSpy;
401
+ };
402
+
403
+ /**
404
+ * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
405
+ * large in one call.
406
+ *
407
+ * @param {String} baseName name of spy class
408
+ * @param {Array} methodNames array of names of methods to make spies
409
+ */
410
+ jasmine.createSpyObj = function(baseName, methodNames) {
411
+ if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
412
+ throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
413
+ }
414
+ var obj = {};
415
+ for (var i = 0; i < methodNames.length; i++) {
416
+ obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
417
+ }
418
+ return obj;
419
+ };
420
+
421
+ /**
422
+ * All parameters are pretty-printed and concatenated together, then written to the current spec's output.
423
+ *
424
+ * Be careful not to leave calls to <code>jasmine.log</code> in production code.
425
+ */
426
+ jasmine.log = function() {
427
+ var spec = jasmine.getEnv().currentSpec;
428
+ spec.log.apply(spec, arguments);
429
+ };
430
+
431
+ /**
432
+ * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
433
+ *
434
+ * @example
435
+ * // spy example
436
+ * var foo = {
437
+ * not: function(bool) { return !bool; }
438
+ * }
439
+ * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
440
+ *
441
+ * @see jasmine.createSpy
442
+ * @param obj
443
+ * @param methodName
444
+ * @returns a Jasmine spy that can be chained with all spy methods
445
+ */
446
+ var spyOn = function(obj, methodName) {
447
+ return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
448
+ };
449
+ if (isCommonJS) exports.spyOn = spyOn;
450
+
451
+ /**
452
+ * Creates a Jasmine spec that will be added to the current suite.
453
+ *
454
+ * // TODO: pending tests
455
+ *
456
+ * @example
457
+ * it('should be true', function() {
458
+ * expect(true).toEqual(true);
459
+ * });
460
+ *
461
+ * @param {String} desc description of this specification
462
+ * @param {Function} func defines the preconditions and expectations of the spec
463
+ */
464
+ var it = function(desc, func) {
465
+ return jasmine.getEnv().it(desc, func);
466
+ };
467
+ if (isCommonJS) exports.it = it;
468
+
469
+ /**
470
+ * Creates a <em>disabled</em> Jasmine spec.
471
+ *
472
+ * A convenience method that allows existing specs to be disabled temporarily during development.
473
+ *
474
+ * @param {String} desc description of this specification
475
+ * @param {Function} func defines the preconditions and expectations of the spec
476
+ */
477
+ var xit = function(desc, func) {
478
+ return jasmine.getEnv().xit(desc, func);
479
+ };
480
+ if (isCommonJS) exports.xit = xit;
481
+
482
+ /**
483
+ * Starts a chain for a Jasmine expectation.
484
+ *
485
+ * It is passed an Object that is the actual value and should chain to one of the many
486
+ * jasmine.Matchers functions.
487
+ *
488
+ * @param {Object} actual Actual value to test against and expected value
489
+ */
490
+ var expect = function(actual) {
491
+ return jasmine.getEnv().currentSpec.expect(actual);
492
+ };
493
+ if (isCommonJS) exports.expect = expect;
494
+
495
+ /**
496
+ * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
497
+ *
498
+ * @param {Function} func Function that defines part of a jasmine spec.
499
+ */
500
+ var runs = function(func) {
501
+ jasmine.getEnv().currentSpec.runs(func);
502
+ };
503
+ if (isCommonJS) exports.runs = runs;
504
+
505
+ /**
506
+ * Waits a fixed time period before moving to the next block.
507
+ *
508
+ * @deprecated Use waitsFor() instead
509
+ * @param {Number} timeout milliseconds to wait
510
+ */
511
+ var waits = function(timeout) {
512
+ jasmine.getEnv().currentSpec.waits(timeout);
513
+ };
514
+ if (isCommonJS) exports.waits = waits;
515
+
516
+ /**
517
+ * Waits for the latchFunction to return true before proceeding to the next block.
518
+ *
519
+ * @param {Function} latchFunction
520
+ * @param {String} optional_timeoutMessage
521
+ * @param {Number} optional_timeout
522
+ */
523
+ var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
524
+ jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
525
+ };
526
+ if (isCommonJS) exports.waitsFor = waitsFor;
527
+
528
+ /**
529
+ * A function that is called before each spec in a suite.
530
+ *
531
+ * Used for spec setup, including validating assumptions.
532
+ *
533
+ * @param {Function} beforeEachFunction
534
+ */
535
+ var beforeEach = function(beforeEachFunction) {
536
+ jasmine.getEnv().beforeEach(beforeEachFunction);
537
+ };
538
+ if (isCommonJS) exports.beforeEach = beforeEach;
539
+
540
+ /**
541
+ * A function that is called after each spec in a suite.
542
+ *
543
+ * Used for restoring any state that is hijacked during spec execution.
544
+ *
545
+ * @param {Function} afterEachFunction
546
+ */
547
+ var afterEach = function(afterEachFunction) {
548
+ jasmine.getEnv().afterEach(afterEachFunction);
549
+ };
550
+ if (isCommonJS) exports.afterEach = afterEach;
551
+
552
+ /**
553
+ * Defines a suite of specifications.
554
+ *
555
+ * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
556
+ * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
557
+ * of setup in some tests.
558
+ *
559
+ * @example
560
+ * // TODO: a simple suite
561
+ *
562
+ * // TODO: a simple suite with a nested describe block
563
+ *
564
+ * @param {String} description A string, usually the class under test.
565
+ * @param {Function} specDefinitions function that defines several specs.
566
+ */
567
+ var describe = function(description, specDefinitions) {
568
+ return jasmine.getEnv().describe(description, specDefinitions);
569
+ };
570
+ if (isCommonJS) exports.describe = describe;
571
+
572
+ /**
573
+ * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
574
+ *
575
+ * @param {String} description A string, usually the class under test.
576
+ * @param {Function} specDefinitions function that defines several specs.
577
+ */
578
+ var xdescribe = function(description, specDefinitions) {
579
+ return jasmine.getEnv().xdescribe(description, specDefinitions);
580
+ };
581
+ if (isCommonJS) exports.xdescribe = xdescribe;
582
+
583
+
584
+ // Provide the XMLHttpRequest class for IE 5.x-6.x:
585
+ jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
586
+ function tryIt(f) {
587
+ try {
588
+ return f();
589
+ } catch(e) {
590
+ }
591
+ return null;
592
+ }
593
+
594
+ var xhr = tryIt(function(){return new ActiveXObject("Msxml2.XMLHTTP.6.0");}) ||
595
+ tryIt(function(){return new ActiveXObject("Msxml2.XMLHTTP.3.0");}) ||
596
+ tryIt(function(){return new ActiveXObject("Msxml2.XMLHTTP");}) ||
597
+ tryIt(function(){return new ActiveXObject("Microsoft.XMLHTTP");});
598
+
599
+ if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
600
+
601
+ return xhr;
602
+ } : XMLHttpRequest;
603
+ /**
604
+ * @namespace
605
+ */
606
+ jasmine.util = {};
607
+
608
+ /**
609
+ * Declare that a child class inherit it's prototype from the parent class.
610
+ *
611
+ * @private
612
+ * @param {Function} childClass
613
+ * @param {Function} parentClass
614
+ */
615
+ jasmine.util.inherit = function(childClass, parentClass) {
616
+ /**
617
+ * @private
618
+ */
619
+ var subclass = function() {
620
+ };
621
+ subclass.prototype = parentClass.prototype;
622
+ childClass.prototype = new subclass();
623
+ };
624
+
625
+ jasmine.util.formatException = function(e) {
626
+ var lineNumber;
627
+ if (e.line) {
628
+ lineNumber = e.line;
629
+ }
630
+ else if (e.lineNumber) {
631
+ lineNumber = e.lineNumber;
632
+ }
633
+
634
+ var file;
635
+
636
+ if (e.sourceURL) {
637
+ file = e.sourceURL;
638
+ }
639
+ else if (e.fileName) {
640
+ file = e.fileName;
641
+ }
642
+
643
+ var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
644
+
645
+ if (file && lineNumber) {
646
+ message += ' in ' + file + ' (line ' + lineNumber + ')';
647
+ }
648
+
649
+ return message;
650
+ };
651
+
652
+ jasmine.util.htmlEscape = function(str) {
653
+ if (!str) return str;
654
+ return str.replace(/&/g, '&amp;')
655
+ .replace(/</g, '&lt;')
656
+ .replace(/>/g, '&gt;');
657
+ };
658
+
659
+ jasmine.util.argsToArray = function(args) {
660
+ var arrayOfArgs = [];
661
+ for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
662
+ return arrayOfArgs;
663
+ };
664
+
665
+ jasmine.util.extend = function(destination, source) {
666
+ for (var property in source) destination[property] = source[property];
667
+ return destination;
668
+ };
669
+
670
+ /**
671
+ * Environment for Jasmine
672
+ *
673
+ * @constructor
674
+ */
675
+ jasmine.Env = function() {
676
+ this.currentSpec = null;
677
+ this.currentSuite = null;
678
+ this.currentRunner_ = new jasmine.Runner(this);
679
+
680
+ this.reporter = new jasmine.MultiReporter();
681
+
682
+ this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
683
+ this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
684
+ this.lastUpdate = 0;
685
+ this.specFilter = function() {
686
+ return true;
687
+ };
688
+
689
+ this.nextSpecId_ = 0;
690
+ this.nextSuiteId_ = 0;
691
+ this.equalityTesters_ = [];
692
+
693
+ // wrap matchers
694
+ this.matchersClass = function() {
695
+ jasmine.Matchers.apply(this, arguments);
696
+ };
697
+ jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
698
+
699
+ jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
700
+ };
701
+
702
+
703
+ jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
704
+ jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
705
+ jasmine.Env.prototype.setInterval = jasmine.setInterval;
706
+ jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
707
+
708
+ /**
709
+ * @returns an object containing jasmine version build info, if set.
710
+ */
711
+ jasmine.Env.prototype.version = function () {
712
+ if (jasmine.version_) {
713
+ return jasmine.version_;
714
+ } else {
715
+ throw new Error('Version not set');
716
+ }
717
+ };
718
+
719
+ /**
720
+ * @returns string containing jasmine version build info, if set.
721
+ */
722
+ jasmine.Env.prototype.versionString = function() {
723
+ if (jasmine.version_) {
724
+ var version = this.version();
725
+ return version.major + "." + version.minor + "." + version.build + " revision " + version.revision;
726
+ } else {
727
+ return "version unknown";
728
+ }
729
+ };
730
+
731
+ /**
732
+ * @returns a sequential integer starting at 0
733
+ */
734
+ jasmine.Env.prototype.nextSpecId = function () {
735
+ return this.nextSpecId_++;
736
+ };
737
+
738
+ /**
739
+ * @returns a sequential integer starting at 0
740
+ */
741
+ jasmine.Env.prototype.nextSuiteId = function () {
742
+ return this.nextSuiteId_++;
743
+ };
744
+
745
+ /**
746
+ * Register a reporter to receive status updates from Jasmine.
747
+ * @param {jasmine.Reporter} reporter An object which will receive status updates.
748
+ */
749
+ jasmine.Env.prototype.addReporter = function(reporter) {
750
+ this.reporter.addReporter(reporter);
751
+ };
752
+
753
+ jasmine.Env.prototype.execute = function() {
754
+ this.currentRunner_.execute();
755
+ };
756
+
757
+ jasmine.Env.prototype.describe = function(description, specDefinitions) {
758
+ var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
759
+
760
+ var parentSuite = this.currentSuite;
761
+ if (parentSuite) {
762
+ parentSuite.add(suite);
763
+ } else {
764
+ this.currentRunner_.add(suite);
765
+ }
766
+
767
+ this.currentSuite = suite;
768
+
769
+ var declarationError = null;
770
+ try {
771
+ specDefinitions.call(suite);
772
+ } catch(e) {
773
+ declarationError = e;
774
+ }
775
+
776
+ this.currentSuite = parentSuite;
777
+
778
+ if (declarationError) {
779
+ this.it("encountered a declaration exception", function() {
780
+ throw declarationError;
781
+ });
782
+ }
783
+
784
+ return suite;
785
+ };
786
+
787
+ jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
788
+ if (this.currentSuite) {
789
+ this.currentSuite.beforeEach(beforeEachFunction);
790
+ } else {
791
+ this.currentRunner_.beforeEach(beforeEachFunction);
792
+ }
793
+ };
794
+
795
+ jasmine.Env.prototype.currentRunner = function () {
796
+ return this.currentRunner_;
797
+ };
798
+
799
+ jasmine.Env.prototype.afterEach = function(afterEachFunction) {
800
+ if (this.currentSuite) {
801
+ this.currentSuite.afterEach(afterEachFunction);
802
+ } else {
803
+ this.currentRunner_.afterEach(afterEachFunction);
804
+ }
805
+
806
+ };
807
+
808
+ jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
809
+ return {
810
+ execute: function() {
811
+ }
812
+ };
813
+ };
814
+
815
+ jasmine.Env.prototype.it = function(description, func) {
816
+ var spec = new jasmine.Spec(this, this.currentSuite, description);
817
+ this.currentSuite.add(spec);
818
+ this.currentSpec = spec;
819
+
820
+ if (func) {
821
+ spec.runs(func);
822
+ }
823
+
824
+ return spec;
825
+ };
826
+
827
+ jasmine.Env.prototype.xit = function(desc, func) {
828
+ return {
829
+ id: this.nextSpecId(),
830
+ runs: function() {
831
+ }
832
+ };
833
+ };
834
+
835
+ jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
836
+ if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
837
+ return true;
838
+ }
839
+
840
+ a.__Jasmine_been_here_before__ = b;
841
+ b.__Jasmine_been_here_before__ = a;
842
+
843
+ var hasKey = function(obj, keyName) {
844
+ return obj !== null && obj[keyName] !== jasmine.undefined;
845
+ };
846
+
847
+ for (var property in b) {
848
+ if (!hasKey(a, property) && hasKey(b, property)) {
849
+ mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
850
+ }
851
+ }
852
+ for (property in a) {
853
+ if (!hasKey(b, property) && hasKey(a, property)) {
854
+ mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
855
+ }
856
+ }
857
+ for (property in b) {
858
+ if (property == '__Jasmine_been_here_before__') continue;
859
+ if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
860
+ 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.");
861
+ }
862
+ }
863
+
864
+ if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
865
+ mismatchValues.push("arrays were not the same length");
866
+ }
867
+
868
+ delete a.__Jasmine_been_here_before__;
869
+ delete b.__Jasmine_been_here_before__;
870
+ return (mismatchKeys.length === 0 && mismatchValues.length === 0);
871
+ };
872
+
873
+ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
874
+ mismatchKeys = mismatchKeys || [];
875
+ mismatchValues = mismatchValues || [];
876
+
877
+ for (var i = 0; i < this.equalityTesters_.length; i++) {
878
+ var equalityTester = this.equalityTesters_[i];
879
+ var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
880
+ if (result !== jasmine.undefined) return result;
881
+ }
882
+
883
+ if (a === b) return true;
884
+
885
+ if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
886
+ return (a == jasmine.undefined && b == jasmine.undefined);
887
+ }
888
+
889
+ if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
890
+ return a === b;
891
+ }
892
+
893
+ if (a instanceof Date && b instanceof Date) {
894
+ return a.getTime() == b.getTime();
895
+ }
896
+
897
+ if (a instanceof jasmine.Matchers.Any) {
898
+ return a.matches(b);
899
+ }
900
+
901
+ if (b instanceof jasmine.Matchers.Any) {
902
+ return b.matches(a);
903
+ }
904
+
905
+ if (jasmine.isString_(a) && jasmine.isString_(b)) {
906
+ return (a == b);
907
+ }
908
+
909
+ if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
910
+ return (a == b);
911
+ }
912
+
913
+ if (typeof a === "object" && typeof b === "object") {
914
+ return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
915
+ }
916
+
917
+ //Straight check
918
+ return (a === b);
919
+ };
920
+
921
+ jasmine.Env.prototype.contains_ = function(haystack, needle) {
922
+ if (jasmine.isArray_(haystack)) {
923
+ for (var i = 0; i < haystack.length; i++) {
924
+ if (this.equals_(haystack[i], needle)) return true;
925
+ }
926
+ return false;
927
+ }
928
+ return haystack.indexOf(needle) >= 0;
929
+ };
930
+
931
+ jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
932
+ this.equalityTesters_.push(equalityTester);
933
+ };
934
+ /** No-op base class for Jasmine reporters.
935
+ *
936
+ * @constructor
937
+ */
938
+ jasmine.Reporter = function() {
939
+ };
940
+
941
+ //noinspection JSUnusedLocalSymbols
942
+ jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
943
+ };
944
+
945
+ //noinspection JSUnusedLocalSymbols
946
+ jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
947
+ };
948
+
949
+ //noinspection JSUnusedLocalSymbols
950
+ jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
951
+ };
952
+
953
+ //noinspection JSUnusedLocalSymbols
954
+ jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
955
+ };
956
+
957
+ //noinspection JSUnusedLocalSymbols
958
+ jasmine.Reporter.prototype.reportSpecResults = function(spec) {
959
+ };
960
+
961
+ //noinspection JSUnusedLocalSymbols
962
+ jasmine.Reporter.prototype.log = function(str) {
963
+ };
964
+
965
+ /**
966
+ * Blocks are functions with executable code that make up a spec.
967
+ *
968
+ * @constructor
969
+ * @param {jasmine.Env} env
970
+ * @param {Function} func
971
+ * @param {jasmine.Spec} spec
972
+ */
973
+ jasmine.Block = function(env, func, spec) {
974
+ this.env = env;
975
+ this.func = func;
976
+ this.spec = spec;
977
+ };
978
+
979
+ jasmine.Block.prototype.execute = function(onComplete) {
980
+ try {
981
+ this.func.apply(this.spec);
982
+ } catch (e) {
983
+ this.spec.fail(e);
984
+ }
985
+ onComplete();
986
+ };
987
+ /** JavaScript API reporter.
988
+ *
989
+ * @constructor
990
+ */
991
+ jasmine.JsApiReporter = function() {
992
+ this.started = false;
993
+ this.finished = false;
994
+ this.suites_ = [];
995
+ this.results_ = {};
996
+ };
997
+
998
+ jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
999
+ this.started = true;
1000
+ var suites = runner.topLevelSuites();
1001
+ for (var i = 0; i < suites.length; i++) {
1002
+ var suite = suites[i];
1003
+ this.suites_.push(this.summarize_(suite));
1004
+ }
1005
+ };
1006
+
1007
+ jasmine.JsApiReporter.prototype.suites = function() {
1008
+ return this.suites_;
1009
+ };
1010
+
1011
+ jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
1012
+ var isSuite = suiteOrSpec instanceof jasmine.Suite;
1013
+ var summary = {
1014
+ id: suiteOrSpec.id,
1015
+ name: suiteOrSpec.description,
1016
+ type: isSuite ? 'suite' : 'spec',
1017
+ children: []
1018
+ };
1019
+
1020
+ if (isSuite) {
1021
+ var children = suiteOrSpec.children();
1022
+ for (var i = 0; i < children.length; i++) {
1023
+ summary.children.push(this.summarize_(children[i]));
1024
+ }
1025
+ }
1026
+ return summary;
1027
+ };
1028
+
1029
+ jasmine.JsApiReporter.prototype.results = function() {
1030
+ return this.results_;
1031
+ };
1032
+
1033
+ jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
1034
+ return this.results_[specId];
1035
+ };
1036
+
1037
+ //noinspection JSUnusedLocalSymbols
1038
+ jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
1039
+ this.finished = true;
1040
+ };
1041
+
1042
+ //noinspection JSUnusedLocalSymbols
1043
+ jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
1044
+ };
1045
+
1046
+ //noinspection JSUnusedLocalSymbols
1047
+ jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
1048
+ this.results_[spec.id] = {
1049
+ messages: spec.results().getItems(),
1050
+ result: spec.results().failedCount > 0 ? "failed" : "passed"
1051
+ };
1052
+ };
1053
+
1054
+ //noinspection JSUnusedLocalSymbols
1055
+ jasmine.JsApiReporter.prototype.log = function(str) {
1056
+ };
1057
+
1058
+ jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
1059
+ var results = {};
1060
+ for (var i = 0; i < specIds.length; i++) {
1061
+ var specId = specIds[i];
1062
+ results[specId] = this.summarizeResult_(this.results_[specId]);
1063
+ }
1064
+ return results;
1065
+ };
1066
+
1067
+ jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
1068
+ var summaryMessages = [];
1069
+ var messagesLength = result.messages.length;
1070
+ for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
1071
+ var resultMessage = result.messages[messageIndex];
1072
+ summaryMessages.push({
1073
+ text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
1074
+ passed: resultMessage.passed ? resultMessage.passed() : true,
1075
+ type: resultMessage.type,
1076
+ message: resultMessage.message,
1077
+ trace: {
1078
+ stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
1079
+ }
1080
+ });
1081
+ }
1082
+
1083
+ return {
1084
+ result : result.result,
1085
+ messages : summaryMessages
1086
+ };
1087
+ };
1088
+
1089
+ /**
1090
+ * @constructor
1091
+ * @param {jasmine.Env} env
1092
+ * @param actual
1093
+ * @param {jasmine.Spec} spec
1094
+ */
1095
+ jasmine.Matchers = function(env, actual, spec, opt_isNot) {
1096
+ this.env = env;
1097
+ this.actual = actual;
1098
+ this.spec = spec;
1099
+ this.isNot = opt_isNot || false;
1100
+ this.reportWasCalled_ = false;
1101
+ };
1102
+
1103
+ // todo: @deprecated as of Jasmine 0.11, remove soon [xw]
1104
+ jasmine.Matchers.pp = function(str) {
1105
+ throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
1106
+ };
1107
+
1108
+ // todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
1109
+ jasmine.Matchers.prototype.report = function(result, failing_message, details) {
1110
+ throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
1111
+ };
1112
+
1113
+ jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
1114
+ for (var methodName in prototype) {
1115
+ if (methodName == 'report') continue;
1116
+ var orig = prototype[methodName];
1117
+ matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
1118
+ }
1119
+ };
1120
+
1121
+ jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
1122
+ return function() {
1123
+ var matcherArgs = jasmine.util.argsToArray(arguments);
1124
+ var result = matcherFunction.apply(this, arguments);
1125
+
1126
+ if (this.isNot) {
1127
+ result = !result;
1128
+ }
1129
+
1130
+ if (this.reportWasCalled_) return result;
1131
+
1132
+ var message;
1133
+ if (!result) {
1134
+ if (this.message) {
1135
+ message = this.message.apply(this, arguments);
1136
+ if (jasmine.isArray_(message)) {
1137
+ message = message[this.isNot ? 1 : 0];
1138
+ }
1139
+ } else {
1140
+ var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
1141
+ message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
1142
+ if (matcherArgs.length > 0) {
1143
+ for (var i = 0; i < matcherArgs.length; i++) {
1144
+ if (i > 0) message += ",";
1145
+ message += " " + jasmine.pp(matcherArgs[i]);
1146
+ }
1147
+ }
1148
+ message += ".";
1149
+ }
1150
+ }
1151
+ var expectationResult = new jasmine.ExpectationResult({
1152
+ matcherName: matcherName,
1153
+ passed: result,
1154
+ expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
1155
+ actual: this.actual,
1156
+ message: message
1157
+ });
1158
+ this.spec.addMatcherResult(expectationResult);
1159
+ return jasmine.undefined;
1160
+ };
1161
+ };
1162
+
1163
+
1164
+
1165
+
1166
+ /**
1167
+ * toBe: compares the actual to the expected using ===
1168
+ * @param expected
1169
+ */
1170
+ jasmine.Matchers.prototype.toBe = function(expected) {
1171
+ return this.actual === expected;
1172
+ };
1173
+
1174
+ /**
1175
+ * toNotBe: compares the actual to the expected using !==
1176
+ * @param expected
1177
+ * @deprecated as of 1.0. Use not.toBe() instead.
1178
+ */
1179
+ jasmine.Matchers.prototype.toNotBe = function(expected) {
1180
+ return this.actual !== expected;
1181
+ };
1182
+
1183
+ /**
1184
+ * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
1185
+ *
1186
+ * @param expected
1187
+ */
1188
+ jasmine.Matchers.prototype.toEqual = function(expected) {
1189
+ return this.env.equals_(this.actual, expected);
1190
+ };
1191
+
1192
+ /**
1193
+ * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
1194
+ * @param expected
1195
+ * @deprecated as of 1.0. Use not.toNotEqual() instead.
1196
+ */
1197
+ jasmine.Matchers.prototype.toNotEqual = function(expected) {
1198
+ return !this.env.equals_(this.actual, expected);
1199
+ };
1200
+
1201
+ /**
1202
+ * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
1203
+ * a pattern or a String.
1204
+ *
1205
+ * @param expected
1206
+ */
1207
+ jasmine.Matchers.prototype.toMatch = function(expected) {
1208
+ return new RegExp(expected).test(this.actual);
1209
+ };
1210
+
1211
+ /**
1212
+ * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
1213
+ * @param expected
1214
+ * @deprecated as of 1.0. Use not.toMatch() instead.
1215
+ */
1216
+ jasmine.Matchers.prototype.toNotMatch = function(expected) {
1217
+ return !(new RegExp(expected).test(this.actual));
1218
+ };
1219
+
1220
+ /**
1221
+ * Matcher that compares the actual to jasmine.undefined.
1222
+ */
1223
+ jasmine.Matchers.prototype.toBeDefined = function() {
1224
+ return (this.actual !== jasmine.undefined);
1225
+ };
1226
+
1227
+ /**
1228
+ * Matcher that compares the actual to jasmine.undefined.
1229
+ */
1230
+ jasmine.Matchers.prototype.toBeUndefined = function() {
1231
+ return (this.actual === jasmine.undefined);
1232
+ };
1233
+
1234
+ /**
1235
+ * Matcher that compares the actual to null.
1236
+ */
1237
+ jasmine.Matchers.prototype.toBeNull = function() {
1238
+ return (this.actual === null);
1239
+ };
1240
+
1241
+ /**
1242
+ * Matcher that boolean not-nots the actual.
1243
+ */
1244
+ jasmine.Matchers.prototype.toBeTruthy = function() {
1245
+ return !!this.actual;
1246
+ };
1247
+
1248
+
1249
+ /**
1250
+ * Matcher that boolean nots the actual.
1251
+ */
1252
+ jasmine.Matchers.prototype.toBeFalsy = function() {
1253
+ return !this.actual;
1254
+ };
1255
+
1256
+
1257
+ /**
1258
+ * Matcher that checks to see if the actual, a Jasmine spy, was called.
1259
+ */
1260
+ jasmine.Matchers.prototype.toHaveBeenCalled = function() {
1261
+ if (arguments.length > 0) {
1262
+ throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
1263
+ }
1264
+
1265
+ if (!jasmine.isSpy(this.actual)) {
1266
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1267
+ }
1268
+
1269
+ this.message = function() {
1270
+ return [
1271
+ "Expected spy " + this.actual.identity + " to have been called.",
1272
+ "Expected spy " + this.actual.identity + " not to have been called."
1273
+ ];
1274
+ };
1275
+
1276
+ return this.actual.wasCalled;
1277
+ };
1278
+
1279
+ /** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
1280
+ jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
1281
+
1282
+ /**
1283
+ * Matcher that checks to see if the actual, a Jasmine spy, was not called.
1284
+ *
1285
+ * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
1286
+ */
1287
+ jasmine.Matchers.prototype.wasNotCalled = function() {
1288
+ if (arguments.length > 0) {
1289
+ throw new Error('wasNotCalled does not take arguments');
1290
+ }
1291
+
1292
+ if (!jasmine.isSpy(this.actual)) {
1293
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1294
+ }
1295
+
1296
+ this.message = function() {
1297
+ return [
1298
+ "Expected spy " + this.actual.identity + " to not have been called.",
1299
+ "Expected spy " + this.actual.identity + " to have been called."
1300
+ ];
1301
+ };
1302
+
1303
+ return !this.actual.wasCalled;
1304
+ };
1305
+
1306
+ /**
1307
+ * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
1308
+ *
1309
+ * @example
1310
+ *
1311
+ */
1312
+ jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
1313
+ var expectedArgs = jasmine.util.argsToArray(arguments);
1314
+ if (!jasmine.isSpy(this.actual)) {
1315
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1316
+ }
1317
+ this.message = function() {
1318
+ if (this.actual.callCount === 0) {
1319
+ // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
1320
+ return [
1321
+ "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
1322
+ "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
1323
+ ];
1324
+ } else {
1325
+ return [
1326
+ "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
1327
+ "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
1328
+ ];
1329
+ }
1330
+ };
1331
+
1332
+ return this.env.contains_(this.actual.argsForCall, expectedArgs);
1333
+ };
1334
+
1335
+ /** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
1336
+ jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
1337
+
1338
+ /** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
1339
+ jasmine.Matchers.prototype.wasNotCalledWith = function() {
1340
+ var expectedArgs = jasmine.util.argsToArray(arguments);
1341
+ if (!jasmine.isSpy(this.actual)) {
1342
+ throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
1343
+ }
1344
+
1345
+ this.message = function() {
1346
+ return [
1347
+ "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
1348
+ "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
1349
+ ];
1350
+ };
1351
+
1352
+ return !this.env.contains_(this.actual.argsForCall, expectedArgs);
1353
+ };
1354
+
1355
+ /**
1356
+ * Matcher that checks that the expected item is an element in the actual Array.
1357
+ *
1358
+ * @param {Object} expected
1359
+ */
1360
+ jasmine.Matchers.prototype.toContain = function(expected) {
1361
+ return this.env.contains_(this.actual, expected);
1362
+ };
1363
+
1364
+ /**
1365
+ * Matcher that checks that the expected item is NOT an element in the actual Array.
1366
+ *
1367
+ * @param {Object} expected
1368
+ * @deprecated as of 1.0. Use not.toNotContain() instead.
1369
+ */
1370
+ jasmine.Matchers.prototype.toNotContain = function(expected) {
1371
+ return !this.env.contains_(this.actual, expected);
1372
+ };
1373
+
1374
+ jasmine.Matchers.prototype.toBeLessThan = function(expected) {
1375
+ return this.actual < expected;
1376
+ };
1377
+
1378
+ jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
1379
+ return this.actual > expected;
1380
+ };
1381
+
1382
+ /**
1383
+ * Matcher that checks that the expected exception was thrown by the actual.
1384
+ *
1385
+ * @param {String} expected
1386
+ */
1387
+ jasmine.Matchers.prototype.toThrow = function(expected) {
1388
+ var result = false;
1389
+ var exception;
1390
+ if (typeof this.actual != 'function') {
1391
+ throw new Error('Actual is not a function');
1392
+ }
1393
+ try {
1394
+ this.actual();
1395
+ } catch (e) {
1396
+ exception = e;
1397
+ }
1398
+ if (exception) {
1399
+ result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
1400
+ }
1401
+
1402
+ var not = this.isNot ? "not " : "";
1403
+
1404
+ this.message = function() {
1405
+ if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
1406
+ return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
1407
+ } else {
1408
+ return "Expected function to throw an exception.";
1409
+ }
1410
+ };
1411
+
1412
+ return result;
1413
+ };
1414
+
1415
+ jasmine.Matchers.Any = function(expectedClass) {
1416
+ this.expectedClass = expectedClass;
1417
+ };
1418
+
1419
+ jasmine.Matchers.Any.prototype.matches = function(other) {
1420
+ if (this.expectedClass == String) {
1421
+ return typeof other == 'string' || other instanceof String;
1422
+ }
1423
+
1424
+ if (this.expectedClass == Number) {
1425
+ return typeof other == 'number' || other instanceof Number;
1426
+ }
1427
+
1428
+ if (this.expectedClass == Function) {
1429
+ return typeof other == 'function' || other instanceof Function;
1430
+ }
1431
+
1432
+ if (this.expectedClass == Object) {
1433
+ return typeof other == 'object';
1434
+ }
1435
+
1436
+ return other instanceof this.expectedClass;
1437
+ };
1438
+
1439
+ jasmine.Matchers.Any.prototype.toString = function() {
1440
+ return '<jasmine.any(' + this.expectedClass + ')>';
1441
+ };
1442
+
1443
+ /**
1444
+ * @constructor
1445
+ */
1446
+ jasmine.MultiReporter = function() {
1447
+ this.subReporters_ = [];
1448
+ };
1449
+ jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
1450
+
1451
+ jasmine.MultiReporter.prototype.addReporter = function(reporter) {
1452
+ this.subReporters_.push(reporter);
1453
+ };
1454
+
1455
+ (function() {
1456
+ var functionNames = [
1457
+ "reportRunnerStarting",
1458
+ "reportRunnerResults",
1459
+ "reportSuiteResults",
1460
+ "reportSpecStarting",
1461
+ "reportSpecResults",
1462
+ "log"
1463
+ ];
1464
+ for (var i = 0; i < functionNames.length; i++) {
1465
+ var functionName = functionNames[i];
1466
+ jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
1467
+ return function() {
1468
+ for (var j = 0; j < this.subReporters_.length; j++) {
1469
+ var subReporter = this.subReporters_[j];
1470
+ if (subReporter[functionName]) {
1471
+ subReporter[functionName].apply(subReporter, arguments);
1472
+ }
1473
+ }
1474
+ };
1475
+ })(functionName);
1476
+ }
1477
+ })();
1478
+ /**
1479
+ * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
1480
+ *
1481
+ * @constructor
1482
+ */
1483
+ jasmine.NestedResults = function() {
1484
+ /**
1485
+ * The total count of results
1486
+ */
1487
+ this.totalCount = 0;
1488
+ /**
1489
+ * Number of passed results
1490
+ */
1491
+ this.passedCount = 0;
1492
+ /**
1493
+ * Number of failed results
1494
+ */
1495
+ this.failedCount = 0;
1496
+ /**
1497
+ * Was this suite/spec skipped?
1498
+ */
1499
+ this.skipped = false;
1500
+ /**
1501
+ * @ignore
1502
+ */
1503
+ this.items_ = [];
1504
+ };
1505
+
1506
+ /**
1507
+ * Roll up the result counts.
1508
+ *
1509
+ * @param result
1510
+ */
1511
+ jasmine.NestedResults.prototype.rollupCounts = function(result) {
1512
+ this.totalCount += result.totalCount;
1513
+ this.passedCount += result.passedCount;
1514
+ this.failedCount += result.failedCount;
1515
+ };
1516
+
1517
+ /**
1518
+ * Adds a log message.
1519
+ * @param values Array of message parts which will be concatenated later.
1520
+ */
1521
+ jasmine.NestedResults.prototype.log = function(values) {
1522
+ this.items_.push(new jasmine.MessageResult(values));
1523
+ };
1524
+
1525
+ /**
1526
+ * Getter for the results: message & results.
1527
+ */
1528
+ jasmine.NestedResults.prototype.getItems = function() {
1529
+ return this.items_;
1530
+ };
1531
+
1532
+ /**
1533
+ * Adds a result, tracking counts (total, passed, & failed)
1534
+ * @param {jasmine.ExpectationResult|jasmine.NestedResults} result
1535
+ */
1536
+ jasmine.NestedResults.prototype.addResult = function(result) {
1537
+ if (result.type != 'log') {
1538
+ if (result.items_) {
1539
+ this.rollupCounts(result);
1540
+ } else {
1541
+ this.totalCount++;
1542
+ if (result.passed()) {
1543
+ this.passedCount++;
1544
+ } else {
1545
+ this.failedCount++;
1546
+ }
1547
+ }
1548
+ }
1549
+ this.items_.push(result);
1550
+ };
1551
+
1552
+ /**
1553
+ * @returns {Boolean} True if <b>everything</b> below passed
1554
+ */
1555
+ jasmine.NestedResults.prototype.passed = function() {
1556
+ return this.passedCount === this.totalCount;
1557
+ };
1558
+ /**
1559
+ * Base class for pretty printing for expectation results.
1560
+ */
1561
+ jasmine.PrettyPrinter = function() {
1562
+ this.ppNestLevel_ = 0;
1563
+ };
1564
+
1565
+ /**
1566
+ * Formats a value in a nice, human-readable string.
1567
+ *
1568
+ * @param value
1569
+ */
1570
+ jasmine.PrettyPrinter.prototype.format = function(value) {
1571
+ if (this.ppNestLevel_ > 40) {
1572
+ throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
1573
+ }
1574
+
1575
+ this.ppNestLevel_++;
1576
+ try {
1577
+ if (value === jasmine.undefined) {
1578
+ this.emitScalar('undefined');
1579
+ } else if (value === null) {
1580
+ this.emitScalar('null');
1581
+ } else if (value === jasmine.getGlobal()) {
1582
+ this.emitScalar('<global>');
1583
+ } else if (value instanceof jasmine.Matchers.Any) {
1584
+ this.emitScalar(value.toString());
1585
+ } else if (typeof value === 'string') {
1586
+ this.emitString(value);
1587
+ } else if (jasmine.isSpy(value)) {
1588
+ this.emitScalar("spy on " + value.identity);
1589
+ } else if (value instanceof RegExp) {
1590
+ this.emitScalar(value.toString());
1591
+ } else if (typeof value === 'function') {
1592
+ this.emitScalar('Function');
1593
+ } else if (typeof value.nodeType === 'number') {
1594
+ this.emitScalar('HTMLNode');
1595
+ } else if (value instanceof Date) {
1596
+ this.emitScalar('Date(' + value + ')');
1597
+ } else if (value.__Jasmine_been_here_before__) {
1598
+ this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
1599
+ } else if (jasmine.isArray_(value) || typeof value == 'object') {
1600
+ value.__Jasmine_been_here_before__ = true;
1601
+ if (jasmine.isArray_(value)) {
1602
+ this.emitArray(value);
1603
+ } else {
1604
+ this.emitObject(value);
1605
+ }
1606
+ delete value.__Jasmine_been_here_before__;
1607
+ } else {
1608
+ this.emitScalar(value.toString());
1609
+ }
1610
+ } finally {
1611
+ this.ppNestLevel_--;
1612
+ }
1613
+ };
1614
+
1615
+ jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
1616
+ for (var property in obj) {
1617
+ if (property == '__Jasmine_been_here_before__') continue;
1618
+ fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
1619
+ obj.__lookupGetter__(property) !== null) : false);
1620
+ }
1621
+ };
1622
+
1623
+ jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
1624
+ jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
1625
+ jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
1626
+ jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
1627
+
1628
+ jasmine.StringPrettyPrinter = function() {
1629
+ jasmine.PrettyPrinter.call(this);
1630
+
1631
+ this.string = '';
1632
+ };
1633
+ jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
1634
+
1635
+ jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
1636
+ this.append(value);
1637
+ };
1638
+
1639
+ jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
1640
+ this.append("'" + value + "'");
1641
+ };
1642
+
1643
+ jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
1644
+ this.append('[ ');
1645
+ for (var i = 0; i < array.length; i++) {
1646
+ if (i > 0) {
1647
+ this.append(', ');
1648
+ }
1649
+ this.format(array[i]);
1650
+ }
1651
+ this.append(' ]');
1652
+ };
1653
+
1654
+ jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
1655
+ var self = this;
1656
+ this.append('{ ');
1657
+ var first = true;
1658
+
1659
+ this.iterateObject(obj, function(property, isGetter) {
1660
+ if (first) {
1661
+ first = false;
1662
+ } else {
1663
+ self.append(', ');
1664
+ }
1665
+
1666
+ self.append(property);
1667
+ self.append(' : ');
1668
+ if (isGetter) {
1669
+ self.append('<getter>');
1670
+ } else {
1671
+ self.format(obj[property]);
1672
+ }
1673
+ });
1674
+
1675
+ this.append(' }');
1676
+ };
1677
+
1678
+ jasmine.StringPrettyPrinter.prototype.append = function(value) {
1679
+ this.string += value;
1680
+ };
1681
+ jasmine.Queue = function(env) {
1682
+ this.env = env;
1683
+ this.blocks = [];
1684
+ this.running = false;
1685
+ this.index = 0;
1686
+ this.offset = 0;
1687
+ this.abort = false;
1688
+ };
1689
+
1690
+ jasmine.Queue.prototype.addBefore = function(block) {
1691
+ this.blocks.unshift(block);
1692
+ };
1693
+
1694
+ jasmine.Queue.prototype.add = function(block) {
1695
+ this.blocks.push(block);
1696
+ };
1697
+
1698
+ jasmine.Queue.prototype.insertNext = function(block) {
1699
+ this.blocks.splice((this.index + this.offset + 1), 0, block);
1700
+ this.offset++;
1701
+ };
1702
+
1703
+ jasmine.Queue.prototype.start = function(onComplete) {
1704
+ this.running = true;
1705
+ this.onComplete = onComplete;
1706
+ this.next_();
1707
+ };
1708
+
1709
+ jasmine.Queue.prototype.isRunning = function() {
1710
+ return this.running;
1711
+ };
1712
+
1713
+ jasmine.Queue.LOOP_DONT_RECURSE = true;
1714
+
1715
+ jasmine.Queue.prototype.next_ = function() {
1716
+ var self = this;
1717
+ var goAgain = true;
1718
+
1719
+ while (goAgain) {
1720
+ goAgain = false;
1721
+
1722
+ if (self.index < self.blocks.length && !this.abort) {
1723
+ var calledSynchronously = true;
1724
+ var completedSynchronously = false;
1725
+
1726
+ var onComplete = function () {
1727
+ if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
1728
+ completedSynchronously = true;
1729
+ return;
1730
+ }
1731
+
1732
+ if (self.blocks[self.index].abort) {
1733
+ self.abort = true;
1734
+ }
1735
+
1736
+ self.offset = 0;
1737
+ self.index++;
1738
+
1739
+ var now = new Date().getTime();
1740
+ if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
1741
+ self.env.lastUpdate = now;
1742
+ self.env.setTimeout(function() {
1743
+ self.next_();
1744
+ }, 0);
1745
+ } else {
1746
+ if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
1747
+ goAgain = true;
1748
+ } else {
1749
+ self.next_();
1750
+ }
1751
+ }
1752
+ };
1753
+ self.blocks[self.index].execute(onComplete);
1754
+
1755
+ calledSynchronously = false;
1756
+ if (completedSynchronously) {
1757
+ onComplete();
1758
+ }
1759
+
1760
+ } else {
1761
+ self.running = false;
1762
+ if (self.onComplete) {
1763
+ self.onComplete();
1764
+ }
1765
+ }
1766
+ }
1767
+ };
1768
+
1769
+ jasmine.Queue.prototype.results = function() {
1770
+ var results = new jasmine.NestedResults();
1771
+ for (var i = 0; i < this.blocks.length; i++) {
1772
+ if (this.blocks[i].results) {
1773
+ results.addResult(this.blocks[i].results());
1774
+ }
1775
+ }
1776
+ return results;
1777
+ };
1778
+
1779
+
1780
+ /**
1781
+ * Runner
1782
+ *
1783
+ * @constructor
1784
+ * @param {jasmine.Env} env
1785
+ */
1786
+ jasmine.Runner = function(env) {
1787
+ var self = this;
1788
+ self.env = env;
1789
+ self.queue = new jasmine.Queue(env);
1790
+ self.before_ = [];
1791
+ self.after_ = [];
1792
+ self.suites_ = [];
1793
+ };
1794
+
1795
+ jasmine.Runner.prototype.execute = function() {
1796
+ var self = this;
1797
+ if (self.env.reporter.reportRunnerStarting) {
1798
+ self.env.reporter.reportRunnerStarting(this);
1799
+ }
1800
+ self.queue.start(function () {
1801
+ self.finishCallback();
1802
+ });
1803
+ };
1804
+
1805
+ jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
1806
+ beforeEachFunction.typeName = 'beforeEach';
1807
+ this.before_.splice(0,0,beforeEachFunction);
1808
+ };
1809
+
1810
+ jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
1811
+ afterEachFunction.typeName = 'afterEach';
1812
+ this.after_.splice(0,0,afterEachFunction);
1813
+ };
1814
+
1815
+
1816
+ jasmine.Runner.prototype.finishCallback = function() {
1817
+ this.env.reporter.reportRunnerResults(this);
1818
+ };
1819
+
1820
+ jasmine.Runner.prototype.addSuite = function(suite) {
1821
+ this.suites_.push(suite);
1822
+ };
1823
+
1824
+ jasmine.Runner.prototype.add = function(block) {
1825
+ if (block instanceof jasmine.Suite) {
1826
+ this.addSuite(block);
1827
+ }
1828
+ this.queue.add(block);
1829
+ };
1830
+
1831
+ jasmine.Runner.prototype.specs = function () {
1832
+ var suites = this.suites();
1833
+ var specs = [];
1834
+ for (var i = 0; i < suites.length; i++) {
1835
+ specs = specs.concat(suites[i].specs());
1836
+ }
1837
+ return specs;
1838
+ };
1839
+
1840
+ jasmine.Runner.prototype.suites = function() {
1841
+ return this.suites_;
1842
+ };
1843
+
1844
+ jasmine.Runner.prototype.topLevelSuites = function() {
1845
+ var topLevelSuites = [];
1846
+ for (var i = 0; i < this.suites_.length; i++) {
1847
+ if (!this.suites_[i].parentSuite) {
1848
+ topLevelSuites.push(this.suites_[i]);
1849
+ }
1850
+ }
1851
+ return topLevelSuites;
1852
+ };
1853
+
1854
+ jasmine.Runner.prototype.results = function() {
1855
+ return this.queue.results();
1856
+ };
1857
+ /**
1858
+ * Internal representation of a Jasmine specification, or test.
1859
+ *
1860
+ * @constructor
1861
+ * @param {jasmine.Env} env
1862
+ * @param {jasmine.Suite} suite
1863
+ * @param {String} description
1864
+ */
1865
+ jasmine.Spec = function(env, suite, description) {
1866
+ if (!env) {
1867
+ throw new Error('jasmine.Env() required');
1868
+ }
1869
+ if (!suite) {
1870
+ throw new Error('jasmine.Suite() required');
1871
+ }
1872
+ var spec = this;
1873
+ spec.id = env.nextSpecId ? env.nextSpecId() : null;
1874
+ spec.env = env;
1875
+ spec.suite = suite;
1876
+ spec.description = description;
1877
+ spec.queue = new jasmine.Queue(env);
1878
+
1879
+ spec.afterCallbacks = [];
1880
+ spec.spies_ = [];
1881
+
1882
+ spec.results_ = new jasmine.NestedResults();
1883
+ spec.results_.description = description;
1884
+ spec.matchersClass = null;
1885
+ };
1886
+
1887
+ jasmine.Spec.prototype.getFullName = function() {
1888
+ return this.suite.getFullName() + ' ' + this.description + '.';
1889
+ };
1890
+
1891
+
1892
+ jasmine.Spec.prototype.results = function() {
1893
+ return this.results_;
1894
+ };
1895
+
1896
+ /**
1897
+ * All parameters are pretty-printed and concatenated together, then written to the spec's output.
1898
+ *
1899
+ * Be careful not to leave calls to <code>jasmine.log</code> in production code.
1900
+ */
1901
+ jasmine.Spec.prototype.log = function() {
1902
+ return this.results_.log(arguments);
1903
+ };
1904
+
1905
+ jasmine.Spec.prototype.runs = function (func) {
1906
+ var block = new jasmine.Block(this.env, func, this);
1907
+ this.addToQueue(block);
1908
+ return this;
1909
+ };
1910
+
1911
+ jasmine.Spec.prototype.addToQueue = function (block) {
1912
+ if (this.queue.isRunning()) {
1913
+ this.queue.insertNext(block);
1914
+ } else {
1915
+ this.queue.add(block);
1916
+ }
1917
+ };
1918
+
1919
+ /**
1920
+ * @param {jasmine.ExpectationResult} result
1921
+ */
1922
+ jasmine.Spec.prototype.addMatcherResult = function(result) {
1923
+ this.results_.addResult(result);
1924
+ };
1925
+
1926
+ jasmine.Spec.prototype.expect = function(actual) {
1927
+ var positive = new (this.getMatchersClass_())(this.env, actual, this);
1928
+ positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
1929
+ return positive;
1930
+ };
1931
+
1932
+ /**
1933
+ * Waits a fixed time period before moving to the next block.
1934
+ *
1935
+ * @deprecated Use waitsFor() instead
1936
+ * @param {Number} timeout milliseconds to wait
1937
+ */
1938
+ jasmine.Spec.prototype.waits = function(timeout) {
1939
+ var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
1940
+ this.addToQueue(waitsFunc);
1941
+ return this;
1942
+ };
1943
+
1944
+ /**
1945
+ * Waits for the latchFunction to return true before proceeding to the next block.
1946
+ *
1947
+ * @param {Function} latchFunction
1948
+ * @param {String} optional_timeoutMessage
1949
+ * @param {Number} optional_timeout
1950
+ */
1951
+ jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
1952
+ var latchFunction_ = null;
1953
+ var optional_timeoutMessage_ = null;
1954
+ var optional_timeout_ = null;
1955
+
1956
+ for (var i = 0; i < arguments.length; i++) {
1957
+ var arg = arguments[i];
1958
+ switch (typeof arg) {
1959
+ case 'function':
1960
+ latchFunction_ = arg;
1961
+ break;
1962
+ case 'string':
1963
+ optional_timeoutMessage_ = arg;
1964
+ break;
1965
+ case 'number':
1966
+ optional_timeout_ = arg;
1967
+ break;
1968
+ }
1969
+ }
1970
+
1971
+ var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
1972
+ this.addToQueue(waitsForFunc);
1973
+ return this;
1974
+ };
1975
+
1976
+ jasmine.Spec.prototype.fail = function (e) {
1977
+ var expectationResult = new jasmine.ExpectationResult({
1978
+ passed: false,
1979
+ message: e ? jasmine.util.formatException(e) : 'Exception'
1980
+ });
1981
+ this.results_.addResult(expectationResult);
1982
+ };
1983
+
1984
+ jasmine.Spec.prototype.getMatchersClass_ = function() {
1985
+ return this.matchersClass || this.env.matchersClass;
1986
+ };
1987
+
1988
+ jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
1989
+ var parent = this.getMatchersClass_();
1990
+ var newMatchersClass = function() {
1991
+ parent.apply(this, arguments);
1992
+ };
1993
+ jasmine.util.inherit(newMatchersClass, parent);
1994
+ jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
1995
+ this.matchersClass = newMatchersClass;
1996
+ };
1997
+
1998
+ jasmine.Spec.prototype.finishCallback = function() {
1999
+ this.env.reporter.reportSpecResults(this);
2000
+ };
2001
+
2002
+ jasmine.Spec.prototype.finish = function(onComplete) {
2003
+ this.removeAllSpies();
2004
+ this.finishCallback();
2005
+ if (onComplete) {
2006
+ onComplete();
2007
+ }
2008
+ };
2009
+
2010
+ jasmine.Spec.prototype.after = function(doAfter) {
2011
+ if (this.queue.isRunning()) {
2012
+ this.queue.add(new jasmine.Block(this.env, doAfter, this));
2013
+ } else {
2014
+ this.afterCallbacks.unshift(doAfter);
2015
+ }
2016
+ };
2017
+
2018
+ jasmine.Spec.prototype.execute = function(onComplete) {
2019
+ var spec = this;
2020
+ if (!spec.env.specFilter(spec)) {
2021
+ spec.results_.skipped = true;
2022
+ spec.finish(onComplete);
2023
+ return;
2024
+ }
2025
+
2026
+ this.env.reporter.reportSpecStarting(this);
2027
+
2028
+ spec.env.currentSpec = spec;
2029
+
2030
+ spec.addBeforesAndAftersToQueue();
2031
+
2032
+ spec.queue.start(function () {
2033
+ spec.finish(onComplete);
2034
+ });
2035
+ };
2036
+
2037
+ jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
2038
+ var runner = this.env.currentRunner();
2039
+ var i;
2040
+
2041
+ for (var suite = this.suite; suite; suite = suite.parentSuite) {
2042
+ for (i = 0; i < suite.before_.length; i++) {
2043
+ this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
2044
+ }
2045
+ }
2046
+ for (i = 0; i < runner.before_.length; i++) {
2047
+ this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
2048
+ }
2049
+ for (i = 0; i < this.afterCallbacks.length; i++) {
2050
+ this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
2051
+ }
2052
+ for (suite = this.suite; suite; suite = suite.parentSuite) {
2053
+ for (i = 0; i < suite.after_.length; i++) {
2054
+ this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
2055
+ }
2056
+ }
2057
+ for (i = 0; i < runner.after_.length; i++) {
2058
+ this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
2059
+ }
2060
+ };
2061
+
2062
+ jasmine.Spec.prototype.explodes = function() {
2063
+ throw 'explodes function should not have been called';
2064
+ };
2065
+
2066
+ jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
2067
+ if (obj == jasmine.undefined) {
2068
+ throw "spyOn could not find an object to spy upon for " + methodName + "()";
2069
+ }
2070
+
2071
+ if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
2072
+ throw methodName + '() method does not exist';
2073
+ }
2074
+
2075
+ if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
2076
+ throw new Error(methodName + ' has already been spied upon');
2077
+ }
2078
+
2079
+ var spyObj = jasmine.createSpy(methodName);
2080
+
2081
+ this.spies_.push(spyObj);
2082
+ spyObj.baseObj = obj;
2083
+ spyObj.methodName = methodName;
2084
+ spyObj.originalValue = obj[methodName];
2085
+
2086
+ obj[methodName] = spyObj;
2087
+
2088
+ return spyObj;
2089
+ };
2090
+
2091
+ jasmine.Spec.prototype.removeAllSpies = function() {
2092
+ for (var i = 0; i < this.spies_.length; i++) {
2093
+ var spy = this.spies_[i];
2094
+ spy.baseObj[spy.methodName] = spy.originalValue;
2095
+ }
2096
+ this.spies_ = [];
2097
+ };
2098
+
2099
+ /**
2100
+ * Internal representation of a Jasmine suite.
2101
+ *
2102
+ * @constructor
2103
+ * @param {jasmine.Env} env
2104
+ * @param {String} description
2105
+ * @param {Function} specDefinitions
2106
+ * @param {jasmine.Suite} parentSuite
2107
+ */
2108
+ jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
2109
+ var self = this;
2110
+ self.id = env.nextSuiteId ? env.nextSuiteId() : null;
2111
+ self.description = description;
2112
+ self.queue = new jasmine.Queue(env);
2113
+ self.parentSuite = parentSuite;
2114
+ self.env = env;
2115
+ self.before_ = [];
2116
+ self.after_ = [];
2117
+ self.children_ = [];
2118
+ self.suites_ = [];
2119
+ self.specs_ = [];
2120
+ };
2121
+
2122
+ jasmine.Suite.prototype.getFullName = function() {
2123
+ var fullName = this.description;
2124
+ for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
2125
+ fullName = parentSuite.description + ' ' + fullName;
2126
+ }
2127
+ return fullName;
2128
+ };
2129
+
2130
+ jasmine.Suite.prototype.finish = function(onComplete) {
2131
+ this.env.reporter.reportSuiteResults(this);
2132
+ this.finished = true;
2133
+ if (typeof(onComplete) == 'function') {
2134
+ onComplete();
2135
+ }
2136
+ };
2137
+
2138
+ jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
2139
+ beforeEachFunction.typeName = 'beforeEach';
2140
+ this.before_.unshift(beforeEachFunction);
2141
+ };
2142
+
2143
+ jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
2144
+ afterEachFunction.typeName = 'afterEach';
2145
+ this.after_.unshift(afterEachFunction);
2146
+ };
2147
+
2148
+ jasmine.Suite.prototype.results = function() {
2149
+ return this.queue.results();
2150
+ };
2151
+
2152
+ jasmine.Suite.prototype.add = function(suiteOrSpec) {
2153
+ this.children_.push(suiteOrSpec);
2154
+ if (suiteOrSpec instanceof jasmine.Suite) {
2155
+ this.suites_.push(suiteOrSpec);
2156
+ this.env.currentRunner().addSuite(suiteOrSpec);
2157
+ } else {
2158
+ this.specs_.push(suiteOrSpec);
2159
+ }
2160
+ this.queue.add(suiteOrSpec);
2161
+ };
2162
+
2163
+ jasmine.Suite.prototype.specs = function() {
2164
+ return this.specs_;
2165
+ };
2166
+
2167
+ jasmine.Suite.prototype.suites = function() {
2168
+ return this.suites_;
2169
+ };
2170
+
2171
+ jasmine.Suite.prototype.children = function() {
2172
+ return this.children_;
2173
+ };
2174
+
2175
+ jasmine.Suite.prototype.execute = function(onComplete) {
2176
+ var self = this;
2177
+ this.queue.start(function () {
2178
+ self.finish(onComplete);
2179
+ });
2180
+ };
2181
+ jasmine.WaitsBlock = function(env, timeout, spec) {
2182
+ this.timeout = timeout;
2183
+ jasmine.Block.call(this, env, null, spec);
2184
+ };
2185
+
2186
+ jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
2187
+
2188
+ jasmine.WaitsBlock.prototype.execute = function (onComplete) {
2189
+ this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
2190
+ this.env.setTimeout(function () {
2191
+ onComplete();
2192
+ }, this.timeout);
2193
+ };
2194
+ /**
2195
+ * A block which waits for some condition to become true, with timeout.
2196
+ *
2197
+ * @constructor
2198
+ * @extends jasmine.Block
2199
+ * @param {jasmine.Env} env The Jasmine environment.
2200
+ * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
2201
+ * @param {Function} latchFunction A function which returns true when the desired condition has been met.
2202
+ * @param {String} message The message to display if the desired condition hasn't been met within the given time period.
2203
+ * @param {jasmine.Spec} spec The Jasmine spec.
2204
+ */
2205
+ jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
2206
+ this.timeout = timeout || env.defaultTimeoutInterval;
2207
+ this.latchFunction = latchFunction;
2208
+ this.message = message;
2209
+ this.totalTimeSpentWaitingForLatch = 0;
2210
+ jasmine.Block.call(this, env, null, spec);
2211
+ };
2212
+ jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
2213
+
2214
+ jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
2215
+
2216
+ jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
2217
+ this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
2218
+ var latchFunctionResult;
2219
+ try {
2220
+ latchFunctionResult = this.latchFunction.apply(this.spec);
2221
+ } catch (e) {
2222
+ this.spec.fail(e);
2223
+ onComplete();
2224
+ return;
2225
+ }
2226
+
2227
+ if (latchFunctionResult) {
2228
+ onComplete();
2229
+ } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
2230
+ var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
2231
+ this.spec.fail({
2232
+ name: 'timeout',
2233
+ message: message
2234
+ });
2235
+
2236
+ this.abort = true;
2237
+ onComplete();
2238
+ } else {
2239
+ this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
2240
+ var self = this;
2241
+ this.env.setTimeout(function() {
2242
+ self.execute(onComplete);
2243
+ }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
2244
+ }
2245
+ };
2246
+ // Mock setTimeout, clearTimeout
2247
+ // Contributed by Pivotal Computer Systems, www.pivotalsf.com
2248
+
2249
+ jasmine.FakeTimer = function() {
2250
+ this.reset();
2251
+
2252
+ var self = this;
2253
+ self.setTimeout = function(funcToCall, millis) {
2254
+ self.timeoutsMade++;
2255
+ self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
2256
+ return self.timeoutsMade;
2257
+ };
2258
+
2259
+ self.setInterval = function(funcToCall, millis) {
2260
+ self.timeoutsMade++;
2261
+ self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
2262
+ return self.timeoutsMade;
2263
+ };
2264
+
2265
+ self.clearTimeout = function(timeoutKey) {
2266
+ self.scheduledFunctions[timeoutKey] = jasmine.undefined;
2267
+ };
2268
+
2269
+ self.clearInterval = function(timeoutKey) {
2270
+ self.scheduledFunctions[timeoutKey] = jasmine.undefined;
2271
+ };
2272
+
2273
+ };
2274
+
2275
+ jasmine.FakeTimer.prototype.reset = function() {
2276
+ this.timeoutsMade = 0;
2277
+ this.scheduledFunctions = {};
2278
+ this.nowMillis = 0;
2279
+ };
2280
+
2281
+ jasmine.FakeTimer.prototype.tick = function(millis) {
2282
+ var oldMillis = this.nowMillis;
2283
+ var newMillis = oldMillis + millis;
2284
+ this.runFunctionsWithinRange(oldMillis, newMillis);
2285
+ this.nowMillis = newMillis;
2286
+ };
2287
+
2288
+ jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
2289
+ var scheduledFunc;
2290
+ var funcsToRun = [];
2291
+ for (var timeoutKey in this.scheduledFunctions) {
2292
+ scheduledFunc = this.scheduledFunctions[timeoutKey];
2293
+ if (scheduledFunc != jasmine.undefined &&
2294
+ scheduledFunc.runAtMillis >= oldMillis &&
2295
+ scheduledFunc.runAtMillis <= nowMillis) {
2296
+ funcsToRun.push(scheduledFunc);
2297
+ this.scheduledFunctions[timeoutKey] = jasmine.undefined;
2298
+ }
2299
+ }
2300
+
2301
+ if (funcsToRun.length > 0) {
2302
+ funcsToRun.sort(function(a, b) {
2303
+ return a.runAtMillis - b.runAtMillis;
2304
+ });
2305
+ for (var i = 0; i < funcsToRun.length; ++i) {
2306
+ try {
2307
+ var funcToRun = funcsToRun[i];
2308
+ this.nowMillis = funcToRun.runAtMillis;
2309
+ funcToRun.funcToCall();
2310
+ if (funcToRun.recurring) {
2311
+ this.scheduleFunction(funcToRun.timeoutKey,
2312
+ funcToRun.funcToCall,
2313
+ funcToRun.millis,
2314
+ true);
2315
+ }
2316
+ } catch(e) {
2317
+ }
2318
+ }
2319
+ this.runFunctionsWithinRange(oldMillis, nowMillis);
2320
+ }
2321
+ };
2322
+
2323
+ jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
2324
+ this.scheduledFunctions[timeoutKey] = {
2325
+ runAtMillis: this.nowMillis + millis,
2326
+ funcToCall: funcToCall,
2327
+ recurring: recurring,
2328
+ timeoutKey: timeoutKey,
2329
+ millis: millis
2330
+ };
2331
+ };
2332
+
2333
+ /**
2334
+ * @namespace
2335
+ */
2336
+ jasmine.Clock = {
2337
+ defaultFakeTimer: new jasmine.FakeTimer(),
2338
+
2339
+ reset: function() {
2340
+ jasmine.Clock.assertInstalled();
2341
+ jasmine.Clock.defaultFakeTimer.reset();
2342
+ },
2343
+
2344
+ tick: function(millis) {
2345
+ jasmine.Clock.assertInstalled();
2346
+ jasmine.Clock.defaultFakeTimer.tick(millis);
2347
+ },
2348
+
2349
+ runFunctionsWithinRange: function(oldMillis, nowMillis) {
2350
+ jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
2351
+ },
2352
+
2353
+ scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
2354
+ jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
2355
+ },
2356
+
2357
+ useMock: function() {
2358
+ if (!jasmine.Clock.isInstalled()) {
2359
+ var spec = jasmine.getEnv().currentSpec;
2360
+ spec.after(jasmine.Clock.uninstallMock);
2361
+
2362
+ jasmine.Clock.installMock();
2363
+ }
2364
+ },
2365
+
2366
+ installMock: function() {
2367
+ jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
2368
+ },
2369
+
2370
+ uninstallMock: function() {
2371
+ jasmine.Clock.assertInstalled();
2372
+ jasmine.Clock.installed = jasmine.Clock.real;
2373
+ },
2374
+
2375
+ real: {
2376
+ setTimeout: jasmine.getGlobal().setTimeout,
2377
+ clearTimeout: jasmine.getGlobal().clearTimeout,
2378
+ setInterval: jasmine.getGlobal().setInterval,
2379
+ clearInterval: jasmine.getGlobal().clearInterval
2380
+ },
2381
+
2382
+ assertInstalled: function() {
2383
+ if (!jasmine.Clock.isInstalled()) {
2384
+ throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
2385
+ }
2386
+ },
2387
+
2388
+ isInstalled: function() {
2389
+ return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
2390
+ },
2391
+
2392
+ installed: null
2393
+ };
2394
+ jasmine.Clock.installed = jasmine.Clock.real;
2395
+
2396
+ //else for IE support
2397
+ jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
2398
+ if (jasmine.Clock.installed.setTimeout.apply) {
2399
+ return jasmine.Clock.installed.setTimeout.apply(this, arguments);
2400
+ } else {
2401
+ return jasmine.Clock.installed.setTimeout(funcToCall, millis);
2402
+ }
2403
+ };
2404
+
2405
+ jasmine.getGlobal().setInterval = function(funcToCall, millis) {
2406
+ if (jasmine.Clock.installed.setInterval.apply) {
2407
+ return jasmine.Clock.installed.setInterval.apply(this, arguments);
2408
+ } else {
2409
+ return jasmine.Clock.installed.setInterval(funcToCall, millis);
2410
+ }
2411
+ };
2412
+
2413
+ jasmine.getGlobal().clearTimeout = function(timeoutKey) {
2414
+ if (jasmine.Clock.installed.clearTimeout.apply) {
2415
+ return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
2416
+ } else {
2417
+ return jasmine.Clock.installed.clearTimeout(timeoutKey);
2418
+ }
2419
+ };
2420
+
2421
+ jasmine.getGlobal().clearInterval = function(timeoutKey) {
2422
+ if (jasmine.Clock.installed.clearTimeout.apply) {
2423
+ return jasmine.Clock.installed.clearInterval.apply(this, arguments);
2424
+ } else {
2425
+ return jasmine.Clock.installed.clearInterval(timeoutKey);
2426
+ }
2427
+ };
2428
+
2429
+
2430
+ jasmine.version_= {
2431
+ "major": 1,
2432
+ "minor": 0,
2433
+ "build": 2,
2434
+ "revision": 1299565706
2435
+ };