diff --git a/docs/src/test-advanced.md b/docs/src/test-advanced.md index 5757fe3521..8e1763afa5 100644 --- a/docs/src/test-advanced.md +++ b/docs/src/test-advanced.md @@ -120,7 +120,7 @@ In addition to everything from the [`workerInfo`](#workerinfo), the following in - `annotations` - [Annotations](./test-annotations.md) that were added to the test. - `snapshotSuffix: string` - Suffix used to locate snapshots for the test. - `snapshotPath(snapshotName: string)` - Function that returns the full path to a particular snapshot for the test. -- `outputDir: string` - Absolute path to the output directory for this test run. +- `outputDir: string` - Path to the output directory for this test run. - `outputPath(...pathSegments: string[])` - Function that returns the full path to a particular output artifact for the test. The following information is accessible after the test body has finished, in fixture teardown: diff --git a/src/test/loader.ts b/src/test/loader.ts index 2bce2b68b9..d3e9a67db2 100644 --- a/src/test/loader.ts +++ b/src/test/loader.ts @@ -188,11 +188,13 @@ export class Loader { let testDir = takeFirst(projectConfig.testDir, rootDir); if (!path.isAbsolute(testDir)) testDir = path.resolve(rootDir, testDir); - + let outputDir = takeFirst(this._configOverrides.outputDir, projectConfig.outputDir, this._config.outputDir, path.resolve(process.cwd(), 'test-results')) + if (!path.isAbsolute(outputDir)) + outputDir = path.resolve(rootDir, outputDir); const fullProject: FullProject = { define: takeFirst(this._configOverrides.define, projectConfig.define, this._config.define, []), expect: takeFirst(this._configOverrides.expect, projectConfig.expect, this._config.expect, undefined), - outputDir: takeFirst(this._configOverrides.outputDir, projectConfig.outputDir, this._config.outputDir, path.resolve(process.cwd(), 'test-results')), + outputDir, repeatEach: takeFirst(this._configOverrides.repeatEach, projectConfig.repeatEach, this._config.repeatEach, 1), retries: takeFirst(this._configOverrides.retries, projectConfig.retries, this._config.retries, 0), metadata: takeFirst(this._configOverrides.metadata, projectConfig.metadata, this._config.metadata, undefined), @@ -347,8 +349,6 @@ function validateProject(project: Project, title: string) { if ('outputDir' in project && project.outputDir !== undefined) { if (typeof project.outputDir !== 'string') throw new Error(`${title}.outputDir must be a string`); - if (!path.isAbsolute(project.outputDir)) - throw new Error(`${title}.outputDir must be an absolute path`); } if ('repeatEach' in project && project.repeatEach !== undefined) { diff --git a/tests/playwright-test/playwright-test-fixtures.ts b/tests/playwright-test/playwright-test-fixtures.ts index 4b4b6dfc63..c11ef3b832 100644 --- a/tests/playwright-test/playwright-test-fixtures.ts +++ b/tests/playwright-test/playwright-test-fixtures.ts @@ -115,6 +115,8 @@ async function runPlaywrightTest(baseDir: string, params: any, env: Env): Promis additionalArgs = params[key]; continue; } + if (key === 'usesCustomOutputDir') + continue; for (const value of Array.isArray(params[key]) ? params[key] : [params[key]]) { const k = key.startsWith('-') ? key : '--' + key; paramList.push(params[key] === true ? `${k}` : `${k}=${value}`); @@ -123,8 +125,9 @@ async function runPlaywrightTest(baseDir: string, params: any, env: Env): Promis const outputDir = path.join(baseDir, 'test-results'); const reportFile = path.join(outputDir, 'report.json'); const args = [path.join(__dirname, '..', '..', 'lib', 'cli', 'cli.js'), 'test']; + if (!params.usesCustomOutputDir) + args.push('--output=' + outputDir) args.push( - '--output=' + outputDir, '--reporter=dot,json', '--workers=2', ...paramList diff --git a/tests/playwright-test/test-output-dir.spec.ts b/tests/playwright-test/test-output-dir.spec.ts index d31ff603af..67a80d4b8d 100644 --- a/tests/playwright-test/test-output-dir.spec.ts +++ b/tests/playwright-test/test-output-dir.spec.ts @@ -231,3 +231,21 @@ test('should not remove folders on non-CI', async ({ runInlineTest }, testInfo) expect(fs.existsSync(testInfo.outputPath('test-results', 'dir-my-test-test-1-retry1'))).toBe(true); expect(fs.existsSync(testInfo.outputPath('test-results', 'dir-my-test-test-1-retry2'))).toBe(true); }); + + +test('should accept a relative path for outputDir', async ({ runInlineTest }, testInfo) => { + const result = await runInlineTest({ + 'my-test.spec.js': ` + const { test } = pwt; + test('test', async ({}, testInfo) => { + expect(testInfo.outputDir).toBe(${JSON.stringify(path.join(testInfo.outputDir, './my-output-dir', 'my-test-test'))}); + }); + `, + 'playwright.config.js': ` + module.exports = { projects: [ + { outputDir: './my-output-dir' }, + ] }; + `, + }, {usesCustomOutputDir: true}); + expect(result.exitCode).toBe(0); +});