diff --git a/packages/playwright/src/common/config.ts b/packages/playwright/src/common/config.ts index f639876e3f..6077d70b7e 100644 --- a/packages/playwright/src/common/config.ts +++ b/packages/playwright/src/common/config.ts @@ -56,6 +56,7 @@ export class FullConfigInternal { testIdMatcher?: Matcher; defineConfigWasUsed = false; shardingMode: Exclude; + lastRunFile: string | undefined; lastRunInfo?: LastRunInfo; constructor(location: ConfigLocation, userConfig: Config, configCLIOverrides: ConfigCLIOverrides) { @@ -95,6 +96,7 @@ export class FullConfigInternal { webServer: null, }; this.shardingMode = takeFirst(configCLIOverrides.shardingMode, userConfig.shardingMode, 'partition'); + this.lastRunFile = configCLIOverrides.lastRunFile; for (const key in userConfig) { if (key.startsWith('@')) (this.config as any)[key] = (userConfig as any)[key]; diff --git a/packages/playwright/src/common/ipc.ts b/packages/playwright/src/common/ipc.ts index 127ec91343..8cf00e677b 100644 --- a/packages/playwright/src/common/ipc.ts +++ b/packages/playwright/src/common/ipc.ts @@ -33,6 +33,7 @@ export type ConfigCLIOverrides = { additionalReporters?: ReporterDescription[]; shard?: { current: number, total: number }; shardingMode?: PlaywrightTestConfig['shardingMode']; + lastRunFile?: string; timeout?: number; ignoreSnapshots?: boolean; updateSnapshots?: 'all'|'none'|'missing'; diff --git a/packages/playwright/src/program.ts b/packages/playwright/src/program.ts index 6ec378e696..285fb576d0 100644 --- a/packages/playwright/src/program.ts +++ b/packages/playwright/src/program.ts @@ -285,6 +285,7 @@ function overridesFromOptions(options: { [key: string]: any }): ConfigCLIOverrid reporter: resolveReporterOption(options.reporter), shard: shardPair ? { current: shardPair[0], total: shardPair[1] } : undefined, shardingMode: options.shardingMode ? options.shardingMode : undefined, + lastRunFile: options.lastRunFile ? path.resolve(process.cwd(), options.lastRunFile) : undefined, timeout: options.timeout ? parseInt(options.timeout, 10) : undefined, ignoreSnapshots: options.ignoreSnapshots ? !!options.ignoreSnapshots : undefined, updateSnapshots: options.updateSnapshots ? 'all' as const : undefined, @@ -351,6 +352,7 @@ const testOptions: [string, string][] = [ ['--headed', `Run tests in headed browsers (default: headless)`], ['--ignore-snapshots', `Ignore screenshot and snapshot expectations`], ['--last-failed', `Only re-run the failures`], + ['--last-run-file', `Path to a json file where the last run information is read from and written to (default: .last-run.json)`], ['--list', `Collect all the tests and report them, but do not run`], ['--max-failures ', `Stop after the first N failures`], ['--no-deps', 'Do not run project dependencies'], diff --git a/packages/playwright/src/runner/runner.ts b/packages/playwright/src/runner/runner.ts index aa17773876..06d752344e 100644 --- a/packages/playwright/src/runner/runner.ts +++ b/packages/playwright/src/runner/runner.ts @@ -160,8 +160,9 @@ async function writeLastRunInfo(testRun: TestRun, status: FullResult['status']) if (!project) return; const outputDir = project.project.outputDir; - await fs.promises.mkdir(outputDir, { recursive: true }); - const lastRunReportFile = path.join(outputDir, '.last-run.json'); + const lastRunReportFile = testRun.config.lastRunFile || path.join(outputDir, '.last-run.json'); + const lastRunReportFileDir = path.dirname(lastRunReportFile); + await fs.promises.mkdir(lastRunReportFileDir, { recursive: true }); const failedTests = testRun.rootSuite?.allTests().filter(t => !t.ok()).map(t => t.id); const testDurations = testRun.rootSuite?.allTests().reduce((map, t) => { if (t.results.length) @@ -178,7 +179,7 @@ export async function readLastRunInfo(config: FullConfigInternal): Promise