askui
Version:
Reliable, automated end-to-end-testing that depends on what is shown on your screen instead of the technology you are running on
132 lines (131 loc) • 6.15 kB
JavaScript
import WebSocket from 'ws';
import { CaptureScreenshotRequest, ControlRequest, StartRecordingRequest, StopRecordingRequest, ReadRecordingRequest, InteractiveAnnotationRequest, GetProcessPidRequest, GetStartingArgumentsRequest, } from '../core/runner-protocol';
import { logger } from '../lib/logger';
import { UiControllerClientConnectionState } from './ui-controller-client-connection-state';
import { ReadRecordingResponseStreamHandler } from './read-recording-response-stream-handler';
import { UiControllerClientError } from './ui-controller-client-error';
import { UiControllerNotConnectedError } from './ui-controller-not-connected-error';
export class UiControllerClient {
constructor(url) {
this.url = url;
this.connectionState = UiControllerClientConnectionState.NOT_CONNECTED;
this.currentReject = UiControllerClient.EMPTY_REJECT;
this.currentResolve = UiControllerClient.EMPTY_RESOLVE;
}
clearResponse() {
this.currentReject = UiControllerClient.EMPTY_REJECT;
this.currentResolve = UiControllerClient.EMPTY_RESOLVE;
}
onMessage(data) {
logger.debug('onMessage');
clearTimeout(this.timeout);
this.timeout = undefined;
const response = JSON.parse(data.toString());
if (response.data.error) {
logger.error(response.data.error);
this.currentReject(new UiControllerClientError(response.data.error));
this.clearResponse();
return;
}
this.currentResolve(response);
if (response.msgName === 'READ_RECORDING_PART_RESPONSE') {
return;
}
this.clearResponse();
}
connect() {
this.connectionState = UiControllerClientConnectionState.CONNECTING;
return new Promise((resolve, reject) => {
try {
this.ws = new WebSocket(this.url);
this.ws.on('message', (data) => {
this.onMessage(data);
});
this.ws.on('open', () => {
this.connectionState = UiControllerClientConnectionState.CONNECTED;
resolve(this.connectionState);
});
this.ws.on('error', (error) => {
this.connectionState = UiControllerClientConnectionState.ERROR;
reject(new UiControllerClientError(`Connection to UI Controller cannot be established,
Probably it was not started. Make sure you started UI Controller with this
Url ${this.url}. Cause: ${error}`));
});
}
catch (error) {
reject(new UiControllerClientError(`Connection to UI Controller cannot be established. Cause: ${error}`));
}
});
}
disconnect() {
var _a;
(_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
}
checkConnection() {
if (this.connectionState !== UiControllerClientConnectionState.CONNECTED) {
throw new UiControllerNotConnectedError();
}
}
sendAndReceive(msg, requestTimeout = UiControllerClient.REQUEST_TIMEOUT_IN_MS) {
this.checkConnection();
return new Promise((resolve, reject) => {
logger.debug(`sendAndReceive - ${JSON.stringify(msg)}`);
this.currentResolve = resolve;
this.currentReject = reject;
try {
this.send(msg, requestTimeout);
if (this.timeout) {
throw new UiControllerClientError(`Clear the current request before setting a new one. Check for missing await. Error: ${JSON.stringify(msg)}`);
}
this.timeout = setTimeout(() => this.currentReject(new UiControllerClientError('Request to UI Controller timed out. It seems that the UI Controller is not running. Please, make sure that it is running when executing tests.')), UiControllerClient.REQUEST_TIMEOUT_IN_MS);
}
catch (error) {
this.currentReject(new UiControllerClientError(`The communication to the UI Controller is broken. Cause: ${error}`));
}
});
}
send(msg, _requestTimeout = UiControllerClient.REQUEST_TIMEOUT_IN_MS) {
this.checkConnection();
if (!this.currentReject || !this.currentResolve) {
throw new UiControllerClientError('Request is not finished! It is not possible to have multiple requests at the same time.');
}
logger.debug(`Send: ${JSON.stringify(msg.msgName)}`);
this.ws.send(JSON.stringify(msg));
}
requestScreenshot() {
return this.sendAndReceive(new CaptureScreenshotRequest());
}
getStartingArguments() {
return this.sendAndReceive(new GetStartingArgumentsRequest());
}
getServerPid() {
return this.sendAndReceive(new GetProcessPidRequest());
}
startVideoRecording() {
return this.sendAndReceive(new StartRecordingRequest());
}
stopVideoRecording() {
return this.sendAndReceive(new StopRecordingRequest());
}
readVideoRecording() {
return new Promise((resolve, reject) => {
const readRecordingStreamHandler = new ReadRecordingResponseStreamHandler(resolve, reject);
this.currentResolve = readRecordingStreamHandler.onMessage.bind(readRecordingStreamHandler);
this.currentReject = readRecordingStreamHandler.onError.bind(readRecordingStreamHandler);
this.send(new ReadRecordingRequest(), 60 * 15 * 1000);
});
}
annotateInteractively(boundingBoxes, imageString) {
return new Promise((resolve, reject) => {
this.currentResolve = resolve;
this.currentReject = reject;
this.send(new InteractiveAnnotationRequest(boundingBoxes, imageString), 60 * 60 * 1000);
});
}
requestControl(controlCommand) {
return this.sendAndReceive(new ControlRequest(controlCommand));
}
}
UiControllerClient.EMPTY_REJECT = (_reason) => { };
UiControllerClient.EMPTY_RESOLVE = (_value) => { };
UiControllerClient.REQUEST_TIMEOUT_IN_MS = 30000;