diff --git a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts index ee2ccac593..6d45e7c6f5 100644 --- a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts +++ b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts @@ -46,7 +46,6 @@ export type TraceViewerRedirectOptions = { reporter?: string[]; webApp?: string; isServer?: boolean; - outputDir?: string; updateSnapshots?: 'all' | 'none' | 'missing'; }; @@ -133,8 +132,6 @@ export async function installRootRedirect(server: HttpServer, traceUrls: string[ params.append('timeout', String(options.timeout)); if (options.headed) params.append('headed', ''); - if (options.outputDir) - params.append('outputDir', options.outputDir); if (options.updateSnapshots) params.append('updateSnapshots', options.updateSnapshots); for (const reporter of options.reporter || []) diff --git a/packages/playwright/src/isomorphic/testServerInterface.ts b/packages/playwright/src/isomorphic/testServerInterface.ts index 22cb9e35ef..ce1c1888d5 100644 --- a/packages/playwright/src/isomorphic/testServerInterface.ts +++ b/packages/playwright/src/isomorphic/testServerInterface.ts @@ -45,7 +45,7 @@ export interface TestServerInterface { installBrowsers(params: {}): Promise; - runGlobalSetup(params: { outputDir?: string }): Promise<{ + runGlobalSetup(params: {}): Promise<{ report: ReportEntry[], status: reporterTypes.FullResult['status'] }>; @@ -82,7 +82,6 @@ export interface TestServerInterface { locations?: string[]; grep?: string; grepInvert?: string; - outputDir?: string; }): Promise<{ report: ReportEntry[], status: reporterTypes.FullResult['status'] @@ -96,7 +95,6 @@ export interface TestServerInterface { headed?: boolean; workers?: number | string; timeout?: number, - outputDir?: string; updateSnapshots?: 'all' | 'none' | 'missing'; reporters?: string[], trace?: 'on' | 'off'; diff --git a/packages/playwright/src/program.ts b/packages/playwright/src/program.ts index 775ef27065..136606b26c 100644 --- a/packages/playwright/src/program.ts +++ b/packages/playwright/src/program.ts @@ -161,7 +161,7 @@ async function runTests(args: string[], opts: { [key: string]: any }) { if (opts.onlyChanged) throw new Error(`--only-changed is not supported in UI mode. If you'd like that to change, see https://github.com/microsoft/playwright/issues/15075 for more details.`); - const status = await testServer.runUIMode(opts.config, { + const status = await testServer.runUIMode(opts.config, cliOverrides, { host: opts.uiHost, port: opts.uiPort ? +opts.uiPort : undefined, args, @@ -172,7 +172,6 @@ async function runTests(args: string[], opts: { [key: string]: any }) { reporter: Array.isArray(opts.reporter) ? opts.reporter : opts.reporter ? [opts.reporter] : undefined, workers: cliOverrides.workers, timeout: cliOverrides.timeout, - outputDir: cliOverrides.outputDir, updateSnapshots: cliOverrides.updateSnapshots, }); await stopProfiling('runner'); @@ -227,7 +226,7 @@ async function runTests(args: string[], opts: { [key: string]: any }) { async function runTestServer(opts: { [key: string]: any }) { const host = opts.host || 'localhost'; const port = opts.port ? +opts.port : 0; - const status = await testServer.runTestServer(opts.config, { host, port }); + const status = await testServer.runTestServer(opts.config, { }, { host, port }); if (status === 'restarted') return; const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1); diff --git a/packages/playwright/src/runner/testServer.ts b/packages/playwright/src/runner/testServer.ts index d4433b2d85..ee3cefaac4 100644 --- a/packages/playwright/src/runner/testServer.ts +++ b/packages/playwright/src/runner/testServer.ts @@ -44,14 +44,16 @@ const originalStderrWrite = process.stderr.write; class TestServer { private _configLocation: ConfigLocation; + private _configCLIOverrides: ConfigCLIOverrides; private _dispatcher: TestServerDispatcher | undefined; - constructor(configLocation: ConfigLocation) { + constructor(configLocation: ConfigLocation, configCLIOverrides: ConfigCLIOverrides) { this._configLocation = configLocation; + this._configCLIOverrides = configCLIOverrides; } async start(options: { host?: string, port?: number }): Promise { - this._dispatcher = new TestServerDispatcher(this._configLocation); + this._dispatcher = new TestServerDispatcher(this._configLocation, this._configCLIOverrides); return await startTraceViewerServer({ ...options, transport: this._dispatcher.transport }); } @@ -63,6 +65,7 @@ class TestServer { export class TestServerDispatcher implements TestServerInterface { private _configLocation: ConfigLocation; + private _configCLIOverrides: ConfigCLIOverrides; private _watcher: Watcher; private _watchedProjectDirs = new Set(); @@ -81,8 +84,9 @@ export class TestServerDispatcher implements TestServerInterface { private _closeOnDisconnect = false; private _populateDependenciesOnList = false; - constructor(configLocation: ConfigLocation) { + constructor(configLocation: ConfigLocation, configCLIOverrides: ConfigCLIOverrides) { this._configLocation = configLocation; + this._configCLIOverrides = configCLIOverrides; this.transport = { onconnect: () => {}, dispatch: (method, params) => (this as any)[method](params), @@ -145,11 +149,8 @@ export class TestServerDispatcher implements TestServerInterface { async runGlobalSetup(params: Parameters[0]): ReturnType { await this.runGlobalTeardown(); - const overrides: ConfigCLIOverrides = { - outputDir: params.outputDir, - }; const { reporter, report } = await this._collectingInternalReporter(new ListReporter()); - const config = await this._loadConfigOrReportError(reporter, overrides); + const config = await this._loadConfigOrReportError(reporter, this._configCLIOverrides); if (!config) return { status: 'failed', report }; @@ -239,9 +240,9 @@ export class TestServerDispatcher implements TestServerInterface { config?: FullConfigInternal, }> { const overrides: ConfigCLIOverrides = { + ...this._configCLIOverrides, repeatEach: 1, retries: 0, - outputDir: params.outputDir, }; const { reporter, report } = await this._collectingInternalReporter(); const config = await this._loadConfigOrReportError(reporter, overrides); @@ -295,6 +296,7 @@ export class TestServerDispatcher implements TestServerInterface { private async _innerRunTests(params: Parameters[0]): ReturnType { await this.stopTests(); const overrides: ConfigCLIOverrides = { + ...this._configCLIOverrides, repeatEach: 1, retries: 0, preserveOutputDir: true, @@ -307,7 +309,6 @@ export class TestServerDispatcher implements TestServerInterface { _optionContextReuseMode: params.reuseContext ? 'when-possible' : undefined, _optionConnectOptions: params.connectWsEndpoint ? { wsEndpoint: params.connectWsEndpoint } : undefined, }, - outputDir: params.outputDir, updateSnapshots: params.updateSnapshots, workers: params.workers, }; @@ -424,9 +425,9 @@ export class TestServerDispatcher implements TestServerInterface { } } -export async function runUIMode(configFile: string | undefined, options: TraceViewerServerOptions & TraceViewerRedirectOptions): Promise { +export async function runUIMode(configFile: string | undefined, configCLIOverrides: ConfigCLIOverrides, options: TraceViewerServerOptions & TraceViewerRedirectOptions): Promise { const configLocation = resolveConfigLocation(configFile); - return await innerRunTestServer(configLocation, options, async (server: HttpServer, cancelPromise: ManualPromise) => { + return await innerRunTestServer(configLocation, configCLIOverrides, options, async (server: HttpServer, cancelPromise: ManualPromise) => { await installRootRedirect(server, [], { ...options, webApp: 'uiMode.html' }); if (options.host !== undefined || options.port !== undefined) { await openTraceInBrowser(server.urlPrefix('human-readable')); @@ -442,18 +443,18 @@ export async function runUIMode(configFile: string | undefined, options: TraceVi }); } -export async function runTestServer(configFile: string | undefined, options: { host?: string, port?: number }): Promise { +export async function runTestServer(configFile: string | undefined, configCLIOverrides: ConfigCLIOverrides, options: { host?: string, port?: number }): Promise { const configLocation = resolveConfigLocation(configFile); - return await innerRunTestServer(configLocation, options, async server => { + return await innerRunTestServer(configLocation, configCLIOverrides, options, async server => { // eslint-disable-next-line no-console console.log('Listening on ' + server.urlPrefix('precise').replace('http:', 'ws:') + '/' + server.wsGuid()); }); } -async function innerRunTestServer(configLocation: ConfigLocation, options: { host?: string, port?: number }, openUI: (server: HttpServer, cancelPromise: ManualPromise, configLocation: ConfigLocation) => Promise): Promise { +async function innerRunTestServer(configLocation: ConfigLocation, configCLIOverrides: ConfigCLIOverrides, options: { host?: string, port?: number }, openUI: (server: HttpServer, cancelPromise: ManualPromise, configLocation: ConfigLocation) => Promise): Promise { if (restartWithExperimentalTsEsm(undefined, true)) return 'restarted'; - const testServer = new TestServer(configLocation); + const testServer = new TestServer(configLocation, configCLIOverrides); const cancelPromise = new ManualPromise(); const sigintWatcher = new SigIntWatcher(); process.stdin.on('close', () => gracefullyProcessExitDoNotHang(0)); diff --git a/packages/playwright/src/runner/watchMode.ts b/packages/playwright/src/runner/watchMode.ts index 2a2c9802f1..bdbe2d5c2d 100644 --- a/packages/playwright/src/runner/watchMode.ts +++ b/packages/playwright/src/runner/watchMode.ts @@ -75,7 +75,7 @@ export async function runWatchModeLoop(configLocation: ConfigLocation, initialOp const options: WatchModeOptions = { ...initialOptions }; let bufferMode = false; - const testServerDispatcher = new TestServerDispatcher(configLocation); + const testServerDispatcher = new TestServerDispatcher(configLocation, {}); const transport = new InMemoryTransport( async data => { const { id, method, params } = JSON.parse(data); diff --git a/packages/trace-viewer/src/ui/uiModeView.tsx b/packages/trace-viewer/src/ui/uiModeView.tsx index ba74e60092..5c6ab7969b 100644 --- a/packages/trace-viewer/src/ui/uiModeView.tsx +++ b/packages/trace-viewer/src/ui/uiModeView.tsx @@ -58,7 +58,6 @@ const queryParams = { workers: searchParams.get('workers') || undefined, timeout: searchParams.has('timeout') ? +searchParams.get('timeout')! : undefined, headed: searchParams.has('headed'), - outputDir: searchParams.get('outputDir') || undefined, updateSnapshots: (searchParams.get('updateSnapshots') as 'all' | 'none' | 'missing' | undefined) || undefined, reporters: searchParams.has('reporter') ? searchParams.getAll('reporter') : undefined, pathSeparator: searchParams.get('pathSeparator') || '/', @@ -187,14 +186,12 @@ export const UIModeView: React.FC<{}> = ({ interceptStdio: true, watchTestDirs: true }); - const { status, report } = await testServerConnection.runGlobalSetup({ - outputDir: queryParams.outputDir, - }); + const { status, report } = await testServerConnection.runGlobalSetup({}); teleSuiteUpdater.processGlobalReport(report); if (status !== 'passed') return; - const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert, outputDir: queryParams.outputDir }); + const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert }); teleSuiteUpdater.processListReport(result.report); testServerConnection.onReport(params => { @@ -296,7 +293,6 @@ export const UIModeView: React.FC<{}> = ({ workers: singleWorker ? '1' : (queryParams.workers === '1' ? undefined : queryParams.workers), timeout: queryParams.timeout, headed: showBrowser, - outputDir: queryParams.outputDir, updateSnapshots: updateSnapshots ? 'all' : queryParams.updateSnapshots, reporters: queryParams.reporters, trace: 'on', @@ -319,7 +315,7 @@ export const UIModeView: React.FC<{}> = ({ commandQueue.current = commandQueue.current.then(async () => { setIsLoading(true); try { - const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert, outputDir: queryParams.outputDir }); + const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert }); teleSuiteUpdater.processListReport(result.report); } catch (e) { // eslint-disable-next-line no-console diff --git a/tests/playwright-test/ui-mode-test-run.spec.ts b/tests/playwright-test/ui-mode-test-run.spec.ts index 9c1120ea04..81316f42ee 100644 --- a/tests/playwright-test/ui-mode-test-run.spec.ts +++ b/tests/playwright-test/ui-mode-test-run.spec.ts @@ -444,3 +444,62 @@ test('should show proper total when using deps', async ({ runUITest }) => { `); await expect(page.getByTestId('status-line')).toHaveText('2/2 passed (100%)'); }); + +test('should respect --tsconfig option', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32797' } +}, async ({ runUITest }) => { + const { page } = await runUITest({ + 'playwright.config.ts': ` + import { foo } from '~/foo'; + export default { + testDir: './tests' + foo, + }; + `, + 'tsconfig.json': `{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "~/*": ["./does-not-exist/*"], + }, + }, + }`, + 'tsconfig.special.json': `{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "~/*": ["./mapped-from-root/*"], + }, + }, + }`, + 'mapped-from-root/foo.ts': ` + export const foo = 42; + `, + 'tests42/tsconfig.json': `{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "~/*": ["../should-be-ignored/*"], + }, + }, + }`, + 'tests42/a.test.ts': ` + import { foo } from '~/foo'; + import { test, expect } from '@playwright/test'; + test('test', ({}) => { + expect(foo).toBe(42); + }); + `, + 'should-be-ignored/foo.ts': ` + export const foo = 43; + `, + }, undefined, { additionalArgs: ['--tsconfig=tsconfig.special.json'] }); + + await page.getByTitle('Run all').click(); + + await expect.poll(dumpTestTree(page)).toBe(` + ▼ ✅ a.test.ts + ✅ test + `); + + await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); +}); \ No newline at end of file