diff --git a/integration_tests/__tests__/test_environment.test.js b/integration_tests/__tests__/test_environment.test.js index 29a333fe01fe..dd8c19c75daa 100644 --- a/integration_tests/__tests__/test_environment.test.js +++ b/integration_tests/__tests__/test_environment.test.js @@ -14,10 +14,9 @@ const runJest = require('../runJest'); const testFixturePackage = require('../test-environment/package.json'); it('respects testEnvironment docblock', () => { - expect(testFixturePackage.jest.testEnvironment).toEqual('node'); + expect(testFixturePackage.jest.testEnvironment).toEqual('./test-environment'); - const result = runJest.json('test-environment').json; + const result = runJest('test-environment'); - expect(result.success).toBe(true); - expect(result.numTotalTests).toBe(1); + expect(result.stdout).toBe('teardown\n'); }); diff --git a/integration_tests/test-environment/__tests__/env.test.js b/integration_tests/test-environment/__tests__/env.test.js index 1781c6be6304..bb16ecc79275 100644 --- a/integration_tests/test-environment/__tests__/env.test.js +++ b/integration_tests/test-environment/__tests__/env.test.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * - * @jest-environment jsdom + * @jest-environment ./test-environment */ 'use strict'; /* eslint-env browser*/ @@ -14,3 +14,7 @@ test('stub', () => { const element = document.createElement('div'); expect(element).not.toBeNull(); }); + +test('stub2', () => { + expect(global.setup).toBe('setup'); +}); diff --git a/integration_tests/test-environment/package.json b/integration_tests/test-environment/package.json index 148788b25446..562e7dbbb38b 100644 --- a/integration_tests/test-environment/package.json +++ b/integration_tests/test-environment/package.json @@ -1,5 +1,5 @@ { "jest": { - "testEnvironment": "node" + "testEnvironment": "./test-environment" } } diff --git a/integration_tests/test-environment/test-environment.js b/integration_tests/test-environment/test-environment.js new file mode 100644 index 000000000000..a09c25195009 --- /dev/null +++ b/integration_tests/test-environment/test-environment.js @@ -0,0 +1,25 @@ +const JSDOMEnvironment = require('../../packages/jest-environment-jsdom'); + +class TestEnvironment extends JSDOMEnvironment { + constructor(config) { + super(config); + } + + async setup() { + this.global.setup = 'setup'; + } + + async teardown() { + console.log('teardown'); + } + + dispose() { + super.dispose(); + } + + runScript(script) { + return super.runScript(script); + } +} + +module.exports = TestEnvironment; diff --git a/packages/jest-environment-jsdom/src/index.js b/packages/jest-environment-jsdom/src/index.js index 825e10847c60..25ab9cc153b0 100644 --- a/packages/jest-environment-jsdom/src/index.js +++ b/packages/jest-environment-jsdom/src/index.js @@ -37,6 +37,14 @@ class JSDOMEnvironment { this.fakeTimers = new FakeTimers(global, this.moduleMocker, config); } + setup(): Promise { + return Promise.resolve(); + } + + teardown(): Promise { + return Promise.resolve(); + } + dispose(): void { if (this.fakeTimers) { this.fakeTimers.dispose(); diff --git a/packages/jest-environment-node/src/index.js b/packages/jest-environment-node/src/index.js index e7093ee1ad81..34e5ae34de50 100644 --- a/packages/jest-environment-node/src/index.js +++ b/packages/jest-environment-node/src/index.js @@ -37,6 +37,14 @@ class NodeEnvironment { this.fakeTimers = new FakeTimers(global, this.moduleMocker, config); } + setup(): Promise { + return Promise.resolve(); + } + + teardown(): Promise { + return Promise.resolve(); + } + dispose() { if (this.fakeTimers) { this.fakeTimers.dispose(); diff --git a/packages/jest-runner/src/run_test.js b/packages/jest-runner/src/run_test.js index a2110f157fa6..8807917b7c13 100644 --- a/packages/jest-runner/src/run_test.js +++ b/packages/jest-runner/src/run_test.js @@ -12,7 +12,6 @@ import type {EnvironmentClass} from 'types/Environment'; import type {GlobalConfig, Path, ProjectConfig} from 'types/Config'; import type {Resolver} from 'types/Resolve'; import type {TestFramework} from 'types/TestRunner'; -import type {TestResult} from 'types/TestResult'; import type RuntimeClass from 'jest-runtime'; import fs from 'fs'; @@ -100,8 +99,15 @@ export default function runTest( mapCoverage: globalConfig.mapCoverage, }); const start = Date.now(); - return testFramework(globalConfig, config, environment, runtime, path) - .then((result: TestResult) => { + return environment.setup().then(async () => { + try { + const result = await testFramework( + globalConfig, + config, + environment, + runtime, + path, + ); const testCount = result.numPassingTests + result.numFailingTests + @@ -113,26 +119,24 @@ export default function runTest( result.console = testConsole.getBuffer(); result.skipped = testCount === result.numPendingTests; result.displayName = config.displayName; - return result; - }) - .then( - result => - Promise.resolve().then(() => { - environment.dispose(); - if (globalConfig.logHeapUsage) { - if (global.gc) { - global.gc(); - } - result.memoryUsage = process.memoryUsage().heapUsed; - } - - // Delay the resolution to allow log messages to be output. - return new Promise(resolve => setImmediate(() => resolve(result))); - }), - err => - Promise.resolve().then(() => { - environment.dispose(); - throw err; - }), - ); + if (environment.teardown) { + await environment.teardown(); + } + environment.dispose(); + if (globalConfig.logHeapUsage) { + if (global.gc) { + global.gc(); + } + result.memoryUsage = process.memoryUsage().heapUsed; + } + // Delay the resolution to allow log messages to be output. + return new Promise(resolve => setImmediate(() => resolve(result))); + } catch (err) { + if (environment.teardown) { + await environment.teardown(); + } + environment.dispose(); + throw err; + } + }); } diff --git a/types/Environment.js b/types/Environment.js index cd129a962779..4314705a8b2a 100644 --- a/types/Environment.js +++ b/types/Environment.js @@ -31,6 +31,8 @@ declare class $JestEnvironment { }, testFilePath: string, moduleMocker: ModuleMocker, + setup(): Promise, + teardown(): Promise, } export type Environment = $JestEnvironment;