diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 16e3f417..71f13379 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -655,6 +655,7 @@ getJasmineRequireObj().Env = function(j$) { onStart: suiteStarted, expectationFactory: expectationFactory, expectationResultFactory: expectationResultFactory, + runnablesExplictlySetGetter: runnablesExplictlySetGetter, resultCallback: function(attrs) { if (!suite.disabled) { clearResourcesForRunnable(suite.id); @@ -1928,6 +1929,7 @@ getJasmineRequireObj().Suite = function() { this.clearStack = attrs.clearStack || function(fn) {fn();}; this.expectationFactory = attrs.expectationFactory; this.expectationResultFactory = attrs.expectationResultFactory; + this.runnablesExplictlySetGetter = attrs.runnablesExplictlySetGetter || function() {}; this.beforeFns = []; this.afterFns = []; @@ -2039,14 +2041,8 @@ getJasmineRequireObj().Suite = function() { }; Suite.prototype.isExecutable = function() { - var foundActive = false; - for(var i = 0; i < this.children.length; i++) { - if(this.children[i].isExecutable()) { - foundActive = true; - break; - } - } - return foundActive; + var runnablesExplicitlySet = this.runnablesExplictlySetGetter(); + return !runnablesExplicitlySet && hasExecutableChild(this.children); }; Suite.prototype.sharedUserContext = function() { @@ -2099,6 +2095,17 @@ getJasmineRequireObj().Suite = function() { return !args[0]; } + function hasExecutableChild(children) { + var foundActive = false; + for (var i = 0; i < children.length; i++) { + if (children[i].isExecutable()) { + foundActive = true; + break; + } + } + return foundActive; + } + function clone(obj) { var clonedObj = {}; for (var prop in obj) { diff --git a/spec/core/SuiteSpec.js b/spec/core/SuiteSpec.js index 761f77eb..60ce8a1d 100644 --- a/spec/core/SuiteSpec.js +++ b/spec/core/SuiteSpec.js @@ -117,6 +117,32 @@ describe("Suite", function() { expect(lastAfter).toHaveBeenCalled(); }); + it("does not run *All functions if runnables are explicitly set", function(){ + var env = new j$.Env(), + fakeQueueRunner = jasmine.createSpy('fake queue runner'), + suite = new j$.Suite({ + env: env, + description: "I am a suite", + queueRunner: fakeQueueRunner, + runnablesExplictlySetGetter: function(){return true;} + }), + beforeAll = jasmine.createSpy('beforeAll'), + afterAll = jasmine.createSpy('afterAll'), + fakeIt = {execute: jasmine.createSpy('it'), isExecutable: function() { return true; } }; + + suite.beforeAll(beforeAll); + suite.afterAll(afterAll); + suite.addChild(fakeIt); + + suite.execute(); + var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns; + + expect(suite.isExecutable()).toBeFalsy(); + expect(suiteFns.length).toEqual(1); + expect(beforeAll).not.toHaveBeenCalled(); + expect(afterAll).not.toHaveBeenCalled(); + }); + it("can be disabled, but still calls callbacks", function() { var env = new j$.Env(), fakeQueueRunner = jasmine.createSpy('fake queue runner'), diff --git a/spec/core/integration/SpecRunningSpec.js b/spec/core/integration/SpecRunningSpec.js index e1675d00..d977d451 100644 --- a/spec/core/integration/SpecRunningSpec.js +++ b/spec/core/integration/SpecRunningSpec.js @@ -228,7 +228,7 @@ describe("jasmine spec running", function () { env.execute(); }); - it('should run beforeAlls before beforeEachs and afterAlls after afterEachs', function() { + it('should run beforeAlls before beforeEachs and afterAlls after afterEachs', function(done) { var actions = []; env.beforeAll(function() { @@ -289,7 +289,7 @@ describe("jasmine spec running", function () { env.execute(); }); - it('should run beforeAlls and afterAlls as beforeEachs and afterEachs in the order declared when runnablesToRun is provided', function() { + it('should run beforeAlls and afterAlls as beforeEachs and afterEachs in the order declared when runnablesToRun is provided', function(done) { var actions = [], spec, spec2; @@ -366,6 +366,30 @@ describe("jasmine spec running", function () { env.execute([spec.id, spec2.id]); }); + it('only runs *Alls once in a focused suite', function(done){ + var actions = []; + + env.fdescribe('Suite', function() { + env.beforeAll(function(){ + actions.push('beforeAll'); + }); + env.it('should run beforeAll once', function() { + actions.push('spec'); + }); + env.afterAll(function(){ + actions.push('afterAll'); + }); + }); + + var assertions = function() { + expect(actions).toEqual(['beforeAll', 'spec', 'afterAll']); + done(); + }; + + env.addReporter({jasmineDone: assertions}); + env.execute(); + }); + describe('focused runnables', function() { it('runs the relevant alls and eachs for each runnable', function(done) { var actions = []; diff --git a/src/core/Env.js b/src/core/Env.js index 44f94c8b..80f1ddae 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -237,6 +237,7 @@ getJasmineRequireObj().Env = function(j$) { onStart: suiteStarted, expectationFactory: expectationFactory, expectationResultFactory: expectationResultFactory, + runnablesExplictlySetGetter: runnablesExplictlySetGetter, resultCallback: function(attrs) { if (!suite.disabled) { clearResourcesForRunnable(suite.id); diff --git a/src/core/Suite.js b/src/core/Suite.js index bafde9ed..8a1ba98a 100644 --- a/src/core/Suite.js +++ b/src/core/Suite.js @@ -9,6 +9,7 @@ getJasmineRequireObj().Suite = function() { this.clearStack = attrs.clearStack || function(fn) {fn();}; this.expectationFactory = attrs.expectationFactory; this.expectationResultFactory = attrs.expectationResultFactory; + this.runnablesExplictlySetGetter = attrs.runnablesExplictlySetGetter || function() {}; this.beforeFns = []; this.afterFns = []; @@ -120,14 +121,8 @@ getJasmineRequireObj().Suite = function() { }; Suite.prototype.isExecutable = function() { - var foundActive = false; - for(var i = 0; i < this.children.length; i++) { - if(this.children[i].isExecutable()) { - foundActive = true; - break; - } - } - return foundActive; + var runnablesExplicitlySet = this.runnablesExplictlySetGetter(); + return !runnablesExplicitlySet && hasExecutableChild(this.children); }; Suite.prototype.sharedUserContext = function() { @@ -180,6 +175,17 @@ getJasmineRequireObj().Suite = function() { return !args[0]; } + function hasExecutableChild(children) { + var foundActive = false; + for (var i = 0; i < children.length; i++) { + if (children[i].isExecutable()) { + foundActive = true; + break; + } + } + return foundActive; + } + function clone(obj) { var clonedObj = {}; for (var prop in obj) {