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']> {
|
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]) {
|
async pingNoReply(params: Parameters<TestServerInterface['ping']>[0]) {
|
||||||
this._sendMessageNoReply('ping');
|
this._sendMessageNoReply('ping', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
async watch(params: Parameters<TestServerInterface['watch']>[0]): ReturnType<TestServerInterface['watch']> {
|
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']> {
|
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']> {
|
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']> {
|
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']> {
|
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']> {
|
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']> {
|
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]) {
|
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']> {
|
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>;
|
stopTests(params: {}): Promise<void>;
|
||||||
|
|
||||||
|
setInterceptStdio(params: { intercept: boolean }): Promise<void>;
|
||||||
|
|
||||||
closeGracefully(params: {}): Promise<void>;
|
closeGracefully(params: {}): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -169,6 +169,8 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
|
|||||||
timeout: cliOverrides.timeout,
|
timeout: cliOverrides.timeout,
|
||||||
});
|
});
|
||||||
await stopProfiling('runner');
|
await stopProfiling('runner');
|
||||||
|
if (status === 'restarted')
|
||||||
|
return;
|
||||||
const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1);
|
const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1);
|
||||||
gracefullyProcessExitDoNotHang(exitCode);
|
gracefullyProcessExitDoNotHang(exitCode);
|
||||||
return;
|
return;
|
||||||
@ -200,6 +202,8 @@ 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')
|
||||||
|
return;
|
||||||
const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1);
|
const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1);
|
||||||
gracefullyProcessExitDoNotHang(exitCode);
|
gracefullyProcessExitDoNotHang(exitCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,16 +39,15 @@ import type { TraceViewerRedirectOptions, TraceViewerServerOptions } from 'playw
|
|||||||
import type { TestRunnerPluginRegistration } from '../plugins';
|
import type { TestRunnerPluginRegistration } from '../plugins';
|
||||||
import { serializeError } from '../util';
|
import { serializeError } from '../util';
|
||||||
|
|
||||||
|
const originalStdoutWrite = process.stdout.write;
|
||||||
|
const originalStderrWrite = process.stderr.write;
|
||||||
|
|
||||||
class TestServer {
|
class TestServer {
|
||||||
private _configFile: string | undefined;
|
private _configFile: string | undefined;
|
||||||
private _dispatcher: TestServerDispatcher | undefined;
|
private _dispatcher: TestServerDispatcher | undefined;
|
||||||
private _originalStdoutWrite: NodeJS.WriteStream['write'];
|
|
||||||
private _originalStderrWrite: NodeJS.WriteStream['write'];
|
|
||||||
|
|
||||||
constructor(configFile: string | undefined) {
|
constructor(configFile: string | undefined) {
|
||||||
this._configFile = configFile;
|
this._configFile = configFile;
|
||||||
this._originalStdoutWrite = process.stdout.write;
|
|
||||||
this._originalStderrWrite = process.stderr.write;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async start(options: { host?: string, port?: number }): Promise<HttpServer> {
|
async start(options: { host?: string, port?: number }): Promise<HttpServer> {
|
||||||
@ -57,28 +56,9 @@ class TestServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async stop() {
|
async stop() {
|
||||||
|
await this._dispatcher?.setInterceptStdio({ intercept: false });
|
||||||
await this._dispatcher?.runGlobalTeardown();
|
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 {
|
class TestServerDispatcher implements TestServerInterface {
|
||||||
@ -341,6 +321,24 @@ class TestServerDispatcher implements TestServerInterface {
|
|||||||
await this._testRun?.run;
|
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() {
|
async closeGracefully() {
|
||||||
gracefullyProcessExitDoNotHang(0);
|
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>) => {
|
return await innerRunTestServer(configFile, 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) {
|
||||||
@ -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 => {
|
return await innerRunTestServer(configFile, options, async server => {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('Listening on ' + server.urlPrefix().replace('http:', 'ws:') + '/' + server.wsGuid());
|
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))
|
if (restartWithExperimentalTsEsm(undefined, true))
|
||||||
return 'passed';
|
return 'restarted';
|
||||||
const testServer = new TestServer(configFile);
|
const testServer = new TestServer(configFile);
|
||||||
const cancelPromise = new ManualPromise<void>();
|
const cancelPromise = new ManualPromise<void>();
|
||||||
const sigintWatcher = new SigIntWatcher();
|
const sigintWatcher = new SigIntWatcher();
|
||||||
@ -397,10 +395,8 @@ async function innerRunTestServer(configFile: string | undefined, options: { hos
|
|||||||
try {
|
try {
|
||||||
const server = await testServer.start(options);
|
const server = await testServer.start(options);
|
||||||
await openUI(server, cancelPromise);
|
await openUI(server, cancelPromise);
|
||||||
testServer.wireStdIO();
|
|
||||||
await cancelPromise;
|
await cancelPromise;
|
||||||
} finally {
|
} finally {
|
||||||
testServer.unwireStdIO();
|
|
||||||
await testServer.stop();
|
await testServer.stop();
|
||||||
sigintWatcher.disarm();
|
sigintWatcher.disarm();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -172,6 +172,7 @@ export const UIModeView: React.FC<{}> = ({
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setWatchedTreeIds({ value: new Set() });
|
setWatchedTreeIds({ value: new Set() });
|
||||||
(async () => {
|
(async () => {
|
||||||
|
await testServerConnection.setInterceptStdio({ intercept: true });
|
||||||
await testServerConnection.watchTestDir({});
|
await testServerConnection.watchTestDir({});
|
||||||
const { status } = await testServerConnection.runGlobalSetup({});
|
const { status } = await testServerConnection.runGlobalSetup({});
|
||||||
if (status !== 'passed')
|
if (status !== 'passed')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user