From a01b65beddeff7add6fe32fa4679f391b78564b1 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 27 Apr 2022 17:01:37 -0800 Subject: [PATCH] chore: drop the legacy global setup mode (#13803) --- packages/playwright-test/src/runner.ts | 17 +- tests/playwright-test/global-setup.spec.ts | 561 ++++++++++----------- 2 files changed, 280 insertions(+), 298 deletions(-) diff --git a/packages/playwright-test/src/runner.ts b/packages/playwright-test/src/runner.ts index ce575440b8..7f5b3f383c 100644 --- a/packages/playwright-test/src/runner.ts +++ b/packages/playwright-test/src/runner.ts @@ -149,13 +149,6 @@ export class Runner { this._reporter = await this._createReporter(!!options.listOnly); const config = this._loader.fullConfig(); - let legacyGlobalTearDown: (() => Promise) | undefined; - if (process.env.PW_TEST_LEGACY_GLOBAL_SETUP_MODE) { - legacyGlobalTearDown = await this._performGlobalSetup(config); - if (!legacyGlobalTearDown) - return { status: 'failed' }; - } - const result = await raceAgainstTimeout(() => this._run(!!options.listOnly, options.filePatternFilter || [], options.projectFilter), config.globalTimeout); let fullResult: FullResult; if (result.timedOut) { @@ -165,7 +158,6 @@ export class Runner { fullResult = result.result; } await this._reporter.onEnd?.(fullResult); - await legacyGlobalTearDown?.(); // Calling process.exit() might truncate large stdout/stderr output. // See https://github.com/nodejs/node/issues/6456. @@ -379,12 +371,9 @@ export class Runner { } // 13. Run Global setup. - let globalTearDown: (() => Promise) | undefined; - if (!process.env.PW_TEST_LEGACY_GLOBAL_SETUP_MODE) { - globalTearDown = await this._performGlobalSetup(config); - if (!globalTearDown) - return { status: 'failed' }; - } + const globalTearDown = await this._performGlobalSetup(config); + if (!globalTearDown) + return { status: 'failed' }; const result: FullResult = { status: 'passed' }; diff --git a/tests/playwright-test/global-setup.spec.ts b/tests/playwright-test/global-setup.spec.ts index 83e73ff258..95d7af269f 100644 --- a/tests/playwright-test/global-setup.spec.ts +++ b/tests/playwright-test/global-setup.spec.ts @@ -16,288 +16,281 @@ import { test, expect, stripAnsi } from './playwright-test-fixtures'; -for (const mode of ['legacy', 'default']) { - test.describe(`${mode} mode`, () => { - const env = { PW_TEST_LEGACY_GLOBAL_SETUP_MODE: mode === 'legacy' ? '1' : undefined }; - - test('globalSetup and globalTeardown should work', async ({ runInlineTest }) => { - const { results, output } = await runInlineTest({ - 'playwright.config.ts': ` - import * as path from 'path'; - module.exports = { - globalSetup: './globalSetup', - globalTeardown: path.join(__dirname, 'globalTeardown.ts'), - }; - `, - 'globalSetup.ts': ` - module.exports = async () => { - await new Promise(f => setTimeout(f, 100)); - global.value = 42; - process.env.FOO = String(global.value); - }; - `, - 'globalTeardown.ts': ` - module.exports = async () => { - console.log('teardown=' + global.value); - }; - `, - 'a.test.js': ` - const { test } = pwt; - test('should work', async ({}, testInfo) => { - expect(process.env.FOO).toBe('42'); - }); - `, - }, undefined, env); - expect(results[0].status).toBe('passed'); - expect(output).toContain('teardown=42'); - }); - - test('globalTeardown runs after failures', async ({ runInlineTest }) => { - const { results, output } = await runInlineTest({ - 'playwright.config.ts': ` - import * as path from 'path'; - module.exports = { - globalSetup: 'globalSetup.ts', - globalTeardown: './globalTeardown.ts', - }; - `, - 'globalSetup.ts': ` - module.exports = async () => { - await new Promise(f => setTimeout(f, 100)); - global.value = 42; - process.env.FOO = String(global.value); - }; - `, - 'globalTeardown.ts': ` - module.exports = async () => { - console.log('teardown=' + global.value); - }; - `, - 'a.test.js': ` - const { test } = pwt; - test('should work', async ({}, testInfo) => { - expect(process.env.FOO).toBe('43'); - }); - `, - }, undefined, env); - expect(results[0].status).toBe('failed'); - expect(output).toContain('teardown=42'); - }); - - test('globalTeardown does not run when globalSetup times out', async ({ runInlineTest }) => { - test.skip(!!env.PW_TEST_LEGACY_GLOBAL_SETUP_MODE); - const result = await runInlineTest({ - 'playwright.config.ts': ` - import * as path from 'path'; - module.exports = { - globalSetup: './globalSetup.ts', - globalTeardown: 'globalTeardown.ts', - globalTimeout: 1000, - }; - `, - 'globalSetup.ts': ` - module.exports = async () => { - await new Promise(f => setTimeout(f, 10000)); - }; - `, - 'globalTeardown.ts': ` - module.exports = async () => { - console.log('teardown='); - }; - `, - 'a.test.js': ` - const { test } = pwt; - test('should not run', async ({}, testInfo) => { - }); - `, - }, undefined, env); - // We did not run tests, so we should only have 1 skipped test. - expect(result.skipped).toBe(1); - expect(result.passed).toBe(0); - expect(result.failed).toBe(0); - expect(result.exitCode).toBe(1); - expect(result.output).not.toContain('teardown='); - }); - - test('globalSetup should work with sync function', async ({ runInlineTest }) => { - const { passed } = await runInlineTest({ - 'playwright.config.ts': ` - import * as path from 'path'; - module.exports = { - globalSetup: './globalSetup.ts', - }; - `, - 'globalSetup.ts': ` - module.exports = () => { - process.env.FOO = JSON.stringify({ foo: 'bar' }); - }; - `, - 'a.test.js': ` - const { test } = pwt; - test('should work', async ({}) => { - const value = JSON.parse(process.env.FOO); - expect(value).toEqual({ foo: 'bar' }); - }); - `, - }, undefined, env); - expect(passed).toBe(1); - }); - - test('globalSetup error should prevent tests from executing', async ({ runInlineTest }) => { - const { passed, output } = await runInlineTest({ - 'playwright.config.ts': ` - import * as path from 'path'; - module.exports = { - globalSetup: './globalSetup.ts', - }; - `, - 'globalSetup.ts': ` - module.exports = () => { - throw new Error('failure in global setup!'); - }; - `, - 'a.test.js': ` - const { test } = pwt; - test('a', async ({}) => { - console.log('this test ran'); - }); - - test('b', async ({}) => { - console.log('this test ran'); - }); - `, - }, { reporter: 'line' }, env); - - expect(stripAnsi(output)).not.toContain('this test ran'); - expect(passed).toBe(0); - }); - - test('globalSetup should throw when passed non-function', async ({ runInlineTest }) => { - const { output } = await runInlineTest({ - 'playwright.config.ts': ` - import * as path from 'path'; - module.exports = { - globalSetup: './globalSetup.ts', - }; - `, - 'globalSetup.ts': ` - module.exports = 42; - `, - 'a.test.js': ` - const { test } = pwt; - test('should work', async ({}) => { - }); - `, - }, undefined, env); - expect(output).toContain(`globalSetup.ts: globalSetup file must export a single function.`); - }); - - test('globalSetup should work with default export and run the returned fn', async ({ runInlineTest }) => { - const { output, exitCode, passed } = await runInlineTest({ - 'playwright.config.ts': ` - import * as path from 'path'; - module.exports = { - globalSetup: './globalSetup.ts', - }; - `, - 'globalSetup.ts': ` - function setup() { - let x = 42; - console.log('\\n%%setup: ' + x); - return async () => { - await x; - console.log('\\n%%teardown: ' + x); - }; - } - export default setup; - `, - 'a.test.js': ` - const { test } = pwt; - test('should work', async ({}) => { - }); - `, - }, undefined, env); - expect(passed).toBe(1); - expect(exitCode).toBe(0); - expect(output).toContain(`%%setup: 42`); - expect(output).toContain(`%%teardown: 42`); - }); - - test('globalSetup should allow requiring a package from node_modules', async ({ runInlineTest }) => { - const { results } = await runInlineTest({ - 'playwright.config.ts': ` - import * as path from 'path'; - module.exports = { - globalSetup: 'my-global-setup' - }; - `, - 'node_modules/my-global-setup/index.js': ` - module.exports = async () => { - await new Promise(f => setTimeout(f, 100)); - global.value = 42; - process.env.FOO = String(global.value); - }; - `, - 'a.test.js': ` - const { test } = pwt; - test('should work', async ({}, testInfo) => { - expect(process.env.FOO).toBe('42'); - }); - `, - }, undefined, env); - expect(results[0].status).toBe('passed'); - }); - - const authFiles = { - 'playwright.config.ts': ` - const config: pwt.PlaywrightTestConfig = { - globalSetup: require.resolve('./auth'), - use: { - baseURL: 'https://www.example.com', - storageState: 'state.json', - }, - }; - export default config; - `, - 'auth.ts': ` - async function globalSetup(config: pwt.FullConfig) { - const { baseURL, storageState } = config.projects[0].use; - const browser = await pwt.chromium.launch(); - const page = await browser.newPage(); - await page.route('**/*', route => { - route.fulfill({ body: '' }).catch(() => {}); - }); - await page.goto(baseURL!); - await page.evaluate(() => { - localStorage['name'] = 'value'; - }); - await page.context().storageState({ path: storageState as string }); - await browser.close(); - }; - export default globalSetup; - `, - 'a.test.ts': ` - const { test } = pwt; - test('should have storage state', async ({ page }) => { - await page.route('**/*', route => { - route.fulfill({ body: '' }).catch(() => {}); - }); - await page.goto('/'); - const value = await page.evaluate(() => localStorage['name']); - expect(value).toBe('value'); - }); - `, - }; - - test('globalSetup should work for auth', async ({ runInlineTest }) => { - const result = await runInlineTest(authFiles, undefined, env); - expect(result.exitCode).toBe(0); - expect(result.passed).toBe(1); - }); - - test('globalSetup auth should compile', async ({ runTSC }) => { - const result = await runTSC(authFiles); - expect(result.exitCode).toBe(0); - }); +test('globalSetup and globalTeardown should work', async ({ runInlineTest }) => { + const { results, output } = await runInlineTest({ + 'playwright.config.ts': ` + import * as path from 'path'; + module.exports = { + globalSetup: './globalSetup', + globalTeardown: path.join(__dirname, 'globalTeardown.ts'), + }; + `, + 'globalSetup.ts': ` + module.exports = async () => { + await new Promise(f => setTimeout(f, 100)); + global.value = 42; + process.env.FOO = String(global.value); + }; + `, + 'globalTeardown.ts': ` + module.exports = async () => { + console.log('teardown=' + global.value); + }; + `, + 'a.test.js': ` + const { test } = pwt; + test('should work', async ({}, testInfo) => { + expect(process.env.FOO).toBe('42'); + }); + `, }); -} + expect(results[0].status).toBe('passed'); + expect(output).toContain('teardown=42'); +}); + +test('globalTeardown runs after failures', async ({ runInlineTest }) => { + const { results, output } = await runInlineTest({ + 'playwright.config.ts': ` + import * as path from 'path'; + module.exports = { + globalSetup: 'globalSetup.ts', + globalTeardown: './globalTeardown.ts', + }; + `, + 'globalSetup.ts': ` + module.exports = async () => { + await new Promise(f => setTimeout(f, 100)); + global.value = 42; + process.env.FOO = String(global.value); + }; + `, + 'globalTeardown.ts': ` + module.exports = async () => { + console.log('teardown=' + global.value); + }; + `, + 'a.test.js': ` + const { test } = pwt; + test('should work', async ({}, testInfo) => { + expect(process.env.FOO).toBe('43'); + }); + `, + }); + expect(results[0].status).toBe('failed'); + expect(output).toContain('teardown=42'); +}); + +test('globalTeardown does not run when globalSetup times out', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'playwright.config.ts': ` + import * as path from 'path'; + module.exports = { + globalSetup: './globalSetup.ts', + globalTeardown: 'globalTeardown.ts', + globalTimeout: 1000, + }; + `, + 'globalSetup.ts': ` + module.exports = async () => { + await new Promise(f => setTimeout(f, 10000)); + }; + `, + 'globalTeardown.ts': ` + module.exports = async () => { + console.log('teardown='); + }; + `, + 'a.test.js': ` + const { test } = pwt; + test('should not run', async ({}, testInfo) => { + }); + `, + }); + // We did not run tests, so we should only have 1 skipped test. + expect(result.skipped).toBe(1); + expect(result.passed).toBe(0); + expect(result.failed).toBe(0); + expect(result.exitCode).toBe(1); + expect(result.output).not.toContain('teardown='); +}); + +test('globalSetup should work with sync function', async ({ runInlineTest }) => { + const { passed } = await runInlineTest({ + 'playwright.config.ts': ` + import * as path from 'path'; + module.exports = { + globalSetup: './globalSetup.ts', + }; + `, + 'globalSetup.ts': ` + module.exports = () => { + process.env.FOO = JSON.stringify({ foo: 'bar' }); + }; + `, + 'a.test.js': ` + const { test } = pwt; + test('should work', async ({}) => { + const value = JSON.parse(process.env.FOO); + expect(value).toEqual({ foo: 'bar' }); + }); + `, + }); + expect(passed).toBe(1); +}); + +test('globalSetup error should prevent tests from executing', async ({ runInlineTest }) => { + const { passed, output } = await runInlineTest({ + 'playwright.config.ts': ` + import * as path from 'path'; + module.exports = { + globalSetup: './globalSetup.ts', + }; + `, + 'globalSetup.ts': ` + module.exports = () => { + throw new Error('failure in global setup!'); + }; + `, + 'a.test.js': ` + const { test } = pwt; + test('a', async ({}) => { + console.log('this test ran'); + }); + + test('b', async ({}) => { + console.log('this test ran'); + }); + `, + }, { reporter: 'line' }); + + expect(stripAnsi(output)).not.toContain('this test ran'); + expect(passed).toBe(0); +}); + +test('globalSetup should throw when passed non-function', async ({ runInlineTest }) => { + const { output } = await runInlineTest({ + 'playwright.config.ts': ` + import * as path from 'path'; + module.exports = { + globalSetup: './globalSetup.ts', + }; + `, + 'globalSetup.ts': ` + module.exports = 42; + `, + 'a.test.js': ` + const { test } = pwt; + test('should work', async ({}) => { + }); + `, + }); + expect(output).toContain(`globalSetup.ts: globalSetup file must export a single function.`); +}); + +test('globalSetup should work with default export and run the returned fn', async ({ runInlineTest }) => { + const { output, exitCode, passed } = await runInlineTest({ + 'playwright.config.ts': ` + import * as path from 'path'; + module.exports = { + globalSetup: './globalSetup.ts', + }; + `, + 'globalSetup.ts': ` + function setup() { + let x = 42; + console.log('\\n%%setup: ' + x); + return async () => { + await x; + console.log('\\n%%teardown: ' + x); + }; + } + export default setup; + `, + 'a.test.js': ` + const { test } = pwt; + test('should work', async ({}) => { + }); + `, + }); + expect(passed).toBe(1); + expect(exitCode).toBe(0); + expect(output).toContain(`%%setup: 42`); + expect(output).toContain(`%%teardown: 42`); +}); + +test('globalSetup should allow requiring a package from node_modules', async ({ runInlineTest }) => { + const { results } = await runInlineTest({ + 'playwright.config.ts': ` + import * as path from 'path'; + module.exports = { + globalSetup: 'my-global-setup' + }; + `, + 'node_modules/my-global-setup/index.js': ` + module.exports = async () => { + await new Promise(f => setTimeout(f, 100)); + global.value = 42; + process.env.FOO = String(global.value); + }; + `, + 'a.test.js': ` + const { test } = pwt; + test('should work', async ({}, testInfo) => { + expect(process.env.FOO).toBe('42'); + }); + `, + }); + expect(results[0].status).toBe('passed'); +}); + +const authFiles = { + 'playwright.config.ts': ` + const config: pwt.PlaywrightTestConfig = { + globalSetup: require.resolve('./auth'), + use: { + baseURL: 'https://www.example.com', + storageState: 'state.json', + }, + }; + export default config; + `, + 'auth.ts': ` + async function globalSetup(config: pwt.FullConfig) { + const { baseURL, storageState } = config.projects[0].use; + const browser = await pwt.chromium.launch(); + const page = await browser.newPage(); + await page.route('**/*', route => { + route.fulfill({ body: '' }).catch(() => {}); + }); + await page.goto(baseURL!); + await page.evaluate(() => { + localStorage['name'] = 'value'; + }); + await page.context().storageState({ path: storageState as string }); + await browser.close(); + }; + export default globalSetup; + `, + 'a.test.ts': ` + const { test } = pwt; + test('should have storage state', async ({ page }) => { + await page.route('**/*', route => { + route.fulfill({ body: '' }).catch(() => {}); + }); + await page.goto('/'); + const value = await page.evaluate(() => localStorage['name']); + expect(value).toBe('value'); + }); + `, +}; + +test('globalSetup should work for auth', async ({ runInlineTest }) => { + const result = await runInlineTest(authFiles); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); +}); + +test('globalSetup auth should compile', async ({ runTSC }) => { + const result = await runTSC(authFiles); + expect(result.exitCode).toBe(0); +});