diff --git a/packages/playwright/src/worker/workerMain.ts b/packages/playwright/src/worker/workerMain.ts index b4878ff659..8bd7f3dcd0 100644 --- a/packages/playwright/src/worker/workerMain.ts +++ b/packages/playwright/src/worker/workerMain.ts @@ -105,6 +105,10 @@ export class WorkerMain extends ProcessRunner { override async gracefullyClose() { try { await this._stop(); + if (!this._config) { + // We never set anything up and we can crash on attempting cleanup + return; + } // Ignore top-level errors, they are already inside TestInfo.errors. const fakeTestInfo = new TestInfoImpl(this._config, this._project, this._params, undefined, 0, () => {}, () => {}, () => {}); const runnable = { type: 'teardown' } as const; @@ -190,15 +194,19 @@ export class WorkerMain extends ProcessRunner { if (this._config) return; - this._config = await deserializeConfig(this._params.config); - this._project = this._config.projects.find(p => p.id === this._params.projectId)!; + const config = await deserializeConfig(this._params.config); + const project = config.projects.find(p => p.id === this._params.projectId); + if (!project) + throw new Error(`Project "${this._params.projectId}" not found in the worker process. Make sure project name does not change.`); + this._config = config; + this._project = project; this._poolBuilder = PoolBuilder.createForWorker(this._project); } async runTestGroup(runPayload: RunPayload) { this._runFinished = new ManualPromise(); const entries = new Map(runPayload.entries.map(e => [e.testId, e])); - let fatalUnknownTestIds; + let fatalUnknownTestIds: string[] | undefined; try { await this._loadIfNeeded(); const fileSuite = await loadTestFile(runPayload.file, this._config.config.rootDir); diff --git a/tests/playwright-test/config.spec.ts b/tests/playwright-test/config.spec.ts index 5550d84253..7870d74706 100644 --- a/tests/playwright-test/config.spec.ts +++ b/tests/playwright-test/config.spec.ts @@ -392,6 +392,24 @@ test('should print nice error when some of the projects are unknown', async ({ r expect(output).toContain('Project(s) "suIte3", "SUite4" not found. Available projects: "suite1", "suite2"'); }); +test('should print nice error when project name is not stable', async ({ runInlineTest }) => { + const { output, exitCode } = await runInlineTest({ + 'playwright.config.ts': ` + module.exports = { projects: [ + { name: \`calculated \$\{Date.now()\}\` }, + ] }; + `, + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + test('pass', async ({}, testInfo) => { + console.log(testInfo.project.name); + }); + ` + }); + expect(exitCode).toBe(1); + expect(output).toContain('not found in the worker process. Make sure project name does not change.'); +}); + test('should work without config file', async ({ runInlineTest }) => { const { exitCode, passed, failed, skipped } = await runInlineTest({ 'playwright.config.ts': `