diff --git a/packages/playwright-test/src/common/configLoader.ts b/packages/playwright-test/src/common/configLoader.ts index 581b263b2f..1a7130e1a9 100644 --- a/packages/playwright-test/src/common/configLoader.ts +++ b/packages/playwright-test/src/common/configLoader.ts @@ -121,7 +121,7 @@ export class ConfigLoader { this._fullConfig.shard = takeFirst(config.shard, baseFullConfig.shard); this._fullConfig._internal.ignoreSnapshots = takeFirst(config.ignoreSnapshots, baseFullConfig._internal.ignoreSnapshots); this._fullConfig.updateSnapshots = takeFirst(config.updateSnapshots, baseFullConfig.updateSnapshots); - this._fullConfig._internal.pluginRegistrations = (config as any)._plugins || []; + this._fullConfig._internal.plugins = ((config as any)._plugins || []).map((p: any) => ({ factory: p })); const workers = takeFirst(config.workers, '50%'); if (typeof workers === 'string') { @@ -449,7 +449,7 @@ export const baseFullConfig: FullConfigInternal = { storeDir: '', maxConcurrentTestGroups: 0, ignoreSnapshots: false, - pluginRegistrations: [], + plugins: [], testTitleMatcher: () => true, testFileFilters: [], listOnly: false, diff --git a/packages/playwright-test/src/common/types.ts b/packages/playwright-test/src/common/types.ts index 0c2b61b14a..e5453b9533 100644 --- a/packages/playwright-test/src/common/types.ts +++ b/packages/playwright-test/src/common/types.ts @@ -48,7 +48,7 @@ type ConfigInternal = { maxConcurrentTestGroups: number; ignoreSnapshots: boolean; webServers: Exclude[]; - pluginRegistrations: TestRunnerPluginRegistration[]; + plugins: TestRunnerPluginRegistration[]; listOnly: boolean; testFileFilters: TestFileFilter[]; testTitleMatcher: Matcher; diff --git a/packages/playwright-test/src/plugins/index.ts b/packages/playwright-test/src/plugins/index.ts index 32d86af9b7..4124f0a556 100644 --- a/packages/playwright-test/src/plugins/index.ts +++ b/packages/playwright-test/src/plugins/index.ts @@ -24,7 +24,10 @@ export interface TestRunnerPlugin { teardown?(): Promise; } -export type TestRunnerPluginRegistration = TestRunnerPlugin | (() => TestRunnerPlugin | Promise); +export type TestRunnerPluginRegistration = { + factory: TestRunnerPlugin | (() => TestRunnerPlugin | Promise); + instance?: TestRunnerPlugin; +}; export { webServer } from './webServerPlugin'; export { gitCommitInfo } from './gitCommitInfoPlugin'; diff --git a/packages/playwright-test/src/runner/runner.ts b/packages/playwright-test/src/runner/runner.ts index 1850cccd7d..31664f9455 100644 --- a/packages/playwright-test/src/runner/runner.ts +++ b/packages/playwright-test/src/runner/runner.ts @@ -53,9 +53,9 @@ export class Runner { const deadline = config.globalTimeout ? monotonicTime() + config.globalTimeout : 0; // Legacy webServer support. - config._internal.pluginRegistrations.push(...webServerPluginsForConfig(config)); + webServerPluginsForConfig(config).forEach(p => config._internal.plugins.push({ factory: p })); // Docker support. - config._internal.pluginRegistrations.push(dockerPlugin); + config._internal.plugins.push({ factory: dockerPlugin }); const reporter = await createReporter(config, listOnly); const taskRunner = listOnly ? createTaskRunnerForList(config, reporter) @@ -64,7 +64,6 @@ export class Runner { const context: TaskRunnerState = { config, reporter, - plugins: [], phases: [], }; diff --git a/packages/playwright-test/src/runner/tasks.ts b/packages/playwright-test/src/runner/tasks.ts index 49f83b580e..f1e236a245 100644 --- a/packages/playwright-test/src/runner/tasks.ts +++ b/packages/playwright-test/src/runner/tasks.ts @@ -19,7 +19,7 @@ import path from 'path'; import { promisify } from 'util'; import { debug, rimraf } from 'playwright-core/lib/utilsBundle'; import { Dispatcher } from './dispatcher'; -import type { TestRunnerPlugin, TestRunnerPluginRegistration } from '../plugins'; +import type { TestRunnerPluginRegistration } from '../plugins'; import type { Multiplexer } from '../reporters/multiplexer'; import type { TestGroup } from '../runner/testGroups'; import { createTestGroups } from '../runner/testGroups'; @@ -41,7 +41,6 @@ type ProjectWithTestGroups = { export type TaskRunnerState = { reporter: Multiplexer; config: FullConfigInternal; - plugins: TestRunnerPlugin[]; rootSuite?: Suite; phases: { dispatcher: Dispatcher, @@ -52,25 +51,20 @@ export type TaskRunnerState = { export function createTaskRunner(config: FullConfigInternal, reporter: Multiplexer): TaskRunner { const taskRunner = new TaskRunner(reporter, config.globalTimeout); - for (const plugin of config._internal.pluginRegistrations) + for (const plugin of config._internal.plugins) taskRunner.addTask('plugin setup', createPluginSetupTask(plugin)); - if (config.globalSetup || config.globalTeardown) - taskRunner.addTask('global setup', createGlobalSetupTask()); taskRunner.addTask('load tests', createLoadTask()); - taskRunner.addTask('shard tests', createTestGroupsTask()); - taskRunner.addTask('prepare to run', createRemoveOutputDirsTask()); - taskRunner.addTask('plugin begin', async ({ rootSuite, plugins }) => { - for (const plugin of plugins) - await plugin.begin?.(rootSuite!); - }); - + taskRunner.addTask('clear output', createRemoveOutputDirsTask()); + taskRunner.addTask('prepare workers', createTestGroupsTask()); + for (const plugin of config._internal.plugins) + taskRunner.addTask('plugin begin', async ({ rootSuite }) => plugin.instance?.begin?.(rootSuite!)); taskRunner.addTask('report begin', async ({ reporter, rootSuite }) => { reporter.onBegin?.(config, rootSuite!); return () => reporter.onEnd(); }); - + if (config.globalSetup || config.globalTeardown) + taskRunner.addTask('global setup', createGlobalSetupTask()); taskRunner.addTask('test suite', createRunTestsTask()); - return taskRunner; } @@ -84,16 +78,14 @@ export function createTaskRunnerForList(config: FullConfigInternal, reporter: Mu return taskRunner; } -function createPluginSetupTask(pluginRegistration: TestRunnerPluginRegistration): Task { - return async ({ config, reporter, plugins }) => { - let plugin: TestRunnerPlugin; - if (typeof pluginRegistration === 'function') - plugin = await pluginRegistration(); +function createPluginSetupTask(plugin: TestRunnerPluginRegistration): Task { + return async ({ config, reporter }) => { + if (typeof plugin.factory === 'function') + plugin.instance = await plugin.factory(); else - plugin = pluginRegistration; - plugins.push(plugin); - await plugin.setup?.(config, config._internal.configDir, reporter); - return () => plugin.teardown?.(); + plugin.instance = plugin.factory; + await plugin.instance?.setup?.(config, config._internal.configDir, reporter); + return () => plugin.instance?.teardown?.(); }; }