evergreen 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/README.rdoc +30 -4
  2. data/config/routes.rb +1 -1
  3. data/lib/evergreen.rb +14 -50
  4. data/lib/evergreen/application.rb +46 -0
  5. data/lib/evergreen/cli.rb +2 -2
  6. data/lib/evergreen/rails.rb +4 -0
  7. data/lib/evergreen/resources/evergreen.css +3 -1
  8. data/lib/evergreen/resources/evergreen.js +3 -0
  9. data/lib/evergreen/runner.rb +124 -36
  10. data/lib/evergreen/server.rb +9 -18
  11. data/lib/evergreen/spec.rb +26 -14
  12. data/lib/evergreen/suite.rb +44 -0
  13. data/lib/evergreen/tasks.rb +6 -0
  14. data/lib/evergreen/template.rb +7 -10
  15. data/lib/evergreen/version.rb +1 -1
  16. data/lib/evergreen/views/layout.erb +1 -0
  17. data/lib/evergreen/views/list.erb +2 -2
  18. data/lib/evergreen/views/spec.erb +18 -10
  19. data/lib/jasmine/Gemfile +6 -0
  20. data/lib/jasmine/MIT.LICENSE +2 -2
  21. data/lib/jasmine/README.markdown +5 -459
  22. data/lib/jasmine/Rakefile +22 -16
  23. data/lib/jasmine/example/SpecRunner.html +1 -1
  24. data/lib/jasmine/jsdoc-template/allclasses.tmpl +17 -0
  25. data/lib/jasmine/jsdoc-template/allfiles.tmpl +56 -0
  26. data/lib/jasmine/jsdoc-template/class.tmpl +646 -0
  27. data/lib/jasmine/jsdoc-template/index.tmpl +39 -0
  28. data/lib/jasmine/jsdoc-template/publish.js +184 -0
  29. data/lib/jasmine/jsdoc-template/static/default.css +162 -0
  30. data/lib/jasmine/jsdoc-template/static/header.html +2 -0
  31. data/lib/jasmine/jsdoc-template/static/index.html +19 -0
  32. data/lib/jasmine/jsdoc-template/symbol.tmpl +35 -0
  33. data/lib/jasmine/lib/jasmine-html.js +12 -6
  34. data/lib/jasmine/lib/jasmine.js +122 -44
  35. data/lib/jasmine/spec/runner.html +0 -1
  36. data/lib/jasmine/spec/suites/CustomMatchersSpec.js +18 -9
  37. data/lib/jasmine/spec/suites/MatchersSpec.js +241 -162
  38. data/lib/jasmine/spec/suites/SpecRunningSpec.js +120 -62
  39. data/lib/jasmine/spec/suites/TrivialReporterSpec.js +3 -0
  40. data/lib/jasmine/spec/suites/WaitsForBlockSpec.js +9 -9
  41. data/lib/jasmine/src/Env.js +1 -0
  42. data/lib/jasmine/src/Matchers.js +35 -17
  43. data/lib/jasmine/src/Queue.js +6 -1
  44. data/lib/jasmine/src/Spec.js +34 -2
  45. data/lib/jasmine/src/WaitsForBlock.js +28 -13
  46. data/lib/jasmine/src/base.js +15 -8
  47. data/lib/jasmine/src/html/TrivialReporter.js +12 -6
  48. data/lib/jasmine/src/version.json +2 -2
  49. data/lib/tasks/evergreen.rake +1 -1
  50. data/spec/meta_spec.rb +21 -2
  51. data/spec/runner_spec.rb +16 -18
  52. data/spec/spec_helper.rb +12 -4
  53. data/spec/spec_spec.rb +4 -11
  54. data/spec/suite1/spec/javascripts/invalid_coffee_spec.coffee +1 -0
  55. data/spec/suite1/spec/javascripts/spec_helper.coffee +1 -1
  56. data/spec/suite2/config/evergreen.rb +5 -0
  57. data/spec/suite2/public_html/foo.js +1 -0
  58. data/spec/suite2/spec/awesome_spec.js +12 -0
  59. data/spec/suite2/spec/failing_spec.js +5 -0
  60. data/spec/suite2/templates/foo.html +1 -0
  61. data/spec/suite_spec.rb +26 -0
  62. data/spec/template_spec.rb +3 -9
  63. metadata +52 -20
  64. data/lib/jasmine/lib/consolex.js +0 -28
@@ -258,86 +258,146 @@ describe("jasmine spec running", function () {
258
258
  expect(another_spec.results().getItems()[0].passed()).toEqual(true);
259
259
  });
260
260
 
261
- it("testWaitsFor", function() {
262
- var doneWaiting = false;
263
- var runsBlockExecuted = false;
264
-
261
+ describe("waitsFor", function() {
262
+ var latchFunction = function() {
263
+ return true;
264
+ };
265
265
  var spec;
266
- env.describe('foo', function() {
267
- spec = env.it('has a waits for', function() {
268
- this.runs(function() {
269
- });
270
266
 
271
- this.waitsFor(500, function() {
272
- return doneWaiting;
273
- });
274
-
275
- this.runs(function() {
276
- runsBlockExecuted = true;
267
+ function makeWaitsForSpec() {
268
+ var args = jasmine.util.argsToArray(arguments);
269
+ env.describe('suite', function() {
270
+ spec = env.it('spec', function() {
271
+ this.waitsFor.apply(this, args);
277
272
  });
278
273
  });
274
+ env.execute();
275
+ }
276
+
277
+ it("should accept args (latchFunction, timeoutMessage, timeout)", function() {
278
+ makeWaitsForSpec(latchFunction, "message", 123);
279
+ var block = spec.queue.blocks[1];
280
+ expect(block.latchFunction).toBe(latchFunction);
281
+ expect(block.timeout).toEqual(123);
282
+ expect(block.message).toEqual('message');
279
283
  });
280
284
 
281
- spec.execute();
282
- expect(runsBlockExecuted).toEqual(false); //, 'should not have executed runs block yet');
283
- fakeTimer.tick(100);
284
- doneWaiting = true;
285
- fakeTimer.tick(100);
286
- expect(runsBlockExecuted).toEqual(true); //, 'should have executed runs block');
287
- });
285
+ it("should accept args (latchFunction, timeout)", function() {
286
+ makeWaitsForSpec(latchFunction, 123);
287
+ var block = spec.queue.blocks[1];
288
+ expect(block.latchFunction).toBe(latchFunction);
289
+ expect(block.timeout).toEqual(123);
290
+ expect(block.message).toEqual(null);
291
+ });
288
292
 
289
- it("testWaitsForFailsWithMessage", function() {
290
- var spec;
291
- env.describe('foo', function() {
292
- spec = env.it('has a waits for', function() {
293
- this.runs(function() {
294
- });
293
+ it("should accept args (latchFunction, timeoutMessage)", function() {
294
+ env.defaultTimeoutInterval = 4321;
295
+ makeWaitsForSpec(latchFunction, "message");
296
+ var block = spec.queue.blocks[1];
297
+ expect(block.latchFunction).toBe(latchFunction);
298
+ expect(block.timeout).toEqual(4321);
299
+ expect(block.message).toEqual('message');
300
+ });
295
301
 
296
- this.waitsFor(500, function() {
297
- return false; // force a timeout
298
- }, 'my awesome condition');
302
+ it("should accept args (latchFunction)", function() {
303
+ env.defaultTimeoutInterval = 4321;
304
+ makeWaitsForSpec(latchFunction);
305
+ var block = spec.queue.blocks[1];
306
+ expect(block.latchFunction).toBe(latchFunction);
307
+ expect(block.timeout).toEqual(4321);
308
+ expect(block.message).toEqual(null);
309
+ });
299
310
 
300
- this.runs(function() {
311
+ it("should accept deprecated args order (timeout, latchFunction, timeoutMessage)", function() {
312
+ makeWaitsForSpec(123, latchFunction, "message");
313
+ var block = spec.queue.blocks[1];
314
+ expect(block.latchFunction).toBe(latchFunction);
315
+ expect(block.timeout).toEqual(123);
316
+ expect(block.message).toEqual('message');
317
+ });
318
+
319
+ it("testWaitsFor", function() {
320
+ var doneWaiting = false;
321
+ var runsBlockExecuted = false;
322
+
323
+ var spec;
324
+ env.describe('foo', function() {
325
+ spec = env.it('has a waits for', function() {
326
+ this.runs(function() {
327
+ });
328
+
329
+ this.waitsFor(500, function() {
330
+ return doneWaiting;
331
+ });
332
+
333
+ this.runs(function() {
334
+ runsBlockExecuted = true;
335
+ });
301
336
  });
302
337
  });
338
+
339
+ spec.execute();
340
+ expect(runsBlockExecuted).toEqual(false); //, 'should not have executed runs block yet');
341
+ fakeTimer.tick(100);
342
+ doneWaiting = true;
343
+ fakeTimer.tick(100);
344
+ expect(runsBlockExecuted).toEqual(true); //, 'should have executed runs block');
303
345
  });
304
346
 
305
- spec.execute();
306
- fakeTimer.tick(1000);
307
- var actual = spec.results().getItems()[0].message;
308
- var expected = 'timeout: timed out after 500 msec waiting for my awesome condition';
309
- expect(actual).toEqual(expected);
310
- });
347
+ it("fails with message", function() {
348
+ var spec;
349
+ env.describe('foo', function() {
350
+ spec = env.it('has a waits for', function() {
351
+ this.runs(function() {
352
+ });
311
353
 
312
- it("waitsFor fails and skips the rest of the spec if timeout is reached and the latch function is still false", function() {
313
- var runsBlockExecuted = false;
354
+ this.waitsFor(500, function() {
355
+ return false; // force a timeout
356
+ }, 'my awesome condition');
314
357
 
315
- var spec;
316
- env.describe('foo', function() {
317
- spec = env.it('has a waits for', function() {
318
- this.runs(function() {
358
+ this.runs(function() {
359
+ });
319
360
  });
361
+ });
362
+
363
+ spec.execute();
364
+ fakeTimer.tick(1000);
365
+ expect(spec.results().getItems()[0].message).toEqual('timeout: timed out after 500 msec waiting for my awesome condition');
366
+ });
367
+
368
+ it("fails and skips the rest of the spec if timeout is reached and the latch function hasn't returned true", function() {
369
+ var runsBlockExecuted = false;
370
+ var subsequentSpecRan = false;
371
+
372
+ var timeoutSpec, subsequentSpec;
373
+ var suite = env.describe('foo', function() {
374
+ timeoutSpec = env.it('has a waits for', function() {
375
+ this.runs(function() {
376
+ });
377
+
378
+ this.waitsFor(500, function() {
379
+ return false;
380
+ });
320
381
 
321
- this.waitsFor(500, function() {
322
- return false;
382
+ this.runs(function() {
383
+ runsBlockExecuted = true;
384
+ });
323
385
  });
324
386
 
325
- this.runs(function() {
326
- runsBlockExecuted = true;
387
+ subsequentSpec = env.it('then carries on to the next test', function() {
388
+ subsequentSpecRan = true;
327
389
  });
328
390
  });
329
- });
330
391
 
331
- spec.execute();
332
- expect(runsBlockExecuted).toEqual(false);
333
- fakeTimer.tick(100);
334
- expect(runsBlockExecuted).toEqual(false);
335
- fakeTimer.tick(400);
336
- expect(runsBlockExecuted).toEqual(false);
337
- var actual = spec.results().getItems()[0].message;
338
- var expected = 'timeout: timed out after 500 msec waiting for something to happen';
339
- expect(actual).toEqual(expected,
340
- 'expected "' + expected + '" but found "' + actual + '"');
392
+ env.execute();
393
+ expect(runsBlockExecuted).toEqual(false);
394
+ fakeTimer.tick(100);
395
+ expect(runsBlockExecuted).toEqual(false);
396
+ fakeTimer.tick(400);
397
+ expect(runsBlockExecuted).toEqual(false);
398
+ expect(timeoutSpec.results().getItems()[0].message).toEqual('timeout: timed out after 500 msec waiting for something to happen');
399
+ expect(subsequentSpecRan).toEqual(true);
400
+ });
341
401
  });
342
402
 
343
403
  it("testSpecAfter", function() {
@@ -520,17 +580,15 @@ describe("jasmine spec running", function () {
520
580
  });
521
581
 
522
582
  describe('#waitsFor should allow consecutive calls', function () {
523
-
524
583
  var foo;
525
584
  beforeEach(function () {
526
-
527
585
  foo = 0;
528
586
  });
529
587
 
530
588
  it('exits immediately (does not stack) if the latchFunction times out', function () {
531
589
  var reachedFirstWaitsFor = false;
532
590
  var reachedSecondWaitsFor = false;
533
- var waitsSuite = env.describe('suite that waits', function () {
591
+ env.describe('suite that waits', function () {
534
592
  env.it('should stack timeouts', function() {
535
593
  this.waitsFor(500, function () {
536
594
  reachedFirstWaitsFor = true;
@@ -546,7 +604,7 @@ describe("jasmine spec running", function () {
546
604
  });
547
605
 
548
606
  expect(reachedFirstWaitsFor).toEqual(false);
549
- waitsSuite.execute();
607
+ env.execute();
550
608
 
551
609
  expect(reachedFirstWaitsFor).toEqual(true);
552
610
  expect(foo).toEqual(0);
@@ -172,6 +172,9 @@ describe("TrivialReporter", function() {
172
172
  var errorDiv = findElement(divs, 'resultMessage log');
173
173
  expect(errorDiv.innerHTML).toEqual("this is a multipart log message");
174
174
  });
175
+
176
+ xit("should work on IE without console.log.apply", function() {
177
+ });
175
178
  });
176
179
 
177
180
  describe("duplicate example names", function() {
@@ -15,7 +15,7 @@ describe('WaitsForBlock', function () {
15
15
  return true;
16
16
  };
17
17
  var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
18
- expect(onComplete).wasNotCalled();
18
+ expect(onComplete).not.toHaveBeenCalled();
19
19
  block.execute(onComplete);
20
20
  expect(onComplete).toHaveBeenCalled();
21
21
  });
@@ -51,22 +51,22 @@ describe('WaitsForBlock', function () {
51
51
  env.clearInterval = fakeTimer.clearInterval;
52
52
  });
53
53
 
54
- it('latchFunction should be retried after 100 ms', function () {
54
+ it('latchFunction should be retried after 10 ms', function () {
55
55
  var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
56
- expect(latchFunction).wasNotCalled();
56
+ expect(latchFunction).not.toHaveBeenCalled();
57
57
  block.execute(onComplete);
58
58
  expect(latchFunction.callCount).toEqual(1);
59
- fakeTimer.tick(50);
59
+ fakeTimer.tick(5);
60
60
  expect(latchFunction.callCount).toEqual(1);
61
- fakeTimer.tick(50);
61
+ fakeTimer.tick(5);
62
62
  expect(latchFunction.callCount).toEqual(2);
63
63
  });
64
64
 
65
65
  it('onComplete should be called if latchFunction returns true before timeout', function () {
66
66
  var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
67
- expect(onComplete).wasNotCalled();
67
+ expect(onComplete).not.toHaveBeenCalled();
68
68
  block.execute(onComplete);
69
- expect(onComplete).wasNotCalled();
69
+ expect(onComplete).not.toHaveBeenCalled();
70
70
  latchFunction.andReturn(true);
71
71
  fakeTimer.tick(100);
72
72
  expect(onComplete).toHaveBeenCalled();
@@ -76,12 +76,12 @@ describe('WaitsForBlock', function () {
76
76
  spyOn(spec, 'fail');
77
77
  var block = new jasmine.WaitsForBlock(env, timeout, latchFunction, message, spec);
78
78
  block.execute(onComplete);
79
- expect(spec.fail).wasNotCalled();
79
+ expect(spec.fail).not.toHaveBeenCalled();
80
80
  fakeTimer.tick(timeout);
81
81
  expect(spec.fail).toHaveBeenCalled();
82
82
  var failMessage = spec.fail.mostRecentCall.args[0].message;
83
83
  expect(failMessage).toMatch(message);
84
- expect(onComplete).wasNotCalled();
84
+ expect(onComplete).toHaveBeenCalled();
85
85
  });
86
86
  });
87
87
  });
@@ -11,6 +11,7 @@ jasmine.Env = function() {
11
11
  this.reporter = new jasmine.MultiReporter();
12
12
 
13
13
  this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
14
+ this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
14
15
  this.lastUpdate = 0;
15
16
  this.specFilter = function() {
16
17
  return true;
@@ -68,7 +68,7 @@ jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
68
68
  message: message
69
69
  });
70
70
  this.spec.addMatcherResult(expectationResult);
71
- return result;
71
+ return jasmine.undefined;
72
72
  };
73
73
  };
74
74
 
@@ -86,6 +86,7 @@ jasmine.Matchers.prototype.toBe = function(expected) {
86
86
  /**
87
87
  * toNotBe: compares the actual to the expected using !==
88
88
  * @param expected
89
+ * @deprecated as of 1.0. Use not.toBe() instead.
89
90
  */
90
91
  jasmine.Matchers.prototype.toNotBe = function(expected) {
91
92
  return this.actual !== expected;
@@ -103,6 +104,7 @@ jasmine.Matchers.prototype.toEqual = function(expected) {
103
104
  /**
104
105
  * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
105
106
  * @param expected
107
+ * @deprecated as of 1.0. Use not.toNotEqual() instead.
106
108
  */
107
109
  jasmine.Matchers.prototype.toNotEqual = function(expected) {
108
110
  return !this.env.equals_(this.actual, expected);
@@ -121,6 +123,7 @@ jasmine.Matchers.prototype.toMatch = function(expected) {
121
123
  /**
122
124
  * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
123
125
  * @param expected
126
+ * @deprecated as of 1.0. Use not.toMatch() instead.
124
127
  */
125
128
  jasmine.Matchers.prototype.toNotMatch = function(expected) {
126
129
  return !(new RegExp(expected).test(this.actual));
@@ -163,11 +166,6 @@ jasmine.Matchers.prototype.toBeFalsy = function() {
163
166
  };
164
167
 
165
168
 
166
- /** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
167
- jasmine.Matchers.prototype.wasCalled = function() {
168
- return this.toHaveBeenCalled();
169
- };
170
-
171
169
  /**
172
170
  * Matcher that checks to see if the actual, a Jasmine spy, was called.
173
171
  */
@@ -181,12 +179,18 @@ jasmine.Matchers.prototype.toHaveBeenCalled = function() {
181
179
  }
182
180
 
183
181
  this.message = function() {
184
- return "Expected spy " + this.actual.identity + " to have been called.";
182
+ return [
183
+ "Expected spy " + this.actual.identity + " to have been called.",
184
+ "Expected spy " + this.actual.identity + " not to have been called."
185
+ ];
185
186
  };
186
187
 
187
188
  return this.actual.wasCalled;
188
189
  };
189
190
 
191
+ /** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
192
+ jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
193
+
190
194
  /**
191
195
  * Matcher that checks to see if the actual, a Jasmine spy, was not called.
192
196
  *
@@ -202,17 +206,15 @@ jasmine.Matchers.prototype.wasNotCalled = function() {
202
206
  }
203
207
 
204
208
  this.message = function() {
205
- return "Expected spy " + this.actual.identity + " to not have been called.";
209
+ return [
210
+ "Expected spy " + this.actual.identity + " to not have been called.",
211
+ "Expected spy " + this.actual.identity + " to have been called."
212
+ ];
206
213
  };
207
214
 
208
215
  return !this.actual.wasCalled;
209
216
  };
210
217
 
211
- /** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
212
- jasmine.Matchers.prototype.wasCalledWith = function() {
213
- return this.toHaveBeenCalledWith.apply(this, arguments);
214
- };
215
-
216
218
  /**
217
219
  * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
218
220
  *
@@ -226,15 +228,25 @@ jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
226
228
  }
227
229
  this.message = function() {
228
230
  if (this.actual.callCount == 0) {
229
- return "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.";
231
+ // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
232
+ return [
233
+ "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
234
+ "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
235
+ ];
230
236
  } else {
231
- return "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall);
237
+ return [
238
+ "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
239
+ "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
240
+ ];
232
241
  }
233
242
  };
234
243
 
235
244
  return this.env.contains_(this.actual.argsForCall, expectedArgs);
236
245
  };
237
246
 
247
+ /** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
248
+ jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
249
+
238
250
  /** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
239
251
  jasmine.Matchers.prototype.wasNotCalledWith = function() {
240
252
  var expectedArgs = jasmine.util.argsToArray(arguments);
@@ -243,7 +255,10 @@ jasmine.Matchers.prototype.wasNotCalledWith = function() {
243
255
  }
244
256
 
245
257
  this.message = function() {
246
- return "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was";
258
+ return [
259
+ "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
260
+ "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
261
+ ]
247
262
  };
248
263
 
249
264
  return !this.env.contains_(this.actual.argsForCall, expectedArgs);
@@ -262,6 +277,7 @@ jasmine.Matchers.prototype.toContain = function(expected) {
262
277
  * Matcher that checks that the expected item is NOT an element in the actual Array.
263
278
  *
264
279
  * @param {Object} expected
280
+ * @deprecated as of 1.0. Use not.toNotContain() instead.
265
281
  */
266
282
  jasmine.Matchers.prototype.toNotContain = function(expected) {
267
283
  return !this.env.contains_(this.actual, expected);
@@ -295,9 +311,11 @@ jasmine.Matchers.prototype.toThrow = function(expected) {
295
311
  result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
296
312
  }
297
313
 
314
+ var not = this.isNot ? "not " : "";
315
+
298
316
  this.message = function() {
299
317
  if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
300
- return ["Expected function to throw", expected.message || expected, ", but it threw", exception.message || exception].join(' ');
318
+ return ["Expected function " + not + "to throw", expected ? expected.message || expected : " an exception", ", but it threw", exception.message || exception].join(' ');
301
319
  } else {
302
320
  return "Expected function to throw an exception.";
303
321
  }
@@ -4,6 +4,7 @@ jasmine.Queue = function(env) {
4
4
  this.running = false;
5
5
  this.index = 0;
6
6
  this.offset = 0;
7
+ this.abort = false;
7
8
  };
8
9
 
9
10
  jasmine.Queue.prototype.addBefore = function(block) {
@@ -38,7 +39,7 @@ jasmine.Queue.prototype.next_ = function() {
38
39
  while (goAgain) {
39
40
  goAgain = false;
40
41
 
41
- if (self.index < self.blocks.length) {
42
+ if (self.index < self.blocks.length && !this.abort) {
42
43
  var calledSynchronously = true;
43
44
  var completedSynchronously = false;
44
45
 
@@ -48,6 +49,10 @@ jasmine.Queue.prototype.next_ = function() {
48
49
  return;
49
50
  }
50
51
 
52
+ if (self.blocks[self.index].abort) {
53
+ self.abort = true;
54
+ }
55
+
51
56
  self.offset = 0;
52
57
  self.index++;
53
58