system-testing 1.0.35 → 1.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.js +3 -0
- package/{dist → build}/system-test-browser-helper.d.ts +2 -2
- package/build/system-test-browser-helper.js +238 -0
- package/build/system-test-communicator.js +105 -0
- package/build/system-test-http-server.js +66 -0
- package/{dist → build}/system-test.d.ts +15 -24
- package/build/system-test.js +696 -0
- package/build/use-system-test.js +79 -0
- package/package.json +10 -6
- package/dist/index.js +0 -3
- package/dist/index.js.map +0 -1
- package/dist/system-test-browser-helper.js +0 -238
- package/dist/system-test-browser-helper.js.map +0 -1
- package/dist/system-test-communicator.js +0 -105
- package/dist/system-test-communicator.js.map +0 -1
- package/dist/system-test-http-server.js +0 -66
- package/dist/system-test-http-server.js.map +0 -1
- package/dist/system-test.js +0 -705
- package/dist/system-test.js.map +0 -1
- package/dist/use-system-test.js +0 -79
- package/dist/use-system-test.js.map +0 -1
- /package/{dist → build}/index.d.ts +0 -0
- /package/{dist → build}/system-test-communicator.d.ts +0 -0
- /package/{dist → build}/system-test-http-server.d.ts +0 -0
- /package/{dist → build}/use-system-test.d.ts +0 -0
package/build/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const stub = "Hello world";
|
|
2
|
+
export { stub };
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxJQUFJLEdBQUcsYUFBYSxDQUFBO0FBRTFCLE9BQU8sRUFBQyxJQUFJLEVBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHN0dWIgPSBcIkhlbGxvIHdvcmxkXCJcblxuZXhwb3J0IHtzdHVifVxuIl19
|
|
@@ -2,7 +2,7 @@ export default class SystemTestBrowserHelper {
|
|
|
2
2
|
static current(): SystemTestBrowserHelper;
|
|
3
3
|
communicator: SystemTestCommunicator;
|
|
4
4
|
_enabled: boolean;
|
|
5
|
-
events: EventEmitter<any>;
|
|
5
|
+
events: EventEmitter<string | symbol, any>;
|
|
6
6
|
startScoundrel(): Promise<void>;
|
|
7
7
|
scoundrelWs: WebSocket;
|
|
8
8
|
scoundrelClientWebSocket: ClientWebSocket;
|
|
@@ -103,6 +103,6 @@ export default class SystemTestBrowserHelper {
|
|
|
103
103
|
sendQuery(sql: string): Promise<Array<Record<string, any>>>;
|
|
104
104
|
}
|
|
105
105
|
import SystemTestCommunicator from "./system-test-communicator.js";
|
|
106
|
-
import EventEmitter from "
|
|
106
|
+
import { EventEmitter } from "eventemitter3";
|
|
107
107
|
import ClientWebSocket from "scoundrel-remote-eval/build/client/connections/web-socket/index.js";
|
|
108
108
|
import Client from "scoundrel-remote-eval/build/client/index.js";
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import Client from "scoundrel-remote-eval/build/client/index.js";
|
|
3
|
+
import ClientWebSocket from "scoundrel-remote-eval/build/client/connections/web-socket/index.js";
|
|
4
|
+
import { digg } from "diggerize";
|
|
5
|
+
import { EventEmitter } from "eventemitter3";
|
|
6
|
+
import SystemTestCommunicator from "./system-test-communicator.js";
|
|
7
|
+
/** @type {{systemTestBrowserHelper: SystemTestBrowserHelper | null}} */
|
|
8
|
+
const shared = {
|
|
9
|
+
systemTestBrowserHelper: null
|
|
10
|
+
};
|
|
11
|
+
export default class SystemTestBrowserHelper {
|
|
12
|
+
static current() {
|
|
13
|
+
if (!shared.systemTestBrowserHelper) {
|
|
14
|
+
throw new Error("No current SystemTestBrowserHelper set");
|
|
15
|
+
}
|
|
16
|
+
return shared.systemTestBrowserHelper;
|
|
17
|
+
}
|
|
18
|
+
constructor() {
|
|
19
|
+
/**
|
|
20
|
+
* @param {any[]} args
|
|
21
|
+
* @returns {void}
|
|
22
|
+
*/
|
|
23
|
+
this.fakeConsoleError = (...args) => {
|
|
24
|
+
this.communicator.sendCommand({ type: "console.error", value: this.consoleLogMessage(args) });
|
|
25
|
+
if (this.originalConsoleError) {
|
|
26
|
+
return this.originalConsoleError(...args);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* @param {any[]} args
|
|
31
|
+
* @returns {void}
|
|
32
|
+
*/
|
|
33
|
+
this.fakeConsoleLog = (...args) => {
|
|
34
|
+
this.communicator.sendCommand({ type: "console.log", value: this.consoleLogMessage(args) });
|
|
35
|
+
if (this.originalConsoleLog) {
|
|
36
|
+
return this.originalConsoleLog(...args);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* @param {{data: {path: string, type: string}}} args
|
|
41
|
+
* @returns {Promise<{result: string} | void>}
|
|
42
|
+
*/
|
|
43
|
+
this.onCommand = async ({ data }) => {
|
|
44
|
+
if (data.type == "initialize") {
|
|
45
|
+
this.events.emit("initialize");
|
|
46
|
+
if (this._onInitializeCallback) {
|
|
47
|
+
await this._onInitializeCallback();
|
|
48
|
+
}
|
|
49
|
+
return { result: "initialized" };
|
|
50
|
+
}
|
|
51
|
+
else if (data.type == "visit") {
|
|
52
|
+
this.events.emit("navigate", { path: data.path });
|
|
53
|
+
}
|
|
54
|
+
else if (data.type == "dismissTo") {
|
|
55
|
+
this.events.emit("dismissTo", { path: data.path });
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
throw new Error(`Unknown command type for SystemTestBrowserHelper: ${data.type}`);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
this.communicator = new SystemTestCommunicator({ parent: this, onCommand: this.onCommand });
|
|
62
|
+
this._enabled = false;
|
|
63
|
+
this.events = new EventEmitter();
|
|
64
|
+
shared.systemTestBrowserHelper = this;
|
|
65
|
+
this.startScoundrel();
|
|
66
|
+
}
|
|
67
|
+
async startScoundrel() {
|
|
68
|
+
this.scoundrelWs = new WebSocket("http://localhost:8090");
|
|
69
|
+
// @ts-expect-error
|
|
70
|
+
this.scoundrelClientWebSocket = new ClientWebSocket(this.scoundrelWs);
|
|
71
|
+
await this.scoundrelClientWebSocket.waitForOpened();
|
|
72
|
+
this.scoundrelClient = new Client(this.scoundrelClientWebSocket);
|
|
73
|
+
this.events.emit("scoundrelStarted");
|
|
74
|
+
}
|
|
75
|
+
waitForScoundrelStarted() {
|
|
76
|
+
return new Promise((resolve) => {
|
|
77
|
+
if (this.scoundrelClient) {
|
|
78
|
+
resolve(undefined);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this.events.once("scoundrelStarted", () => {
|
|
82
|
+
resolve(undefined);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
getScoundrel() {
|
|
88
|
+
if (!this.scoundrelClient) {
|
|
89
|
+
throw new Error("Scoundrel client is not started yet");
|
|
90
|
+
}
|
|
91
|
+
return this.scoundrelClient;
|
|
92
|
+
}
|
|
93
|
+
connectOnError() {
|
|
94
|
+
window.addEventListener("error", (event) => {
|
|
95
|
+
this.handleError({
|
|
96
|
+
type: "error",
|
|
97
|
+
error: event.error,
|
|
98
|
+
errorClass: event.error?.name,
|
|
99
|
+
file: event.filename,
|
|
100
|
+
line: event.lineno,
|
|
101
|
+
message: event.message || "Unknown error",
|
|
102
|
+
url: window.location.href
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
connectUnhandledRejection() {
|
|
107
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
108
|
+
this.handleError({
|
|
109
|
+
type: "unhandledrejection",
|
|
110
|
+
error: event.reason,
|
|
111
|
+
errorClass: "UnhandledRejection",
|
|
112
|
+
message: event.reason.message || event.reason || "Unhandled promise rejection without a message",
|
|
113
|
+
url: window.location.href
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* @param {object} data
|
|
119
|
+
* @param {string} [data.backtrace]
|
|
120
|
+
* @param {Error} [data.error]
|
|
121
|
+
* @param {string} [data.errorClass]
|
|
122
|
+
* @param {string} [data.file]
|
|
123
|
+
* @param {number} [data.line]
|
|
124
|
+
* @param {string} [data.message]
|
|
125
|
+
* @param {string} [data.type]
|
|
126
|
+
* @param {string} [data.url]
|
|
127
|
+
* @returns {void}
|
|
128
|
+
*/
|
|
129
|
+
handleError(data) {
|
|
130
|
+
let backtrace;
|
|
131
|
+
if (data.error && data.error.stack) {
|
|
132
|
+
backtrace = data.error.stack.split("\n");
|
|
133
|
+
backtrace.shift();
|
|
134
|
+
backtrace = backtrace.join("\n");
|
|
135
|
+
}
|
|
136
|
+
else if (data.file) {
|
|
137
|
+
backtrace = `${data.file}:${data.line}`;
|
|
138
|
+
}
|
|
139
|
+
data.backtrace = backtrace;
|
|
140
|
+
this.communicator.sendCommand(data);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* @returns {void}
|
|
144
|
+
*/
|
|
145
|
+
connectWebSocket() {
|
|
146
|
+
this.ws = new WebSocket("ws://localhost:1985");
|
|
147
|
+
this.communicator.ws = this.ws;
|
|
148
|
+
this.ws.addEventListener("error", digg(this, "communicator", "onError"));
|
|
149
|
+
this.ws.addEventListener("open", digg(this, "communicator", "onOpen"));
|
|
150
|
+
this.ws.addEventListener("message", (event) => this.communicator.onMessage(event.data));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* @returns {void}
|
|
154
|
+
*/
|
|
155
|
+
enableOnBrowser() {
|
|
156
|
+
this._enabled = true;
|
|
157
|
+
this.connectWebSocket();
|
|
158
|
+
this.connectOnError();
|
|
159
|
+
this.connectUnhandledRejection();
|
|
160
|
+
this.overrideConsoleLog();
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* @returns {boolean}
|
|
164
|
+
*/
|
|
165
|
+
getEnabled() { return this._enabled; }
|
|
166
|
+
/**
|
|
167
|
+
* @returns {EventEmitter}
|
|
168
|
+
*/
|
|
169
|
+
getEvents() { return this.events; }
|
|
170
|
+
/**
|
|
171
|
+
* @param {any} arg
|
|
172
|
+
* @param {any[]} [scannedObjects]
|
|
173
|
+
* @returns {any}
|
|
174
|
+
*/
|
|
175
|
+
consoleLogMessage(arg, scannedObjects = []) {
|
|
176
|
+
if (Array.isArray(arg)) {
|
|
177
|
+
if (scannedObjects.includes(arg)) {
|
|
178
|
+
return "[recursive]";
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
scannedObjects.push(arg);
|
|
182
|
+
}
|
|
183
|
+
const result = [];
|
|
184
|
+
for (const value of arg) {
|
|
185
|
+
result.push(this.consoleLogMessage(value, scannedObjects));
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
else if (Object.prototype.toString.call(arg) === '[object Object]') {
|
|
190
|
+
if (scannedObjects.includes(arg)) {
|
|
191
|
+
return "[recursive]";
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
scannedObjects.push(arg);
|
|
195
|
+
}
|
|
196
|
+
/** @type {Record<string, any>} */
|
|
197
|
+
const result = {};
|
|
198
|
+
for (const key in arg) {
|
|
199
|
+
result[key] = this.consoleLogMessage(arg[key], scannedObjects);
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
else if (typeof arg == "object") {
|
|
204
|
+
return `[object ${arg?.constructor?.name}]`;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
return arg;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* @param {function() : void} callback
|
|
212
|
+
* @returns {void}
|
|
213
|
+
*/
|
|
214
|
+
onInitialize(callback) {
|
|
215
|
+
this._onInitializeCallback = callback;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* @returns {void}
|
|
219
|
+
*/
|
|
220
|
+
overrideConsoleLog() {
|
|
221
|
+
if (this.originalConsoleError || this.originalConsoleLog) {
|
|
222
|
+
throw new Error("Console methods has already been overridden!");
|
|
223
|
+
}
|
|
224
|
+
this.originalConsoleError = console.error;
|
|
225
|
+
this.originalConsoleLog = console.log;
|
|
226
|
+
console.error = this.fakeConsoleError;
|
|
227
|
+
console.log = this.fakeConsoleLog;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* @param {string} sql
|
|
231
|
+
* @returns {Promise<Array<Record<string, any>>>}
|
|
232
|
+
*/
|
|
233
|
+
async sendQuery(sql) {
|
|
234
|
+
// @ts-expect-error
|
|
235
|
+
return await this.communicator.sendCommand({ type: "query", sql });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3lzdGVtLXRlc3QtYnJvd3Nlci1oZWxwZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvc3lzdGVtLXRlc3QtYnJvd3Nlci1oZWxwZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sTUFBTSxNQUFNLDZDQUE2QyxDQUFBO0FBQ2hFLE9BQU8sZUFBZSxNQUFNLG9FQUFvRSxDQUFBO0FBQ2hHLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxXQUFXLENBQUE7QUFDOUIsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGVBQWUsQ0FBQTtBQUUxQyxPQUFPLHNCQUFzQixNQUFNLCtCQUErQixDQUFBO0FBRWxFLHdFQUF3RTtBQUN4RSxNQUFNLE1BQU0sR0FBRztJQUNiLHVCQUF1QixFQUFFLElBQUk7Q0FDOUIsQ0FBQTtBQUVELE1BQU0sQ0FBQyxPQUFPLE9BQU8sdUJBQXVCO0lBQzFDLE1BQU0sQ0FBQyxPQUFPO1FBQ1osSUFBSSxDQUFDLE1BQU0sQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sSUFBSSxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQTtRQUMzRCxDQUFDO1FBRUQsT0FBTyxNQUFNLENBQUMsdUJBQXVCLENBQUE7SUFDdkMsQ0FBQztJQUVEO1FBZ0lBOzs7V0FHRztRQUNILHFCQUFnQixHQUFHLENBQUMsR0FBRyxJQUFJLEVBQUUsRUFBRTtZQUM3QixJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxFQUFDLElBQUksRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsRUFBQyxDQUFDLENBQUE7WUFFM0YsSUFBSSxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztnQkFDOUIsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQTtZQUMzQyxDQUFDO1FBQ0gsQ0FBQyxDQUFBO1FBRUQ7OztXQUdH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RyxDQUFBO1FBRXJDLE9BQU8sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFBO1FBQ3JDLE9BQU8sQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQTtJQUNuQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLFNBQVMsQ0FBQyxHQUFHO1FBQ2pCLG1CQUFtQjtRQUNuQixPQUFPLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsRUFBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBQyxDQUFDLENBQUE7SUFDbEUsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBDbGllbnQgZnJvbSBcInNjb3VuZHJlbC1yZW1vdGUtZXZhbC9idWlsZC9jbGllbnQvaW5kZXguanNcIlxuaW1wb3J0IENsaWVudFdlYlNvY2tldCBmcm9tIFwic2NvdW5kcmVsLXJlbW90ZS1ldmFsL2J1aWxkL2NsaWVudC9jb25uZWN0aW9ucy93ZWItc29ja2V0L2luZGV4LmpzXCJcbmltcG9ydCB7ZGlnZ30gZnJvbSBcImRpZ2dlcml6ZVwiXG5pbXBvcnQge0V2ZW50RW1pdHRlcn0gZnJvbSBcImV2ZW50ZW1pdHRlcjNcIlxuXG5pbXBvcnQgU3lzdGVtVGVzdENvbW11bmljYXRvciBmcm9tIFwiLi9zeXN0ZW0tdGVzdC1jb21tdW5pY2F0b3IuanNcIlxuXG4vKiogQHR5cGUge3tzeXN0ZW1UZXN0QnJvd3NlckhlbHBlcjogU3lzdGVtVGVzdEJyb3dzZXJIZWxwZXIgfCBudWxsfX0gKi9cbmNvbnN0IHNoYXJlZCA9IHtcbiAgc3lzdGVtVGVzdEJyb3dzZXJIZWxwZXI6IG51bGxcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3lzdGVtVGVzdEJyb3dzZXJIZWxwZXIge1xuICBzdGF0aWMgY3VycmVudCgpIHtcbiAgICBpZiAoIXNoYXJlZC5zeXN0ZW1UZXN0QnJvd3NlckhlbHBlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gY3VycmVudCBTeXN0ZW1UZXN0QnJvd3NlckhlbHBlciBzZXRcIilcbiAgICB9XG5cbiAgICByZXR1cm4gc2hhcmVkLnN5c3RlbVRlc3RCcm93c2VySGVscGVyXG4gIH1cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmNvbW11bmljYXRvciA9IG5ldyBTeXN0ZW1UZXN0Q29tbXVuaWNhdG9yKHtwYXJlbnQ6IHRoaXMsIG9uQ29tbWFuZDogdGhpcy5vbkNvbW1hbmR9KVxuICAgIHRoaXMuX2VuYWJsZWQgPSBmYWxzZVxuICAgIHRoaXMuZXZlbnRzID0gbmV3IEV2ZW50RW1pdHRlcigpXG5cbiAgICBzaGFyZWQuc3lzdGVtVGVzdEJyb3dzZXJIZWxwZXIgPSB0aGlzXG5cbiAgICB0aGlzLnN0YXJ0U2NvdW5kcmVsKClcbiAgfVxuXG4gIGFzeW5jIHN0YXJ0U2NvdW5kcmVsKCkge1xuICAgIHRoaXMuc2NvdW5kcmVsV3MgPSBuZXcgV2ViU29ja2V0KFwiaHR0cDovL2xvY2FsaG9zdDo4MDkwXCIpXG5cbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgdGhpcy5zY291bmRyZWxDbGllbnRXZWJTb2NrZXQgPSBuZXcgQ2xpZW50V2ViU29ja2V0KHRoaXMuc2NvdW5kcmVsV3MpXG5cbiAgICBhd2FpdCB0aGlzLnNjb3VuZHJlbENsaWVudFdlYlNvY2tldC53YWl0Rm9yT3BlbmVkKClcblxuICAgIHRoaXMuc2NvdW5kcmVsQ2xpZW50ID0gbmV3IENsaWVudCh0aGlzLnNjb3VuZHJlbENsaWVudFdlYlNvY2tldClcbiAgICB0aGlzLmV2ZW50cy5lbWl0KFwic2NvdW5kcmVsU3RhcnRlZFwiKVxuICB9XG5cbiAgd2FpdEZvclNjb3VuZHJlbFN0YXJ0ZWQoKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICBpZiAodGhpcy5zY291bmRyZWxDbGllbnQpIHtcbiAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmV2ZW50cy5vbmNlKFwic2NvdW5kcmVsU3RhcnRlZFwiLCAoKSA9PiB7XG4gICAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIGdldFNjb3VuZHJlbCgpIHtcbiAgICBpZiAoIXRoaXMuc2NvdW5kcmVsQ2xpZW50KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTY291bmRyZWwgY2xpZW50IGlzIG5vdCBzdGFydGVkIHlldFwiKVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnNjb3VuZHJlbENsaWVudFxuICB9XG5cbiAgY29ubmVjdE9uRXJyb3IoKSB7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCAoZXZlbnQpID0+IHtcbiAgICAgIHRoaXMuaGFuZGxlRXJyb3Ioe1xuICAgICAgICB0eXBlOiBcImVycm9yXCIsXG4gICAgICAgIGVycm9yOiBldmVudC5lcnJvcixcbiAgICAgICAgZXJyb3JDbGFzczogZXZlbnQuZXJyb3I/Lm5hbWUsXG4gICAgICAgIGZpbGU6IGV2ZW50LmZpbGVuYW1lLFxuICAgICAgICBsaW5lOiBldmVudC5saW5lbm8sXG4gICAgICAgIG1lc3NhZ2U6IGV2ZW50Lm1lc3NhZ2UgfHwgXCJVbmtub3duIGVycm9yXCIsXG4gICAgICAgIHVybDogd2luZG93LmxvY2F0aW9uLmhyZWZcbiAgICAgIH0pXG4gICAgfSlcbiAgfVxuXG4gIGNvbm5lY3RVbmhhbmRsZWRSZWplY3Rpb24oKSB7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJ1bmhhbmRsZWRyZWplY3Rpb25cIiwgKGV2ZW50KSA9PiB7XG4gICAgICB0aGlzLmhhbmRsZUVycm9yKHtcbiAgICAgICAgdHlwZTogXCJ1bmhhbmRsZWRyZWplY3Rpb25cIixcbiAgICAgICAgZXJyb3I6IGV2ZW50LnJlYXNvbixcbiAgICAgICAgZXJyb3JDbGFzczogXCJVbmhhbmRsZWRSZWplY3Rpb25cIixcbiAgICAgICAgbWVzc2FnZTogZXZlbnQucmVhc29uLm1lc3NhZ2UgfHwgZXZlbnQucmVhc29uIHx8IFwiVW5oYW5kbGVkIHByb21pc2UgcmVqZWN0aW9uIHdpdGhvdXQgYSBtZXNzYWdlXCIsXG4gICAgICAgIHVybDogd2luZG93LmxvY2F0aW9uLmhyZWZcbiAgICAgIH0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge29iamVjdH0gZGF0YVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2RhdGEuYmFja3RyYWNlXVxuICAgKiBAcGFyYW0ge0Vycm9yfSBbZGF0YS5lcnJvcl1cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtkYXRhLmVycm9yQ2xhc3NdXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbZGF0YS5maWxlXVxuICAgKiBAcGFyYW0ge251bWJlcn0gW2RhdGEubGluZV1cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtkYXRhLm1lc3NhZ2VdXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbZGF0YS50eXBlXVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2RhdGEudXJsXVxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGhhbmRsZUVycm9yKGRhdGEpIHtcbiAgICBsZXQgYmFja3RyYWNlXG5cbiAgICBpZiAoZGF0YS5lcnJvciAmJiBkYXRhLmVycm9yLnN0YWNrKSB7XG4gICAgICBiYWNrdHJhY2UgPSBkYXRhLmVycm9yLnN0YWNrLnNwbGl0KFwiXFxuXCIpXG4gICAgICBiYWNrdHJhY2Uuc2hpZnQoKVxuICAgICAgYmFja3RyYWNlID0gYmFja3RyYWNlLmpvaW4oXCJcXG5cIilcbiAgICB9IGVsc2UgaWYgKGRhdGEuZmlsZSkge1xuICAgICAgYmFja3RyYWNlID0gYCR7ZGF0YS5maWxlfToke2RhdGEubGluZX1gXG4gICAgfVxuXG4gICAgZGF0YS5iYWNrdHJhY2UgPSBiYWNrdHJhY2VcblxuICAgIHRoaXMuY29tbXVuaWNhdG9yLnNlbmRDb21tYW5kKGRhdGEpXG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBjb25uZWN0V2ViU29ja2V0KCkge1xuICAgIHRoaXMud3MgPSBuZXcgV2ViU29ja2V0KFwid3M6Ly9sb2NhbGhvc3Q6MTk4NVwiKVxuICAgIHRoaXMuY29tbXVuaWNhdG9yLndzID0gdGhpcy53c1xuICAgIHRoaXMud3MuYWRkRXZlbnRMaXN0ZW5lcihcImVycm9yXCIsIGRpZ2codGhpcywgXCJjb21tdW5pY2F0b3JcIiwgXCJvbkVycm9yXCIpKVxuICAgIHRoaXMud3MuYWRkRXZlbnRMaXN0ZW5lcihcIm9wZW5cIiwgZGlnZyh0aGlzLCBcImNvbW11bmljYXRvclwiLCBcIm9uT3BlblwiKSlcbiAgICB0aGlzLndzLmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIChldmVudCkgPT4gdGhpcy5jb21tdW5pY2F0b3Iub25NZXNzYWdlKGV2ZW50LmRhdGEpKVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgZW5hYmxlT25Ccm93c2VyKCkge1xuICAgIHRoaXMuX2VuYWJsZWQgPSB0cnVlXG4gICAgdGhpcy5jb25uZWN0V2ViU29ja2V0KClcbiAgICB0aGlzLmNvbm5lY3RPbkVycm9yKClcbiAgICB0aGlzLmNvbm5lY3RVbmhhbmRsZWRSZWplY3Rpb24oKVxuICAgIHRoaXMub3ZlcnJpZGVDb25zb2xlTG9nKClcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIGdldEVuYWJsZWQoKSB7IHJldHVybiB0aGlzLl9lbmFibGVkIH1cblxuICAvKipcbiAgICogQHJldHVybnMge0V2ZW50RW1pdHRlcn1cbiAgICovXG4gIGdldEV2ZW50cygpIHsgcmV0dXJuIHRoaXMuZXZlbnRzIH1cblxuICAvKipcbiAgICogQHBhcmFtIHthbnlbXX0gYXJnc1xuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGZha2VDb25zb2xlRXJyb3IgPSAoLi4uYXJncykgPT4ge1xuICAgIHRoaXMuY29tbXVuaWNhdG9yLnNlbmRDb21tYW5kKHt0eXBlOiBcImNvbnNvbGUuZXJyb3JcIiwgdmFsdWU6IHRoaXMuY29uc29sZUxvZ01lc3NhZ2UoYXJncyl9KVxuXG4gICAgaWYgKHRoaXMub3JpZ2luYWxDb25zb2xlRXJyb3IpIHtcbiAgICAgIHJldHVybiB0aGlzLm9yaWdpbmFsQ29uc29sZUVycm9yKC4uLmFyZ3MpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3NcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBmYWtlQ29uc29sZUxvZyA9ICguLi5hcmdzKSA9PiB7XG4gICAgdGhpcy5jb21tdW5pY2F0b3Iuc2VuZENvbW1hbmQoe3R5cGU6IFwiY29uc29sZS5sb2dcIiwgdmFsdWU6IHRoaXMuY29uc29sZUxvZ01lc3NhZ2UoYXJncyl9KVxuXG4gICAgaWYgKHRoaXMub3JpZ2luYWxDb25zb2xlTG9nKSB7XG4gICAgICByZXR1cm4gdGhpcy5vcmlnaW5hbENvbnNvbGVMb2coLi4uYXJncylcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHthbnl9IGFyZ1xuICAgKiBAcGFyYW0ge2FueVtdfSBbc2Nhbm5lZE9iamVjdHNdXG4gICAqIEByZXR1cm5zIHthbnl9XG4gICAqL1xuICBjb25zb2xlTG9nTWVzc2FnZShhcmcsIHNjYW5uZWRPYmplY3RzID0gW10pIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBpZiAoc2Nhbm5lZE9iamVjdHMuaW5jbHVkZXMoYXJnKSkge1xuICAgICAgICByZXR1cm4gXCJbcmVjdXJzaXZlXVwiXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzY2FubmVkT2JqZWN0cy5wdXNoKGFyZylcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzdWx0ID0gW11cblxuICAgICAgZm9yIChjb25zdCB2YWx1ZSBvZiBhcmcpIHtcbiAgICAgICAgcmVzdWx0LnB1c2godGhpcy5jb25zb2xlTG9nTWVzc2FnZSh2YWx1ZSwgc2Nhbm5lZE9iamVjdHMpKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0XG4gICAgfSBlbHNlIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYXJnKSA9PT0gJ1tvYmplY3QgT2JqZWN0XScpIHtcbiAgICAgIGlmIChzY2FubmVkT2JqZWN0cy5pbmNsdWRlcyhhcmcpKSB7XG4gICAgICAgIHJldHVybiBcIltyZWN1cnNpdmVdXCJcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNjYW5uZWRPYmplY3RzLnB1c2goYXJnKVxuICAgICAgfVxuXG4gICAgICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIGFueT59ICovXG4gICAgICBjb25zdCByZXN1bHQgPSB7fVxuXG4gICAgICBmb3IgKGNvbnN0IGtleSBpbiBhcmcpIHtcbiAgICAgICAgcmVzdWx0W2tleV0gPSB0aGlzLmNvbnNvbGVMb2dNZXNzYWdlKGFyZ1trZXldLCBzY2FubmVkT2JqZWN0cylcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3VsdFxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyZyA9PSBcIm9iamVjdFwiKSB7XG4gICAgICByZXR1cm4gYFtvYmplY3QgJHthcmc/LmNvbnN0cnVjdG9yPy5uYW1lfV1gXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBhcmdcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHt7ZGF0YToge3BhdGg6IHN0cmluZywgdHlwZTogc3RyaW5nfX19IGFyZ3NcbiAgICogQHJldHVybnMge1Byb21pc2U8e3Jlc3VsdDogc3RyaW5nfSB8IHZvaWQ+fVxuICAgKi9cbiAgb25Db21tYW5kID0gYXN5bmMgKHtkYXRhfSkgPT4ge1xuICAgIGlmIChkYXRhLnR5cGUgPT0gXCJpbml0aWFsaXplXCIpIHtcbiAgICAgIHRoaXMuZXZlbnRzLmVtaXQoXCJpbml0aWFsaXplXCIpXG5cbiAgICAgIGlmICh0aGlzLl9vbkluaXRpYWxpemVDYWxsYmFjaykge1xuICAgICAgICBhd2FpdCB0aGlzLl9vbkluaXRpYWxpemVDYWxsYmFjaygpXG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7cmVzdWx0OiBcImluaXRpYWxpemVkXCJ9XG4gICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT0gXCJ2aXNpdFwiKSB7XG4gICAgICB0aGlzLmV2ZW50cy5lbWl0KFwibmF2aWdhdGVcIiwge3BhdGg6IGRhdGEucGF0aH0pXG4gICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT0gXCJkaXNtaXNzVG9cIikge1xuICAgICAgdGhpcy5ldmVudHMuZW1pdChcImRpc21pc3NUb1wiLCB7cGF0aDogZGF0YS5wYXRofSlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGNvbW1hbmQgdHlwZSBmb3IgU3lzdGVtVGVzdEJyb3dzZXJIZWxwZXI6ICR7ZGF0YS50eXBlfWApXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oKSA6IHZvaWR9IGNhbGxiYWNrXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgb25Jbml0aWFsaXplKGNhbGxiYWNrKSB7XG4gICAgdGhpcy5fb25Jbml0aWFsaXplQ2FsbGJhY2sgPSBjYWxsYmFja1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgb3ZlcnJpZGVDb25zb2xlTG9nKCkge1xuICAgIGlmICh0aGlzLm9yaWdpbmFsQ29uc29sZUVycm9yIHx8IHRoaXMub3JpZ2luYWxDb25zb2xlTG9nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb25zb2xlIG1ldGhvZHMgaGFzIGFscmVhZHkgYmVlbiBvdmVycmlkZGVuIVwiKVxuICAgIH1cblxuICAgIHRoaXMub3JpZ2luYWxDb25zb2xlRXJyb3IgPSBjb25zb2xlLmVycm9yXG4gICAgdGhpcy5vcmlnaW5hbENvbnNvbGVMb2cgPSBjb25zb2xlLmxvZ1xuXG4gICAgY29uc29sZS5lcnJvciA9IHRoaXMuZmFrZUNvbnNvbGVFcnJvclxuICAgIGNvbnNvbGUubG9nID0gdGhpcy5mYWtlQ29uc29sZUxvZ1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzcWxcbiAgICogQHJldHVybnMge1Byb21pc2U8QXJyYXk8UmVjb3JkPHN0cmluZywgYW55Pj4+fVxuICAgKi9cbiAgYXN5bmMgc2VuZFF1ZXJ5KHNxbCkge1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5jb21tdW5pY2F0b3Iuc2VuZENvbW1hbmQoe3R5cGU6IFwicXVlcnlcIiwgc3FsfSlcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
export default class SystemTestCommunicator {
|
|
3
|
+
/**
|
|
4
|
+
* @param {object} args
|
|
5
|
+
* @param {(args: Record<string, any>) => Promise<{result: string} | void>} args.onCommand
|
|
6
|
+
* @param {object} [args.parent]
|
|
7
|
+
*/
|
|
8
|
+
constructor({ onCommand, parent }) {
|
|
9
|
+
/** @type {Record<string, {resolve: (data: any) => void, reject: (data: any) => void}>} */
|
|
10
|
+
this._responses = {};
|
|
11
|
+
/** @type {Record<string, any>} */
|
|
12
|
+
this._sendQueue = [];
|
|
13
|
+
this._sendQueueCount = 0;
|
|
14
|
+
/** @type {WebSocket | null} */
|
|
15
|
+
this.ws = null;
|
|
16
|
+
/** @param {Error} error */
|
|
17
|
+
this.onError = (error) => {
|
|
18
|
+
console.error("onWebSocketClientError", error);
|
|
19
|
+
};
|
|
20
|
+
/** @param {string} rawData */
|
|
21
|
+
this.onMessage = async (rawData) => {
|
|
22
|
+
/** @type {{data: any, id: number, type: string, isTrusted?: boolean}} */
|
|
23
|
+
const data = JSON.parse(rawData);
|
|
24
|
+
if (data.isTrusted) {
|
|
25
|
+
// Ignore
|
|
26
|
+
}
|
|
27
|
+
else if (data.type == "command") {
|
|
28
|
+
try {
|
|
29
|
+
const result = await this.onCommand({ data: data.data });
|
|
30
|
+
this.respond(data.id, { result });
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (error instanceof Error) {
|
|
34
|
+
this.respond(data.id, { error: error.message });
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
this.respond(data.id, { error: error });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (data.type == "response") {
|
|
42
|
+
const response = this._responses[data.id];
|
|
43
|
+
if (!response) {
|
|
44
|
+
throw new Error(`No such response: ${data.id}`);
|
|
45
|
+
}
|
|
46
|
+
delete this._responses[data.id];
|
|
47
|
+
if (data.data.error) {
|
|
48
|
+
response.reject(data.data.error);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
response.resolve(data.data.result);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
throw new Error(`Unknown type for SystemTestCommunicator: ${data.type}: ${JSON.stringify(data)}`);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
this.onOpen = () => {
|
|
59
|
+
this.flushSendQueue();
|
|
60
|
+
};
|
|
61
|
+
this.onCommand = onCommand;
|
|
62
|
+
this.parent = parent;
|
|
63
|
+
}
|
|
64
|
+
flushSendQueue() {
|
|
65
|
+
while (this._sendQueue.length !== 0) {
|
|
66
|
+
const data = this._sendQueue.shift();
|
|
67
|
+
if (!this.ws || this.ws.readyState !== 1) {
|
|
68
|
+
throw new Error("WebSocket is not open");
|
|
69
|
+
}
|
|
70
|
+
this.ws.send(JSON.stringify(data));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* @param {Record<string, any>} data
|
|
75
|
+
* @returns {void}
|
|
76
|
+
*/
|
|
77
|
+
send(data) {
|
|
78
|
+
this._sendQueue.push(data);
|
|
79
|
+
if (this.ws.readyState == 1) {
|
|
80
|
+
this.flushSendQueue();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Sends a command and returns a promise that resolves with the response.
|
|
85
|
+
* @param {Record<string, any>} data - The command data to send.
|
|
86
|
+
* @returns {Promise<void>} A promise that resolves with the response data.
|
|
87
|
+
*/
|
|
88
|
+
sendCommand(data) {
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
const id = this._sendQueueCount;
|
|
91
|
+
this._sendQueueCount += 1;
|
|
92
|
+
this._responses[id] = { resolve, reject };
|
|
93
|
+
this.send({ type: "command", id, data });
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* @param {number} id
|
|
98
|
+
* @param {Record<string, any>} data
|
|
99
|
+
* @returns {void}
|
|
100
|
+
*/
|
|
101
|
+
respond(id, data) {
|
|
102
|
+
this.send({ type: "response", id, data });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3lzdGVtLXRlc3QtY29tbXVuaWNhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3N5c3RlbS10ZXN0LWNvbW11bmljYXRvci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosTUFBTSxDQUFDLE9BQU8sT0FBTyxzQkFBc0I7SUFZekM7Ozs7T0FJRztJQUNILFlBQVksRUFBQyxTQUFTLEVBQUUsTUFBTSxFQUFDO1FBaEIvQiwwRkFBMEY7UUFDMUYsZUFBVSxHQUFHLEVBQUUsQ0FBQTtRQUVmLGtDQUFrQztRQUNsQyxlQUFVLEdBQUcsRUFBRSxDQUFBO1FBRWYsb0JBQWUsR0FBRyxDQUFDLENBQUE7UUFFbkIsK0JBQStCO1FBQy9CLE9BQUUsR0FBRyxJQUFJLENBQUE7UUF3QlQsMkJBQTJCO1FBQzNCLFlBQU8sR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ2xCLE9BQU8sQ0FBQyxLQUFLLENBQUMsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLENBQUE7UUFDaEQsQ0FBQyxDQUFBO1FBRUQsOEJBQThCO1FBQzlCLGNBQVMsR0FBRyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7WUFDNUIseUVBQXlFO1lBQ3pFLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7WUFFaEMsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ25CLFNBQVM7WUFDWCxDQUFDO2lCQUFNLElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxTQUFTLEVBQUUsQ0FBQztnQkFDbEMsSUFBSSxDQUFDO29CQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFDLENBQUMsQ0FBQTtvQkFFdEQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUMsTUFBTSxFQUFDLENBQUMsQ0FBQTtnQkFD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QUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUMsQ0FBQTtZQUV2QyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQTtRQUN4QyxDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsT0FBTyxDQUFDLEVBQUUsRUFBRSxJQUFJO1FBQ2QsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBQyxDQUFDLENBQUE7SUFDekMsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN5c3RlbVRlc3RDb21tdW5pY2F0b3Ige1xuICAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIHtyZXNvbHZlOiAoZGF0YTogYW55KSA9PiB2b2lkLCByZWplY3Q6IChkYXRhOiBhbnkpID0+IHZvaWR9Pn0gKi9cbiAgX3Jlc3BvbnNlcyA9IHt9XG5cbiAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSAqL1xuICBfc2VuZFF1ZXVlID0gW11cblxuICBfc2VuZFF1ZXVlQ291bnQgPSAwXG5cbiAgLyoqIEB0eXBlIHtXZWJTb2NrZXQgfCBudWxsfSAqL1xuICB3cyA9IG51bGxcblxuICAvKipcbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3NcbiAgICogQHBhcmFtIHsoYXJnczogUmVjb3JkPHN0cmluZywgYW55PikgPT4gUHJvbWlzZTx7cmVzdWx0OiBzdHJpbmd9IHwgdm9pZD59IGFyZ3Mub25Db21tYW5kXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBbYXJncy5wYXJlbnRdXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7b25Db21tYW5kLCBwYXJlbnR9KSB7XG4gICAgdGhpcy5vbkNvbW1hbmQgPSBvbkNvbW1hbmRcbiAgICB0aGlzLnBhcmVudCA9IHBhcmVudFxuICB9XG5cbiAgZmx1c2hTZW5kUXVldWUoKSB7XG4gICAgd2hpbGUgKHRoaXMuX3NlbmRRdWV1ZS5sZW5ndGggIT09IDApIHtcbiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLl9zZW5kUXVldWUuc2hpZnQoKVxuXG4gICAgICBpZiAoIXRoaXMud3MgfHwgdGhpcy53cy5yZWFkeVN0YXRlICE9PSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIldlYlNvY2tldCBpcyBub3Qgb3BlblwiKVxuICAgICAgfVxuXG4gICAgICB0aGlzLndzLnNlbmQoSlNPTi5zdHJpbmdpZnkoZGF0YSkpXG4gICAgfVxuICB9XG5cbiAgLyoqIEBwYXJhbSB7RXJyb3J9IGVycm9yICovXG4gIG9uRXJyb3IgPSAoZXJyb3IpID0+IHtcbiAgICBjb25zb2xlLmVycm9yKFwib25XZWJTb2NrZXRDbGllbnRFcnJvclwiLCBlcnJvcilcbiAgfVxuXG4gIC8qKiBAcGFyYW0ge3N0cmluZ30gcmF3RGF0YSAqL1xuICBvbk1lc3NhZ2UgPSBhc3luYyAocmF3RGF0YSkgPT4ge1xuICAgIC8qKiBAdHlwZSB7e2RhdGE6IGFueSwgaWQ6IG51bWJlciwgdHlwZTogc3RyaW5nLCBpc1RydXN0ZWQ/OiBib29sZWFufX0gKi9cbiAgICBjb25zdCBkYXRhID0gSlNPTi5wYXJzZShyYXdEYXRhKVxuXG4gICAgaWYgKGRhdGEuaXNUcnVzdGVkKSB7XG4gICAgICAvLyBJZ25vcmVcbiAgICB9IGVsc2UgaWYgKGRhdGEudHlwZSA9PSBcImNvbW1hbmRcIikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5vbkNvbW1hbmQoe2RhdGE6IGRhdGEuZGF0YX0pXG5cbiAgICAgICAgdGhpcy5yZXNwb25kKGRhdGEuaWQsIHtyZXN1bHR9KVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICB0aGlzLnJlc3BvbmQoZGF0YS5pZCwge2Vycm9yOiBlcnJvci5tZXNzYWdlfSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnJlc3BvbmQoZGF0YS5pZCwge2Vycm9yOiBlcnJvcn0pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGRhdGEudHlwZSA9PSBcInJlc3BvbnNlXCIpIHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gdGhpcy5fcmVzcG9uc2VzW2RhdGEuaWRdXG5cbiAgICAgIGlmICghcmVzcG9uc2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBzdWNoIHJlc3BvbnNlOiAke2RhdGEuaWR9YClcbiAgICAgIH1cblxuICAgICAgZGVsZXRlIHRoaXMuX3Jlc3BvbnNlc1tkYXRhLmlkXVxuXG4gICAgICBpZiAoZGF0YS5kYXRhLmVycm9yKSB7XG4gICAgICAgIHJlc3BvbnNlLnJlamVjdChkYXRhLmRhdGEuZXJyb3IpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNwb25zZS5yZXNvbHZlKGRhdGEuZGF0YS5yZXN1bHQpXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biB0eXBlIGZvciBTeXN0ZW1UZXN0Q29tbXVuaWNhdG9yOiAke2RhdGEudHlwZX06ICR7SlNPTi5zdHJpbmdpZnkoZGF0YSl9YClcbiAgICB9XG4gIH1cblxuICBvbk9wZW4gPSAoKSA9PiB7XG4gICAgdGhpcy5mbHVzaFNlbmRRdWV1ZSgpXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBkYXRhXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc2VuZChkYXRhKSB7XG4gICAgdGhpcy5fc2VuZFF1ZXVlLnB1c2goZGF0YSlcblxuICAgIGlmICh0aGlzLndzLnJlYWR5U3RhdGUgPT0gMSkge1xuICAgICAgdGhpcy5mbHVzaFNlbmRRdWV1ZSgpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNlbmRzIGEgY29tbWFuZCBhbmQgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSByZXNwb25zZS5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBkYXRhIC0gVGhlIGNvbW1hbmQgZGF0YSB0byBzZW5kLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgcmVzcG9uc2UgZGF0YS5cbiAgICovXG4gIHNlbmRDb21tYW5kKGRhdGEpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY29uc3QgaWQgPSB0aGlzLl9zZW5kUXVldWVDb3VudFxuXG4gICAgICB0aGlzLl9zZW5kUXVldWVDb3VudCArPSAxXG4gICAgICB0aGlzLl9yZXNwb25zZXNbaWRdID0ge3Jlc29sdmUsIHJlamVjdH1cblxuICAgICAgdGhpcy5zZW5kKHt0eXBlOiBcImNvbW1hbmRcIiwgaWQsIGRhdGF9KVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IGlkXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gZGF0YVxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHJlc3BvbmQoaWQsIGRhdGEpIHtcbiAgICB0aGlzLnNlbmQoe3R5cGU6IFwicmVzcG9uc2VcIiwgaWQsIGRhdGF9KVxuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import http from "node:http";
|
|
4
|
+
import mime from "mime";
|
|
5
|
+
import url from "url";
|
|
6
|
+
export default class SystemTestHttpServer {
|
|
7
|
+
constructor() {
|
|
8
|
+
/**
|
|
9
|
+
* @param {http.IncomingMessage} request
|
|
10
|
+
* @param {http.ServerResponse} response
|
|
11
|
+
* @returns {Promise<void>}
|
|
12
|
+
*/
|
|
13
|
+
this.onHttpServerRequest = async (request, response) => {
|
|
14
|
+
if (!request.url) {
|
|
15
|
+
response.statusCode = 400;
|
|
16
|
+
response.end("Bad Request");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const parsedUrl = url.parse(request.url);
|
|
20
|
+
let filePath = `${process.cwd()}/dist${parsedUrl.pathname}`;
|
|
21
|
+
if (filePath.endsWith("/")) {
|
|
22
|
+
filePath += "index.html";
|
|
23
|
+
}
|
|
24
|
+
let fileExists;
|
|
25
|
+
try {
|
|
26
|
+
await fs.stat(filePath);
|
|
27
|
+
fileExists = true;
|
|
28
|
+
}
|
|
29
|
+
catch (_error) { // eslint-disable-line no-unused-vars
|
|
30
|
+
fileExists = false;
|
|
31
|
+
}
|
|
32
|
+
if (!fileExists) {
|
|
33
|
+
filePath = `${process.cwd()}/dist/index.html`;
|
|
34
|
+
}
|
|
35
|
+
const fileContent = await fs.readFile(filePath);
|
|
36
|
+
const mimeType = mime.getType(filePath);
|
|
37
|
+
response.statusCode = 200;
|
|
38
|
+
if (mimeType) {
|
|
39
|
+
response.setHeader("Content-Type", mimeType);
|
|
40
|
+
}
|
|
41
|
+
response.end(fileContent);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** @returns {void} */
|
|
45
|
+
close() {
|
|
46
|
+
if (!this.httpServer) {
|
|
47
|
+
throw new Error("HTTP server is not initialized");
|
|
48
|
+
}
|
|
49
|
+
this.httpServer.close();
|
|
50
|
+
}
|
|
51
|
+
/** @returns {Promise<void>} */
|
|
52
|
+
async start() {
|
|
53
|
+
this.basePath = await fs.realpath(`${__dirname}/../..`);
|
|
54
|
+
await this.startHttpServer();
|
|
55
|
+
}
|
|
56
|
+
/** @returns {Promise<void>} */
|
|
57
|
+
startHttpServer() {
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
this.httpServer = http.createServer(this.onHttpServerRequest);
|
|
60
|
+
this.httpServer.listen(1984, "localhost", () => {
|
|
61
|
+
resolve();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3lzdGVtLXRlc3QtaHR0cC1zZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvc3lzdGVtLXRlc3QtaHR0cC1zZXJ2ZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ2pDLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQTtBQUM1QixPQUFPLElBQUksTUFBTSxNQUFNLENBQUE7QUFDdkIsT0FBTyxHQUFHLE1BQU0sS0FBSyxDQUFBO0FBRXJCLE1BQU0sQ0FBQyxPQUFPLE9BQU8sb0JBQW9CO0lBQXpDO1FBVUU7Ozs7V0FJRztRQUNILHdCQUFtQixHQUFHLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEVBQUU7WUFDaEQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDakIsUUFBUSxDQUFDLFVBQVUsR0FBRyxHQUFHLENBQUE7Z0JBQ3pCLFFBQVEsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUE7Z0JBQzNCLE9BQU07WUFDUixDQUFDO1lBRUQsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUE7WUFDeEMsSUFBSSxRQUFRLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxFQUFFLFFBQVEsU0FBUyxDQUFDLFFBQVEsRUFBRSxDQUFBO1lBRTNELElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUMzQixRQUFRLElBQUksWUFBWSxDQUFBO1lBQzFCLENBQUM7WUFFRCxJQUFJLFVBQVUsQ0FBQTtZQUVkLElBQUksQ0FBQztnQkFDSCxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7Z0JBQ3ZCLFVBQVUsR0FBRyxJQUFJLENBQUE7WUFDbkIsQ0FBQztZQUFDLE9BQU8sTUFBTSxFQUFFLENBQUMsQ0FBQyxxQ0FBcUM7Z0JBQ3RELFVBQVUsR0FBRyxLQUFLLENBQUE7WUFDcEIsQ0FBQztZQUVELElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDaEIsUUFBUSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxrQkFBa0IsQ0FBQTtZQUMvQyxDQUFDO1lBRUQsTUFBTSxXQUFXLEdBQUcsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1lBQy9DLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7WUFFdkMsUUFBUSxDQUFDLFVBQVUsR0FBRyxHQUFHLENBQUE7WUFFekIsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDYixRQUFRLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxRQUFRLENBQUMsQ0FBQTtZQUM5QyxDQUFDO1lBRUQsUUFBUSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQTtRQUMzQixDQUFDLENBQUE7SUFpQkgsQ0FBQztJQXBFQyxzQkFBc0I7SUFDdEIsS0FBSztRQUNILElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFBO1FBQ25ELENBQUM7UUFFRCxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFBO0lBQ3pCLENBQUM7SUE4Q0QsK0JBQStCO0lBQy9CLEtBQUssQ0FBQyxLQUFLO1FBQ1QsSUFBSSxDQUFDLFFBQVEsR0FBRyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxTQUFTLFFBQVEsQ0FBQyxDQUFBO1FBQ3ZELE1BQU0sSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFBO0lBQzlCLENBQUM7SUFFRCwrQkFBK0I7SUFDL0IsZUFBZTtRQUNiLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUM3QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUE7WUFDN0QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxHQUFHLEVBQUU7Z0JBQzdDLE9BQU8sRUFBRSxDQUFBO1lBQ1gsQ0FBQyxDQUFDLENBQUE7UUFDSixDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgZnMgZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIlxuaW1wb3J0IGh0dHAgZnJvbSBcIm5vZGU6aHR0cFwiXG5pbXBvcnQgbWltZSBmcm9tIFwibWltZVwiXG5pbXBvcnQgdXJsIGZyb20gXCJ1cmxcIlxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTeXN0ZW1UZXN0SHR0cFNlcnZlciB7XG4gIC8qKiBAcmV0dXJucyB7dm9pZH0gKi9cbiAgY2xvc2UoKSB7XG4gICAgaWYgKCF0aGlzLmh0dHBTZXJ2ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkhUVFAgc2VydmVyIGlzIG5vdCBpbml0aWFsaXplZFwiKVxuICAgIH1cblxuICAgIHRoaXMuaHR0cFNlcnZlci5jbG9zZSgpXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtodHRwLkluY29taW5nTWVzc2FnZX0gcmVxdWVzdFxuICAgKiBAcGFyYW0ge2h0dHAuU2VydmVyUmVzcG9uc2V9IHJlc3BvbnNlXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgb25IdHRwU2VydmVyUmVxdWVzdCA9IGFzeW5jIChyZXF1ZXN0LCByZXNwb25zZSkgPT4ge1xuICAgIGlmICghcmVxdWVzdC51cmwpIHtcbiAgICAgIHJlc3BvbnNlLnN0YXR1c0NvZGUgPSA0MDBcbiAgICAgIHJlc3BvbnNlLmVuZChcIkJhZCBSZXF1ZXN0XCIpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBjb25zdCBwYXJzZWRVcmwgPSB1cmwucGFyc2UocmVxdWVzdC51cmwpXG4gICAgbGV0IGZpbGVQYXRoID0gYCR7cHJvY2Vzcy5jd2QoKX0vZGlzdCR7cGFyc2VkVXJsLnBhdGhuYW1lfWBcblxuICAgIGlmIChmaWxlUGF0aC5lbmRzV2l0aChcIi9cIikpIHtcbiAgICAgIGZpbGVQYXRoICs9IFwiaW5kZXguaHRtbFwiXG4gICAgfVxuXG4gICAgbGV0IGZpbGVFeGlzdHNcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmcy5zdGF0KGZpbGVQYXRoKVxuICAgICAgZmlsZUV4aXN0cyA9IHRydWVcbiAgICB9IGNhdGNoIChfZXJyb3IpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICAgICAgZmlsZUV4aXN0cyA9IGZhbHNlXG4gICAgfVxuXG4gICAgaWYgKCFmaWxlRXhpc3RzKSB7XG4gICAgICBmaWxlUGF0aCA9IGAke3Byb2Nlc3MuY3dkKCl9L2Rpc3QvaW5kZXguaHRtbGBcbiAgICB9XG5cbiAgICBjb25zdCBmaWxlQ29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoKVxuICAgIGNvbnN0IG1pbWVUeXBlID0gbWltZS5nZXRUeXBlKGZpbGVQYXRoKVxuXG4gICAgcmVzcG9uc2Uuc3RhdHVzQ29kZSA9IDIwMFxuXG4gICAgaWYgKG1pbWVUeXBlKSB7XG4gICAgICByZXNwb25zZS5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgbWltZVR5cGUpXG4gICAgfVxuXG4gICAgcmVzcG9uc2UuZW5kKGZpbGVDb250ZW50KVxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAqL1xuICBhc3luYyBzdGFydCgpIHtcbiAgICB0aGlzLmJhc2VQYXRoID0gYXdhaXQgZnMucmVhbHBhdGgoYCR7X19kaXJuYW1lfS8uLi8uLmApXG4gICAgYXdhaXQgdGhpcy5zdGFydEh0dHBTZXJ2ZXIoKVxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAqL1xuICBzdGFydEh0dHBTZXJ2ZXIoKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICB0aGlzLmh0dHBTZXJ2ZXIgPSBodHRwLmNyZWF0ZVNlcnZlcih0aGlzLm9uSHR0cFNlcnZlclJlcXVlc3QpXG4gICAgICB0aGlzLmh0dHBTZXJ2ZXIubGlzdGVuKDE5ODQsIFwibG9jYWxob3N0XCIsICgpID0+IHtcbiAgICAgICAgcmVzb2x2ZSgpXG4gICAgICB9KVxuICAgIH0pXG4gIH1cbn1cbiJdfQ==
|
|
@@ -34,6 +34,7 @@ export default class SystemTest {
|
|
|
34
34
|
_started: boolean;
|
|
35
35
|
_driverTimeouts: number;
|
|
36
36
|
_timeouts: number;
|
|
37
|
+
/** @returns {SystemTestCommunicator} */
|
|
37
38
|
getCommunicator(): SystemTestCommunicator;
|
|
38
39
|
_host: string;
|
|
39
40
|
_port: number;
|
|
@@ -45,9 +46,7 @@ export default class SystemTest {
|
|
|
45
46
|
* @returns {string | undefined}
|
|
46
47
|
*/
|
|
47
48
|
getBaseSelector(): string | undefined;
|
|
48
|
-
/**
|
|
49
|
-
* @returns {import("selenium-webdriver").WebDriver}
|
|
50
|
-
*/
|
|
49
|
+
/** @returns {import("selenium-webdriver").WebDriver} */
|
|
51
50
|
getDriver(): import("selenium-webdriver").WebDriver;
|
|
52
51
|
/**
|
|
53
52
|
* Sets the base selector for scoping element searches
|
|
@@ -76,7 +75,7 @@ export default class SystemTest {
|
|
|
76
75
|
/**
|
|
77
76
|
* Finds all elements by CSS selector
|
|
78
77
|
* @param {string} selector
|
|
79
|
-
* @param {object} args
|
|
78
|
+
* @param {object} [args]
|
|
80
79
|
* @param {number} [args.timeout]
|
|
81
80
|
* @param {boolean} [args.visible]
|
|
82
81
|
* @param {boolean} [args.useBaseSelector]
|
|
@@ -96,17 +95,17 @@ export default class SystemTest {
|
|
|
96
95
|
/**
|
|
97
96
|
* Finds a single element by CSS selector
|
|
98
97
|
* @param {string} selector
|
|
99
|
-
* @param {object} args
|
|
98
|
+
* @param {object} [args]
|
|
100
99
|
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
101
100
|
*/
|
|
102
101
|
find(selector: string, args?: object): Promise<import("selenium-webdriver").WebElement>;
|
|
103
102
|
/**
|
|
104
103
|
* Finds a single element by test ID
|
|
105
104
|
* @param {string} testID
|
|
106
|
-
* @param {object} args
|
|
105
|
+
* @param {object} [args]
|
|
107
106
|
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
108
107
|
*/
|
|
109
|
-
findByTestID(testID: string, args
|
|
108
|
+
findByTestID(testID: string, args?: object): Promise<import("selenium-webdriver").WebElement>;
|
|
110
109
|
/**
|
|
111
110
|
* @param {string|import("selenium-webdriver").WebElement} elementOrIdentifier
|
|
112
111
|
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
@@ -124,20 +123,16 @@ export default class SystemTest {
|
|
|
124
123
|
* @returns {Promise<string[]>}
|
|
125
124
|
*/
|
|
126
125
|
getBrowserLogs(): Promise<string[]>;
|
|
127
|
-
/**
|
|
128
|
-
* @returns {Promise<string>}
|
|
129
|
-
*/
|
|
126
|
+
/** @returns {Promise<string>} */
|
|
130
127
|
getCurrentUrl(): Promise<string>;
|
|
131
|
-
/**
|
|
132
|
-
* @returns {number}
|
|
133
|
-
*/
|
|
128
|
+
/** @returns {number} */
|
|
134
129
|
getTimeouts(): number;
|
|
135
130
|
/**
|
|
136
131
|
* Interacts with an element by calling a method on it with the given arguments.
|
|
137
132
|
* Retrying on ElementNotInteractableError.
|
|
138
|
-
* @param {import("selenium-webdriver").WebElement|string} elementOrIdentifier
|
|
139
|
-
* @param {string} methodName
|
|
140
|
-
* @param {...any} args
|
|
133
|
+
* @param {import("selenium-webdriver").WebElement|string} elementOrIdentifier The element or a CSS selector to find the element.
|
|
134
|
+
* @param {string} methodName The method name to call on the element.
|
|
135
|
+
* @param {...any} args Arguments to pass to the method.
|
|
141
136
|
* @returns {Promise<any>}
|
|
142
137
|
*/
|
|
143
138
|
interact(elementOrIdentifier: import("selenium-webdriver").WebElement | string, methodName: string, ...args: any[]): Promise<any>;
|
|
@@ -149,11 +144,11 @@ export default class SystemTest {
|
|
|
149
144
|
expectNoElement(selector: string): Promise<void>;
|
|
150
145
|
/**
|
|
151
146
|
* @param {string} selector
|
|
152
|
-
* @param {object} args
|
|
147
|
+
* @param {object} [args]
|
|
153
148
|
* @param {boolean} [args.useBaseSelector]
|
|
154
149
|
* @returns {Promise<void>}
|
|
155
150
|
*/
|
|
156
|
-
waitForNoSelector(selector: string, args
|
|
151
|
+
waitForNoSelector(selector: string, args?: {
|
|
157
152
|
useBaseSelector?: boolean;
|
|
158
153
|
}): Promise<void>;
|
|
159
154
|
/**
|
|
@@ -167,9 +162,7 @@ export default class SystemTest {
|
|
|
167
162
|
* @returns {Promise<void>}
|
|
168
163
|
*/
|
|
169
164
|
expectNotificationMessage(expectedNotificationMessage: string): Promise<void>;
|
|
170
|
-
/**
|
|
171
|
-
* @returns {Promise<void>}
|
|
172
|
-
*/
|
|
165
|
+
/** @returns {Promise<void>} */
|
|
173
166
|
dismissNotificationMessages(): Promise<void>;
|
|
174
167
|
/**
|
|
175
168
|
* Indicates whether the system test has been started
|
|
@@ -249,9 +242,7 @@ export default class SystemTest {
|
|
|
249
242
|
*/
|
|
250
243
|
onWebSocketConnection: (ws: WebSocket) => Promise<void>;
|
|
251
244
|
ws: WebSocket;
|
|
252
|
-
/**
|
|
253
|
-
* @returns {void}
|
|
254
|
-
*/
|
|
245
|
+
/** @returns {void} */
|
|
255
246
|
onWebSocketClose: () => void;
|
|
256
247
|
/**
|
|
257
248
|
* Handles an error reported from the browser
|