Store configCLIOptions in test server

This commit is contained in:
Yury Semikhatsky 2024-09-24 18:32:12 -07:00
parent 3af53a70d0
commit 79ca5f3d36
5 changed files with 22 additions and 43 deletions

View file

@ -46,9 +46,7 @@ export type TraceViewerRedirectOptions = {
reporter?: string[]; reporter?: string[];
webApp?: string; webApp?: string;
isServer?: boolean; isServer?: boolean;
outputDir?: string;
updateSnapshots?: 'all' | 'none' | 'missing'; updateSnapshots?: 'all' | 'none' | 'missing';
tsconfig?: string;
}; };
export type TraceViewerAppOptions = { export type TraceViewerAppOptions = {
@ -134,12 +132,8 @@ export async function installRootRedirect(server: HttpServer, traceUrls: string[
params.append('timeout', String(options.timeout)); params.append('timeout', String(options.timeout));
if (options.headed) if (options.headed)
params.append('headed', ''); params.append('headed', '');
if (options.outputDir)
params.append('outputDir', options.outputDir);
if (options.updateSnapshots) if (options.updateSnapshots)
params.append('updateSnapshots', options.updateSnapshots); params.append('updateSnapshots', options.updateSnapshots);
if (options.tsconfig)
params.append('tsconfig', options.tsconfig);
for (const reporter of options.reporter || []) for (const reporter of options.reporter || [])
params.append('reporter', reporter); params.append('reporter', reporter);

View file

@ -45,7 +45,7 @@ export interface TestServerInterface {
installBrowsers(params: {}): Promise<void>; installBrowsers(params: {}): Promise<void>;
runGlobalSetup(params: { outputDir?: string, tsconfig?: string }): Promise<{ runGlobalSetup(params: {}): Promise<{
report: ReportEntry[], report: ReportEntry[],
status: reporterTypes.FullResult['status'] status: reporterTypes.FullResult['status']
}>; }>;
@ -82,8 +82,6 @@ export interface TestServerInterface {
locations?: string[]; locations?: string[];
grep?: string; grep?: string;
grepInvert?: string; grepInvert?: string;
outputDir?: string;
tsconfig?: string;
}): Promise<{ }): Promise<{
report: ReportEntry[], report: ReportEntry[],
status: reporterTypes.FullResult['status'] status: reporterTypes.FullResult['status']
@ -97,9 +95,7 @@ export interface TestServerInterface {
headed?: boolean; headed?: boolean;
workers?: number | string; workers?: number | string;
timeout?: number, timeout?: number,
outputDir?: string;
updateSnapshots?: 'all' | 'none' | 'missing'; updateSnapshots?: 'all' | 'none' | 'missing';
tsconfig?: string;
reporters?: string[], reporters?: string[],
trace?: 'on' | 'off'; trace?: 'on' | 'off';
video?: 'on' | 'off'; video?: 'on' | 'off';

View file

@ -161,7 +161,7 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
if (opts.onlyChanged) 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.`); 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, host: opts.uiHost,
port: opts.uiPort ? +opts.uiPort : undefined, port: opts.uiPort ? +opts.uiPort : undefined,
args, args,
@ -172,9 +172,7 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
reporter: Array.isArray(opts.reporter) ? opts.reporter : opts.reporter ? [opts.reporter] : undefined, reporter: Array.isArray(opts.reporter) ? opts.reporter : opts.reporter ? [opts.reporter] : undefined,
workers: cliOverrides.workers, workers: cliOverrides.workers,
timeout: cliOverrides.timeout, timeout: cliOverrides.timeout,
outputDir: cliOverrides.outputDir,
updateSnapshots: cliOverrides.updateSnapshots, updateSnapshots: cliOverrides.updateSnapshots,
tsconfig: cliOverrides.tsconfig,
}); });
await stopProfiling('runner'); await stopProfiling('runner');
if (status === 'restarted') if (status === 'restarted')
@ -228,7 +226,7 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
async function runTestServer(opts: { [key: string]: any }) { async function runTestServer(opts: { [key: string]: any }) {
const host = opts.host || 'localhost'; const host = opts.host || 'localhost';
const port = opts.port ? +opts.port : 0; 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') if (status === 'restarted')
return; return;
const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1); const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1);

View file

@ -44,14 +44,16 @@ const originalStderrWrite = process.stderr.write;
class TestServer { class TestServer {
private _configLocation: ConfigLocation; private _configLocation: ConfigLocation;
private _configCLIOverrides: ConfigCLIOverrides;
private _dispatcher: TestServerDispatcher | undefined; private _dispatcher: TestServerDispatcher | undefined;
constructor(configLocation: ConfigLocation) { constructor(configLocation: ConfigLocation, configCLIOverrides: ConfigCLIOverrides) {
this._configLocation = configLocation; this._configLocation = configLocation;
this._configCLIOverrides = configCLIOverrides;
} }
async start(options: { host?: string, port?: number }): Promise<HttpServer> { async start(options: { host?: string, port?: number }): Promise<HttpServer> {
this._dispatcher = new TestServerDispatcher(this._configLocation); this._dispatcher = new TestServerDispatcher(this._configLocation, this._configCLIOverrides);
return await startTraceViewerServer({ ...options, transport: this._dispatcher.transport }); return await startTraceViewerServer({ ...options, transport: this._dispatcher.transport });
} }
@ -63,6 +65,7 @@ class TestServer {
export class TestServerDispatcher implements TestServerInterface { export class TestServerDispatcher implements TestServerInterface {
private _configLocation: ConfigLocation; private _configLocation: ConfigLocation;
private _configCLIOverrides: ConfigCLIOverrides;
private _watcher: Watcher; private _watcher: Watcher;
private _watchedProjectDirs = new Set<string>(); private _watchedProjectDirs = new Set<string>();
@ -81,8 +84,9 @@ export class TestServerDispatcher implements TestServerInterface {
private _closeOnDisconnect = false; private _closeOnDisconnect = false;
private _populateDependenciesOnList = false; private _populateDependenciesOnList = false;
constructor(configLocation: ConfigLocation) { constructor(configLocation: ConfigLocation, configCLIOverrides: ConfigCLIOverrides) {
this._configLocation = configLocation; this._configLocation = configLocation;
this._configCLIOverrides = configCLIOverrides;
this.transport = { this.transport = {
onconnect: () => {}, onconnect: () => {},
dispatch: (method, params) => (this as any)[method](params), dispatch: (method, params) => (this as any)[method](params),
@ -145,12 +149,8 @@ export class TestServerDispatcher implements TestServerInterface {
async runGlobalSetup(params: Parameters<TestServerInterface['runGlobalSetup']>[0]): ReturnType<TestServerInterface['runGlobalSetup']> { async runGlobalSetup(params: Parameters<TestServerInterface['runGlobalSetup']>[0]): ReturnType<TestServerInterface['runGlobalSetup']> {
await this.runGlobalTeardown(); await this.runGlobalTeardown();
const overrides: ConfigCLIOverrides = {
outputDir: params.outputDir,
tsconfig: params.tsconfig,
};
const { reporter, report } = await this._collectingInternalReporter(new ListReporter()); 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) if (!config)
return { status: 'failed', report }; return { status: 'failed', report };
@ -240,10 +240,9 @@ export class TestServerDispatcher implements TestServerInterface {
config?: FullConfigInternal, config?: FullConfigInternal,
}> { }> {
const overrides: ConfigCLIOverrides = { const overrides: ConfigCLIOverrides = {
...this._configCLIOverrides,
repeatEach: 1, repeatEach: 1,
retries: 0, retries: 0,
outputDir: params.outputDir,
tsconfig: params.tsconfig,
}; };
const { reporter, report } = await this._collectingInternalReporter(); const { reporter, report } = await this._collectingInternalReporter();
const config = await this._loadConfigOrReportError(reporter, overrides); const config = await this._loadConfigOrReportError(reporter, overrides);
@ -297,6 +296,7 @@ export class TestServerDispatcher implements TestServerInterface {
private async _innerRunTests(params: Parameters<TestServerInterface['runTests']>[0]): ReturnType<TestServerInterface['runTests']> { private async _innerRunTests(params: Parameters<TestServerInterface['runTests']>[0]): ReturnType<TestServerInterface['runTests']> {
await this.stopTests(); await this.stopTests();
const overrides: ConfigCLIOverrides = { const overrides: ConfigCLIOverrides = {
...this._configCLIOverrides,
repeatEach: 1, repeatEach: 1,
retries: 0, retries: 0,
preserveOutputDir: true, preserveOutputDir: true,
@ -309,8 +309,6 @@ export class TestServerDispatcher implements TestServerInterface {
_optionContextReuseMode: params.reuseContext ? 'when-possible' : undefined, _optionContextReuseMode: params.reuseContext ? 'when-possible' : undefined,
_optionConnectOptions: params.connectWsEndpoint ? { wsEndpoint: params.connectWsEndpoint } : undefined, _optionConnectOptions: params.connectWsEndpoint ? { wsEndpoint: params.connectWsEndpoint } : undefined,
}, },
outputDir: params.outputDir,
tsconfig: params.tsconfig,
updateSnapshots: params.updateSnapshots, updateSnapshots: params.updateSnapshots,
workers: params.workers, workers: params.workers,
}; };
@ -427,9 +425,9 @@ export class TestServerDispatcher implements TestServerInterface {
} }
} }
export async function runUIMode(configFile: string | undefined, options: TraceViewerServerOptions & TraceViewerRedirectOptions): Promise<reporterTypes.FullResult['status'] | 'restarted'> { export async function runUIMode(configFile: string | undefined, configCLIOverrides: ConfigCLIOverrides, options: TraceViewerServerOptions & TraceViewerRedirectOptions): Promise<reporterTypes.FullResult['status'] | 'restarted'> {
const configLocation = resolveConfigLocation(configFile); const configLocation = resolveConfigLocation(configFile);
return await innerRunTestServer(configLocation, options, async (server: HttpServer, cancelPromise: ManualPromise<void>) => { return await innerRunTestServer(configLocation, configCLIOverrides, options, async (server: HttpServer, cancelPromise: ManualPromise<void>) => {
await installRootRedirect(server, [], { ...options, webApp: 'uiMode.html' }); await installRootRedirect(server, [], { ...options, webApp: 'uiMode.html' });
if (options.host !== undefined || options.port !== undefined) { if (options.host !== undefined || options.port !== undefined) {
await openTraceInBrowser(server.urlPrefix('human-readable')); await openTraceInBrowser(server.urlPrefix('human-readable'));
@ -445,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<reporterTypes.FullResult['status'] | 'restarted'> { export async function runTestServer(configFile: string | undefined, configCLIOverrides: ConfigCLIOverrides, options: { host?: string, port?: number }): Promise<reporterTypes.FullResult['status'] | 'restarted'> {
const configLocation = resolveConfigLocation(configFile); 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 // eslint-disable-next-line no-console
console.log('Listening on ' + server.urlPrefix('precise').replace('http:', 'ws:') + '/' + server.wsGuid()); 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<void>, configLocation: ConfigLocation) => Promise<void>): Promise<reporterTypes.FullResult['status'] | 'restarted'> { async function innerRunTestServer(configLocation: ConfigLocation, configCLIOverrides: ConfigCLIOverrides, options: { host?: string, port?: number }, openUI: (server: HttpServer, cancelPromise: ManualPromise<void>, configLocation: ConfigLocation) => Promise<void>): Promise<reporterTypes.FullResult['status'] | 'restarted'> {
if (restartWithExperimentalTsEsm(undefined, true)) if (restartWithExperimentalTsEsm(undefined, true))
return 'restarted'; return 'restarted';
const testServer = new TestServer(configLocation); const testServer = new TestServer(configLocation, configCLIOverrides);
const cancelPromise = new ManualPromise<void>(); const cancelPromise = new ManualPromise<void>();
const sigintWatcher = new SigIntWatcher(); const sigintWatcher = new SigIntWatcher();
process.stdin.on('close', () => gracefullyProcessExitDoNotHang(0)); process.stdin.on('close', () => gracefullyProcessExitDoNotHang(0));

View file

@ -58,11 +58,9 @@ const queryParams = {
workers: searchParams.get('workers') || undefined, workers: searchParams.get('workers') || undefined,
timeout: searchParams.has('timeout') ? +searchParams.get('timeout')! : undefined, timeout: searchParams.has('timeout') ? +searchParams.get('timeout')! : undefined,
headed: searchParams.has('headed'), headed: searchParams.has('headed'),
outputDir: searchParams.get('outputDir') || undefined,
updateSnapshots: (searchParams.get('updateSnapshots') as 'all' | 'none' | 'missing' | undefined) || undefined, updateSnapshots: (searchParams.get('updateSnapshots') as 'all' | 'none' | 'missing' | undefined) || undefined,
reporters: searchParams.has('reporter') ? searchParams.getAll('reporter') : undefined, reporters: searchParams.has('reporter') ? searchParams.getAll('reporter') : undefined,
pathSeparator: searchParams.get('pathSeparator') || '/', pathSeparator: searchParams.get('pathSeparator') || '/',
tsconfig: searchParams.get('tsconfig') || undefined,
}; };
if (queryParams.updateSnapshots && !['all', 'none', 'missing'].includes(queryParams.updateSnapshots)) if (queryParams.updateSnapshots && !['all', 'none', 'missing'].includes(queryParams.updateSnapshots))
queryParams.updateSnapshots = undefined; queryParams.updateSnapshots = undefined;
@ -188,15 +186,12 @@ export const UIModeView: React.FC<{}> = ({
interceptStdio: true, interceptStdio: true,
watchTestDirs: true watchTestDirs: true
}); });
const { status, report } = await testServerConnection.runGlobalSetup({ const { status, report } = await testServerConnection.runGlobalSetup({});
outputDir: queryParams.outputDir,
tsconfig: queryParams.tsconfig,
});
teleSuiteUpdater.processGlobalReport(report); teleSuiteUpdater.processGlobalReport(report);
if (status !== 'passed') if (status !== 'passed')
return; return;
const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert, outputDir: queryParams.outputDir, tsconfig: queryParams.tsconfig }); const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert });
teleSuiteUpdater.processListReport(result.report); teleSuiteUpdater.processListReport(result.report);
testServerConnection.onReport(params => { testServerConnection.onReport(params => {
@ -298,11 +293,9 @@ export const UIModeView: React.FC<{}> = ({
workers: singleWorker ? '1' : (queryParams.workers === '1' ? undefined : queryParams.workers), workers: singleWorker ? '1' : (queryParams.workers === '1' ? undefined : queryParams.workers),
timeout: queryParams.timeout, timeout: queryParams.timeout,
headed: showBrowser, headed: showBrowser,
outputDir: queryParams.outputDir,
updateSnapshots: updateSnapshots ? 'all' : queryParams.updateSnapshots, updateSnapshots: updateSnapshots ? 'all' : queryParams.updateSnapshots,
reporters: queryParams.reporters, reporters: queryParams.reporters,
trace: 'on', trace: 'on',
tsconfig: queryParams.tsconfig,
}); });
// Clear pending tests in case of interrupt. // Clear pending tests in case of interrupt.
for (const test of testModel.rootSuite?.allTests() || []) { for (const test of testModel.rootSuite?.allTests() || []) {
@ -322,7 +315,7 @@ export const UIModeView: React.FC<{}> = ({
commandQueue.current = commandQueue.current.then(async () => { commandQueue.current = commandQueue.current.then(async () => {
setIsLoading(true); setIsLoading(true);
try { try {
const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert, outputDir: queryParams.outputDir, tsconfig: queryParams.tsconfig }); const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert });
teleSuiteUpdater.processListReport(result.report); teleSuiteUpdater.processListReport(result.report);
} catch (e) { } catch (e) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console