diff --git a/src/test/loader.ts b/src/test/loader.ts index 1102d4ae82..8ad810ec86 100644 --- a/src/test/loader.ts +++ b/src/test/loader.ts @@ -22,6 +22,7 @@ import { Suite } from './test'; import { SerializedLoaderData } from './ipc'; import * as path from 'path'; import * as url from 'url'; +import * as fs from 'fs'; import { ProjectImpl } from './project'; import { Reporter } from '../../types/testReporter'; import { LaunchConfig } from '../../types/test'; @@ -74,9 +75,9 @@ export class Loader { // Resolve script hooks relative to the root dir. if (this._config.globalSetup) - this._config.globalSetup = path.resolve(rootDir, this._config.globalSetup); + this._config.globalSetup = resolveScript(this._config.globalSetup, rootDir); if (this._config.globalTeardown) - this._config.globalTeardown = path.resolve(rootDir, this._config.globalTeardown); + this._config.globalTeardown = resolveScript(this._config.globalTeardown, rootDir); const configUse = mergeObjects(this._defaultConfig.use, this._config.use); this._config = mergeObjects(mergeObjects(this._defaultConfig, this._config), { use: configUse }); @@ -444,3 +445,10 @@ function resolveReporters(reporters: Config['reporter'], rootDir: string): Repor return [require.resolve(id, { paths: [ rootDir ] }), arg]; }); } + +function resolveScript(id: string, rootDir: string) { + const localPath = path.resolve(rootDir, id); + if (fs.existsSync(localPath)) + return localPath; + return require.resolve(id, { paths: [rootDir] }); +} diff --git a/tests/playwright-test/global-setup.spec.ts b/tests/playwright-test/global-setup.spec.ts index 2898e04c08..a661bed8da 100644 --- a/tests/playwright-test/global-setup.spec.ts +++ b/tests/playwright-test/global-setup.spec.ts @@ -21,7 +21,7 @@ test('globalSetup and globalTeardown should work', async ({ runInlineTest }) => 'playwright.config.ts': ` import * as path from 'path'; module.exports = { - globalSetup: './globalSetup.ts', + globalSetup: './globalSetup', globalTeardown: path.join(__dirname, 'globalTeardown.ts'), }; `, @@ -54,7 +54,7 @@ test('globalTeardown runs after failures', async ({ runInlineTest }) => { import * as path from 'path'; module.exports = { globalSetup: 'globalSetup.ts', - globalTeardown: 'globalTeardown.ts', + globalTeardown: './globalTeardown.ts', }; `, 'globalSetup.ts': ` @@ -85,7 +85,7 @@ test('globalTeardown does not run when globalSetup times out', async ({ runInlin 'playwright.config.ts': ` import * as path from 'path'; module.exports = { - globalSetup: 'globalSetup.ts', + globalSetup: './globalSetup.ts', globalTeardown: 'globalTeardown.ts', globalTimeout: 1000, }; @@ -119,7 +119,7 @@ test('globalSetup should be run before requiring tests', async ({ runInlineTest 'playwright.config.ts': ` import * as path from 'path'; module.exports = { - globalSetup: 'globalSetup.ts', + globalSetup: './globalSetup.ts', }; `, 'globalSetup.ts': ` @@ -143,7 +143,7 @@ test('globalSetup should work with sync function', async ({ runInlineTest }) => 'playwright.config.ts': ` import * as path from 'path'; module.exports = { - globalSetup: 'globalSetup.ts', + globalSetup: './globalSetup.ts', }; `, 'globalSetup.ts': ` @@ -167,7 +167,7 @@ test('globalSetup should throw when passed non-function', async ({ runInlineTest 'playwright.config.ts': ` import * as path from 'path'; module.exports = { - globalSetup: 'globalSetup.ts', + globalSetup: './globalSetup.ts', }; `, 'globalSetup.ts': ` @@ -187,7 +187,7 @@ test('globalSetup should work with default export and run the returned fn', asyn 'playwright.config.ts': ` import * as path from 'path'; module.exports = { - globalSetup: 'globalSetup.ts', + globalSetup: './globalSetup.ts', }; `, 'globalSetup.ts': ` @@ -212,3 +212,28 @@ test('globalSetup should work with default export and run the returned fn', asyn 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'); +}); \ No newline at end of file