From d45fa8a43077b38dc4880b3b04d79f45dd5780f9 Mon Sep 17 00:00:00 2001 From: Scott Hovestadt Date: Fri, 12 Apr 2019 11:36:22 -0700 Subject: [PATCH 1/6] Pass docblock pragmas to test environment constructor. --- packages/jest-environment/src/index.ts | 14 ++++++++------ packages/jest-runner/src/runTest.ts | 5 +++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/jest-environment/src/index.ts b/packages/jest-environment/src/index.ts index f1b262c6ce98..d72167965f43 100644 --- a/packages/jest-environment/src/index.ts +++ b/packages/jest-environment/src/index.ts @@ -14,17 +14,19 @@ import {JestFakeTimers as FakeTimers} from '@jest/fake-timers'; type JestMockFn = typeof jestMock.fn; type JestMockSpyOn = typeof jestMock.spyOn; -export type EnvironmentContext = { - console?: Console; - testPath?: Config.Path; -}; +// In Jest 25, remove `Partial` since it's incorrect. The properties are always +// passed, or not. The context itself is optional, not properties within it. +export type EnvironmentContext = Partial<{ + console: Console; + dockblockPragmas: {[key: string]: string | Array}; + testPath: Config.Path; +}>; // TODO: type this better: https://nodejs.org/api/modules.html#modules_the_module_wrapper type ModuleWrapper = (...args: Array) => unknown; export declare class JestEnvironment { - constructor(config: Config.ProjectConfig); - constructor(config: Config.ProjectConfig, context: EnvironmentContext); + constructor(config: Config.ProjectConfig, context?: EnvironmentContext); global: Global.Global; fakeTimers: FakeTimers | null; moduleMocker: ModuleMocker | null; diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index dadef559f159..e26f97107451 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -85,8 +85,8 @@ async function runTestInternal( context?: TestRunnerContext, ): Promise { const testSource = fs.readFileSync(path, 'utf8'); - const parsedDocblock = docblock.parse(docblock.extract(testSource)); - const customEnvironment = parsedDocblock['jest-environment']; + const dockblockPragmas = docblock.parse(docblock.extract(testSource)); + const customEnvironment = dockblockPragmas['jest-environment']; let testEnvironment = config.testEnvironment; @@ -144,6 +144,7 @@ async function runTestInternal( const environment = new TestEnvironment(config, { console: testConsole, + dockblockPragmas, testPath: path, }); const leakDetector = config.detectLeaks From 88fdc852a52c3e2340ea903fa1935caebb47f211 Mon Sep 17 00:00:00 2001 From: Scott Hovestadt Date: Fri, 12 Apr 2019 13:22:14 -0700 Subject: [PATCH 2/6] Add test and documentation. --- docs/Configuration.md | 11 +++++++++-- e2e/__tests__/testEnvironment.test.ts | 2 +- e2e/test-environment/EsmDefaultEnvironment.js | 5 +++-- e2e/test-environment/__tests__/esmDefault.test.js | 5 +++++ packages/jest-environment/src/index.ts | 2 +- packages/jest-runner/src/runTest.ts | 7 ++++--- 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/docs/Configuration.md b/docs/Configuration.md index b5c33f13455a..357c81f9987c 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -861,6 +861,8 @@ test('use jsdom in this test file', () => { You can create your own module that will be used for setting up the test environment. The module must export a class with `setup`, `teardown` and `runScript` methods. You can also pass variables from this module to your test suites by assigning them to `this.global` object – this will make them available in your test suites as global variables. +Any docblock pragmas in test files will be passed to the environment constructor and can be used for per-test configuration. + _Note: TestEnvironment is sandboxed. Each test suite will trigger setup/teardown in their own TestEnvironment._ Example: @@ -870,15 +872,20 @@ Example: const NodeEnvironment = require('jest-environment-node'); class CustomEnvironment extends NodeEnvironment { - constructor(config, context) { + constructor(config, {testPath, docblockPragmas}) { super(config, context); - this.testPath = context.testPath; + this.testPath = testPath; + this.docblockPragmas = docblockPragmas; } async setup() { await super.setup(); await someSetupTasks(this.testPath); this.global.someGlobalObject = createGlobalObject(); + + if (this.docblockPragmas['my-custom-pragma'] !== undefined) { + // ... + } } async teardown() { diff --git a/e2e/__tests__/testEnvironment.test.ts b/e2e/__tests__/testEnvironment.test.ts index 141fed8eb310..6783ba921969 100644 --- a/e2e/__tests__/testEnvironment.test.ts +++ b/e2e/__tests__/testEnvironment.test.ts @@ -15,5 +15,5 @@ it('respects testEnvironment docblock', () => { const {json: result} = runWithJson('test-environment'); expect(result.success).toBe(true); - expect(result.numTotalTests).toBe(2); + expect(result.numTotalTests).toBe(3); }); diff --git a/e2e/test-environment/EsmDefaultEnvironment.js b/e2e/test-environment/EsmDefaultEnvironment.js index a15261466885..20908cec4c64 100644 --- a/e2e/test-environment/EsmDefaultEnvironment.js +++ b/e2e/test-environment/EsmDefaultEnvironment.js @@ -11,9 +11,10 @@ exports.__esModule = true; const NodeEnvironment = require('jest-environment-node'); class Env extends NodeEnvironment { - constructor(...args) { - super(...args); + constructor(config, options) { + super(config, options); this.global.property = 'value'; + this.global.myCustomPragma = options.docblockPragmas['my-custom-pragma']; } } diff --git a/e2e/test-environment/__tests__/esmDefault.test.js b/e2e/test-environment/__tests__/esmDefault.test.js index a978d0b9e1f6..69f43bb84fe4 100644 --- a/e2e/test-environment/__tests__/esmDefault.test.js +++ b/e2e/test-environment/__tests__/esmDefault.test.js @@ -5,9 +5,14 @@ * LICENSE file in the root directory of this source tree. * * @jest-environment ./EsmDefaultEnvironment.js + * @my-custom-pragma pragma-value */ 'use strict'; test('access env', () => { expect(property).toBe('value'); // eslint-disable-line no-undef }); + +test('docblock pragmas', () => { + expect(myCustomPragma).toEqual('pragma-value'); // eslint-disable-line no-undef +}); diff --git a/packages/jest-environment/src/index.ts b/packages/jest-environment/src/index.ts index d72167965f43..00fb37b8fab8 100644 --- a/packages/jest-environment/src/index.ts +++ b/packages/jest-environment/src/index.ts @@ -18,7 +18,7 @@ type JestMockSpyOn = typeof jestMock.spyOn; // passed, or not. The context itself is optional, not properties within it. export type EnvironmentContext = Partial<{ console: Console; - dockblockPragmas: {[key: string]: string | Array}; + docblockPragmas: {[key: string]: string | Array}; testPath: Config.Path; }>; diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index e26f97107451..346995874949 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -85,8 +85,8 @@ async function runTestInternal( context?: TestRunnerContext, ): Promise { const testSource = fs.readFileSync(path, 'utf8'); - const dockblockPragmas = docblock.parse(docblock.extract(testSource)); - const customEnvironment = dockblockPragmas['jest-environment']; + const docblockPragmas = docblock.parse(docblock.extract(testSource)); + const customEnvironment = docblockPragmas['jest-environment']; let testEnvironment = config.testEnvironment; @@ -142,9 +142,10 @@ async function runTestInternal( testConsole = new BufferedConsole(() => runtime && runtime.getSourceMaps()); } + // console.log('dockblockPragmas', dockblockPragmas); const environment = new TestEnvironment(config, { console: testConsole, - dockblockPragmas, + docblockPragmas, testPath: path, }); const leakDetector = config.detectLeaks From 65c63f4a50655d8a9c8e416bbc720136fc4665d9 Mon Sep 17 00:00:00 2001 From: Scott Hovestadt Date: Fri, 12 Apr 2019 13:32:02 -0700 Subject: [PATCH 3/6] Update Configuration.md --- docs/Configuration.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/Configuration.md b/docs/Configuration.md index 357c81f9987c..01cd50f533e9 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -861,7 +861,7 @@ test('use jsdom in this test file', () => { You can create your own module that will be used for setting up the test environment. The module must export a class with `setup`, `teardown` and `runScript` methods. You can also pass variables from this module to your test suites by assigning them to `this.global` object – this will make them available in your test suites as global variables. -Any docblock pragmas in test files will be passed to the environment constructor and can be used for per-test configuration. +Any docblock pragmas in test files will be passed to the environment constructor and can be used for per-test configuration. If the pragma does not have a value, it will be present in the object with it's value set to an empty string. If the pragma is not present, it will not be present in the object. _Note: TestEnvironment is sandboxed. Each test suite will trigger setup/teardown in their own TestEnvironment._ @@ -883,7 +883,8 @@ class CustomEnvironment extends NodeEnvironment { await someSetupTasks(this.testPath); this.global.someGlobalObject = createGlobalObject(); - if (this.docblockPragmas['my-custom-pragma'] !== undefined) { + // Will trigger if docblock contains @my-custom-pragma my-pragma-value + if (this.docblockPragmas['my-custom-pragma'] === 'my-pragma-value') { // ... } } From 0afaa339a4cca2a1a78edb9b5a2672c615efaa8a Mon Sep 17 00:00:00 2001 From: Scott Hovestadt Date: Fri, 12 Apr 2019 13:34:58 -0700 Subject: [PATCH 4/6] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e23216d3f0a3..30ed31b65ec4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Features - `[expect]` Improve report when matcher fails, part 15 ([#8281](https://github.com/facebook/jest/pull/8281)) +- `[jest-runner]` Pass docblock pragmas to TestEnvironment constructor ([#8320](https://github.com/facebook/jest/pull/8320)) ### Fixes From 3ce1c594b0bd5551b4fe70a5f8ec9e12d857807d Mon Sep 17 00:00:00 2001 From: Scott Hovestadt Date: Fri, 12 Apr 2019 13:35:57 -0700 Subject: [PATCH 5/6] Update runTest.ts --- packages/jest-runner/src/runTest.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index 346995874949..860105dc99e1 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -142,7 +142,6 @@ async function runTestInternal( testConsole = new BufferedConsole(() => runtime && runtime.getSourceMaps()); } - // console.log('dockblockPragmas', dockblockPragmas); const environment = new TestEnvironment(config, { console: testConsole, docblockPragmas, From 740075b452c5a9d9482afd551dffe79feb3da9be Mon Sep 17 00:00:00 2001 From: Scott Hovestadt Date: Sat, 13 Apr 2019 10:48:05 -0700 Subject: [PATCH 6/6] Move docblock pragmas test into own files. --- e2e/test-environment/DocblockPragmasEnvironment.js | 14 ++++++++++++++ e2e/test-environment/EsmDefaultEnvironment.js | 1 - .../__tests__/docblockPragmas.test.js | 10 ++++++++++ e2e/test-environment/__tests__/esmDefault.test.js | 5 ----- 4 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 e2e/test-environment/DocblockPragmasEnvironment.js create mode 100644 e2e/test-environment/__tests__/docblockPragmas.test.js diff --git a/e2e/test-environment/DocblockPragmasEnvironment.js b/e2e/test-environment/DocblockPragmasEnvironment.js new file mode 100644 index 000000000000..6868bc3d4093 --- /dev/null +++ b/e2e/test-environment/DocblockPragmasEnvironment.js @@ -0,0 +1,14 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + +'use strict'; + +const JSDOMEnvironment = require('jest-environment-jsdom'); + +class TestEnvironment extends JSDOMEnvironment { + constructor(config, context) { + super(config, context); + this.global.myCustomPragma = context.docblockPragmas['my-custom-pragma']; + } +} + +module.exports = TestEnvironment; diff --git a/e2e/test-environment/EsmDefaultEnvironment.js b/e2e/test-environment/EsmDefaultEnvironment.js index 20908cec4c64..6c3e9ad5b769 100644 --- a/e2e/test-environment/EsmDefaultEnvironment.js +++ b/e2e/test-environment/EsmDefaultEnvironment.js @@ -14,7 +14,6 @@ class Env extends NodeEnvironment { constructor(config, options) { super(config, options); this.global.property = 'value'; - this.global.myCustomPragma = options.docblockPragmas['my-custom-pragma']; } } diff --git a/e2e/test-environment/__tests__/docblockPragmas.test.js b/e2e/test-environment/__tests__/docblockPragmas.test.js new file mode 100644 index 000000000000..213e5c22a273 --- /dev/null +++ b/e2e/test-environment/__tests__/docblockPragmas.test.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * @jest-environment ./DocblockPragmasEnvironment.js + * @my-custom-pragma pragma-value + */ + +test('docblock pragmas', () => { + expect(myCustomPragma).toEqual('pragma-value'); // eslint-disable-line no-undef +}); diff --git a/e2e/test-environment/__tests__/esmDefault.test.js b/e2e/test-environment/__tests__/esmDefault.test.js index 69f43bb84fe4..a978d0b9e1f6 100644 --- a/e2e/test-environment/__tests__/esmDefault.test.js +++ b/e2e/test-environment/__tests__/esmDefault.test.js @@ -5,14 +5,9 @@ * LICENSE file in the root directory of this source tree. * * @jest-environment ./EsmDefaultEnvironment.js - * @my-custom-pragma pragma-value */ 'use strict'; test('access env', () => { expect(property).toBe('value'); // eslint-disable-line no-undef }); - -test('docblock pragmas', () => { - expect(myCustomPragma).toEqual('pragma-value'); // eslint-disable-line no-undef -});