From a9e0075c46772ffcae6c109999088fa1ab348e52 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 7 Mar 2021 14:51:59 +0100 Subject: [PATCH] fix: remove support for `runScript` (#11155) --- CHANGELOG.md | 1 + docs/Configuration.md | 6 +++--- docs/Puppeteer.md | 4 ++-- .../testEnvironmentRunScript.test.ts.snap | 3 +++ .../testEnvironmentRunScript.test.ts | 17 +++++++++++++++++ e2e/test-environment-async/TestEnvironment.js | 4 ++-- .../EnvUsingRunScript.js | 14 ++++++++++++++ .../__tests__/envUsingRunScript.test.js | 11 +++++++++++ e2e/test-environment-run-script/package.json | 5 +++++ examples/mongodb/mongo-environment.js | 4 ++-- packages/jest-environment-jsdom/src/index.ts | 13 +++---------- packages/jest-environment-node/src/index.ts | 11 +---------- packages/jest-environment/src/index.ts | 19 +++++-------------- packages/jest-runner/src/runTest.ts | 8 ++++++++ packages/jest-runtime/src/index.ts | 11 +++-------- 15 files changed, 80 insertions(+), 51 deletions(-) create mode 100644 e2e/__tests__/__snapshots__/testEnvironmentRunScript.test.ts.snap create mode 100644 e2e/__tests__/testEnvironmentRunScript.test.ts create mode 100644 e2e/test-environment-run-script/EnvUsingRunScript.js create mode 100644 e2e/test-environment-run-script/__tests__/envUsingRunScript.test.js create mode 100644 e2e/test-environment-run-script/package.json diff --git a/CHANGELOG.md b/CHANGELOG.md index d88b455e2597..05b7b43b370b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ - `[jest-console]` `console.dir` now respects the second argument correctly ([#10638](https://github.com/facebook/jest/pull/10638)) - `[jest-core]` Don't report PerformanceObserver as open handle ([#11123](https://github.com/facebook/jest/pull/11123)) - `[jest-each]` [**BREAKING**] Ignore excess words in headings ([#8766](https://github.com/facebook/jest/pull/8766)) +- `[jest-environment]` [**BREAKING**] Drop support for `runScript` for test environments ([#11155](https://github.com/facebook/jest/pull/11155)) - `[jest-environment-jsdom]` Use inner realm’s `ArrayBuffer` constructor ([#10885](https://github.com/facebook/jest/pull/10885)) - `[jest-globals]` [**BREAKING**] Disallow return values other than a `Promise` from hooks and tests ([#10512](https://github.com/facebook/jest/pull/10512)) - `[jest-globals]` [**BREAKING**] Disallow mixing a done callback and returning a `Promise` from hooks and tests ([#10512](https://github.com/facebook/jest/pull/10512)) diff --git a/docs/Configuration.md b/docs/Configuration.md index a419b32977aa..2e881907de14 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -1030,7 +1030,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. +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 `getVmContext` 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. The class may optionally expose an asynchronous `handleTestEvent` method to bind to events fired by [`jest-circus`](https://github.com/facebook/jest/tree/master/packages/jest-circus). Normally, `jest-circus` test runner would pause until a promise returned from `handleTestEvent` gets fulfilled, **except for the next events**: `start_describe_definition`, `finish_describe_definition`, `add_hook`, `add_test` or `error` (for the up-to-date list you can look at [SyncEvent type in the types definitions](https://github.com/facebook/jest/tree/master/packages/jest-types/src/Circus.ts)). That is caused by backward compatibility reasons and `process.on('unhandledRejection', callback)` signature, but that usually should not be a problem for most of the use cases. @@ -1076,8 +1076,8 @@ class CustomEnvironment extends NodeEnvironment { await super.teardown(); } - runScript(script) { - return super.runScript(script); + getVmContext() { + return super.getVmContext(); } async handleTestEvent(event, state) { diff --git a/docs/Puppeteer.md b/docs/Puppeteer.md index e071d8161fe3..504056c75992 100644 --- a/docs/Puppeteer.md +++ b/docs/Puppeteer.md @@ -110,8 +110,8 @@ class PuppeteerEnvironment extends NodeEnvironment { await super.teardown(); } - runScript(script) { - return super.runScript(script); + getVmContext() { + return super.getVmContext(); } } diff --git a/e2e/__tests__/__snapshots__/testEnvironmentRunScript.test.ts.snap b/e2e/__tests__/__snapshots__/testEnvironmentRunScript.test.ts.snap new file mode 100644 index 000000000000..87e8e5590d01 --- /dev/null +++ b/e2e/__tests__/__snapshots__/testEnvironmentRunScript.test.ts.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`throw error if test env does not have getVmContext 1`] = `"Test environment found at \\"/EnvUsingRunScript.js\\" does not export a \\"getVmContext\\" method, which is mandatory from Jest 27. This method is a replacement for \\"runScript\\"."`; diff --git a/e2e/__tests__/testEnvironmentRunScript.test.ts b/e2e/__tests__/testEnvironmentRunScript.test.ts new file mode 100644 index 000000000000..5aee9f9a0e64 --- /dev/null +++ b/e2e/__tests__/testEnvironmentRunScript.test.ts @@ -0,0 +1,17 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {resolve, sep} from 'path'; +import runJest from '../runJest'; + +it('throw error if test env does not have getVmContext', () => { + const DIR = resolve(__dirname, '../test-environment-run-script'); + const {exitCode, stderr} = runJest(DIR); + + expect(stderr.replace(`${DIR}${sep}`, '/')).toMatchSnapshot(); + expect(exitCode).toBe(1); +}); diff --git a/e2e/test-environment-async/TestEnvironment.js b/e2e/test-environment-async/TestEnvironment.js index 95cda7ce15a5..62097b44e614 100644 --- a/e2e/test-environment-async/TestEnvironment.js +++ b/e2e/test-environment-async/TestEnvironment.js @@ -34,8 +34,8 @@ class TestEnvironment extends JSDOMEnvironment { }); } - runScript(script) { - return super.runScript(script); + getVmContext() { + return super.getVmContext(); } } diff --git a/e2e/test-environment-run-script/EnvUsingRunScript.js b/e2e/test-environment-run-script/EnvUsingRunScript.js new file mode 100644 index 000000000000..0c106dd9970c --- /dev/null +++ b/e2e/test-environment-run-script/EnvUsingRunScript.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +'use strict'; + +module.exports = class Env { + constructor() { + this.global = global; + this.moduleMocker = {}; + } +}; diff --git a/e2e/test-environment-run-script/__tests__/envUsingRunScript.test.js b/e2e/test-environment-run-script/__tests__/envUsingRunScript.test.js new file mode 100644 index 000000000000..0394ba971bb0 --- /dev/null +++ b/e2e/test-environment-run-script/__tests__/envUsingRunScript.test.js @@ -0,0 +1,11 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +'use strict'; + +test('dummy', () => { + throw new Error('nothing to see here'); +}); diff --git a/e2e/test-environment-run-script/package.json b/e2e/test-environment-run-script/package.json new file mode 100644 index 000000000000..24a9c8a6da69 --- /dev/null +++ b/e2e/test-environment-run-script/package.json @@ -0,0 +1,5 @@ +{ + "jest": { + "testEnvironment": "/EnvUsingRunScript.js" + } +} diff --git a/examples/mongodb/mongo-environment.js b/examples/mongodb/mongo-environment.js index 849f9f804b97..7f4f8618eb19 100644 --- a/examples/mongodb/mongo-environment.js +++ b/examples/mongodb/mongo-environment.js @@ -29,8 +29,8 @@ class MongoEnvironment extends NodeEnvironment { await super.teardown(); } - runScript(script) { - return super.runScript(script); + getVmContext() { + return super.getVmContext(); } } diff --git a/packages/jest-environment-jsdom/src/index.ts b/packages/jest-environment-jsdom/src/index.ts index b466af646069..9e795c520d4d 100644 --- a/packages/jest-environment-jsdom/src/index.ts +++ b/packages/jest-environment-jsdom/src/index.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import type {Context, Script} from 'vm'; +import type {Context} from 'vm'; import {JSDOM, VirtualConsole} from 'jsdom'; import type {EnvironmentContext, JestEnvironment} from '@jest/environment'; import {LegacyFakeTimers, ModernFakeTimers} from '@jest/fake-timers'; @@ -30,12 +30,12 @@ class JSDOMEnvironment implements JestEnvironment { errorEventListener: ((event: Event & {error: Error}) => void) | null; moduleMocker: ModuleMocker | null; - constructor(config: Config.ProjectConfig, options: EnvironmentContext = {}) { + constructor(config: Config.ProjectConfig, options?: EnvironmentContext) { this.dom = new JSDOM('', { pretendToBeVisual: true, runScripts: 'dangerously', url: config.testURL, - virtualConsole: new VirtualConsole().sendTo(options.console || console), + virtualConsole: new VirtualConsole().sendTo(options?.console || console), ...config.testEnvironmentOptions, }); const global = (this.global = (this.dom.window.document @@ -125,13 +125,6 @@ class JSDOMEnvironment implements JestEnvironment { this.fakeTimersModern = null; } - runScript(script: Script): T | null { - if (this.dom) { - return script.runInContext(this.dom.getInternalVMContext()); - } - return null; - } - getVmContext(): Context | null { if (this.dom) { return this.dom.getInternalVMContext(); diff --git a/packages/jest-environment-node/src/index.ts b/packages/jest-environment-node/src/index.ts index 6fdfa89d313e..021166370fe2 100644 --- a/packages/jest-environment-node/src/index.ts +++ b/packages/jest-environment-node/src/index.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {Context, Script, createContext, runInContext} from 'vm'; +import {Context, createContext, runInContext} from 'vm'; import type {JestEnvironment} from '@jest/environment'; import {LegacyFakeTimers, ModernFakeTimers} from '@jest/fake-timers'; import type {Config, Global} from '@jest/types'; @@ -104,15 +104,6 @@ class NodeEnvironment implements JestEnvironment { this.fakeTimersModern = null; } - // TS infers the return type to be `any`, since that's what `runInContext` - // returns. - runScript(script: Script): T | null { - if (this.context) { - return script.runInContext(this.context); - } - return null; - } - getVmContext(): Context | null { return this.context; } diff --git a/packages/jest-environment/src/index.ts b/packages/jest-environment/src/index.ts index 3b858b922160..3ea78562c32e 100644 --- a/packages/jest-environment/src/index.ts +++ b/packages/jest-environment/src/index.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import type {Context, Script} from 'vm'; +import type {Context} from 'vm'; import type {LegacyFakeTimers, ModernFakeTimers} from '@jest/fake-timers'; import type {Circus, Config, Global} from '@jest/types'; import type { @@ -14,13 +14,11 @@ import type { ModuleMocker, } from 'jest-mock'; -// 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<{ +export type EnvironmentContext = { console: Console; docblockPragmas: Record>; testPath: Config.Path; -}>; +}; // Different Order than https://nodejs.org/api/modules.html#modules_the_module_wrapper , however needs to be in the form [jest-transform]ScriptTransformer accepts export type ModuleWrapper = ( @@ -40,17 +38,10 @@ export declare class JestEnvironment { fakeTimers: LegacyFakeTimers | null; fakeTimersModern: ModernFakeTimers | null; moduleMocker: ModuleMocker | null; - /** - * @deprecated implement getVmContext instead - */ - runScript(script: Script): T | null; - getVmContext?(): Context | null; + getVmContext(): Context | null; setup(): Promise; teardown(): Promise; - handleTestEvent?( - event: Circus.Event, - state: Circus.State, - ): void | Promise; + handleTestEvent?: Circus.EventHandler; } export type Module = NodeModule; diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index d68c7cfb7677..05b93bbf9f4d 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -142,6 +142,14 @@ async function runTestInternal( docblockPragmas, testPath: path, }); + + if (typeof environment.getVmContext !== 'function') { + console.error( + `Test environment found at "${testEnvironment}" does not export a "getVmContext" method, which is mandatory from Jest 27. This method is a replacement for "runScript".`, + ); + process.exit(1); + } + const leakDetector = config.detectLeaks ? new LeakDetector(environment) : null; diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 238d25943198..1468149e6dca 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -1108,15 +1108,10 @@ export default class Runtime { let runScript: RunScriptEvalResult | null = null; - // Use this if available instead of deprecated `JestEnvironment.runScript` - if (typeof this._environment.getVmContext === 'function') { - const vmContext = this._environment.getVmContext(); + const vmContext = this._environment.getVmContext(); - if (vmContext) { - runScript = script.runInContext(vmContext, {filename}); - } - } else { - runScript = this._environment.runScript(script); + if (vmContext) { + runScript = script.runInContext(vmContext, {filename}); } if (runScript !== null) {