diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index b0962e5c..b274cc30 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -1188,6 +1188,7 @@ getJasmineRequireObj().Env = function(j$) { let reporter; let topSuite; let runner; + let parallelLodingState = null; // 'specs', 'helpers', or null for non-parallel /** * This represents the available options to configure Jasmine. @@ -1634,6 +1635,10 @@ getJasmineRequireObj().Env = function(j$) { reportSpecDone }); + this.setParallelLoadingState = function(state) { + parallelLodingState = state; + }; + this.parallelReset = function() { // TODO: ensure that autoCleanClosures was false suiteBuilder.parallelReset(); @@ -1801,6 +1806,16 @@ getJasmineRequireObj().Env = function(j$) { } } + function ensureNonParallelOrInHelperOrInDescribe(method) { + if (parallelLodingState === 'specs' && !suiteBuilder.inDescribe()) { + throw new Error( + 'In parallel mode, ' + + method + + ' must be in a describe block or in a helper file' + ); + } + } + this.describe = function(description, definitionFn) { ensureIsNotNested('describe'); return suiteBuilder.describe(description, definitionFn).metadata; @@ -1922,6 +1937,7 @@ getJasmineRequireObj().Env = function(j$) { this.beforeEach = function(beforeEachFunction, timeout) { ensureIsNotNested('beforeEach'); + ensureNonParallelOrInHelperOrInDescribe('beforeEach'); suiteBuilder.beforeEach(beforeEachFunction, timeout); }; @@ -1932,6 +1948,7 @@ getJasmineRequireObj().Env = function(j$) { this.afterEach = function(afterEachFunction, timeout) { ensureIsNotNested('afterEach'); + ensureNonParallelOrInHelperOrInDescribe('afterEach'); suiteBuilder.afterEach(afterEachFunction, timeout); }; @@ -9876,6 +9893,10 @@ getJasmineRequireObj().SuiteBuilder = function(j$) { this.focusedRunables = []; } + inDescribe() { + return this.currentDeclarationSuite_ !== this.topSuite; + } + parallelReset() { this.topSuite.removeChildren(); this.topSuite.reset(); diff --git a/spec/core/EnvSpec.js b/spec/core/EnvSpec.js index 85ab4d6d..f798c80b 100644 --- a/spec/core/EnvSpec.js +++ b/spec/core/EnvSpec.js @@ -394,6 +394,28 @@ describe('Env', function() { env.beforeEach(function() {}, 2147483648); }).toThrowError('Timeout value cannot be greater than 2147483647'); }); + + it('throws when called at the top level in a spec file in parallel mode', function() { + env.setParallelLoadingState('specs'); + expect(function() { + env.beforeEach(function() {}); + }).toThrowError( + 'In parallel mode, beforeEach must be in a describe block or in a helper file' + ); + }); + + it('does not throw when called at the top level in a helper file in parallel mode', function() { + env.setParallelLoadingState('helpers'); + env.beforeEach(function() {}); + }); + + it('does not throw when called in a describe in a spec file in parallel mode', function() { + env.setParallelLoadingState('specs'); + env.describe('a suite', function() { + env.beforeEach(function() {}); + env.it('a spec'); + }); + }); }); describe('#beforeAll', function() { @@ -438,6 +460,28 @@ describe('Env', function() { env.afterEach(function() {}, 2147483648); }).toThrowError('Timeout value cannot be greater than 2147483647'); }); + + it('throws when called at the top level in a spec file in parallel mode', function() { + env.setParallelLoadingState('specs'); + expect(function() { + env.afterEach(function() {}); + }).toThrowError( + 'In parallel mode, afterEach must be in a describe block or in a helper file' + ); + }); + + it('does not throw when called at the top level in a helper file in parallel mode', function() { + env.setParallelLoadingState('helpers'); + env.afterEach(function() {}); + }); + + it('does not throw when called in a describe in a spec file in parallel mode', function() { + env.setParallelLoadingState('specs'); + env.describe('a suite', function() { + env.afterEach(function() {}); + env.it('a spec'); + }); + }); }); describe('#afterAll', function() { diff --git a/src/core/Env.js b/src/core/Env.js index 3886aa29..7e934987 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -46,6 +46,7 @@ getJasmineRequireObj().Env = function(j$) { let reporter; let topSuite; let runner; + let parallelLodingState = null; // 'specs', 'helpers', or null for non-parallel /** * This represents the available options to configure Jasmine. @@ -492,6 +493,10 @@ getJasmineRequireObj().Env = function(j$) { reportSpecDone }); + this.setParallelLoadingState = function(state) { + parallelLodingState = state; + }; + this.parallelReset = function() { // TODO: ensure that autoCleanClosures was false suiteBuilder.parallelReset(); @@ -659,6 +664,16 @@ getJasmineRequireObj().Env = function(j$) { } } + function ensureNonParallelOrInHelperOrInDescribe(method) { + if (parallelLodingState === 'specs' && !suiteBuilder.inDescribe()) { + throw new Error( + 'In parallel mode, ' + + method + + ' must be in a describe block or in a helper file' + ); + } + } + this.describe = function(description, definitionFn) { ensureIsNotNested('describe'); return suiteBuilder.describe(description, definitionFn).metadata; @@ -780,6 +795,7 @@ getJasmineRequireObj().Env = function(j$) { this.beforeEach = function(beforeEachFunction, timeout) { ensureIsNotNested('beforeEach'); + ensureNonParallelOrInHelperOrInDescribe('beforeEach'); suiteBuilder.beforeEach(beforeEachFunction, timeout); }; @@ -790,6 +806,7 @@ getJasmineRequireObj().Env = function(j$) { this.afterEach = function(afterEachFunction, timeout) { ensureIsNotNested('afterEach'); + ensureNonParallelOrInHelperOrInDescribe('afterEach'); suiteBuilder.afterEach(afterEachFunction, timeout); }; diff --git a/src/core/SuiteBuilder.js b/src/core/SuiteBuilder.js index d17e2451..4ed6f8ce 100644 --- a/src/core/SuiteBuilder.js +++ b/src/core/SuiteBuilder.js @@ -22,6 +22,10 @@ getJasmineRequireObj().SuiteBuilder = function(j$) { this.focusedRunables = []; } + inDescribe() { + return this.currentDeclarationSuite_ !== this.topSuite; + } + parallelReset() { this.topSuite.removeChildren(); this.topSuite.reset();