mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: opt into stdio forwarding (#30185)
This commit is contained in:
parent
a950a7b86b
commit
7afd4170ea
@ -115,11 +115,11 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
|
||||
}
|
||||
|
||||
async ping(params: Parameters<TestServerInterface['ping']>[0]): ReturnType<TestServerInterface['ping']> {
|
||||
await this._sendMessage('ping');
|
||||
await this._sendMessage('ping', params);
|
||||
}
|
||||
|
||||
async pingNoReply(params: Parameters<TestServerInterface['ping']>[0]) {
|
||||
this._sendMessageNoReply('ping');
|
||||
this._sendMessageNoReply('ping', params);
|
||||
}
|
||||
|
||||
async watch(params: Parameters<TestServerInterface['watch']>[0]): ReturnType<TestServerInterface['watch']> {
|
||||
@ -151,19 +151,19 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
|
||||
}
|
||||
|
||||
async checkBrowsers(params: Parameters<TestServerInterface['checkBrowsers']>[0]): ReturnType<TestServerInterface['checkBrowsers']> {
|
||||
return await this._sendMessage('checkBrowsers');
|
||||
return await this._sendMessage('checkBrowsers', params);
|
||||
}
|
||||
|
||||
async installBrowsers(params: Parameters<TestServerInterface['installBrowsers']>[0]): ReturnType<TestServerInterface['installBrowsers']> {
|
||||
await this._sendMessage('installBrowsers');
|
||||
await this._sendMessage('installBrowsers', params);
|
||||
}
|
||||
|
||||
async runGlobalSetup(params: Parameters<TestServerInterface['runGlobalSetup']>[0]): ReturnType<TestServerInterface['runGlobalSetup']> {
|
||||
return await this._sendMessage('runGlobalSetup');
|
||||
return await this._sendMessage('runGlobalSetup', params);
|
||||
}
|
||||
|
||||
async runGlobalTeardown(params: Parameters<TestServerInterface['runGlobalTeardown']>[0]): ReturnType<TestServerInterface['runGlobalTeardown']> {
|
||||
return await this._sendMessage('runGlobalTeardown');
|
||||
return await this._sendMessage('runGlobalTeardown', params);
|
||||
}
|
||||
|
||||
async listFiles(params: Parameters<TestServerInterface['listFiles']>[0]): ReturnType<TestServerInterface['listFiles']> {
|
||||
@ -183,14 +183,18 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
|
||||
}
|
||||
|
||||
async stopTests(params: Parameters<TestServerInterface['stopTests']>[0]): ReturnType<TestServerInterface['stopTests']> {
|
||||
await this._sendMessage('stopTests');
|
||||
await this._sendMessage('stopTests', params);
|
||||
}
|
||||
|
||||
stopTestsNoReply(params: Parameters<TestServerInterface['stopTests']>[0]) {
|
||||
this._sendMessageNoReply('stopTests');
|
||||
this._sendMessageNoReply('stopTests', params);
|
||||
}
|
||||
|
||||
async setInterceptStdio(params: Parameters<TestServerInterface['setInterceptStdio']>[0]): ReturnType<TestServerInterface['setInterceptStdio']> {
|
||||
await this._sendMessage('setInterceptStdio', params);
|
||||
}
|
||||
|
||||
async closeGracefully(params: Parameters<TestServerInterface['closeGracefully']>[0]): ReturnType<TestServerInterface['closeGracefully']> {
|
||||
await this._sendMessage('closeGracefully');
|
||||
await this._sendMessage('closeGracefully', params);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,6 +90,8 @@ export interface TestServerInterface {
|
||||
|
||||
stopTests(params: {}): Promise<void>;
|
||||
|
||||
setInterceptStdio(params: { intercept: boolean }): Promise<void>;
|
||||
|
||||
closeGracefully(params: {}): Promise<void>;
|
||||
}
|
||||
|
||||
|
||||
@ -169,6 +169,8 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
|
||||
timeout: cliOverrides.timeout,
|
||||
});
|
||||
await stopProfiling('runner');
|
||||
if (status === 'restarted')
|
||||
return;
|
||||
const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1);
|
||||
gracefullyProcessExitDoNotHang(exitCode);
|
||||
return;
|
||||
@ -200,6 +202,8 @@ 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 });
|
||||
if (status === 'restarted')
|
||||
return;
|
||||
const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1);
|
||||
gracefullyProcessExitDoNotHang(exitCode);
|
||||
}
|
||||
|
||||
@ -39,16 +39,15 @@ import type { TraceViewerRedirectOptions, TraceViewerServerOptions } from 'playw
|
||||
import type { TestRunnerPluginRegistration } from '../plugins';
|
||||
import { serializeError } from '../util';
|
||||
|
||||
const originalStdoutWrite = process.stdout.write;
|
||||
const originalStderrWrite = process.stderr.write;
|
||||
|
||||
class TestServer {
|
||||
private _configFile: string | undefined;
|
||||
private _dispatcher: TestServerDispatcher | undefined;
|
||||
private _originalStdoutWrite: NodeJS.WriteStream['write'];
|
||||
private _originalStderrWrite: NodeJS.WriteStream['write'];
|
||||
|
||||
constructor(configFile: string | undefined) {
|
||||
this._configFile = configFile;
|
||||
this._originalStdoutWrite = process.stdout.write;
|
||||
this._originalStderrWrite = process.stderr.write;
|
||||
}
|
||||
|
||||
async start(options: { host?: string, port?: number }): Promise<HttpServer> {
|
||||
@ -57,28 +56,9 @@ class TestServer {
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await this._dispatcher?.setInterceptStdio({ intercept: false });
|
||||
await this._dispatcher?.runGlobalTeardown();
|
||||
}
|
||||
|
||||
wireStdIO() {
|
||||
if (!process.env.PWTEST_DEBUG) {
|
||||
process.stdout.write = (chunk: string | Buffer) => {
|
||||
this._dispatcher?._dispatchEvent('stdio', chunkToPayload('stdout', chunk));
|
||||
return true;
|
||||
};
|
||||
process.stderr.write = (chunk: string | Buffer) => {
|
||||
this._dispatcher?._dispatchEvent('stdio', chunkToPayload('stderr', chunk));
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
unwireStdIO() {
|
||||
if (!process.env.PWTEST_DEBUG) {
|
||||
process.stdout.write = this._originalStdoutWrite;
|
||||
process.stderr.write = this._originalStderrWrite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestServerDispatcher implements TestServerInterface {
|
||||
@ -341,6 +321,24 @@ class TestServerDispatcher implements TestServerInterface {
|
||||
await this._testRun?.run;
|
||||
}
|
||||
|
||||
async setInterceptStdio(params: Parameters<TestServerInterface['setInterceptStdio']>[0]): ReturnType<TestServerInterface['setInterceptStdio']> {
|
||||
if (process.env.PWTEST_DEBUG)
|
||||
return;
|
||||
if (params.intercept) {
|
||||
process.stdout.write = (chunk: string | Buffer) => {
|
||||
this._dispatchEvent('stdio', chunkToPayload('stdout', chunk));
|
||||
return true;
|
||||
};
|
||||
process.stderr.write = (chunk: string | Buffer) => {
|
||||
this._dispatchEvent('stdio', chunkToPayload('stderr', chunk));
|
||||
return true;
|
||||
};
|
||||
} else {
|
||||
process.stdout.write = originalStdoutWrite;
|
||||
process.stderr.write = originalStderrWrite;
|
||||
}
|
||||
}
|
||||
|
||||
async closeGracefully() {
|
||||
gracefullyProcessExitDoNotHang(0);
|
||||
}
|
||||
@ -362,7 +360,7 @@ class TestServerDispatcher implements TestServerInterface {
|
||||
}
|
||||
}
|
||||
|
||||
export async function runUIMode(configFile: string | undefined, options: TraceViewerServerOptions & TraceViewerRedirectOptions): Promise<reporterTypes.FullResult['status']> {
|
||||
export async function runUIMode(configFile: string | undefined, options: TraceViewerServerOptions & TraceViewerRedirectOptions): Promise<reporterTypes.FullResult['status'] | 'restarted'> {
|
||||
return await innerRunTestServer(configFile, options, async (server: HttpServer, cancelPromise: ManualPromise<void>) => {
|
||||
await installRootRedirect(server, [], { ...options, webApp: 'uiMode.html' });
|
||||
if (options.host !== undefined || options.port !== undefined) {
|
||||
@ -379,16 +377,16 @@ 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']> {
|
||||
export async function runTestServer(configFile: string | undefined, options: { host?: string, port?: number }): Promise<reporterTypes.FullResult['status'] | 'restarted'> {
|
||||
return await innerRunTestServer(configFile, options, async server => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Listening on ' + server.urlPrefix().replace('http:', 'ws:') + '/' + server.wsGuid());
|
||||
});
|
||||
}
|
||||
|
||||
async function innerRunTestServer(configFile: string | undefined, options: { host?: string, port?: number }, openUI: (server: HttpServer, cancelPromise: ManualPromise<void>) => Promise<void>): Promise<reporterTypes.FullResult['status']> {
|
||||
async function innerRunTestServer(configFile: string | undefined, options: { host?: string, port?: number }, openUI: (server: HttpServer, cancelPromise: ManualPromise<void>) => Promise<void>): Promise<reporterTypes.FullResult['status'] | 'restarted'> {
|
||||
if (restartWithExperimentalTsEsm(undefined, true))
|
||||
return 'passed';
|
||||
return 'restarted';
|
||||
const testServer = new TestServer(configFile);
|
||||
const cancelPromise = new ManualPromise<void>();
|
||||
const sigintWatcher = new SigIntWatcher();
|
||||
@ -397,10 +395,8 @@ async function innerRunTestServer(configFile: string | undefined, options: { hos
|
||||
try {
|
||||
const server = await testServer.start(options);
|
||||
await openUI(server, cancelPromise);
|
||||
testServer.wireStdIO();
|
||||
await cancelPromise;
|
||||
} finally {
|
||||
testServer.unwireStdIO();
|
||||
await testServer.stop();
|
||||
sigintWatcher.disarm();
|
||||
}
|
||||
|
||||
@ -172,6 +172,7 @@ export const UIModeView: React.FC<{}> = ({
|
||||
setIsLoading(true);
|
||||
setWatchedTreeIds({ value: new Set() });
|
||||
(async () => {
|
||||
await testServerConnection.setInterceptStdio({ intercept: true });
|
||||
await testServerConnection.watchTestDir({});
|
||||
const { status } = await testServerConnection.runGlobalSetup({});
|
||||
if (status !== 'passed')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user