chore(ui): separate transport from TestServerConnection

This commit is contained in:
Simon Knott 2024-08-13 11:31:54 +02:00
parent a28f51a0f3
commit 37ecf7700e
No known key found for this signature in database
GPG key ID: 8CEDC00028084AEC
5 changed files with 27 additions and 19 deletions

View file

@ -19,7 +19,9 @@ import * as events from './events';
// -- Reuse boundary -- Everything below this line is reused in the vscode extension. // -- Reuse boundary -- Everything below this line is reused in the vscode extension.
export class TestServerConnection implements TestServerInterface, TestServerInterfaceEvents { export type TestServerSocket = Pick<WebSocket, 'addEventListener' | 'send' | 'close'>;
abstract class TestServerConnection implements TestServerInterface, TestServerInterfaceEvents {
readonly onClose: events.Event<void>; readonly onClose: events.Event<void>;
readonly onReport: events.Event<any>; readonly onReport: events.Event<any>;
readonly onStdio: events.Event<{ type: 'stderr' | 'stdout'; text?: string | undefined; buffer?: string | undefined; }>; readonly onStdio: events.Event<{ type: 'stderr' | 'stdout'; text?: string | undefined; buffer?: string | undefined; }>;
@ -33,20 +35,20 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
private _onLoadTraceRequestedEmitter = new events.EventEmitter<{ traceUrl: string }>(); private _onLoadTraceRequestedEmitter = new events.EventEmitter<{ traceUrl: string }>();
private _lastId = 0; private _lastId = 0;
private _ws: WebSocket; private _socket: TestServerSocket;
private _callbacks = new Map<number, { resolve: (arg: any) => void, reject: (arg: Error) => void }>(); private _callbacks = new Map<number, { resolve: (arg: any) => void, reject: (arg: Error) => void }>();
private _connectedPromise: Promise<void>; private _connectedPromise: Promise<void>;
private _isClosed = false; private _isClosed = false;
constructor(wsURL: string) { constructor(socket: TestServerSocket) {
this.onClose = this._onCloseEmitter.event; this.onClose = this._onCloseEmitter.event;
this.onReport = this._onReportEmitter.event; this.onReport = this._onReportEmitter.event;
this.onStdio = this._onStdioEmitter.event; this.onStdio = this._onStdioEmitter.event;
this.onTestFilesChanged = this._onTestFilesChangedEmitter.event; this.onTestFilesChanged = this._onTestFilesChangedEmitter.event;
this.onLoadTraceRequested = this._onLoadTraceRequestedEmitter.event; this.onLoadTraceRequested = this._onLoadTraceRequestedEmitter.event;
this._ws = new WebSocket(wsURL); this._socket = socket;
this._ws.addEventListener('message', event => { this._socket.addEventListener('message', event => {
const message = JSON.parse(String(event.data)); const message = JSON.parse(String(event.data));
const { id, result, error, method, params } = message; const { id, result, error, method, params } = message;
if (id) { if (id) {
@ -64,10 +66,10 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
}); });
const pingInterval = setInterval(() => this._sendMessage('ping').catch(() => {}), 30000); const pingInterval = setInterval(() => this._sendMessage('ping').catch(() => {}), 30000);
this._connectedPromise = new Promise<void>((f, r) => { this._connectedPromise = new Promise<void>((f, r) => {
this._ws.addEventListener('open', () => f()); this._socket.addEventListener('open', () => f());
this._ws.addEventListener('error', r); this._socket.addEventListener('error', r);
}); });
this._ws.addEventListener('close', () => { this._socket.addEventListener('close', () => {
this._isClosed = true; this._isClosed = true;
this._onCloseEmitter.fire(); this._onCloseEmitter.fire();
clearInterval(pingInterval); clearInterval(pingInterval);
@ -85,7 +87,7 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
await this._connectedPromise; await this._connectedPromise;
const id = ++this._lastId; const id = ++this._lastId;
const message = { id, method, params }; const message = { id, method, params };
this._ws.send(JSON.stringify(message)); this._socket.send(JSON.stringify(message));
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._callbacks.set(id, { resolve, reject }); this._callbacks.set(id, { resolve, reject });
}); });
@ -200,8 +202,14 @@ export class TestServerConnection implements TestServerInterface, TestServerInte
close() { close() {
try { try {
this._ws.close(); this._socket.close();
} catch { } catch {
} }
} }
} }
export class WSTestServerConnection extends TestServerConnection {
constructor(wsURL: string) {
super(new WebSocket(wsURL));
}
}

View file

@ -29,7 +29,7 @@ import type { SourceLocation } from './modelUtil';
import { testStatusIcon } from './testUtils'; import { testStatusIcon } from './testUtils';
import type { TestModel } from './uiModeModel'; import type { TestModel } from './uiModeModel';
import './uiModeTestListView.css'; import './uiModeTestListView.css';
import type { TestServerConnection } from '@testIsomorphic/testServerConnection'; import type { WSTestServerConnection } from '@testIsomorphic/testServerConnection';
import { TagView } from './tag'; import { TagView } from './tag';
const TestTreeView = TreeView<TreeItem>; const TestTreeView = TreeView<TreeItem>;
@ -37,7 +37,7 @@ const TestTreeView = TreeView<TreeItem>;
export const TestListView: React.FC<{ export const TestListView: React.FC<{
filterText: string, filterText: string,
testTree: TestTree, testTree: TestTree,
testServerConnection: TestServerConnection | undefined, testServerConnection: WSTestServerConnection | undefined,
testModel?: TestModel, testModel?: TestModel,
runTests: (mode: 'bounce-if-busy' | 'queue-if-busy', testIds: Set<string>) => void, runTests: (mode: 'bounce-if-busy' | 'queue-if-busy', testIds: Set<string>) => void,
runningState?: { testIds: Set<string>, itemSelectedByUser?: boolean, completed?: boolean }, runningState?: { testIds: Set<string>, itemSelectedByUser?: boolean, completed?: boolean },

View file

@ -33,7 +33,7 @@ import { useDarkModeSetting } from '@web/theme';
import { clsx, settings, useSetting } from '@web/uiUtils'; import { clsx, settings, useSetting } from '@web/uiUtils';
import { statusEx, TestTree } from '@testIsomorphic/testTree'; import { statusEx, TestTree } from '@testIsomorphic/testTree';
import type { TreeItem } from '@testIsomorphic/testTree'; import type { TreeItem } from '@testIsomorphic/testTree';
import { TestServerConnection } from '@testIsomorphic/testServerConnection'; import { WSTestServerConnection } from '@testIsomorphic/testServerConnection';
import { pathSeparator } from './uiModeModel'; import { pathSeparator } from './uiModeModel';
import type { TestModel } from './uiModeModel'; import type { TestModel } from './uiModeModel';
import { FiltersView } from './uiModeFiltersView'; import { FiltersView } from './uiModeFiltersView';
@ -95,7 +95,7 @@ export const UIModeView: React.FC<{}> = ({
const [collapseAllCount, setCollapseAllCount] = React.useState(0); const [collapseAllCount, setCollapseAllCount] = React.useState(0);
const [isDisconnected, setIsDisconnected] = React.useState(false); const [isDisconnected, setIsDisconnected] = React.useState(false);
const [hasBrowsers, setHasBrowsers] = React.useState(true); const [hasBrowsers, setHasBrowsers] = React.useState(true);
const [testServerConnection, setTestServerConnection] = React.useState<TestServerConnection>(); const [testServerConnection, setTestServerConnection] = React.useState<WSTestServerConnection>();
const [teleSuiteUpdater, setTeleSuiteUpdater] = React.useState<TeleSuiteUpdater>(); const [teleSuiteUpdater, setTeleSuiteUpdater] = React.useState<TeleSuiteUpdater>();
const [settingsVisible, setSettingsVisible] = React.useState(false); const [settingsVisible, setSettingsVisible] = React.useState(false);
const [testingOptionsVisible, setTestingOptionsVisible] = React.useState(false); const [testingOptionsVisible, setTestingOptionsVisible] = React.useState(false);
@ -135,7 +135,7 @@ export const UIModeView: React.FC<{}> = ({
const inputRef = React.useRef<HTMLInputElement>(null); const inputRef = React.useRef<HTMLInputElement>(null);
const reloadTests = React.useCallback(() => { const reloadTests = React.useCallback(() => {
setTestServerConnection(new TestServerConnection(wsURL.toString())); setTestServerConnection(new WSTestServerConnection(wsURL.toString()));
}, []); }, []);
// Load tests on startup. // Load tests on startup.

View file

@ -21,7 +21,7 @@ import { MultiTraceModel } from './modelUtil';
import './workbenchLoader.css'; import './workbenchLoader.css';
import { toggleTheme } from '@web/theme'; import { toggleTheme } from '@web/theme';
import { Workbench } from './workbench'; import { Workbench } from './workbench';
import { TestServerConnection } from '@testIsomorphic/testServerConnection'; import { WSTestServerConnection } from '@testIsomorphic/testServerConnection';
export const WorkbenchLoader: React.FunctionComponent<{ export const WorkbenchLoader: React.FunctionComponent<{
}> = () => { }> = () => {
@ -102,7 +102,7 @@ export const WorkbenchLoader: React.FunctionComponent<{
const guid = new URLSearchParams(window.location.search).get('ws'); const guid = new URLSearchParams(window.location.search).get('ws');
const wsURL = new URL(`../${guid}`, window.location.toString()); const wsURL = new URL(`../${guid}`, window.location.toString());
wsURL.protocol = (window.location.protocol === 'https:' ? 'wss:' : 'ws:'); wsURL.protocol = (window.location.protocol === 'https:' ? 'wss:' : 'ws:');
const testServerConnection = new TestServerConnection(wsURL.toString()); const testServerConnection = new WSTestServerConnection(wsURL.toString());
testServerConnection.onLoadTraceRequested(async params => { testServerConnection.onLoadTraceRequested(async params => {
setTraceURLs(params.traceUrl ? [params.traceUrl] : []); setTraceURLs(params.traceUrl ? [params.traceUrl] : []);
setDragOver(false); setDragOver(false);

View file

@ -15,9 +15,9 @@
*/ */
import { test as baseTest, expect } from './ui-mode-fixtures'; import { test as baseTest, expect } from './ui-mode-fixtures';
import { TestServerConnection } from '../../packages/playwright/lib/isomorphic/testServerConnection'; import { WSTestServerConnection } from '../../packages/playwright/lib/isomorphic/testServerConnection';
class TestServerConnectionUnderTest extends TestServerConnection { class TestServerConnectionUnderTest extends WSTestServerConnection {
events: [string, any][] = []; events: [string, any][] = [];
constructor(wsUrl: string) { constructor(wsUrl: string) {