system-testing 1.0.78 → 1.0.79
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/README.md +219 -6
- package/build/browser-command-client.d.ts +19 -0
- package/build/browser-command-client.js +39 -0
- package/build/browser-command-runner.d.ts +27 -0
- package/build/browser-command-runner.js +144 -0
- package/build/browser-process.d.ts +45 -0
- package/build/browser-process.js +127 -0
- package/build/browser-registry.d.ts +34 -0
- package/build/browser-registry.js +110 -0
- package/build/browser.d.ts +222 -0
- package/build/browser.js +358 -0
- package/build/cli-helpers.d.ts +16 -0
- package/build/cli-helpers.js +141 -0
- package/build/cli.d.ts +2 -0
- package/build/cli.js +72 -0
- package/build/drivers/webdriver-driver.d.ts +4 -4
- package/build/drivers/webdriver-driver.js +10 -9
- package/build/index.d.ts +9 -1
- package/build/index.js +10 -3
- package/build/system-test-browser-helper.d.ts +6 -12
- package/build/system-test-browser-helper.js +12 -13
- package/build/system-test.d.ts +3 -189
- package/build/system-test.js +6 -220
- package/build/use-system-test-expo.d.ts +16 -0
- package/build/use-system-test-expo.js +34 -0
- package/build/use-system-test-react-native.d.ts +25 -0
- package/build/use-system-test-react-native.js +20 -0
- package/build/use-system-test-shape-hook.d.ts +35 -0
- package/build/use-system-test-shape-hook.js +74 -0
- package/build/use-system-test.d.ts +19 -10
- package/build/use-system-test.js +26 -72
- package/package.json +9 -3
package/build/browser.js
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import moment from "moment";
|
|
4
|
+
import { prettify } from "htmlfy";
|
|
5
|
+
import timeout from "awaitery/build/timeout.js";
|
|
6
|
+
import SeleniumDriver from "./drivers/selenium-driver.js";
|
|
7
|
+
import AppiumDriver from "./drivers/appium-driver.js";
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {object} BrowserArgs
|
|
10
|
+
* @property {boolean} [debug] Enable debug logging.
|
|
11
|
+
* @property {BrowserDriverConfig} [driver] Driver configuration.
|
|
12
|
+
* @property {import("./system-test-communicator.js").default} [communicator] Optional command communicator for helper-driven navigation.
|
|
13
|
+
* @property {string} [screenshotsPath] Directory used for saved screenshots and browser artifacts.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {object} BrowserDriverConfig
|
|
17
|
+
* @property {"selenium"|"appium"} [type] Driver implementation to use.
|
|
18
|
+
* @property {Record<string, any>} [options] Driver-specific options.
|
|
19
|
+
*/
|
|
20
|
+
/** Generic browser session wrapper around the configured driver. */
|
|
21
|
+
export default class Browser {
|
|
22
|
+
/** @param {BrowserArgs} [args] */
|
|
23
|
+
constructor({ debug = false, driver, communicator, screenshotsPath = `${process.cwd()}/tmp/screenshots`, ...restArgs } = {}) {
|
|
24
|
+
/** @type {import("selenium-webdriver").WebDriver | undefined} */
|
|
25
|
+
this.driver = undefined;
|
|
26
|
+
/** @type {import("./drivers/webdriver-driver.js").default | undefined} */
|
|
27
|
+
this.driverAdapter = undefined;
|
|
28
|
+
this._debug = false;
|
|
29
|
+
/** @type {BrowserDriverConfig | undefined} */
|
|
30
|
+
this._driverConfig = undefined;
|
|
31
|
+
/** @type {Error | undefined} */
|
|
32
|
+
this._httpServerError = undefined;
|
|
33
|
+
/**
|
|
34
|
+
* @param {Error} error
|
|
35
|
+
* @returns {void}
|
|
36
|
+
*/
|
|
37
|
+
this.onHttpServerError = (error) => {
|
|
38
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
39
|
+
this._httpServerError = error instanceof Error ? error : new Error(errorMessage);
|
|
40
|
+
console.error(`HTTP server error: ${errorMessage}`);
|
|
41
|
+
};
|
|
42
|
+
const restArgsKeys = Object.keys(restArgs);
|
|
43
|
+
if (restArgsKeys.length > 0) {
|
|
44
|
+
throw new Error(`Unknown browser arguments: ${restArgsKeys.join(", ")}`);
|
|
45
|
+
}
|
|
46
|
+
this._debug = debug;
|
|
47
|
+
this._driverConfig = driver;
|
|
48
|
+
this._screenshotsPath = screenshotsPath;
|
|
49
|
+
this.communicator = communicator;
|
|
50
|
+
this.driverAdapter = this.createDriver(driver);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* @param {BrowserDriverConfig} [driverConfig]
|
|
54
|
+
* @returns {import("./drivers/webdriver-driver.js").default}
|
|
55
|
+
*/
|
|
56
|
+
createDriver(driverConfig = {}) {
|
|
57
|
+
const { type = "selenium", options, ...restArgs } = driverConfig;
|
|
58
|
+
const restArgsKeys = Object.keys(restArgs);
|
|
59
|
+
if (restArgsKeys.length > 0) {
|
|
60
|
+
throw new Error(`Unknown driver args: ${restArgsKeys.join(", ")}`);
|
|
61
|
+
}
|
|
62
|
+
if (type === "selenium") {
|
|
63
|
+
return new SeleniumDriver({ browser: this, options });
|
|
64
|
+
}
|
|
65
|
+
if (type === "appium") {
|
|
66
|
+
return new AppiumDriver({ browser: this, options });
|
|
67
|
+
}
|
|
68
|
+
throw new Error(`Unsupported driver type: ${type}`);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* @param {import("./system-test-communicator.js").default | undefined} communicator
|
|
72
|
+
* @returns {void}
|
|
73
|
+
*/
|
|
74
|
+
setCommunicator(communicator) {
|
|
75
|
+
this.communicator = communicator;
|
|
76
|
+
}
|
|
77
|
+
/** @returns {boolean} */
|
|
78
|
+
communicatorExists() {
|
|
79
|
+
return Boolean(this.communicator);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* @param {string} baseSelector
|
|
83
|
+
* @returns {void}
|
|
84
|
+
*/
|
|
85
|
+
setBaseSelector(baseSelector) { this._baseSelector = baseSelector; }
|
|
86
|
+
/** @returns {string | undefined} */
|
|
87
|
+
getBaseSelector() { return this._baseSelector; }
|
|
88
|
+
/**
|
|
89
|
+
* @param {string} selector
|
|
90
|
+
* @returns {string}
|
|
91
|
+
*/
|
|
92
|
+
getSelector(selector) {
|
|
93
|
+
return this.getBaseSelector() ? `${this.getBaseSelector()} ${selector}` : selector;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* @param {...any} args
|
|
97
|
+
* @returns {void}
|
|
98
|
+
*/
|
|
99
|
+
debugError(...args) {
|
|
100
|
+
console.error("[Browser error]", ...args);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* @param {...any} args
|
|
104
|
+
* @returns {void}
|
|
105
|
+
*/
|
|
106
|
+
debugLog(...args) {
|
|
107
|
+
if (this._debug) {
|
|
108
|
+
console.log("[Browser debug]", ...args);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** @returns {void} */
|
|
112
|
+
throwIfHttpServerError() {
|
|
113
|
+
if (this._httpServerError) {
|
|
114
|
+
throw new Error(`HTTP server error: ${this._httpServerError.message}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** @returns {import("selenium-webdriver").WebDriver} */
|
|
118
|
+
getDriver() {
|
|
119
|
+
return this.getDriverAdapter().getWebDriver();
|
|
120
|
+
}
|
|
121
|
+
/** @returns {import("./drivers/webdriver-driver.js").default} */
|
|
122
|
+
getDriverAdapter() {
|
|
123
|
+
if (!this.driverAdapter) {
|
|
124
|
+
throw new Error("Driver hasn't been initialized yet");
|
|
125
|
+
}
|
|
126
|
+
return this.driverAdapter;
|
|
127
|
+
}
|
|
128
|
+
/** @returns {number} */
|
|
129
|
+
getTimeouts() { return this.getDriverAdapter().getTimeouts(); }
|
|
130
|
+
/** @returns {Promise<void>} */
|
|
131
|
+
async restoreTimeouts() {
|
|
132
|
+
await this.getDriverAdapter().restoreTimeouts();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* @param {number} newTimeout
|
|
136
|
+
* @returns {Promise<void>}
|
|
137
|
+
*/
|
|
138
|
+
async driverSetTimeouts(newTimeout) {
|
|
139
|
+
await this.getDriverAdapter().driverSetTimeouts(newTimeout);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* @param {number} newTimeout
|
|
143
|
+
* @returns {Promise<void>}
|
|
144
|
+
*/
|
|
145
|
+
async setTimeouts(newTimeout) {
|
|
146
|
+
await this.getDriverAdapter().setTimeouts(newTimeout);
|
|
147
|
+
}
|
|
148
|
+
/** @returns {Promise<string[]>} */
|
|
149
|
+
async getBrowserLogs() {
|
|
150
|
+
return await this.getDriverAdapter().getBrowserLogs();
|
|
151
|
+
}
|
|
152
|
+
/** @returns {Promise<string>} */
|
|
153
|
+
async getCurrentUrl() {
|
|
154
|
+
return await this.getDriverAdapter().getCurrentUrl();
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* @param {string} selector
|
|
158
|
+
* @param {import("./system-test.js").FindArgs} [args]
|
|
159
|
+
* @returns {Promise<import("selenium-webdriver").WebElement[]>}
|
|
160
|
+
*/
|
|
161
|
+
async all(selector, args = {}) {
|
|
162
|
+
return await this.getDriverAdapter().all(selector, args);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* @param {string} selector
|
|
166
|
+
* @param {import("./system-test.js").FindArgs} [args]
|
|
167
|
+
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
168
|
+
*/
|
|
169
|
+
async find(selector, args = {}) {
|
|
170
|
+
return await this.getDriverAdapter().find(selector, args);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* @param {string} testID
|
|
174
|
+
* @param {import("./system-test.js").FindArgs} [args]
|
|
175
|
+
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
176
|
+
*/
|
|
177
|
+
async findByTestID(testID, args) {
|
|
178
|
+
return await this.getDriverAdapter().findByTestID(testID, args);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* @param {string} selector
|
|
182
|
+
* @param {import("./system-test.js").FindArgs} [args]
|
|
183
|
+
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
184
|
+
*/
|
|
185
|
+
async findNoWait(selector, args = {}) {
|
|
186
|
+
return await this.getDriverAdapter().findNoWait(selector, args);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* @param {string | import("selenium-webdriver").WebElement} elementOrIdentifier
|
|
190
|
+
* @param {import("./system-test.js").FindArgs} [args]
|
|
191
|
+
* @returns {Promise<void>}
|
|
192
|
+
*/
|
|
193
|
+
async click(elementOrIdentifier, args) {
|
|
194
|
+
await this.getDriverAdapter().click(elementOrIdentifier, args);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* @param {import("selenium-webdriver").WebElement|string|{selector: string} & import("./system-test.js").FindArgs} elementOrIdentifier
|
|
198
|
+
* @param {string} methodName
|
|
199
|
+
* @param {...any} args
|
|
200
|
+
* @returns {Promise<any>}
|
|
201
|
+
*/
|
|
202
|
+
async interact(elementOrIdentifier, methodName, ...args) {
|
|
203
|
+
return await this.getDriverAdapter().interact(elementOrIdentifier, methodName, ...args);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* @param {string} selector
|
|
207
|
+
* @param {import("./system-test.js").WaitForNoSelectorArgs} [args]
|
|
208
|
+
* @returns {Promise<void>}
|
|
209
|
+
*/
|
|
210
|
+
async waitForNoSelector(selector, args = {}) {
|
|
211
|
+
await this.getDriverAdapter().waitForNoSelector(selector, args);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* @param {string} selector
|
|
215
|
+
* @param {import("./system-test.js").FindArgs} [args]
|
|
216
|
+
* @returns {Promise<void>}
|
|
217
|
+
*/
|
|
218
|
+
async expectNoElement(selector, args = {}) {
|
|
219
|
+
let found = false;
|
|
220
|
+
try {
|
|
221
|
+
await this.findNoWait(selector, args);
|
|
222
|
+
found = true;
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
if (error instanceof Error && error.message.startsWith("Element couldn't be found after ")) {
|
|
226
|
+
// Ignore
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (found) {
|
|
233
|
+
throw new Error(`Expected not to find: ${selector}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/** @returns {Promise<string>} */
|
|
237
|
+
async getHTML() {
|
|
238
|
+
return await this.getDriverAdapter().getHTML();
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* @param {string} path
|
|
242
|
+
* @returns {Promise<void>}
|
|
243
|
+
*/
|
|
244
|
+
async driverVisit(path) {
|
|
245
|
+
await this.getDriverAdapter().driverVisit(path);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* @param {string} type
|
|
249
|
+
* @param {string} path
|
|
250
|
+
* @returns {Promise<void>}
|
|
251
|
+
*/
|
|
252
|
+
async sendBrowserCommand(type, path) {
|
|
253
|
+
if (!this.communicator) {
|
|
254
|
+
throw new Error("Communicator hasn't been initialized yet");
|
|
255
|
+
}
|
|
256
|
+
await timeout({ timeout: this.getTimeouts(), errorMessage: `timeout while sending browser command ${type}: ${path}` }, async () => await this.communicator.sendCommand({ type, path }));
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Visits a path using the injected browser helper when available, otherwise navigates directly with the driver.
|
|
260
|
+
* @param {string} path
|
|
261
|
+
* @returns {Promise<void>}
|
|
262
|
+
*/
|
|
263
|
+
async visit(path) {
|
|
264
|
+
if (this.communicatorExists()) {
|
|
265
|
+
await this.sendBrowserCommand("visit", path);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
await timeout({ timeout: this.getTimeouts(), errorMessage: `timeout while visiting path: ${path}` }, async () => await this.driverVisit(path));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Dismisses to a path via the injected browser helper when available, otherwise navigates directly with the driver.
|
|
273
|
+
* @param {string} path
|
|
274
|
+
* @returns {Promise<void>}
|
|
275
|
+
*/
|
|
276
|
+
async dismissTo(path) {
|
|
277
|
+
if (this.communicatorExists()) {
|
|
278
|
+
await this.sendBrowserCommand("dismissTo", path);
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
await timeout({ timeout: this.getTimeouts(), errorMessage: `timeout while dismissing to path: ${path}` }, async () => await this.driverVisit(path));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Formats browser logs for console output and truncates overly long output.
|
|
286
|
+
* @param {string[]} logs
|
|
287
|
+
* @param {number} [maxLines]
|
|
288
|
+
* @returns {string[]}
|
|
289
|
+
*/
|
|
290
|
+
formatBrowserLogsForConsole(logs, maxLines = 200) {
|
|
291
|
+
if (!Array.isArray(logs) || logs.length === 0) {
|
|
292
|
+
return ["(no browser logs)"];
|
|
293
|
+
}
|
|
294
|
+
if (logs.length <= maxLines) {
|
|
295
|
+
return logs;
|
|
296
|
+
}
|
|
297
|
+
const keptLogs = logs.slice(logs.length - maxLines);
|
|
298
|
+
const hiddenCount = logs.length - maxLines;
|
|
299
|
+
return [`(showing last ${maxLines} of ${logs.length} browser logs, ${hiddenCount} omitted)`, ...keptLogs];
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* @param {string[]} logs
|
|
303
|
+
* @returns {void}
|
|
304
|
+
*/
|
|
305
|
+
printBrowserLogsForFailure(logs) {
|
|
306
|
+
console.log("Browser logs:");
|
|
307
|
+
for (const line of this.formatBrowserLogsForConsole(logs)) {
|
|
308
|
+
console.log(line);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Takes a screenshot, writes HTML/browser logs to disk, and returns the collected artifacts.
|
|
313
|
+
* @returns {Promise<{currentUrl: string, html: string, htmlPath: string, logs: string[], logsPath: string, screenshotPath: string}>}
|
|
314
|
+
*/
|
|
315
|
+
async takeScreenshot() {
|
|
316
|
+
this.debugLog("Getting path for screenshots");
|
|
317
|
+
const path = this._screenshotsPath;
|
|
318
|
+
this.debugLog(`Creating dir with recursive: ${path}`);
|
|
319
|
+
await fs.mkdir(path, { recursive: true });
|
|
320
|
+
this.debugLog("Getting screenshot image content");
|
|
321
|
+
const imageContent = await timeout({ timeout: 5000, errorMessage: "timeout while taking screenshot" }, async () => await this.getDriverAdapter().takeScreenshot());
|
|
322
|
+
this.debugLog("Generating date variables");
|
|
323
|
+
const now = new Date();
|
|
324
|
+
const timestamp = moment(now).format("YYYY-MM-DD-HH-MM-SS");
|
|
325
|
+
const screenshotPath = `${path}/${timestamp}.png`;
|
|
326
|
+
const htmlPath = `${path}/${timestamp}.html`;
|
|
327
|
+
const logsPath = `${path}/${timestamp}.logs.txt`;
|
|
328
|
+
this.debugLog("Getting browser logs");
|
|
329
|
+
const logs = await timeout({ timeout: 5000, errorMessage: "timeout while reading browser logs" }, async () => await this.getBrowserLogs());
|
|
330
|
+
const html = await timeout({ timeout: 5000, errorMessage: "timeout while reading page HTML" }, async () => await this.getHTML());
|
|
331
|
+
const htmlPretty = prettify(html);
|
|
332
|
+
this.printBrowserLogsForFailure(logs);
|
|
333
|
+
this.debugLog("Writing files");
|
|
334
|
+
await fs.writeFile(htmlPath, htmlPretty);
|
|
335
|
+
await fs.writeFile(logsPath, logs.join("\n"));
|
|
336
|
+
await fs.writeFile(screenshotPath, imageContent, "base64");
|
|
337
|
+
const currentUrl = await this.getCurrentUrl();
|
|
338
|
+
console.log("Current URL:", currentUrl);
|
|
339
|
+
console.log("Logs:", logsPath);
|
|
340
|
+
console.log("Screenshot:", screenshotPath);
|
|
341
|
+
console.log("HTML:", htmlPath);
|
|
342
|
+
return {
|
|
343
|
+
currentUrl,
|
|
344
|
+
html,
|
|
345
|
+
htmlPath,
|
|
346
|
+
logs,
|
|
347
|
+
logsPath,
|
|
348
|
+
screenshotPath
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
/** @returns {Promise<void>} */
|
|
352
|
+
async stopDriver() {
|
|
353
|
+
if (this.driverAdapter) {
|
|
354
|
+
await this.driverAdapter.stop();
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJvd3Nlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9icm93c2VyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUNqQyxPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUE7QUFDM0IsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLFFBQVEsQ0FBQTtBQUMvQixPQUFPLE9BQU8sTUFBTSwyQkFBMkIsQ0FBQTtBQUMvQyxPQUFPLGNBQWMsTUFBTSw4QkFBOEIsQ0FBQTtBQUN6RCxPQUFPLFlBQVksTUFBTSw0QkFBNEIsQ0FBQTtBQUVyRDs7Ozs7O0dBTUc7QUFDSDs7OztHQUlHO0FBRUgsb0VBQW9FO0FBQ3BFLE1BQU0sQ0FBQyxPQUFPLE9BQU8sT0FBTztJQWExQixrQ0FBa0M7SUFDbEMsWUFBWSxFQUFDLEtBQUssR0FBRyxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxlQUFlLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxFQUFFLGtCQUFrQixFQUFFLEdBQUcsUUFBUSxFQUFDLEdBQUcsRUFBRTtRQWJ6SCxpRUFBaUU7UUFDakUsV0FBTSxHQUFHLFNBQVMsQ0FBQTtRQUVsQiwwRUFBMEU7UUFDMUUsa0JBQWEsR0FBRyxTQUFTLENBQUE7UUFFekIsV0FBTSxHQUFHLEtBQUssQ0FBQTtRQUNkLDhDQUE4QztRQUM5QyxrQkFBYSxHQUFHLFNBQVMsQ0FBQTtRQUN6QixnQ0FBZ0M7UUFDaEMscUJBQWdCLEdBQUcsU0FBUyxDQUFBO1FBK0Y1Qjs7O1dBR0c7UUFDSCxzQkFBaUIsR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQzVCLE1BQU0sWUFBWSxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUUzRSxJQUFJLENBQUMsZ0JBQWdCLEdBQUcs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O1FBRTlCLE9BQU87WUFDTCxVQUFVO1lBQ1YsSUFBSTtZQUNKLFFBQVE7WUFDUixJQUFJO1lBQ0osUUFBUTtZQUNSLGNBQWM7U0FDZixDQUFBO0lBQ0gsQ0FBQztJQUVELCtCQUErQjtJQUMvQixLQUFLLENBQUMsVUFBVTtRQUNkLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3ZCLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUNqQyxDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBmcyBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiXG5pbXBvcnQgbW9tZW50IGZyb20gXCJtb21lbnRcIlxuaW1wb3J0IHtwcmV0dGlmeX0gZnJvbSBcImh0bWxmeVwiXG5pbXBvcnQgdGltZW91dCBmcm9tIFwiYXdhaXRlcnkvYnVpbGQvdGltZW91dC5qc1wiXG5pbXBvcnQgU2VsZW5pdW1Ecml2ZXIgZnJvbSBcIi4vZHJpdmVycy9zZWxlbml1bS1kcml2ZXIuanNcIlxuaW1wb3J0IEFwcGl1bURyaXZlciBmcm9tIFwiLi9kcml2ZXJzL2FwcGl1bS1kcml2ZXIuanNcIlxuXG4vKipcbiAqIEB0eXBlZGVmIHtvYmplY3R9IEJyb3dzZXJBcmdzXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtkZWJ1Z10gRW5hYmxlIGRlYnVnIGxvZ2dpbmcuXG4gKiBAcHJvcGVydHkge0Jyb3dzZXJEcml2ZXJDb25maWd9IFtkcml2ZXJdIERyaXZlciBjb25maWd1cmF0aW9uLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL3N5c3RlbS10ZXN0LWNvbW11bmljYXRvci5qc1wiKS5kZWZhdWx0fSBbY29tbXVuaWNhdG9yXSBPcHRpb25hbCBjb21tYW5kIGNvbW11bmljYXRvciBmb3IgaGVscGVyLWRyaXZlbiBuYXZpZ2F0aW9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtzY3JlZW5zaG90c1BhdGhdIERpcmVjdG9yeSB1c2VkIGZvciBzYXZlZCBzY3JlZW5zaG90cyBhbmQgYnJvd3NlciBhcnRpZmFjdHMuXG4gKi9cbi8qKlxuICogQHR5cGVkZWYge29iamVjdH0gQnJvd3NlckRyaXZlckNvbmZpZ1xuICogQHByb3BlcnR5IHtcInNlbGVuaXVtXCJ8XCJhcHBpdW1cIn0gW3R5cGVdIERyaXZlciBpbXBsZW1lbnRhdGlvbiB0byB1c2UuXG4gKiBAcHJvcGVydHkge1JlY29yZDxzdHJpbmcsIGFueT59IFtvcHRpb25zXSBEcml2ZXItc3BlY2lmaWMgb3B0aW9ucy5cbiAqL1xuXG4vKiogR2VuZXJpYyBicm93c2VyIHNlc3Npb24gd3JhcHBlciBhcm91bmQgdGhlIGNvbmZpZ3VyZWQgZHJpdmVyLiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQnJvd3NlciB7XG4gIC8qKiBAdHlwZSB7aW1wb3J0KFwic2VsZW5pdW0td2ViZHJpdmVyXCIpLldlYkRyaXZlciB8IHVuZGVmaW5lZH0gKi9cbiAgZHJpdmVyID0gdW5kZWZpbmVkXG5cbiAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL2RyaXZlcnMvd2ViZHJpdmVyLWRyaXZlci5qc1wiKS5kZWZhdWx0IHwgdW5kZWZpbmVkfSAqL1xuICBkcml2ZXJBZGFwdGVyID0gdW5kZWZpbmVkXG5cbiAgX2RlYnVnID0gZmFsc2VcbiAgLyoqIEB0eXBlIHtCcm93c2VyRHJpdmVyQ29uZmlnIHwgdW5kZWZpbmVkfSAqL1xuICBfZHJpdmVyQ29uZmlnID0gdW5kZWZpbmVkXG4gIC8qKiBAdHlwZSB7RXJyb3IgfCB1bmRlZmluZWR9ICovXG4gIF9odHRwU2VydmVyRXJyb3IgPSB1bmRlZmluZWRcblxuICAvKiogQHBhcmFtIHtCcm93c2VyQXJnc30gW2FyZ3NdICovXG4gIGNvbnN0cnVjdG9yKHtkZWJ1ZyA9IGZhbHNlLCBkcml2ZXIsIGNvbW11bmljYXRvciwgc2NyZWVuc2hvdHNQYXRoID0gYCR7cHJvY2Vzcy5jd2QoKX0vdG1wL3NjcmVlbnNob3RzYCwgLi4ucmVzdEFyZ3N9ID0ge30pIHtcbiAgICBjb25zdCByZXN0QXJnc0tleXMgPSBPYmplY3Qua2V5cyhyZXN0QXJncylcblxuICAgIGlmIChyZXN0QXJnc0tleXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGJyb3dzZXIgYXJndW1lbnRzOiAke3Jlc3RBcmdzS2V5cy5qb2luKFwiLCBcIil9YClcbiAgICB9XG5cbiAgICB0aGlzLl9kZWJ1ZyA9IGRlYnVnXG4gICAgdGhpcy5fZHJpdmVyQ29uZmlnID0gZHJpdmVyXG4gICAgdGhpcy5fc2NyZWVuc2hvdHNQYXRoID0gc2NyZWVuc2hvdHNQYXRoXG4gICAgdGhpcy5jb21tdW5pY2F0b3IgPSBjb21tdW5pY2F0b3JcbiAgICB0aGlzLmRyaXZlckFkYXB0ZXIgPSB0aGlzLmNyZWF0ZURyaXZlcihkcml2ZXIpXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtCcm93c2VyRHJpdmVyQ29uZmlnfSBbZHJpdmVyQ29uZmlnXVxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi9kcml2ZXJzL3dlYmRyaXZlci1kcml2ZXIuanNcIikuZGVmYXVsdH1cbiAgICovXG4gIGNyZWF0ZURyaXZlcihkcml2ZXJDb25maWcgPSB7fSkge1xuICAgIGNvbnN0IHt0eXBlID0gXCJzZWxlbml1bVwiLCBvcHRpb25zLCAuLi5yZXN0QXJnc30gPSBkcml2ZXJDb25maWdcbiAgICBjb25zdCByZXN0QXJnc0tleXMgPSBPYmplY3Qua2V5cyhyZXN0QXJncylcblxuICAgIGlmIChyZXN0QXJnc0tleXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGRyaXZlciBhcmdzOiAke3Jlc3RBcmdzS2V5cy5qb2luKFwiLCBcIil9YClcbiAgICB9XG5cbiAgICBpZiAodHlwZSA9PT0gXCJzZWxlbml1bVwiKSB7XG4gICAgICByZXR1cm4gbmV3IFNlbGVuaXVtRHJpdmVyKHticm93c2VyOiB0aGlzLCBvcHRpb25zfSlcbiAgICB9XG5cbiAgICBpZiAodHlwZSA9PT0gXCJhcHBpdW1cIikge1xuICAgICAgcmV0dXJuIG5ldyBBcHBpdW1Ecml2ZXIoe2Jyb3dzZXI6IHRoaXMsIG9wdGlvbnN9KVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgZHJpdmVyIHR5cGU6ICR7dHlwZX1gKVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zeXN0ZW0tdGVzdC1jb21tdW5pY2F0b3IuanNcIikuZGVmYXVsdCB8IHVuZGVmaW5lZH0gY29tbXVuaWNhdG9yXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc2V0Q29tbXVuaWNhdG9yKGNvbW11bmljYXRvcikge1xuICAgIHRoaXMuY29tbXVuaWNhdG9yID0gY29tbXVuaWNhdG9yXG4gIH1cblxuICAvKiogQHJldHVybnMge2Jvb2xlYW59ICovXG4gIGNvbW11bmljYXRvckV4aXN0cygpIHtcbiAgICByZXR1cm4gQm9vbGVhbih0aGlzLmNvbW11bmljYXRvcilcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYmFzZVNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc2V0QmFzZVNlbGVjdG9yKGJhc2VTZWxlY3RvcikgeyB0aGlzLl9iYXNlU2VsZWN0b3IgPSBiYXNlU2VsZWN0b3IgfVxuXG4gIC8qKiBAcmV0dXJucyB7c3RyaW5nIHwgdW5kZWZpbmVkfSAqL1xuICBnZXRCYXNlU2VsZWN0b3IoKSB7IHJldHVybiB0aGlzLl9iYXNlU2VsZWN0b3IgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3JcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIGdldFNlbGVjdG9yKHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QmFzZVNlbGVjdG9yKCkgPyBgJHt0aGlzLmdldEJhc2VTZWxlY3RvcigpfSAke3NlbGVjdG9yfWAgOiBzZWxlY3RvclxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7Li4uYW55fSBhcmdzXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgZGVidWdFcnJvciguLi5hcmdzKSB7XG4gICAgY29uc29sZS5lcnJvcihcIltCcm93c2VyIGVycm9yXVwiLCAuLi5hcmdzKVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7Li4uYW55fSBhcmdzXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgZGVidWdMb2coLi4uYXJncykge1xuICAgIGlmICh0aGlzLl9kZWJ1Zykge1xuICAgICAgY29uc29sZS5sb2coXCJbQnJvd3NlciBkZWJ1Z11cIiwgLi4uYXJncylcbiAgICB9XG4gIH1cblxuICAvKiogQHJldHVybnMge3ZvaWR9ICovXG4gIHRocm93SWZIdHRwU2VydmVyRXJyb3IoKSB7XG4gICAgaWYgKHRoaXMuX2h0dHBTZXJ2ZXJFcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBIVFRQIHNlcnZlciBlcnJvcjogJHt0aGlzLl9odHRwU2VydmVyRXJyb3IubWVzc2FnZX1gKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Vycm9yfSBlcnJvclxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIG9uSHR0cFNlcnZlckVycm9yID0gKGVycm9yKSA9PiB7XG4gICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG5cbiAgICB0aGlzLl9odHRwU2VydmVyRXJyb3IgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlKVxuICAgIGNvbnNvbGUuZXJyb3IoYEhUVFAgc2VydmVyIGVycm9yOiAke2Vycm9yTWVzc2FnZX1gKVxuICB9XG5cbiAgLyoqIEByZXR1cm5zIHtpbXBvcnQoXCJzZWxlbml1bS13ZWJkcml2ZXJcIikuV2ViRHJpdmVyfSAqL1xuICBnZXREcml2ZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0RHJpdmVyQWRhcHRlcigpLmdldFdlYkRyaXZlcigpXG4gIH1cblxuICAvKiogQHJldHVybnMge2ltcG9ydChcIi4vZHJpdmVycy93ZWJkcml2ZXItZHJpdmVyLmpzXCIpLmRlZmF1bHR9ICovXG4gIGdldERyaXZlckFkYXB0ZXIoKSB7XG4gICAgaWYgKCF0aGlzLmRyaXZlckFkYXB0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkRyaXZlciBoYXNuJ3QgYmVlbiBpbml0aWFsaXplZCB5ZXRcIilcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5kcml2ZXJBZGFwdGVyXG4gIH1cblxuICAvKiogQHJldHVybnMge251bWJlcn0gKi9cbiAgZ2V0VGltZW91dHMoKSB7IHJldHVybiB0aGlzLmdldERyaXZlckFkYXB0ZXIoKS5nZXRUaW1lb3V0cygpIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8dm9pZD59ICovXG4gIGFzeW5jIHJlc3RvcmVUaW1lb3V0cygpIHtcbiAgICBhd2FpdCB0aGlzLmdldERyaXZlckFkYXB0ZXIoKS5yZXN0b3JlVGltZW91dHMoKVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBuZXdUaW1lb3V0XG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgZHJpdmVyU2V0VGltZW91dHMobmV3VGltZW91dCkge1xuICAgIGF3YWl0IHRoaXMuZ2V0RHJpdmVyQWRhcHRlcigpLmRyaXZlclNldFRpbWVvdXRzKG5ld1RpbWVvdXQpXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IG5ld1RpbWVvdXRcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBzZXRUaW1lb3V0cyhuZXdUaW1lb3V0KSB7XG4gICAgYXdhaXQgdGhpcy5nZXREcml2ZXJBZGFwdGVyKCkuc2V0VGltZW91dHMobmV3VGltZW91dClcbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmdbXT59ICovXG4gIGFzeW5jIGdldEJyb3dzZXJMb2dzKCkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmdldERyaXZlckFkYXB0ZXIoKS5nZXRCcm93c2VyTG9ncygpXG4gIH1cblxuICAvKiogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gKi9cbiAgYXN5bmMgZ2V0Q3VycmVudFVybCgpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5nZXREcml2ZXJBZGFwdGVyKCkuZ2V0Q3VycmVudFVybCgpXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IHNlbGVjdG9yXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zeXN0ZW0tdGVzdC5qc1wiKS5GaW5kQXJnc30gW2FyZ3NdXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGltcG9ydChcInNlbGVuaXVtLXdlYmRyaXZlclwiKS5XZWJFbGVtZW50W10+fVxuICAgKi9cbiAgYXN5bmMgYWxsKHNlbGVjdG9yLCBhcmdzID0ge30pIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5nZXREcml2ZXJBZGFwdGVyKCkuYWxsKHNlbGVjdG9yLCBhcmdzKVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvclxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc3lzdGVtLXRlc3QuanNcIikuRmluZEFyZ3N9IFthcmdzXVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxpbXBvcnQoXCJzZWxlbml1bS13ZWJkcml2ZXJcIikuV2ViRWxlbWVudD59XG4gICAqL1xuICBhc3luYyBmaW5kKHNlbGVjdG9yLCBhcmdzID0ge30pIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5nZXREcml2ZXJBZGFwdGVyKCkuZmluZChzZWxlY3RvciwgYXJncylcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGVzdElEXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zeXN0ZW0tdGVzdC5qc1wiKS5GaW5kQXJnc30gW2FyZ3NdXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGltcG9ydChcInNlbGVuaXVtLXdlYmRyaXZlclwiKS5XZWJFbGVtZW50Pn1cbiAgICovXG4gIGFzeW5jIGZpbmRCeVRlc3RJRCh0ZXN0SUQsIGFyZ3MpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5nZXREcml2ZXJBZGFwdGVyKCkuZmluZEJ5VGVzdElEKHRlc3RJRCwgYXJncylcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3JcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3N5c3RlbS10ZXN0LmpzXCIpLkZpbmRBcmdzfSBbYXJnc11cbiAgICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwic2VsZW5pdW0td2ViZHJpdmVyXCIpLldlYkVsZW1lbnQ+fVxuICAgKi9cbiAgYXN5bmMgZmluZE5vV2FpdChzZWxlY3RvciwgYXJncyA9IHt9KSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0RHJpdmVyQWRhcHRlcigpLmZpbmROb1dhaXQoc2VsZWN0b3IsIGFyZ3MpXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBpbXBvcnQoXCJzZWxlbml1bS13ZWJkcml2ZXJcIikuV2ViRWxlbWVudH0gZWxlbWVudE9ySWRlbnRpZmllclxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc3lzdGVtLXRlc3QuanNcIikuRmluZEFyZ3N9IFthcmdzXVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGNsaWNrKGVsZW1lbnRPcklkZW50aWZpZXIsIGFyZ3MpIHtcbiAgICBhd2FpdCB0aGlzLmdldERyaXZlckFkYXB0ZXIoKS5jbGljayhlbGVtZW50T3JJZGVudGlmaWVyLCBhcmdzKVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwic2VsZW5pdW0td2ViZHJpdmVyXCIpLldlYkVsZW1lbnR8c3RyaW5nfHtzZWxlY3Rvcjogc3RyaW5nfSAmIGltcG9ydChcIi4vc3lzdGVtLXRlc3QuanNcIikuRmluZEFyZ3N9IGVsZW1lbnRPcklkZW50aWZpZXJcbiAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZE5hbWVcbiAgICogQHBhcmFtIHsuLi5hbnl9IGFyZ3NcbiAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAgICovXG4gIGFzeW5jIGludGVyYWN0KGVsZW1lbnRPcklkZW50aWZpZXIsIG1ldGhvZE5hbWUsIC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5nZXREcml2ZXJBZGFwdGVyKCkuaW50ZXJhY3QoZWxlbWVudE9ySWRlbnRpZmllciwgbWV0aG9kTmFtZSwgLi4uYXJncylcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3JcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3N5c3RlbS10ZXN0LmpzXCIpLldhaXRGb3JOb1NlbGVjdG9yQXJnc30gW2FyZ3NdXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgd2FpdEZvck5vU2VsZWN0b3Ioc2VsZWN0b3IsIGFyZ3MgPSB7fSkge1xuICAgIGF3YWl0IHRoaXMuZ2V0RHJpdmVyQWRhcHRlcigpLndhaXRGb3JOb1NlbGVjdG9yKHNlbGVjdG9yLCBhcmdzKVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RvclxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc3lzdGVtLXRlc3QuanNcIikuRmluZEFyZ3N9IFthcmdzXVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGV4cGVjdE5vRWxlbWVudChzZWxlY3RvciwgYXJncyA9IHt9KSB7XG4gICAgbGV0IGZvdW5kID0gZmFsc2VcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmZpbmROb1dhaXQoc2VsZWN0b3IsIGFyZ3MpXG4gICAgICBmb3VuZCA9IHRydWVcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgJiYgZXJyb3IubWVzc2FnZS5zdGFydHNXaXRoKFwiRWxlbWVudCBjb3VsZG4ndCBiZSBmb3VuZCBhZnRlciBcIikpIHtcbiAgICAgICAgLy8gSWdub3JlXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnJvclxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChmb3VuZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBub3QgdG8gZmluZDogJHtzZWxlY3Rvcn1gKVxuICAgIH1cbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAqL1xuICBhc3luYyBnZXRIVE1MKCkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmdldERyaXZlckFkYXB0ZXIoKS5nZXRIVE1MKClcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcGF0aFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGRyaXZlclZpc2l0KHBhdGgpIHtcbiAgICBhd2FpdCB0aGlzLmdldERyaXZlckFkYXB0ZXIoKS5kcml2ZXJWaXNpdChwYXRoKVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgc2VuZEJyb3dzZXJDb21tYW5kKHR5cGUsIHBhdGgpIHtcbiAgICBpZiAoIXRoaXMuY29tbXVuaWNhdG9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb21tdW5pY2F0b3IgaGFzbid0IGJlZW4gaW5pdGlhbGl6ZWQgeWV0XCIpXG4gICAgfVxuXG4gICAgYXdhaXQgdGltZW91dChcbiAgICAgIHt0aW1lb3V0OiB0aGlzLmdldFRpbWVvdXRzKCksIGVycm9yTWVzc2FnZTogYHRpbWVvdXQgd2hpbGUgc2VuZGluZyBicm93c2VyIGNvbW1hbmQgJHt0eXBlfTogJHtwYXRofWB9LFxuICAgICAgYXN5bmMgKCkgPT4gYXdhaXQgdGhpcy5jb21tdW5pY2F0b3Iuc2VuZENvbW1hbmQoe3R5cGUsIHBhdGh9KVxuICAgIClcbiAgfVxuXG4gIC8qKlxuICAgKiBWaXNpdHMgYSBwYXRoIHVzaW5nIHRoZSBpbmplY3RlZCBicm93c2VyIGhlbHBlciB3aGVuIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIG5hdmlnYXRlcyBkaXJlY3RseSB3aXRoIHRoZSBkcml2ZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgdmlzaXQocGF0aCkge1xuICAgIGlmICh0aGlzLmNvbW11bmljYXRvckV4aXN0cygpKSB7XG4gICAgICBhd2FpdCB0aGlzLnNlbmRCcm93c2VyQ29tbWFuZChcInZpc2l0XCIsIHBhdGgpXG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRpbWVvdXQoXG4gICAgICAgIHt0aW1lb3V0OiB0aGlzLmdldFRpbWVvdXRzKCksIGVycm9yTWVzc2FnZTogYHRpbWVvdXQgd2hpbGUgdmlzaXRpbmcgcGF0aDogJHtwYXRofWB9LFxuICAgICAgICBhc3luYyAoKSA9PiBhd2FpdCB0aGlzLmRyaXZlclZpc2l0KHBhdGgpXG4gICAgICApXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERpc21pc3NlcyB0byBhIHBhdGggdmlhIHRoZSBpbmplY3RlZCBicm93c2VyIGhlbHBlciB3aGVuIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIG5hdmlnYXRlcyBkaXJlY3RseSB3aXRoIHRoZSBkcml2ZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgZGlzbWlzc1RvKHBhdGgpIHtcbiAgICBpZiAodGhpcy5jb21tdW5pY2F0b3JFeGlzdHMoKSkge1xuICAgICAgYXdhaXQgdGhpcy5zZW5kQnJvd3NlckNvbW1hbmQoXCJkaXNtaXNzVG9cIiwgcGF0aClcbiAgICB9IGVsc2Uge1xuICAgICAgYXdhaXQgdGltZW91dChcbiAgICAgICAge3RpbWVvdXQ6IHRoaXMuZ2V0VGltZW91dHMoKSwgZXJyb3JNZXNzYWdlOiBgdGltZW91dCB3aGlsZSBkaXNtaXNzaW5nIHRvIHBhdGg6ICR7cGF0aH1gfSxcbiAgICAgICAgYXN5bmMgKCkgPT4gYXdhaXQgdGhpcy5kcml2ZXJWaXNpdChwYXRoKVxuICAgICAgKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JtYXRzIGJyb3dzZXIgbG9ncyBmb3IgY29uc29sZSBvdXRwdXQgYW5kIHRydW5jYXRlcyBvdmVybHkgbG9uZyBvdXRwdXQuXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IGxvZ3NcbiAgICogQHBhcmFtIHtudW1iZXJ9IFttYXhMaW5lc11cbiAgICogQHJldHVybnMge3N0cmluZ1tdfVxuICAgKi9cbiAgZm9ybWF0QnJvd3NlckxvZ3NGb3JDb25zb2xlKGxvZ3MsIG1heExpbmVzID0gMjAwKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGxvZ3MpIHx8IGxvZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gW1wiKG5vIGJyb3dzZXIgbG9ncylcIl1cbiAgICB9XG5cbiAgICBpZiAobG9ncy5sZW5ndGggPD0gbWF4TGluZXMpIHtcbiAgICAgIHJldHVybiBsb2dzXG4gICAgfVxuXG4gICAgY29uc3Qga2VwdExvZ3MgPSBsb2dzLnNsaWNlKGxvZ3MubGVuZ3RoIC0gbWF4TGluZXMpXG4gICAgY29uc3QgaGlkZGVuQ291bnQgPSBsb2dzLmxlbmd0aCAtIG1heExpbmVzXG5cbiAgICByZXR1cm4gW2Aoc2hvd2luZyBsYXN0ICR7bWF4TGluZXN9IG9mICR7bG9ncy5sZW5ndGh9IGJyb3dzZXIgbG9ncywgJHtoaWRkZW5Db3VudH0gb21pdHRlZClgLCAuLi5rZXB0TG9nc11cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBsb2dzXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgcHJpbnRCcm93c2VyTG9nc0ZvckZhaWx1cmUobG9ncykge1xuICAgIGNvbnNvbGUubG9nKFwiQnJvd3NlciBsb2dzOlwiKVxuXG4gICAgZm9yIChjb25zdCBsaW5lIG9mIHRoaXMuZm9ybWF0QnJvd3NlckxvZ3NGb3JDb25zb2xlKGxvZ3MpKSB7XG4gICAgICBjb25zb2xlLmxvZyhsaW5lKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUYWtlcyBhIHNjcmVlbnNob3QsIHdyaXRlcyBIVE1ML2Jyb3dzZXIgbG9ncyB0byBkaXNrLCBhbmQgcmV0dXJucyB0aGUgY29sbGVjdGVkIGFydGlmYWN0cy5cbiAgICogQHJldHVybnMge1Byb21pc2U8e2N1cnJlbnRVcmw6IHN0cmluZywgaHRtbDogc3RyaW5nLCBodG1sUGF0aDogc3RyaW5nLCBsb2dzOiBzdHJpbmdbXSwgbG9nc1BhdGg6IHN0cmluZywgc2NyZWVuc2hvdFBhdGg6IHN0cmluZ30+fVxuICAgKi9cbiAgYXN5bmMgdGFrZVNjcmVlbnNob3QoKSB7XG4gICAgdGhpcy5kZWJ1Z0xvZyhcIkdldHRpbmcgcGF0aCBmb3Igc2NyZWVuc2hvdHNcIilcbiAgICBjb25zdCBwYXRoID0gdGhpcy5fc2NyZWVuc2hvdHNQYXRoXG5cbiAgICB0aGlzLmRlYnVnTG9nKGBDcmVhdGluZyBkaXIgd2l0aCByZWN1cnNpdmU6ICR7cGF0aH1gKVxuICAgIGF3YWl0IGZzLm1rZGlyKHBhdGgsIHtyZWN1cnNpdmU6IHRydWV9KVxuXG4gICAgdGhpcy5kZWJ1Z0xvZyhcIkdldHRpbmcgc2NyZWVuc2hvdCBpbWFnZSBjb250ZW50XCIpXG4gICAgY29uc3QgaW1hZ2VDb250ZW50ID0gYXdhaXQgdGltZW91dCh7dGltZW91dDogNTAwMCwgZXJyb3JNZXNzYWdlOiBcInRpbWVvdXQgd2hpbGUgdGFraW5nIHNjcmVlbnNob3RcIn0sIGFzeW5jICgpID0+IGF3YWl0IHRoaXMuZ2V0RHJpdmVyQWRhcHRlcigpLnRha2VTY3JlZW5zaG90KCkpXG5cbiAgICB0aGlzLmRlYnVnTG9nKFwiR2VuZXJhdGluZyBkYXRlIHZhcmlhYmxlc1wiKVxuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKClcbiAgICBjb25zdCB0aW1lc3RhbXAgPSBtb21lbnQobm93KS5mb3JtYXQoXCJZWVlZLU1NLURELUhILU1NLVNTXCIpXG4gICAgY29uc3Qgc2NyZWVuc2hvdFBhdGggPSBgJHtwYXRofS8ke3RpbWVzdGFtcH0ucG5nYFxuICAgIGNvbnN0IGh0bWxQYXRoID0gYCR7cGF0aH0vJHt0aW1lc3RhbXB9Lmh0bWxgXG4gICAgY29uc3QgbG9nc1BhdGggPSBgJHtwYXRofS8ke3RpbWVzdGFtcH0ubG9ncy50eHRgXG5cbiAgICB0aGlzLmRlYnVnTG9nKFwiR2V0dGluZyBicm93c2VyIGxvZ3NcIilcbiAgICBjb25zdCBsb2dzID0gYXdhaXQgdGltZW91dCh7dGltZW91dDogNTAwMCwgZXJyb3JNZXNzYWdlOiBcInRpbWVvdXQgd2hpbGUgcmVhZGluZyBicm93c2VyIGxvZ3NcIn0sIGFzeW5jICgpID0+IGF3YWl0IHRoaXMuZ2V0QnJvd3NlckxvZ3MoKSlcbiAgICBjb25zdCBodG1sID0gYXdhaXQgdGltZW91dCh7dGltZW91dDogNTAwMCwgZXJyb3JNZXNzYWdlOiBcInRpbWVvdXQgd2hpbGUgcmVhZGluZyBwYWdlIEhUTUxcIn0sIGFzeW5jICgpID0+IGF3YWl0IHRoaXMuZ2V0SFRNTCgpKVxuICAgIGNvbnN0IGh0bWxQcmV0dHkgPSBwcmV0dGlmeShodG1sKVxuICAgIHRoaXMucHJpbnRCcm93c2VyTG9nc0ZvckZhaWx1cmUobG9ncylcblxuICAgIHRoaXMuZGVidWdMb2coXCJXcml0aW5nIGZpbGVzXCIpXG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKGh0bWxQYXRoLCBodG1sUHJldHR5KVxuICAgIGF3YWl0IGZzLndyaXRlRmlsZShsb2dzUGF0aCwgbG9ncy5qb2luKFwiXFxuXCIpKVxuICAgIGF3YWl0IGZzLndyaXRlRmlsZShzY3JlZW5zaG90UGF0aCwgaW1hZ2VDb250ZW50LCBcImJhc2U2NFwiKVxuXG4gICAgY29uc3QgY3VycmVudFVybCA9IGF3YWl0IHRoaXMuZ2V0Q3VycmVudFVybCgpXG5cbiAgICBjb25zb2xlLmxvZyhcIkN1cnJlbnQgVVJMOlwiLCBjdXJyZW50VXJsKVxuICAgIGNvbnNvbGUubG9nKFwiTG9nczpcIiwgbG9nc1BhdGgpXG4gICAgY29uc29sZS5sb2coXCJTY3JlZW5zaG90OlwiLCBzY3JlZW5zaG90UGF0aClcbiAgICBjb25zb2xlLmxvZyhcIkhUTUw6XCIsIGh0bWxQYXRoKVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGN1cnJlbnRVcmwsXG4gICAgICBodG1sLFxuICAgICAgaHRtbFBhdGgsXG4gICAgICBsb2dzLFxuICAgICAgbG9nc1BhdGgsXG4gICAgICBzY3JlZW5zaG90UGF0aFxuICAgIH1cbiAgfVxuXG4gIC8qKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gKi9cbiAgYXN5bmMgc3RvcERyaXZlcigpIHtcbiAgICBpZiAodGhpcy5kcml2ZXJBZGFwdGVyKSB7XG4gICAgICBhd2FpdCB0aGlzLmRyaXZlckFkYXB0ZXIuc3RvcCgpXG4gICAgfVxuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string[]} argv
|
|
3
|
+
* @returns {{_: string[], flags: Record<string, any>}}
|
|
4
|
+
*/
|
|
5
|
+
export function parseArgv(argv: string[]): {
|
|
6
|
+
_: string[];
|
|
7
|
+
flags: Record<string, any>;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* @param {Record<string, any>} flags
|
|
11
|
+
* @returns {{command: string, args: Record<string, any>}}
|
|
12
|
+
*/
|
|
13
|
+
export function resolveBrowserCommand(flags: Record<string, any>): {
|
|
14
|
+
command: string;
|
|
15
|
+
args: Record<string, any>;
|
|
16
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string[]} argv
|
|
3
|
+
* @returns {{_: string[], flags: Record<string, any>}}
|
|
4
|
+
*/
|
|
5
|
+
export function parseArgv(argv) {
|
|
6
|
+
const result = { _: [], flags: {} };
|
|
7
|
+
const setFlag = (key, value) => {
|
|
8
|
+
if (!(key in result.flags)) {
|
|
9
|
+
result.flags[key] = value;
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (!Array.isArray(result.flags[key])) {
|
|
13
|
+
result.flags[key] = [result.flags[key]];
|
|
14
|
+
}
|
|
15
|
+
result.flags[key].push(value);
|
|
16
|
+
};
|
|
17
|
+
for (let index = 0; index < argv.length; index++) {
|
|
18
|
+
const value = argv[index];
|
|
19
|
+
if (!value.startsWith("--")) {
|
|
20
|
+
result._.push(value);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const flag = value.slice(2);
|
|
24
|
+
if (flag.includes("=")) {
|
|
25
|
+
const [key, ...rest] = flag.split("=");
|
|
26
|
+
setFlag(key, rest.join("="));
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const nextValue = argv[index + 1];
|
|
30
|
+
if (nextValue && !nextValue.startsWith("--")) {
|
|
31
|
+
setFlag(flag, nextValue);
|
|
32
|
+
index += 1;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
setFlag(flag, true);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* @param {Record<string, any>} flags
|
|
42
|
+
* @returns {{command: string, args: Record<string, any>}}
|
|
43
|
+
*/
|
|
44
|
+
export function resolveBrowserCommand(flags) {
|
|
45
|
+
if (flags.visit) {
|
|
46
|
+
return { args: { url: flags.visit }, command: "visit" };
|
|
47
|
+
}
|
|
48
|
+
if (flags["dismiss-to"]) {
|
|
49
|
+
return { args: { path: flags["dismiss-to"] }, command: "dismissTo" };
|
|
50
|
+
}
|
|
51
|
+
if (flags["find-by-test-id"]) {
|
|
52
|
+
return {
|
|
53
|
+
args: {
|
|
54
|
+
testID: flags["find-by-test-id"],
|
|
55
|
+
timeout: flags.timeout,
|
|
56
|
+
useBaseSelector: flags["use-base-selector"],
|
|
57
|
+
visible: flags.visible
|
|
58
|
+
},
|
|
59
|
+
command: "findByTestID"
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (flags.find) {
|
|
63
|
+
return {
|
|
64
|
+
args: {
|
|
65
|
+
selector: flags.find,
|
|
66
|
+
timeout: flags.timeout,
|
|
67
|
+
useBaseSelector: flags["use-base-selector"],
|
|
68
|
+
visible: flags.visible
|
|
69
|
+
},
|
|
70
|
+
command: "find"
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (flags.click) {
|
|
74
|
+
return {
|
|
75
|
+
args: {
|
|
76
|
+
selector: flags.click,
|
|
77
|
+
timeout: flags.timeout,
|
|
78
|
+
useBaseSelector: flags["use-base-selector"],
|
|
79
|
+
visible: flags.visible
|
|
80
|
+
},
|
|
81
|
+
command: "click"
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
if (flags["wait-for-no-selector"]) {
|
|
85
|
+
return {
|
|
86
|
+
args: {
|
|
87
|
+
selector: flags["wait-for-no-selector"],
|
|
88
|
+
useBaseSelector: flags["use-base-selector"]
|
|
89
|
+
},
|
|
90
|
+
command: "waitForNoSelector"
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (flags["expect-no-element"]) {
|
|
94
|
+
return {
|
|
95
|
+
args: {
|
|
96
|
+
selector: flags["expect-no-element"],
|
|
97
|
+
useBaseSelector: flags["use-base-selector"]
|
|
98
|
+
},
|
|
99
|
+
command: "expectNoElement"
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (flags["set-base-selector"]) {
|
|
103
|
+
return { args: { selector: flags["set-base-selector"] }, command: "setBaseSelector" };
|
|
104
|
+
}
|
|
105
|
+
if (flags["get-html"]) {
|
|
106
|
+
return { args: {}, command: "getHTML" };
|
|
107
|
+
}
|
|
108
|
+
if (flags["get-browser-logs"]) {
|
|
109
|
+
return { args: {}, command: "getBrowserLogs" };
|
|
110
|
+
}
|
|
111
|
+
if (flags["get-current-url"]) {
|
|
112
|
+
return { args: {}, command: "getCurrentUrl" };
|
|
113
|
+
}
|
|
114
|
+
if (flags["take-screenshot"]) {
|
|
115
|
+
return { args: {}, command: "takeScreenshot" };
|
|
116
|
+
}
|
|
117
|
+
if (flags.command) {
|
|
118
|
+
const args = {};
|
|
119
|
+
if (flags.url)
|
|
120
|
+
args.url = flags.url;
|
|
121
|
+
if (flags.path)
|
|
122
|
+
args.path = flags.path;
|
|
123
|
+
if (flags.selector)
|
|
124
|
+
args.selector = flags.selector;
|
|
125
|
+
if (flags["test-id"])
|
|
126
|
+
args.testID = flags["test-id"];
|
|
127
|
+
if (flags.method)
|
|
128
|
+
args.methodName = flags.method;
|
|
129
|
+
if (flags.arg)
|
|
130
|
+
args.args = Array.isArray(flags.arg) ? flags.arg : [flags.arg];
|
|
131
|
+
if (flags.timeout)
|
|
132
|
+
args.timeout = flags.timeout;
|
|
133
|
+
if (flags.visible !== undefined)
|
|
134
|
+
args.visible = flags.visible;
|
|
135
|
+
if (flags["use-base-selector"] !== undefined)
|
|
136
|
+
args.useBaseSelector = flags["use-base-selector"];
|
|
137
|
+
return { args, command: flags.command };
|
|
138
|
+
}
|
|
139
|
+
throw new Error("No browser command was given");
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLWhlbHBlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY2xpLWhlbHBlcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLFNBQVMsQ0FBQyxJQUFJO0lBQzVCLE1BQU0sTUFBTSxHQUFHLEVBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFDLENBQUE7SUFDakMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDN0IsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzNCLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFBO1lBQ3pCLE9BQU07UUFDUixDQUFDO1FBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDdEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUN6QyxDQUFDO1FBRUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDL0IsQ0FBQyxDQUFBO0lBRUQsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztRQUNqRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7UUFFekIsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUM1QixNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMs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LENBQUMsOEJBQThCLENBQUMsQ0FBQTtBQUNqRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBhcmd2XG4gKiBAcmV0dXJucyB7e186IHN0cmluZ1tdLCBmbGFnczogUmVjb3JkPHN0cmluZywgYW55Pn19XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUFyZ3YoYXJndikge1xuICBjb25zdCByZXN1bHQgPSB7XzogW10sIGZsYWdzOiB7fX1cbiAgY29uc3Qgc2V0RmxhZyA9IChrZXksIHZhbHVlKSA9PiB7XG4gICAgaWYgKCEoa2V5IGluIHJlc3VsdC5mbGFncykpIHtcbiAgICAgIHJlc3VsdC5mbGFnc1trZXldID0gdmFsdWVcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmICghQXJyYXkuaXNBcnJheShyZXN1bHQuZmxhZ3Nba2V5XSkpIHtcbiAgICAgIHJlc3VsdC5mbGFnc1trZXldID0gW3Jlc3VsdC5mbGFnc1trZXldXVxuICAgIH1cblxuICAgIHJlc3VsdC5mbGFnc1trZXldLnB1c2godmFsdWUpXG4gIH1cblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgYXJndi5sZW5ndGg7IGluZGV4KyspIHtcbiAgICBjb25zdCB2YWx1ZSA9IGFyZ3ZbaW5kZXhdXG5cbiAgICBpZiAoIXZhbHVlLnN0YXJ0c1dpdGgoXCItLVwiKSkge1xuICAgICAgcmVzdWx0Ll8ucHVzaCh2YWx1ZSlcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuXG4gICAgY29uc3QgZmxhZyA9IHZhbHVlLnNsaWNlKDIpXG5cbiAgICBpZiAoZmxhZy5pbmNsdWRlcyhcIj1cIikpIHtcbiAgICAgIGNvbnN0IFtrZXksIC4uLnJlc3RdID0gZmxhZy5zcGxpdChcIj1cIilcblxuICAgICAgc2V0RmxhZyhrZXksIHJlc3Quam9pbihcIj1cIikpXG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIGNvbnN0IG5leHRWYWx1ZSA9IGFyZ3ZbaW5kZXggKyAxXVxuXG4gICAgaWYgKG5leHRWYWx1ZSAmJiAhbmV4dFZhbHVlLnN0YXJ0c1dpdGgoXCItLVwiKSkge1xuICAgICAgc2V0RmxhZyhmbGFnLCBuZXh0VmFsdWUpXG4gICAgICBpbmRleCArPSAxXG4gICAgfSBlbHNlIHtcbiAgICAgIHNldEZsYWcoZmxhZywgdHJ1ZSlcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzdWx0XG59XG5cbi8qKlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBmbGFnc1xuICogQHJldHVybnMge3tjb21tYW5kOiBzdHJpbmcsIGFyZ3M6IFJlY29yZDxzdHJpbmcsIGFueT59fVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUJyb3dzZXJDb21tYW5kKGZsYWdzKSB7XG4gIGlmIChmbGFncy52aXNpdCkge1xuICAgIHJldHVybiB7YXJnczoge3VybDogZmxhZ3MudmlzaXR9LCBjb21tYW5kOiBcInZpc2l0XCJ9XG4gIH1cblxuICBpZiAoZmxhZ3NbXCJkaXNtaXNzLXRvXCJdKSB7XG4gICAgcmV0dXJuIHthcmdzOiB7cGF0aDogZmxhZ3NbXCJkaXNtaXNzLXRvXCJdfSwgY29tbWFuZDogXCJkaXNtaXNzVG9cIn1cbiAgfVxuXG4gIGlmIChmbGFnc1tcImZpbmQtYnktdGVzdC1pZFwiXSkge1xuICAgIHJldHVybiB7XG4gICAgICBhcmdzOiB7XG4gICAgICAgIHRlc3RJRDogZmxhZ3NbXCJmaW5kLWJ5LXRlc3QtaWRcIl0sXG4gICAgICAgIHRpbWVvdXQ6IGZsYWdzLnRpbWVvdXQsXG4gICAgICAgIHVzZUJhc2VTZWxlY3RvcjogZmxhZ3NbXCJ1c2UtYmFzZS1zZWxlY3RvclwiXSxcbiAgICAgICAgdmlzaWJsZTogZmxhZ3MudmlzaWJsZVxuICAgICAgfSxcbiAgICAgIGNvbW1hbmQ6IFwiZmluZEJ5VGVzdElEXCJcbiAgICB9XG4gIH1cblxuICBpZiAoZmxhZ3MuZmluZCkge1xuICAgIHJldHVybiB7XG4gICAgICBhcmdzOiB7XG4gICAgICAgIHNlbGVjdG9yOiBmbGFncy5maW5kLFxuICAgICAgICB0aW1lb3V0OiBmbGFncy50aW1lb3V0LFxuICAgICAgICB1c2VCYXNlU2VsZWN0b3I6IGZsYWdzW1widXNlLWJhc2Utc2VsZWN0b3JcIl0sXG4gICAgICAgIHZpc2libGU6IGZsYWdzLnZpc2libGVcbiAgICAgIH0sXG4gICAgICBjb21tYW5kOiBcImZpbmRcIlxuICAgIH1cbiAgfVxuXG4gIGlmIChmbGFncy5jbGljaykge1xuICAgIHJldHVybiB7XG4gICAgICBhcmdzOiB7XG4gICAgICAgIHNlbGVjdG9yOiBmbGFncy5jbGljayxcbiAgICAgICAgdGltZW91dDogZmxhZ3MudGltZW91dCxcbiAgICAgICAgdXNlQmFzZVNlbGVjdG9yOiBmbGFnc1tcInVzZS1iYXNlLXNlbGVjdG9yXCJdLFxuICAgICAgICB2aXNpYmxlOiBmbGFncy52aXNpYmxlXG4gICAgICB9LFxuICAgICAgY29tbWFuZDogXCJjbGlja1wiXG4gICAgfVxuICB9XG5cbiAgaWYgKGZsYWdzW1wid2FpdC1mb3Itbm8tc2VsZWN0b3JcIl0pIHtcbiAgICByZXR1cm4ge1xuICAgICAgYXJnczoge1xuICAgICAgICBzZWxlY3RvcjogZmxhZ3NbXCJ3YWl0LWZvci1uby1zZWxlY3RvclwiXSxcbiAgICAgICAgdXNlQmFzZVNlbGVjdG9yOiBmbGFnc1tcInVzZS1iYXNlLXNlbGVjdG9yXCJdXG4gICAgICB9LFxuICAgICAgY29tbWFuZDogXCJ3YWl0Rm9yTm9TZWxlY3RvclwiXG4gICAgfVxuICB9XG5cbiAgaWYgKGZsYWdzW1wiZXhwZWN0LW5vLWVsZW1lbnRcIl0pIHtcbiAgICByZXR1cm4ge1xuICAgICAgYXJnczoge1xuICAgICAgICBzZWxlY3RvcjogZmxhZ3NbXCJleHBlY3Qtbm8tZWxlbWVudFwiXSxcbiAgICAgICAgdXNlQmFzZVNlbGVjdG9yOiBmbGFnc1tcInVzZS1iYXNlLXNlbGVjdG9yXCJdXG4gICAgICB9LFxuICAgICAgY29tbWFuZDogXCJleHBlY3ROb0VsZW1lbnRcIlxuICAgIH1cbiAgfVxuXG4gIGlmIChmbGFnc1tcInNldC1iYXNlLXNlbGVjdG9yXCJdKSB7XG4gICAgcmV0dXJuIHthcmdzOiB7c2VsZWN0b3I6IGZsYWdzW1wic2V0LWJhc2Utc2VsZWN0b3JcIl19LCBjb21tYW5kOiBcInNldEJhc2VTZWxlY3RvclwifVxuICB9XG5cbiAgaWYgKGZsYWdzW1wiZ2V0LWh0bWxcIl0pIHtcbiAgICByZXR1cm4ge2FyZ3M6IHt9LCBjb21tYW5kOiBcImdldEhUTUxcIn1cbiAgfVxuXG4gIGlmIChmbGFnc1tcImdldC1icm93c2VyLWxvZ3NcIl0pIHtcbiAgICByZXR1cm4ge2FyZ3M6IHt9LCBjb21tYW5kOiBcImdldEJyb3dzZXJMb2dzXCJ9XG4gIH1cblxuICBpZiAoZmxhZ3NbXCJnZXQtY3VycmVudC11cmxcIl0pIHtcbiAgICByZXR1cm4ge2FyZ3M6IHt9LCBjb21tYW5kOiBcImdldEN1cnJlbnRVcmxcIn1cbiAgfVxuXG4gIGlmIChmbGFnc1tcInRha2Utc2NyZWVuc2hvdFwiXSkge1xuICAgIHJldHVybiB7YXJnczoge30sIGNvbW1hbmQ6IFwidGFrZVNjcmVlbnNob3RcIn1cbiAgfVxuXG4gIGlmIChmbGFncy5jb21tYW5kKSB7XG4gICAgY29uc3QgYXJncyA9IHt9XG5cbiAgICBpZiAoZmxhZ3MudXJsKSBhcmdzLnVybCA9IGZsYWdzLnVybFxuICAgIGlmIChmbGFncy5wYXRoKSBhcmdzLnBhdGggPSBmbGFncy5wYXRoXG4gICAgaWYgKGZsYWdzLnNlbGVjdG9yKSBhcmdzLnNlbGVjdG9yID0gZmxhZ3Muc2VsZWN0b3JcbiAgICBpZiAoZmxhZ3NbXCJ0ZXN0LWlkXCJdKSBhcmdzLnRlc3RJRCA9IGZsYWdzW1widGVzdC1pZFwiXVxuICAgIGlmIChmbGFncy5tZXRob2QpIGFyZ3MubWV0aG9kTmFtZSA9IGZsYWdzLm1ldGhvZFxuICAgIGlmIChmbGFncy5hcmcpIGFyZ3MuYXJncyA9IEFycmF5LmlzQXJyYXkoZmxhZ3MuYXJnKSA/IGZsYWdzLmFyZyA6IFtmbGFncy5hcmddXG4gICAgaWYgKGZsYWdzLnRpbWVvdXQpIGFyZ3MudGltZW91dCA9IGZsYWdzLnRpbWVvdXRcbiAgICBpZiAoZmxhZ3MudmlzaWJsZSAhPT0gdW5kZWZpbmVkKSBhcmdzLnZpc2libGUgPSBmbGFncy52aXNpYmxlXG4gICAgaWYgKGZsYWdzW1widXNlLWJhc2Utc2VsZWN0b3JcIl0gIT09IHVuZGVmaW5lZCkgYXJncy51c2VCYXNlU2VsZWN0b3IgPSBmbGFnc1tcInVzZS1iYXNlLXNlbGVjdG9yXCJdXG5cbiAgICByZXR1cm4ge2FyZ3MsIGNvbW1hbmQ6IGZsYWdzLmNvbW1hbmR9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoXCJObyBicm93c2VyIGNvbW1hbmQgd2FzIGdpdmVuXCIpXG59XG4iXX0=
|
package/build/cli.d.ts
ADDED