mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore(ui): decouple TestServerConnection from websocket transport (#32274)
Preparation for https://github.com/microsoft/playwright/issues/32076.
This commit is contained in:
parent
785ca19e51
commit
3fb33e7144
@ -19,6 +19,48 @@ import * as events from './events';
|
||||
|
||||
// -- Reuse boundary -- Everything below this line is reused in the vscode extension.
|
||||
|
||||
export interface TestServerTransport {
|
||||
onmessage(listener: (message: string) => void): void;
|
||||
onopen(listener: () => void): void;
|
||||
onerror(listener: () => void): void;
|
||||
onclose(listener: () => void): void;
|
||||
|
||||
send(data: string): void;
|
||||
close(): void;
|
||||
}
|
||||
|
||||
export class WebSocketTestServerTransport implements TestServerTransport {
|
||||
private _ws: WebSocket;
|
||||
|
||||
constructor(url: string | URL) {
|
||||
this._ws = new WebSocket(url);
|
||||
}
|
||||
|
||||
onmessage(listener: (message: string) => void) {
|
||||
this._ws.addEventListener('message', event => listener(event.data));
|
||||
}
|
||||
|
||||
onopen(listener: () => void) {
|
||||
this._ws.addEventListener('open', listener);
|
||||
}
|
||||
|
||||
onerror(listener: () => void) {
|
||||
this._ws.addEventListener('error', listener);
|
||||
}
|
||||
|
||||
onclose(listener: () => void) {
|
||||
this._ws.addEventListener('close', listener);
|
||||
}
|
||||
|
||||
send(data: string) {
|
||||
this._ws.send(data);
|
||||
}
|
||||
|
||||
close() {
|
||||
this._ws.close();
|
||||
}
|
||||
}
|
||||
|
||||
export class TestServerConnection implements TestServerInterface, TestServerInterfaceEvents {
|
||||
readonly onClose: events.Event<void>;
|
||||
readonly onReport: events.Event<any>;
|
||||
@ -33,21 +75,21 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
|
||||
private _onLoadTraceRequestedEmitter = new events.EventEmitter<{ traceUrl: string }>();
|
||||
|
||||
private _lastId = 0;
|
||||
private _ws: WebSocket;
|
||||
private _transport: TestServerTransport;
|
||||
private _callbacks = new Map<number, { resolve: (arg: any) => void, reject: (arg: Error) => void }>();
|
||||
private _connectedPromise: Promise<void>;
|
||||
private _isClosed = false;
|
||||
|
||||
constructor(wsURL: string) {
|
||||
constructor(transport: TestServerTransport) {
|
||||
this.onClose = this._onCloseEmitter.event;
|
||||
this.onReport = this._onReportEmitter.event;
|
||||
this.onStdio = this._onStdioEmitter.event;
|
||||
this.onTestFilesChanged = this._onTestFilesChangedEmitter.event;
|
||||
this.onLoadTraceRequested = this._onLoadTraceRequestedEmitter.event;
|
||||
|
||||
this._ws = new WebSocket(wsURL);
|
||||
this._ws.addEventListener('message', event => {
|
||||
const message = JSON.parse(String(event.data));
|
||||
this._transport = transport;
|
||||
this._transport.onmessage(data => {
|
||||
const message = JSON.parse(data);
|
||||
const { id, result, error, method, params } = message;
|
||||
if (id) {
|
||||
const callback = this._callbacks.get(id);
|
||||
@ -62,12 +104,12 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
|
||||
this._dispatchEvent(method, params);
|
||||
}
|
||||
});
|
||||
const pingInterval = setInterval(() => this._sendMessage('ping').catch(() => {}), 30000);
|
||||
const pingInterval = setInterval(() => this._sendMessage('ping').catch(() => { }), 30000);
|
||||
this._connectedPromise = new Promise<void>((f, r) => {
|
||||
this._ws.addEventListener('open', () => f());
|
||||
this._ws.addEventListener('error', r);
|
||||
this._transport.onopen(f);
|
||||
this._transport.onerror(r);
|
||||
});
|
||||
this._ws.addEventListener('close', () => {
|
||||
this._transport.onclose(() => {
|
||||
this._isClosed = true;
|
||||
this._onCloseEmitter.fire();
|
||||
clearInterval(pingInterval);
|
||||
@ -85,14 +127,14 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
|
||||
await this._connectedPromise;
|
||||
const id = ++this._lastId;
|
||||
const message = { id, method, params };
|
||||
this._ws.send(JSON.stringify(message));
|
||||
this._transport.send(JSON.stringify(message));
|
||||
return new Promise((resolve, reject) => {
|
||||
this._callbacks.set(id, { resolve, reject });
|
||||
});
|
||||
}
|
||||
|
||||
private _sendMessageNoReply(method: string, params?: any) {
|
||||
this._sendMessage(method, params).catch(() => {});
|
||||
this._sendMessage(method, params).catch(() => { });
|
||||
}
|
||||
|
||||
private _dispatchEvent(method: string, params?: any) {
|
||||
@ -200,8 +242,8 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
|
||||
|
||||
close() {
|
||||
try {
|
||||
this._ws.close();
|
||||
this._transport.close();
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -32,7 +32,7 @@ import { useDarkModeSetting } from '@web/theme';
|
||||
import { clsx, settings, useSetting } from '@web/uiUtils';
|
||||
import { statusEx, TestTree } from '@testIsomorphic/testTree';
|
||||
import type { TreeItem } from '@testIsomorphic/testTree';
|
||||
import { TestServerConnection } from '@testIsomorphic/testServerConnection';
|
||||
import { TestServerConnection, WebSocketTestServerTransport } from '@testIsomorphic/testServerConnection';
|
||||
import { FiltersView } from './uiModeFiltersView';
|
||||
import { TestListView } from './uiModeTestListView';
|
||||
import { TraceView } from './uiModeTraceView';
|
||||
@ -134,7 +134,7 @@ export const UIModeView: React.FC<{}> = ({
|
||||
const inputRef = React.useRef<HTMLInputElement>(null);
|
||||
|
||||
const reloadTests = React.useCallback(() => {
|
||||
setTestServerConnection(new TestServerConnection(wsURL.toString()));
|
||||
setTestServerConnection(new TestServerConnection(new WebSocketTestServerTransport(wsURL)));
|
||||
}, []);
|
||||
|
||||
// Load tests on startup.
|
||||
|
||||
@ -21,7 +21,7 @@ import { MultiTraceModel } from './modelUtil';
|
||||
import './workbenchLoader.css';
|
||||
import { toggleTheme } from '@web/theme';
|
||||
import { Workbench } from './workbench';
|
||||
import { TestServerConnection } from '@testIsomorphic/testServerConnection';
|
||||
import { TestServerConnection, WebSocketTestServerTransport } from '@testIsomorphic/testServerConnection';
|
||||
|
||||
export const WorkbenchLoader: React.FunctionComponent<{
|
||||
}> = () => {
|
||||
@ -102,7 +102,7 @@ export const WorkbenchLoader: React.FunctionComponent<{
|
||||
const guid = new URLSearchParams(window.location.search).get('ws');
|
||||
const wsURL = new URL(`../${guid}`, window.location.toString());
|
||||
wsURL.protocol = (window.location.protocol === 'https:' ? 'wss:' : 'ws:');
|
||||
const testServerConnection = new TestServerConnection(wsURL.toString());
|
||||
const testServerConnection = new TestServerConnection(new WebSocketTestServerTransport(wsURL));
|
||||
testServerConnection.onLoadTraceRequested(async params => {
|
||||
setTraceURLs(params.traceUrl ? [params.traceUrl] : []);
|
||||
setDragOver(false);
|
||||
|
||||
@ -15,13 +15,13 @@
|
||||
*/
|
||||
import { test as baseTest, expect } from './ui-mode-fixtures';
|
||||
|
||||
import { TestServerConnection } from '../../packages/playwright/lib/isomorphic/testServerConnection';
|
||||
import { TestServerConnection, WebSocketTestServerTransport } from '../../packages/playwright/lib/isomorphic/testServerConnection';
|
||||
|
||||
class TestServerConnectionUnderTest extends TestServerConnection {
|
||||
events: [string, any][] = [];
|
||||
|
||||
constructor(wsUrl: string) {
|
||||
super(wsUrl);
|
||||
super(new WebSocketTestServerTransport(wsUrl));
|
||||
this.onTestFilesChanged(params => this.events.push(['testFilesChanged', params]));
|
||||
this.onStdio(params => this.events.push(['stdio', params]));
|
||||
this.onLoadTraceRequested(params => this.events.push(['loadTraceRequested', params]));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user