chore: add trace viewer methods to testServer

This commit is contained in:
Rui Figueira 2024-09-14 22:26:07 +01:00
parent 77e2624a68
commit b487297460
3 changed files with 69 additions and 1 deletions

View file

@ -67,12 +67,14 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
readonly onStdio: events.Event<{ type: 'stderr' | 'stdout'; text?: string | undefined; buffer?: string | undefined; }>;
readonly onTestFilesChanged: events.Event<{ testFiles: string[] }>;
readonly onLoadTraceRequested: events.Event<{ traceUrl: string }>;
readonly onTraceViewerEvent: events.Event<{ method: string; params: any; }>;
private _onCloseEmitter = new events.EventEmitter<void>();
private _onReportEmitter = new events.EventEmitter<any>();
private _onStdioEmitter = new events.EventEmitter<{ type: 'stderr' | 'stdout'; text?: string | undefined; buffer?: string | undefined; }>();
private _onTestFilesChangedEmitter = new events.EventEmitter<{ testFiles: string[] }>();
private _onLoadTraceRequestedEmitter = new events.EventEmitter<{ traceUrl: string }>();
private _onTraceViewerEventEmitter = new events.EventEmitter<{ method: string; params: any }>();
private _lastId = 0;
private _transport: TestServerTransport;
@ -86,6 +88,7 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
this.onStdio = this._onStdioEmitter.event;
this.onTestFilesChanged = this._onTestFilesChangedEmitter.event;
this.onLoadTraceRequested = this._onLoadTraceRequestedEmitter.event;
this.onTraceViewerEvent = this._onTraceViewerEventEmitter.event;
this._transport = transport;
this._transport.onmessage(data => {
@ -146,6 +149,8 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
this._onTestFilesChangedEmitter.fire(params);
else if (method === 'loadTraceRequested')
this._onLoadTraceRequestedEmitter.fire(params);
else if (method === 'traceViewerEvent')
this._onTraceViewerEventEmitter.fire(params);
}
async initialize(params: Parameters<TestServerInterface['initialize']>[0]): ReturnType<TestServerInterface['initialize']> {
@ -236,6 +241,22 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
this._sendMessageNoReply('stopTests', params);
}
async openTraceViewer(params: Parameters<TestServerInterface['openTraceViewer']>[0]): ReturnType<TestServerInterface['openTraceViewer']> {
await this._sendMessage('openTraceViewer', params);
}
async closeTraceViewer(params: Parameters<TestServerInterface['closeTraceViewer']>[0]): ReturnType<TestServerInterface['closeTraceViewer']> {
await this._sendMessage('closeTraceViewer', params);
}
async dispatchTraceViewerEvent(params: Parameters<TestServerInterface['dispatchTraceViewerEvent']>[0]): ReturnType<TestServerInterface['dispatchTraceViewerEvent']> {
await this._sendMessage('dispatchTraceViewerEvent', params);
}
dispatchTraceViewerEventNoReply(params: Parameters<TestServerInterface['dispatchTraceViewerEvent']>[0]) {
this._sendMessageNoReply('dispatchTraceViewerEvent', params);
}
async closeGracefully(params: Parameters<TestServerInterface['closeGracefully']>[0]): ReturnType<TestServerInterface['closeGracefully']> {
await this._sendMessage('closeGracefully', params);
}

View file

@ -21,6 +21,7 @@ import type { JsonEvent } from './teleReceiver';
// -- Reuse boundary -- Everything below this line is reused in the vscode extension.
export type ReportEntry = JsonEvent;
export type TraceViewerEvent = JsonEvent;
export interface TestServerInterface {
initialize(params: {
@ -114,6 +115,12 @@ export interface TestServerInterface {
stopTests(params: {}): Promise<void>;
openTraceViewer(params: { traceViewerURL: string; openInBrowser?: boolean }): Promise<void>;
closeTraceViewer(params: {}): Promise<void>;
dispatchTraceViewerEvent(params: { method: string; params: any; }): Promise<void>;
closeGracefully(params: {}): Promise<void>;
}
@ -122,6 +129,7 @@ export interface TestServerInterfaceEvents {
onStdio: Event<{ type: 'stdout' | 'stderr', text?: string, buffer?: string }>;
onTestFilesChanged: Event<{ testFiles: string[] }>;
onLoadTraceRequested: Event<{ traceUrl: string }>;
onTraceViewerEvent: Event<{ method: string; params: any; }>;
}
export interface TestServerInterfaceEventEmitters {
@ -129,4 +137,5 @@ export interface TestServerInterfaceEventEmitters {
dispatchEvent(event: 'stdio', params: { type: 'stdout' | 'stderr', text?: string, buffer?: string }): void;
dispatchEvent(event: 'testFilesChanged', params: { testFiles: string[] }): void;
dispatchEvent(event: 'loadTraceRequested', params: { traceUrl: string }): void;
dispatchEvent(event: 'traceViewerEvent', params: { method: string; params: any; }): void;
}

View file

@ -16,7 +16,7 @@
import fs from 'fs';
import path from 'path';
import { installRootRedirect, openTraceInBrowser, openTraceViewerApp, registry, startTraceViewerServer } from 'playwright-core/lib/server';
import { installRootRedirect, openTraceInBrowser, openTraceViewerApp, registry, serverSideCallMetadata, startTraceViewerServer } from 'playwright-core/lib/server';
import { ManualPromise, gracefullyProcessExitDoNotHang, isUnderTest } from 'playwright-core/lib/utils';
import type { Transport, HttpServer } from 'playwright-core/lib/utils';
import type * as reporterTypes from '../../types/testReporter';
@ -38,6 +38,7 @@ import { serializeError } from '../util';
import { baseFullConfig } from '../isomorphic/teleReceiver';
import { InternalReporter } from '../reporters/internalReporter';
import type { ReporterV2 } from '../reporters/reporterV2';
import type { Page } from 'playwright-core/lib/server/page';
const originalStdoutWrite = process.stdout.write;
const originalStderrWrite = process.stderr.write;
@ -80,6 +81,7 @@ export class TestServerDispatcher implements TestServerInterface {
private _watchTestDirs = false;
private _closeOnDisconnect = false;
private _populateDependenciesOnList = false;
private _traceViewerPagePromise: Promise<Page> | undefined;
constructor(configLocation: ConfigLocation) {
this._configLocation = configLocation;
@ -390,6 +392,42 @@ export class TestServerDispatcher implements TestServerInterface {
}
}
async openTraceViewer(params: { traceViewerURL: string; openInBrowser?: boolean }): Promise<void> {
if (this._traceViewerPagePromise)
throw new Error(`Trace Viewer already open`);
if (params.openInBrowser) {
await openTraceInBrowser(params.traceViewerURL);
} else {
this._traceViewerPagePromise = openTraceViewerApp(params.traceViewerURL, 'chromium', {
headless: isUnderTest() && process.env.PWTEST_HEADED_FOR_TEST !== '1',
persistentContextOptions: {
handleSIGINT: false,
},
});
const page = await this._traceViewerPagePromise;
page.on('close', () => {
this._traceViewerPagePromise = undefined;
this._dispatchEvent('traceViewerEvent', { method: 'didClose', params: {} });
});
}
}
async closeTraceViewer(): Promise<void> {
if (!this._traceViewerPagePromise)
return;
const page = await this._traceViewerPagePromise;
await page.close(serverSideCallMetadata());
this._traceViewerPagePromise = undefined;
}
async dispatchTraceViewerEvent(params: { method: string; params: any; }): Promise<void> {
if (params.method === 'loadTraceRequested')
this._dispatchEvent('loadTraceRequested', params.params);
else
this._dispatchEvent('traceViewerEvent', params);
}
async closeGracefully() {
gracefullyProcessExitDoNotHang(0);
}