system-testing 1.0.73 → 1.0.74
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 +51 -1
- package/build/drivers/appium-driver.d.ts +97 -0
- package/build/drivers/appium-driver.js +316 -0
- package/build/drivers/selenium-driver.d.ts +36 -0
- package/build/drivers/selenium-driver.js +44 -0
- package/build/drivers/webdriver-driver.d.ts +173 -0
- package/build/drivers/webdriver-driver.js +462 -0
- package/build/system-test-browser-helper.d.ts +4 -0
- package/build/system-test-browser-helper.js +28 -3
- package/build/system-test.d.ts +80 -10
- package/build/system-test.js +148 -299
- package/build/use-system-test.js +6 -1
- package/package.json +10 -3
package/README.md
CHANGED
|
@@ -62,10 +62,40 @@ describe("Sign in page", () => {
|
|
|
62
62
|
})
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
### Driver selection
|
|
66
|
+
|
|
67
|
+
SystemTest uses Selenium by default. To use Appium instead, pass a driver config when creating the instance:
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
await SystemTest.run({
|
|
71
|
+
driver: {
|
|
72
|
+
type: "appium",
|
|
73
|
+
options: {
|
|
74
|
+
serverArgs: {
|
|
75
|
+
useDrivers: ["uiautomator2"],
|
|
76
|
+
port: 4723
|
|
77
|
+
},
|
|
78
|
+
capabilities: {
|
|
79
|
+
platformName: "Android",
|
|
80
|
+
"appium:automationName": "UiAutomator2",
|
|
81
|
+
"appium:deviceName": "Android Emulator",
|
|
82
|
+
"appium:app": "/path/to/app.apk"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}, async (systemTest) => {
|
|
87
|
+
await systemTest.findByTestId("loginScreen")
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If you already run an Appium server, provide `serverUrl` instead of `serverArgs`. By default, `findByTestId` uses the Appium `accessibility id` strategy. To use CSS instead (for web contexts), set `options.testIdStrategy` to `"css"` and optionally `options.testIdAttribute` (defaults to `"data-testid"`).
|
|
92
|
+
|
|
65
93
|
### Using `useSystemTest` in your Expo app
|
|
66
94
|
|
|
67
95
|
`useSystemTest` wires your Expo app to the system-testing runner: it listens for WebSocket commands, initializes the browser helper, and lets tests navigate or reset state. Add it near the root layout of your Expo Router app (for example in `_layout.tsx` or a top-level provider component).
|
|
68
96
|
|
|
97
|
+
To enable system tests in native builds, set `EXPO_PUBLIC_SYSTEM_TEST=true` at build time (and optionally `EXPO_PUBLIC_SYSTEM_TEST_HOST` to reach the test runner from a device/emulator). For native Appium runs, set `SYSTEM_TEST_HOST=native` in the test environment and point Appium at your APK.
|
|
98
|
+
|
|
69
99
|
Minimal example:
|
|
70
100
|
|
|
71
101
|
```jsx
|
|
@@ -104,12 +134,32 @@ Notes:
|
|
|
104
134
|
- If you need scoundrel remote evaluation, wait for `systemTestBrowserHelper` and register your classes there, as shown in the commented snippet above.
|
|
105
135
|
- Add a root wrapper with `testID="systemTestingComponent"` (and optionally `data-focussed="true"`) around your app so the runner has a stable element to detect and scope selectors against.
|
|
106
136
|
- From your tests, use `await systemTest.getScoundrelClient()` to obtain the browser Scoundrel client for remote evaluation.
|
|
137
|
+
- `useSystemTest` calls `useRouter()` from `expo-router`. If you are not using Expo Router, install `expo-router` or provide your own guard to avoid navigation errors.
|
|
138
|
+
|
|
139
|
+
### Root path and `blankText`
|
|
140
|
+
|
|
141
|
+
`SystemTest.run()` visits `SystemTest.rootPath` (defaults to `/blank?systemTest=true`) and waits for an element with `testID="blankText"` inside the focused `systemTestingComponent`. If your app does not have a `/blank` route, set a custom root path and ensure the element exists on that screen.
|
|
142
|
+
|
|
143
|
+
Example setup:
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
import SystemTest from "system-testing/build/system-test.js"
|
|
147
|
+
|
|
148
|
+
SystemTest.rootPath = "/?platform=web&systemTest=true"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```jsx
|
|
152
|
+
<View testID="systemTestingComponent" dataSet={{focussed: "true"}}>
|
|
153
|
+
<Text testID="blankText">Blank</Text>
|
|
154
|
+
{children}
|
|
155
|
+
</View>
|
|
156
|
+
```
|
|
107
157
|
|
|
108
158
|
### Base selector and focused container
|
|
109
159
|
|
|
110
160
|
System tests scope selectors to the active screen by default. The app marks the active layout container with `data-focussed="true"` on the element with `data-testid="systemTestingComponent"`. In the dummy app, the root layout wraps the navigator and sets `data-focussed="true"` once so the base selector stays stable across screens.
|
|
111
161
|
|
|
112
|
-
`SystemTest.find` and `SystemTest.findByTestID` use a base selector that targets the focused container:
|
|
162
|
+
`SystemTest.find` and `SystemTest.findByTestId` (alias `findByTestID`) use a base selector that targets the focused container:
|
|
113
163
|
|
|
114
164
|
```css
|
|
115
165
|
[data-testid='systemTestingComponent'][data-focussed='true']
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} AppiumDriverOptions
|
|
3
|
+
* @property {string} [serverUrl] Remote Appium server URL to connect to.
|
|
4
|
+
* @property {Record<string, any>} [serverArgs] Options passed to the Appium server.
|
|
5
|
+
* @property {string[]} [useDrivers] Appium driver names to load when starting the server.
|
|
6
|
+
* @property {Record<string, any>} [capabilities] Desired capabilities for the session.
|
|
7
|
+
* @property {string} [browserName] Browser name for web sessions.
|
|
8
|
+
* @property {"accessibilityId"|"css"|"id"} [testIdStrategy] Strategy for resolving test IDs.
|
|
9
|
+
* @property {string} [testIdAttribute] Attribute name when using the CSS test ID strategy.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {object} FindArgs
|
|
13
|
+
* @property {number} [timeout] Override timeout for lookup.
|
|
14
|
+
* @property {boolean} [visible] Whether to require elements to be visible.
|
|
15
|
+
* @property {boolean} [useBaseSelector] Whether to scope by the base selector.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Appium driver backed by the Appium server package.
|
|
19
|
+
*/
|
|
20
|
+
export default class AppiumDriver extends WebDriverDriver {
|
|
21
|
+
serverUrl: any;
|
|
22
|
+
appiumServer: import("@appium/types").AppiumServer;
|
|
23
|
+
/**
|
|
24
|
+
* @param {string} testId
|
|
25
|
+
* @param {FindArgs} [args]
|
|
26
|
+
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
27
|
+
*/
|
|
28
|
+
findByAccessibilityId(testId: string, args?: FindArgs): Promise<import("selenium-webdriver").WebElement>;
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} testId
|
|
31
|
+
* @param {FindArgs} [args]
|
|
32
|
+
* @returns {Promise<import("selenium-webdriver").WebElement[]>}
|
|
33
|
+
*/
|
|
34
|
+
allByAccessibilityId(testId: string, args?: FindArgs): Promise<import("selenium-webdriver").WebElement[]>;
|
|
35
|
+
/**
|
|
36
|
+
* @param {string} testId
|
|
37
|
+
* @param {FindArgs} [args]
|
|
38
|
+
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
39
|
+
*/
|
|
40
|
+
findById(testId: string, args?: FindArgs): Promise<import("selenium-webdriver").WebElement>;
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} testId
|
|
43
|
+
* @param {FindArgs} [args]
|
|
44
|
+
* @returns {Promise<import("selenium-webdriver").WebElement[]>}
|
|
45
|
+
*/
|
|
46
|
+
allById(testId: string, args?: FindArgs): Promise<import("selenium-webdriver").WebElement[]>;
|
|
47
|
+
/**
|
|
48
|
+
* @param {Record<string, any>} serverArgs
|
|
49
|
+
* @returns {string}
|
|
50
|
+
*/
|
|
51
|
+
buildServerUrl(serverArgs: Record<string, any>): string;
|
|
52
|
+
}
|
|
53
|
+
export type AppiumDriverOptions = {
|
|
54
|
+
/**
|
|
55
|
+
* Remote Appium server URL to connect to.
|
|
56
|
+
*/
|
|
57
|
+
serverUrl?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Options passed to the Appium server.
|
|
60
|
+
*/
|
|
61
|
+
serverArgs?: Record<string, any>;
|
|
62
|
+
/**
|
|
63
|
+
* Appium driver names to load when starting the server.
|
|
64
|
+
*/
|
|
65
|
+
useDrivers?: string[];
|
|
66
|
+
/**
|
|
67
|
+
* Desired capabilities for the session.
|
|
68
|
+
*/
|
|
69
|
+
capabilities?: Record<string, any>;
|
|
70
|
+
/**
|
|
71
|
+
* Browser name for web sessions.
|
|
72
|
+
*/
|
|
73
|
+
browserName?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Strategy for resolving test IDs.
|
|
76
|
+
*/
|
|
77
|
+
testIdStrategy?: "accessibilityId" | "css" | "id";
|
|
78
|
+
/**
|
|
79
|
+
* Attribute name when using the CSS test ID strategy.
|
|
80
|
+
*/
|
|
81
|
+
testIdAttribute?: string;
|
|
82
|
+
};
|
|
83
|
+
export type FindArgs = {
|
|
84
|
+
/**
|
|
85
|
+
* Override timeout for lookup.
|
|
86
|
+
*/
|
|
87
|
+
timeout?: number;
|
|
88
|
+
/**
|
|
89
|
+
* Whether to require elements to be visible.
|
|
90
|
+
*/
|
|
91
|
+
visible?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Whether to scope by the base selector.
|
|
94
|
+
*/
|
|
95
|
+
useBaseSelector?: boolean;
|
|
96
|
+
};
|
|
97
|
+
import WebDriverDriver from "./webdriver-driver.js";
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { Builder, By } from "selenium-webdriver";
|
|
2
|
+
import timeout from "awaitery/build/timeout.js";
|
|
3
|
+
import WebDriverDriver from "./webdriver-driver.js";
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} AppiumDriverOptions
|
|
6
|
+
* @property {string} [serverUrl] Remote Appium server URL to connect to.
|
|
7
|
+
* @property {Record<string, any>} [serverArgs] Options passed to the Appium server.
|
|
8
|
+
* @property {string[]} [useDrivers] Appium driver names to load when starting the server.
|
|
9
|
+
* @property {Record<string, any>} [capabilities] Desired capabilities for the session.
|
|
10
|
+
* @property {string} [browserName] Browser name for web sessions.
|
|
11
|
+
* @property {"accessibilityId"|"css"|"id"} [testIdStrategy] Strategy for resolving test IDs.
|
|
12
|
+
* @property {string} [testIdAttribute] Attribute name when using the CSS test ID strategy.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {object} FindArgs
|
|
16
|
+
* @property {number} [timeout] Override timeout for lookup.
|
|
17
|
+
* @property {boolean} [visible] Whether to require elements to be visible.
|
|
18
|
+
* @property {boolean} [useBaseSelector] Whether to scope by the base selector.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Appium driver backed by the Appium server package.
|
|
22
|
+
*/
|
|
23
|
+
export default class AppiumDriver extends WebDriverDriver {
|
|
24
|
+
/**
|
|
25
|
+
* @returns {Promise<void>}
|
|
26
|
+
*/
|
|
27
|
+
async start() {
|
|
28
|
+
const serverArgs = { ...(this.options.serverArgs ?? {}) };
|
|
29
|
+
if (this.options.useDrivers && !serverArgs.useDrivers) {
|
|
30
|
+
serverArgs.useDrivers = this.options.useDrivers;
|
|
31
|
+
}
|
|
32
|
+
if (this.options.serverUrl) {
|
|
33
|
+
this.serverUrl = this.options.serverUrl;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const appiumModule = await import("appium");
|
|
37
|
+
const appiumMain = appiumModule.main ?? appiumModule.default?.main;
|
|
38
|
+
if (!appiumMain) {
|
|
39
|
+
throw new Error("Appium main() is unavailable from the appium package");
|
|
40
|
+
}
|
|
41
|
+
this.appiumServer = await appiumMain(serverArgs);
|
|
42
|
+
this.serverUrl = this.buildServerUrl(serverArgs);
|
|
43
|
+
}
|
|
44
|
+
const capabilities = this.options.capabilities ? { ...this.options.capabilities } : {};
|
|
45
|
+
if (this.options.browserName && !capabilities.browserName) {
|
|
46
|
+
capabilities.browserName = this.options.browserName;
|
|
47
|
+
}
|
|
48
|
+
if (capabilities.browserName === undefined) {
|
|
49
|
+
capabilities.browserName = "";
|
|
50
|
+
}
|
|
51
|
+
const builder = new Builder().usingServer(this.serverUrl);
|
|
52
|
+
if (Object.keys(capabilities).length > 0) {
|
|
53
|
+
builder.withCapabilities(capabilities);
|
|
54
|
+
}
|
|
55
|
+
const webDriver = await builder.build();
|
|
56
|
+
this.setWebDriver(webDriver);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* @returns {Promise<void>}
|
|
60
|
+
*/
|
|
61
|
+
async stop() {
|
|
62
|
+
try {
|
|
63
|
+
await super.stop();
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
if (this.appiumServer?.close) {
|
|
67
|
+
await timeout({ timeout: this.getTimeouts(), errorMessage: "timeout while closing Appium server" }, async () => await this.appiumServer.close());
|
|
68
|
+
}
|
|
69
|
+
this.appiumServer = undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* @returns {Promise<string[]>}
|
|
74
|
+
*/
|
|
75
|
+
async getBrowserLogs() {
|
|
76
|
+
const platformName = this.options.capabilities?.platformName;
|
|
77
|
+
const browserName = this.options.capabilities?.browserName ?? this.options.browserName;
|
|
78
|
+
const isAndroid = typeof platformName === "string" && platformName.toLowerCase() === "android";
|
|
79
|
+
if (isAndroid && !browserName) {
|
|
80
|
+
let entries;
|
|
81
|
+
try {
|
|
82
|
+
entries = await this.getWebDriver().manage().logs().get("logcat");
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
const logcatLogs = [];
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
const messageMatch = entry.message.match(/^(.+) (\d+):(\d+) (.+)$/);
|
|
90
|
+
const message = messageMatch ? messageMatch[4] : entry.message;
|
|
91
|
+
logcatLogs.push(`${entry.level.name}: ${message}`);
|
|
92
|
+
}
|
|
93
|
+
return logcatLogs;
|
|
94
|
+
}
|
|
95
|
+
return await super.getBrowserLogs();
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Finds a single element by test ID.
|
|
99
|
+
* @param {string} testId
|
|
100
|
+
* @param {FindArgs} [args]
|
|
101
|
+
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
102
|
+
*/
|
|
103
|
+
async findByTestId(testId, args) {
|
|
104
|
+
const testIdStrategy = this.options.testIdStrategy ?? "accessibilityId";
|
|
105
|
+
if (testIdStrategy === "css") {
|
|
106
|
+
const testIdAttribute = this.options.testIdAttribute ?? "data-testid";
|
|
107
|
+
return await this.find(`[${testIdAttribute}='${testId}']`, args);
|
|
108
|
+
}
|
|
109
|
+
if (testIdStrategy === "id") {
|
|
110
|
+
return await this.findById(testId, args);
|
|
111
|
+
}
|
|
112
|
+
return await this.findByAccessibilityId(testId, args);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Finds a single element by test ID.
|
|
116
|
+
* @param {string} testID
|
|
117
|
+
* @param {FindArgs} [args]
|
|
118
|
+
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
119
|
+
*/
|
|
120
|
+
async findByTestID(testID, args) {
|
|
121
|
+
return await this.findByTestId(testID, args);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* @param {string} testId
|
|
125
|
+
* @param {FindArgs} [args]
|
|
126
|
+
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
127
|
+
*/
|
|
128
|
+
async findByAccessibilityId(testId, args = {}) {
|
|
129
|
+
const startTime = Date.now();
|
|
130
|
+
let elements = [];
|
|
131
|
+
try {
|
|
132
|
+
elements = await this.allByAccessibilityId(testId, args);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
// Re-throw to recover stack trace
|
|
136
|
+
if (error instanceof Error) {
|
|
137
|
+
if (error.message.startsWith("Wait timed out after")) {
|
|
138
|
+
elements = [];
|
|
139
|
+
}
|
|
140
|
+
throw new Error(`${error.constructor.name} - ${error.message} (accessibility id: ${testId})`);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
throw new Error(`${typeof error} - ${error} (accessibility id: ${testId})`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (elements.length > 1) {
|
|
147
|
+
throw new Error(`More than 1 elements (${elements.length}) was found by accessibility id: ${testId}`);
|
|
148
|
+
}
|
|
149
|
+
if (!elements[0]) {
|
|
150
|
+
const elapsedSeconds = (Date.now() - startTime) / 1000;
|
|
151
|
+
throw new Error(`Element couldn't be found after ${elapsedSeconds.toFixed(2)}s by accessibility id: ${testId}`);
|
|
152
|
+
}
|
|
153
|
+
return elements[0];
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* @param {string} testId
|
|
157
|
+
* @param {FindArgs} [args]
|
|
158
|
+
* @returns {Promise<import("selenium-webdriver").WebElement[]>}
|
|
159
|
+
*/
|
|
160
|
+
async allByAccessibilityId(testId, args = {}) {
|
|
161
|
+
const { visible = true, timeout, ...restArgs } = args;
|
|
162
|
+
const restArgsKeys = Object.keys(restArgs).filter((key) => key !== "useBaseSelector");
|
|
163
|
+
let actualTimeout;
|
|
164
|
+
if (timeout === undefined) {
|
|
165
|
+
actualTimeout = this._driverTimeouts;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
actualTimeout = timeout;
|
|
169
|
+
}
|
|
170
|
+
if (restArgsKeys.length > 0)
|
|
171
|
+
throw new Error(`Unknown arguments: ${restArgsKeys.join(", ")}`);
|
|
172
|
+
const startTime = Date.now();
|
|
173
|
+
const getTimeLeft = () => Math.max(actualTimeout - (Date.now() - startTime), 0);
|
|
174
|
+
const getElements = async () => {
|
|
175
|
+
const foundElements = await this.getWebDriver().findElements(new By("accessibility id", testId));
|
|
176
|
+
if (visible !== true && visible !== false) {
|
|
177
|
+
return foundElements;
|
|
178
|
+
}
|
|
179
|
+
const filteredElements = [];
|
|
180
|
+
for (const element of foundElements) {
|
|
181
|
+
const isDisplayed = await element.isDisplayed();
|
|
182
|
+
if (visible && !isDisplayed)
|
|
183
|
+
continue;
|
|
184
|
+
if (!visible && isDisplayed)
|
|
185
|
+
continue;
|
|
186
|
+
filteredElements.push(element);
|
|
187
|
+
}
|
|
188
|
+
return filteredElements;
|
|
189
|
+
};
|
|
190
|
+
let elements = [];
|
|
191
|
+
while (true) {
|
|
192
|
+
const timeLeft = actualTimeout == 0 ? 0 : getTimeLeft();
|
|
193
|
+
try {
|
|
194
|
+
if (timeLeft == 0) {
|
|
195
|
+
elements = await getElements();
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
await this.getWebDriver().wait(async () => {
|
|
199
|
+
elements = await getElements();
|
|
200
|
+
return elements.length > 0;
|
|
201
|
+
}, timeLeft);
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
if (error instanceof Error && error.constructor.name === "TimeoutError" && getTimeLeft() > 0) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
throw new Error(`Couldn't get elements with accessibility id: ${testId}: ${error instanceof Error ? error.message : error}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return elements;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* @param {string} testId
|
|
216
|
+
* @param {FindArgs} [args]
|
|
217
|
+
* @returns {Promise<import("selenium-webdriver").WebElement>}
|
|
218
|
+
*/
|
|
219
|
+
async findById(testId, args = {}) {
|
|
220
|
+
const startTime = Date.now();
|
|
221
|
+
let elements = [];
|
|
222
|
+
try {
|
|
223
|
+
elements = await this.allById(testId, args);
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
// Re-throw to recover stack trace
|
|
227
|
+
if (error instanceof Error) {
|
|
228
|
+
if (error.message.startsWith("Wait timed out after")) {
|
|
229
|
+
elements = [];
|
|
230
|
+
}
|
|
231
|
+
throw new Error(`${error.constructor.name} - ${error.message} (id: ${testId})`);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
throw new Error(`${typeof error} - ${error} (id: ${testId})`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (elements.length > 1) {
|
|
238
|
+
throw new Error(`More than 1 elements (${elements.length}) was found by id: ${testId}`);
|
|
239
|
+
}
|
|
240
|
+
if (!elements[0]) {
|
|
241
|
+
const elapsedSeconds = (Date.now() - startTime) / 1000;
|
|
242
|
+
throw new Error(`Element couldn't be found after ${elapsedSeconds.toFixed(2)}s by id: ${testId}`);
|
|
243
|
+
}
|
|
244
|
+
return elements[0];
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* @param {string} testId
|
|
248
|
+
* @param {FindArgs} [args]
|
|
249
|
+
* @returns {Promise<import("selenium-webdriver").WebElement[]>}
|
|
250
|
+
*/
|
|
251
|
+
async allById(testId, args = {}) {
|
|
252
|
+
const { visible = true, timeout, ...restArgs } = args;
|
|
253
|
+
const restArgsKeys = Object.keys(restArgs).filter((key) => key !== "useBaseSelector");
|
|
254
|
+
let actualTimeout;
|
|
255
|
+
if (timeout === undefined) {
|
|
256
|
+
actualTimeout = this._driverTimeouts;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
actualTimeout = timeout;
|
|
260
|
+
}
|
|
261
|
+
if (restArgsKeys.length > 0)
|
|
262
|
+
throw new Error(`Unknown arguments: ${restArgsKeys.join(", ")}`);
|
|
263
|
+
const startTime = Date.now();
|
|
264
|
+
const getTimeLeft = () => Math.max(actualTimeout - (Date.now() - startTime), 0);
|
|
265
|
+
const getElements = async () => {
|
|
266
|
+
const foundElements = await this.getWebDriver().findElements(By.id(testId));
|
|
267
|
+
if (visible !== true && visible !== false) {
|
|
268
|
+
return foundElements;
|
|
269
|
+
}
|
|
270
|
+
const filteredElements = [];
|
|
271
|
+
for (const element of foundElements) {
|
|
272
|
+
const isDisplayed = await element.isDisplayed();
|
|
273
|
+
if (visible && !isDisplayed)
|
|
274
|
+
continue;
|
|
275
|
+
if (!visible && isDisplayed)
|
|
276
|
+
continue;
|
|
277
|
+
filteredElements.push(element);
|
|
278
|
+
}
|
|
279
|
+
return filteredElements;
|
|
280
|
+
};
|
|
281
|
+
let elements = [];
|
|
282
|
+
while (true) {
|
|
283
|
+
const timeLeft = actualTimeout == 0 ? 0 : getTimeLeft();
|
|
284
|
+
try {
|
|
285
|
+
if (timeLeft == 0) {
|
|
286
|
+
elements = await getElements();
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
await this.getWebDriver().wait(async () => {
|
|
290
|
+
elements = await getElements();
|
|
291
|
+
return elements.length > 0;
|
|
292
|
+
}, timeLeft);
|
|
293
|
+
}
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
if (error instanceof Error && error.constructor.name === "TimeoutError" && getTimeLeft() > 0) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
throw new Error(`Couldn't get elements with id: ${testId}: ${error instanceof Error ? error.message : error}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return elements;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* @param {Record<string, any>} serverArgs
|
|
307
|
+
* @returns {string}
|
|
308
|
+
*/
|
|
309
|
+
buildServerUrl(serverArgs) {
|
|
310
|
+
const address = serverArgs.address ?? "127.0.0.1";
|
|
311
|
+
const port = serverArgs.port ?? 4723;
|
|
312
|
+
const basePath = serverArgs.basePath ? (serverArgs.basePath.startsWith("/") ? serverArgs.basePath : `/${serverArgs.basePath}`) : "";
|
|
313
|
+
return `http://${address}:${port}${basePath}`;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwaXVtLWRyaXZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kcml2ZXJzL2FwcGl1bS1kcml2ZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE9BQU8sRUFBRSxFQUFFLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQTtBQUM5QyxPQUFPLE9BQU8sTUFBTSwyQkFBMkIsQ0FBQTtBQUMvQyxPQUFPLGVBQWUsTUFBTSx1QkFBdUIsQ0FBQTtBQUVuRDs7Ozs7Ozs7O0dBU0c7QUFDSDs7Ozs7R0FLRztBQUVIOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyxZQUFhLFNBQVEsZUFBZTtJQUN2RDs7T0FFRztJQUNILEtBQUssQ0FBQyxLQUFLO1FBQ1QsTUFBTSxVQUFVLEdBQUcsRUFBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDLEVBQUMsQ0FBQTtRQUV2RCxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3RELFVBQVUsQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUE7UUFDakQsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUMzQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFBO1FBQ3pDLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxZQUFZLEdBQUcsTUFBTSxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDM0MsTUFBTSxVQUFVLEdBQUcsWUFBWSxDQUFDLElBQUksSUFBSSxZQUFZLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQTtZQUVsRSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsc0RBQXNELENBQUMsQ0FBQTtZQUN6RSxDQUFDO1lBRUQsSUFBSSxDQUFDLFlBQVksR0FBRyxNQUFNLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQTtZQUNoRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDbEQsQ0FBQztRQUVELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxFQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFBO1FBRXBGLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDMUQsWUFBWSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQTtRQUNyRCxDQUFDO1FBQ0QsSUFBSSxZQUFZLENBQUMsV0FBVyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzNDLFlBQVksQ0FBQyxXQUFXLEdBQUcsRUFBRSxDQUFBO1FBQy9CLENBQUM7UUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUE7UUFFekQsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN6QyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLENBQUE7UUFDeEMsQ0FBQztRQUVELE1BQU0sU0FBUyxHQUFHLE1BQU0sT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBRXZDLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUE7SUFDOUIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLElBQUk7UUFDUixJQUFJLENBQUM7WUFDSCxNQUFNLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUNwQixDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsS0FBSyxFQUFFLENBQUM7Z0JBQzdCLE1BQU0sT0FBTyxDQUFDLEVBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRSxZQUFZLEVBQUUscUNBQXFDLEVBQUMsRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFBO1lBQ2hKLENBQUM7WUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLFNBQVMsQ0FBQTtRQUMvQixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLGNBQWM7UUFDbEIsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFBO1FBQzVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLFdBQVcsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQTtRQUN0RixNQUFNLFNBQVMsR0FBRyxPQUFPLFlBQVksS0FBSyxRQUFRLElBQUksWUFBWSxDQUFDLFdBQVcsRUFBRSxLQUFLLFNBQVMsQ0FBQTtRQUU5RixJQUFJLFNBQVMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzlCLElBQUksT0FBTyxDQUFBO1lBRVgsSUFBSSxDQUFDO2dCQUNILE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDbkUsQ0FBQztZQUFDLE1BQU0sQ0FBQztnQkFDUCxPQUFPLEVBQUUsQ0FBQTtZQUNYLENBQUM7WUFFRCxNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUE7WUFFckIsS0FBSyxNQUFNLEtBQUssSUFBSSxPQUFPLEVBQUUsQ0FBQztnQkFDNUIsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQTtnQkFDbkUsTUFBTSxPQUFPLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUE7Z0JBRTlELFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQyxDQUFBO1lBQ3BELENBQUM7WUFFRCxPQUFPLFVBQVUsQ0FBQTtRQUNuQixDQUFDO1FBRUQsT0FBTyxNQUFNLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQTtJQUNyQyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxJQUFJO1FBQzdCLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxJQUFJLGlCQUFpQixDQUFBO1FBRXZFLElBQUksY0FBYyxLQUFLLEtBQUssRUFBRSxDQUFDO1lBQzdCLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxJQUFJLGFBQWEsQ0FBQTtZQUNyRSxPQUFPLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLGVBQWUsS0FBSyxNQUFNLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUNsRSxDQUFDO1FBQ0QsSUFBSSxjQUFjLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDNUIsT0FBTyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFBO1FBQzFDLENBQUM7UUFFRCxPQUFPLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQTtJQUN2RCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxJQUFJO1FBQzdCLE9BQU8sTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQTtJQUM5QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsSUFBSSxHQUFHLEVBQUU7UUFDM0MsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFBO1FBQzVCLElBQUksUUFBUSxHQUFHLEVBQUUsQ0FBQTtRQUVqQixJQUFJLENBQUM7WUFDSCxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFBO1FBQzFELENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2Ysa0NBQWtDO1lBQ2xDLElBQUksS0FBSyxZQUFZLEtBQUssRUFBRSxDQUFDO2dCQUMzQixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLHNCQUFzQixDQUFDLEVBQUUsQ0FBQztvQkFDckQsUUFBUSxHQUFHLEVBQUUsQ0FBQTtnQkFDZixDQUFDO2dCQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksTUFBTSxLQUFLLENBQUMsT0FBTyx1QkFBdUIsTUFBTSxHQUFHLENBQUMsQ0FBQTtZQUMvRixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLE9BQU8sS0FBSyxNQUFNLEtBQUssdUJBQXVCLE1BQU0sR0FBRyxDQUFDLENBQUE7WUFDN0UsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsUUFBUSxDQUFDLE1BQU0sb0NBQW9DLE1BQU0sRUFBRSxDQUFDLENBQUE7UUFDdkcsQ0FBQztRQUVELElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNqQixNQUFNLGNBQWMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUE7WUFDdEQsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQ0FBbUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsMEJBQTBCLE1BQU0sRUFBRSxDQUFDLENBQUE7UUFDakgsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3BCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLG9CQUFvQixDQUFDLE1BQU0sRUFBRSxJQUFJLEdBQUcsRUFBRTtRQUMxQyxNQUFNLEVBQUMsT0FBTyxHQUFHLElBQUksRUFBRSxPQUFPLEVBQUUsR0FBRyxRQUFRLEVBQUMsR0FBRyxJQUFJLENBQUE7UUFDbkQsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxpQkFBaUIsQ0FBQyxDQUFBO1FBQ3JGLElBQUksYUFBYSxDQUFBO1FBRWpCLElBQUksT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzFCLGFBQWEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFBO1FBQ3RDLENBQUM7YUFBTSxDQUFDO1lBQ04sYUFBYSxHQUFHLE9BQU8sQ0FBQTtRQUN6QixDQUFDO1FBRUQsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUM7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUU3RixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUE7UUFDNUIsTUFBTSxXQUFXLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7UUFDL0UsTUFBTSxXQUFXLEdBQUcsS0FBSyxJQUFJLEVBQUU7WUFDN0IsTUFBTSxhQUFhLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDLGtCQUFrQixFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUE7WUFFaEcsSUFBSSxPQUFPLEtBQUssSUFBSSxJQUFJLE9BQU8sS0FBSyxLQUFLLEVBQUUsQ0FBQztnQkFDMUMsT0FBTyxhQUFhLENBQUE7WUFDdEIsQ0FBQztZQUVELE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxDQUFBO1lBRTNCLEtBQUssTUFBTSxPQUFPLElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ3BDLE1BQU0sV0FBVyxHQUFHLE1BQU0sT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFBO2dCQUUvQyxJQUFJLE9BQU8sSUFBSSxDQUFDLFdBQVc7b0JBQUUsU0FBUTtnQkFDckMsSUFBSSxDQUFDLE9BQU8sSUFBSSxXQUFXO29CQUFFLFNBQVE7Z0JBRXJDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQTtZQUNoQyxDQUFDO1lBRUQsT0FBTyxnQkFBZ0IsQ0FBQTtRQUN6QixDQUFDLENBQUE7UUFDRCxJQUFJLFFBQVEsR0FBRyxFQUFFLENBQUE7UUFFakIsT0FBTyxJQUFJLEVBQUUsQ0FBQztZQUNaLE1BQU0sUUFBUSxHQUFHLGFBQWEsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUE7WUFFdkQsSUFBSSxDQUFDO2dCQUNILElBQUksUUFBUSxJQUFJLENBQUMsRUFBRSxDQUFDO29CQUNsQixRQUFRLEdBQUcsTUFBTSxXQUFXLEVBQUUsQ0FBQTtnQkFDaEMsQ0FBQztxQkFBTSxDQUFDO29CQUNOLE1BQU0sSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksRUFBRTt3QkFDeEMsUUFBUSxHQUFHLE1BQU0sV0FBVyxFQUFFLENBQUE7d0JBRTlCLE9BQU8sUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUE7b0JBQzVCLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQTtnQkFDZCxDQUFDO2dCQUVELE1BQUs7WUFDUCxDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixJQUFJLEtBQUssWUFBWSxLQUFLLElBQUksS0FBSyxDQUFDLFdBQVcsQ0FBQyxJQUFJLEtBQUssY0FBYyxJQUFJLFdBQVcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUM3RixTQUFRO2dCQUNWLENBQUM7Z0JBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxnREFBZ0QsTUFBTSxLQUFLLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUE7WUFDOUgsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLFFBQVEsQ0FBQTtJQUNqQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksR0FBRyxFQUFFO1FBQzlCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQTtRQUM1QixJQUFJLFFBQVEsR0FBRyxFQUFFLENBQUE7UUFFakIsSUFBSSxDQUFDO1lBQ0gsUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFDN0MsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixrQ0FBa0M7WUFDbEMsSUFBSSxLQUFLLFlBQVksS0FBSyxFQUFFLENBQUM7Z0JBQzNCLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsc0JBQXNCLENBQUMsRUFBRSxDQUFDO29CQUNyRCxRQUFRLEdBQUcsRUFBRSxDQUFBO2dCQUNmLENBQUM7Z0JBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUMsSUFBSSxNQUFNLEtBQUssQ0FBQyxPQUFPLFNBQVMsTUFBTSxHQUFHLENBQUMsQ0FBQTtZQUNqRixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLE9BQU8sS0FBSyxNQUFNLEtBQUssU0FBUyxNQUFNLEdBQUcsQ0FBQyxDQUFBO1lBQy9ELENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLFFBQVEsQ0FBQyxNQUFNLHNCQUFzQixNQUFNLEVBQUUsQ0FBQyxDQUFBO1FBQ3pGLENBQUM7UUFFRCxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDakIsTUFBTSxjQUFjLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsU0FBUyxDQUFDLEdBQUcsSUFBSSxDQUFBO1lBQ3RELE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFlBQVksTUFBTSxFQUFFLENBQUMsQ0FBQTtRQUNuRyxDQUFDO1FBRUQsT0FBTyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDcEIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxJQUFJLEdBQUcsRUFBRTtRQUM3QixNQUFNLEVBQUMsT0FBTyxHQUFHLElBQUksRUFBRSxPQUFPLEVBQUUsR0FBRyxRQUFRLEVBQUMsR0FBRyxJQUFJLENBQUE7UUFDbkQsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxpQkFBaUIsQ0FBQyxDQUFBO1FBQ3JGLElBQUksYUFBYSxDQUFBO1FBRWpCLElBQUksT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzFCLGFBQWEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFBO1FBQ3RDLENBQUM7YUFBTSxDQUFDO1lBQ04sYUFBYSxHQUFHLE9BQU8sQ0FBQTtRQUN6QixDQUFDO1FBRUQsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUM7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUU3RixNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUE7UUFDNUIsTUFBTSxXQUFXLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7UUFDL0UsTUFBTSxXQUFXLEdBQUcsS0FBSyxJQUFJLEVBQUU7WUFDN0IsTUFBTSxhQUFhLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQTtZQUUzRSxJQUFJLE9BQU8sS0FBSyxJQUFJLElBQUksT0FBTyxLQUFLLEtBQUssRUFBRSxDQUFDO2dCQUMxQyxPQUFPLGFBQWEsQ0FBQTtZQUN0QixDQUFDO1lBRUQsTUFBTSxnQkFBZ0IsR0FBRyxFQUFFLENBQUE7WUFFM0IsS0FBSyxNQUFNLE9BQU8sSUFBSSxhQUFhLEVBQUUsQ0FBQztnQkFDcEMsTUFBTSxXQUFXLEdBQUcsTUFBTSxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUE7Z0JBRS9DLElBQUksT0FBTyxJQUFJLENBQUMsV0FBVztvQkFBRSxTQUFRO2dCQUNyQyxJQUFJLENBQUMsT0FBTyxJQUFJLFdBQVc7b0JBQUUsU0FBUTtnQkFFckMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBQ2hDLENBQUM7WUFFRCxPQUFPLGdCQUFnQixDQUFBO1FBQ3pCLENBQUMsQ0FBQTtRQUNELElBQUksUUFBUSxHQUFHLEVBQUUsQ0FBQTtRQUVqQixPQUFPLElBQUksRUFBRSxDQUFDO1lBQ1osTUFBTSxRQUFRLEdBQUcsYUFBYSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQTtZQUV2RCxJQUFJLENBQUM7Z0JBQ0gsSUFBSSxRQUFRLElBQUksQ0FBQyxFQUFFLENBQUM7b0JBQ2xCLFFBQVEsR0FBRyxNQUFNLFdBQVcsRUFBRSxDQUFBO2dCQUNoQyxDQUFDO3FCQUFNLENBQUM7b0JBQ04sTUFBTSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFO3dCQUN4QyxRQUFRLEdBQUcsTUFBTSxXQUFXLEVBQUUsQ0FBQTt3QkFFOUIsT0FBTyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQTtvQkFDNUIsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFBO2dCQUNkLENBQUM7Z0JBRUQsTUFBSztZQUNQLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLElBQUksS0FBSyxZQUFZLEtBQUssSUFBSSxLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksS0FBSyxjQUFjLElBQUksV0FBVyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUM7b0JBQzdGLFNBQVE7Z0JBQ1YsQ0FBQztnQkFFRCxNQUFNLElBQUksS0FBSyxDQUFDLGtDQUFrQyxNQUFNLEtBQUssS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQTtZQUNoSCxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFBO0lBQ2pCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsVUFBVTtRQUN2QixNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsT0FBTyxJQUFJLFdBQVcsQ0FBQTtRQUNqRCxNQUFNLElBQUksR0FBRyxVQUFVLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQTtRQUNwQyxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUE7UUFFbkksT0FBTyxVQUFVLE9BQU8sSUFBSSxJQUFJLEdBQUcsUUFBUSxFQUFFLENBQUE7SUFDL0MsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtCdWlsZGVyLCBCeX0gZnJvbSBcInNlbGVuaXVtLXdlYmRyaXZlclwiXG5pbXBvcnQgdGltZW91dCBmcm9tIFwiYXdhaXRlcnkvYnVpbGQvdGltZW91dC5qc1wiXG5pbXBvcnQgV2ViRHJpdmVyRHJpdmVyIGZyb20gXCIuL3dlYmRyaXZlci1kcml2ZXIuanNcIlxuXG4vKipcbiAqIEB0eXBlZGVmIHtvYmplY3R9IEFwcGl1bURyaXZlck9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbc2VydmVyVXJsXSBSZW1vdGUgQXBwaXVtIHNlcnZlciBVUkwgdG8gY29ubmVjdCB0by5cbiAqIEBwcm9wZXJ0eSB7UmVjb3JkPHN0cmluZywgYW55Pn0gW3NlcnZlckFyZ3NdIE9wdGlvbnMgcGFzc2VkIHRvIHRoZSBBcHBpdW0gc2VydmVyLlxuICogQHByb3BlcnR5IHtzdHJpbmdbXX0gW3VzZURyaXZlcnNdIEFwcGl1bSBkcml2ZXIgbmFtZXMgdG8gbG9hZCB3aGVuIHN0YXJ0aW5nIHRoZSBzZXJ2ZXIuXG4gKiBAcHJvcGVydHkge1JlY29yZDxzdHJpbmcsIGFueT59IFtjYXBhYmlsaXRpZXNdIERlc2lyZWQgY2FwYWJpbGl0aWVzIGZvciB0aGUgc2Vzc2lvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbYnJvd3Nlck5hbWVdIEJyb3dzZXIgbmFtZSBmb3Igd2ViIHNlc3Npb25zLlxuICogQHByb3BlcnR5IHtcImFjY2Vzc2liaWxpdHlJZFwifFwiY3NzXCJ8XCJpZFwifSBbdGVzdElkU3RyYXRlZ3ldIFN0cmF0ZWd5IGZvciByZXNvbHZpbmcgdGVzdCBJRHMuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW3Rlc3RJZEF0dHJpYnV0ZV0gQXR0cmlidXRlIG5hbWUgd2hlbiB1c2luZyB0aGUgQ1NTIHRlc3QgSUQgc3RyYXRlZ3kuXG4gKi9cbi8qKlxuICogQHR5cGVkZWYge29iamVjdH0gRmluZEFyZ3NcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbdGltZW91dF0gT3ZlcnJpZGUgdGltZW91dCBmb3IgbG9va3VwLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbdmlzaWJsZV0gV2hldGhlciB0byByZXF1aXJlIGVsZW1lbnRzIHRvIGJlIHZpc2libGUuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFt1c2VCYXNlU2VsZWN0b3JdIFdoZXRoZXIgdG8gc2NvcGUgYnkgdGhlIGJhc2Ugc2VsZWN0b3IuXG4gKi9cblxuLyoqXG4gKiBBcHBpdW0gZHJpdmVyIGJhY2tlZCBieSB0aGUgQXBwaXVtIHNlcnZlciBwYWNrYWdlLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBcHBpdW1Ecml2ZXIgZXh0ZW5kcyBXZWJEcml2ZXJEcml2ZXIge1xuICAvKipcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBzdGFydCgpIHtcbiAgICBjb25zdCBzZXJ2ZXJBcmdzID0gey4uLih0aGlzLm9wdGlvbnMuc2VydmVyQXJncyA/PyB7fSl9XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLnVzZURyaXZlcnMgJiYgIXNlcnZlckFyZ3MudXNlRHJpdmVycykge1xuICAgICAgc2VydmVyQXJncy51c2VEcml2ZXJzID0gdGhpcy5vcHRpb25zLnVzZURyaXZlcnNcbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLnNlcnZlclVybCkge1xuICAgICAgdGhpcy5zZXJ2ZXJVcmwgPSB0aGlzLm9wdGlvbnMuc2VydmVyVXJsXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGFwcGl1bU1vZHVsZSA9IGF3YWl0IGltcG9ydChcImFwcGl1bVwiKVxuICAgICAgY29uc3QgYXBwaXVtTWFpbiA9IGFwcGl1bU1vZHVsZS5tYWluID8/IGFwcGl1bU1vZHVsZS5kZWZhdWx0Py5tYWluXG5cbiAgICAgIGlmICghYXBwaXVtTWFpbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBcHBpdW0gbWFpbigpIGlzIHVuYXZhaWxhYmxlIGZyb20gdGhlIGFwcGl1bSBwYWNrYWdlXCIpXG4gICAgICB9XG5cbiAgICAgIHRoaXMuYXBwaXVtU2VydmVyID0gYXdhaXQgYXBwaXVtTWFpbihzZXJ2ZXJBcmdzKVxuICAgICAgdGhpcy5zZXJ2ZXJVcmwgPSB0aGlzLmJ1aWxkU2VydmVyVXJsKHNlcnZlckFyZ3MpXG4gICAgfVxuXG4gICAgY29uc3QgY2FwYWJpbGl0aWVzID0gdGhpcy5vcHRpb25zLmNhcGFiaWxpdGllcyA/IHsuLi50aGlzLm9wdGlvbnMuY2FwYWJpbGl0aWVzfSA6IHt9XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmJyb3dzZXJOYW1lICYmICFjYXBhYmlsaXRpZXMuYnJvd3Nlck5hbWUpIHtcbiAgICAgIGNhcGFiaWxpdGllcy5icm93c2VyTmFtZSA9IHRoaXMub3B0aW9ucy5icm93c2VyTmFtZVxuICAgIH1cbiAgICBpZiAoY2FwYWJpbGl0aWVzLmJyb3dzZXJOYW1lID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNhcGFiaWxpdGllcy5icm93c2VyTmFtZSA9IFwiXCJcbiAgICB9XG5cbiAgICBjb25zdCBidWlsZGVyID0gbmV3IEJ1aWxkZXIoKS51c2luZ1NlcnZlcih0aGlzLnNlcnZlclVybClcblxuICAgIGlmIChPYmplY3Qua2V5cyhjYXBhYmlsaXRpZXMpLmxlbmd0aCA+IDApIHtcbiAgICAgIGJ1aWxkZXIud2l0aENhcGFiaWxpdGllcyhjYXBhYmlsaXRpZXMpXG4gICAgfVxuXG4gICAgY29uc3Qgd2ViRHJpdmVyID0gYXdhaXQgYnVpbGRlci5idWlsZCgpXG5cbiAgICB0aGlzLnNldFdlYkRyaXZlcih3ZWJEcml2ZXIpXG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBzdG9wKCkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBzdXBlci5zdG9wKClcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKHRoaXMuYXBwaXVtU2VydmVyPy5jbG9zZSkge1xuICAgICAgICBhd2FpdCB0aW1lb3V0KHt0aW1lb3V0OiB0aGlzLmdldFRpbWVvdXRzKCksIGVycm9yTWVzc2FnZTogXCJ0aW1lb3V0IHdoaWxlIGNsb3NpbmcgQXBwaXVtIHNlcnZlclwifSwgYXN5bmMgKCkgPT4gYXdhaXQgdGhpcy5hcHBpdW1TZXJ2ZXIuY2xvc2UoKSlcbiAgICAgIH1cblxuICAgICAgdGhpcy5hcHBpdW1TZXJ2ZXIgPSB1bmRlZmluZWRcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW10+fVxuICAgKi9cbiAgYXN5bmMgZ2V0QnJvd3NlckxvZ3MoKSB7XG4gICAgY29uc3QgcGxhdGZvcm1OYW1lID0gdGhpcy5vcHRpb25zLmNhcGFiaWxpdGllcz8ucGxhdGZvcm1OYW1lXG4gICAgY29uc3QgYnJvd3Nlck5hbWUgPSB0aGlzLm9wdGlvbnMuY2FwYWJpbGl0aWVzPy5icm93c2VyTmFtZSA/PyB0aGlzLm9wdGlvbnMuYnJvd3Nlck5hbWVcbiAgICBjb25zdCBpc0FuZHJvaWQgPSB0eXBlb2YgcGxhdGZvcm1OYW1lID09PSBcInN0cmluZ1wiICYmIHBsYXRmb3JtTmFtZS50b0xvd2VyQ2FzZSgpID09PSBcImFuZHJvaWRcIlxuXG4gICAgaWYgKGlzQW5kcm9pZCAmJiAhYnJvd3Nlck5hbWUpIHtcbiAgICAgIGxldCBlbnRyaWVzXG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGVudHJpZXMgPSBhd2FpdCB0aGlzLmdldFdlYkRyaXZlcigpLm1hbmFnZSgpLmxvZ3MoKS5nZXQoXCJsb2djYXRcIilcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gW11cbiAgICAgIH1cblxuICAgICAgY29uc3QgbG9nY2F0TG9ncyA9IFtdXG5cbiAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgICBjb25zdCBtZXNzYWdlTWF0Y2ggPSBlbnRyeS5tZXNzYWdlLm1hdGNoKC9eKC4rKSAoXFxkKyk6KFxcZCspICguKykkLylcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9IG1lc3NhZ2VNYXRjaCA/IG1lc3NhZ2VNYXRjaFs0XSA6IGVudHJ5Lm1lc3NhZ2VcblxuICAgICAgICBsb2djYXRMb2dzLnB1c2goYCR7ZW50cnkubGV2ZWwubmFtZX06ICR7bWVzc2FnZX1gKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gbG9nY2F0TG9nc1xuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCBzdXBlci5nZXRCcm93c2VyTG9ncygpXG4gIH1cblxuICAvKipcbiAgICogRmluZHMgYSBzaW5nbGUgZWxlbWVudCBieSB0ZXN0IElELlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGVzdElkXG4gICAqIEBwYXJhbSB7RmluZEFyZ3N9IFthcmdzXVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxpbXBvcnQoXCJzZWxlbml1bS13ZWJkcml2ZXJcIikuV2ViRWxlbWVudD59XG4gICAqL1xuICBhc3luYyBmaW5kQnlUZXN0SWQodGVzdElkLCBhcmdzKSB7XG4gICAgY29uc3QgdGVzdElkU3RyYXRlZ3kgPSB0aGlzLm9wdGlvbnMudGVzdElkU3RyYXRlZ3kgPz8gXCJhY2Nlc3NpYmlsaXR5SWRcIlxuXG4gICAgaWYgKHRlc3RJZFN0cmF0ZWd5ID09PSBcImNzc1wiKSB7XG4gICAgICBjb25zdCB0ZXN0SWRBdHRyaWJ1dGUgPSB0aGlzLm9wdGlvbnMudGVzdElkQXR0cmlidXRlID8/IFwiZGF0YS10ZXN0aWRcIlxuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZmluZChgWyR7dGVzdElkQXR0cmlidXRlfT0nJHt0ZXN0SWR9J11gLCBhcmdzKVxuICAgIH1cbiAgICBpZiAodGVzdElkU3RyYXRlZ3kgPT09IFwiaWRcIikge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZmluZEJ5SWQodGVzdElkLCBhcmdzKVxuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCB0aGlzLmZpbmRCeUFjY2Vzc2liaWxpdHlJZCh0ZXN0SWQsIGFyZ3MpXG4gIH1cblxuICAvKipcbiAgICogRmluZHMgYSBzaW5nbGUgZWxlbWVudCBieSB0ZXN0IElELlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGVzdElEXG4gICAqIEBwYXJhbSB7RmluZEFyZ3N9IFthcmdzXVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxpbXBvcnQoXCJzZWxlbml1bS13ZWJkcml2ZXJcIikuV2ViRWxlbWVudD59XG4gICAqL1xuICBhc3luYyBmaW5kQnlUZXN0SUQodGVzdElELCBhcmdzKSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZmluZEJ5VGVzdElkKHRlc3RJRCwgYXJncylcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGVzdElkXG4gICAqIEBwYXJhbSB7RmluZEFyZ3N9IFthcmdzXVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxpbXBvcnQoXCJzZWxlbml1bS13ZWJkcml2ZXJcIikuV2ViRWxlbWVudD59XG4gICAqL1xuICBhc3luYyBmaW5kQnlBY2Nlc3NpYmlsaXR5SWQodGVzdElkLCBhcmdzID0ge30pIHtcbiAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpXG4gICAgbGV0IGVsZW1lbnRzID0gW11cblxuICAgIHRyeSB7XG4gICAgICBlbGVtZW50cyA9IGF3YWl0IHRoaXMuYWxsQnlBY2Nlc3NpYmlsaXR5SWQodGVzdElkLCBhcmdzKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBSZS10aHJvdyB0byByZWNvdmVyIHN0YWNrIHRyYWNlXG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICBpZiAoZXJyb3IubWVzc2FnZS5zdGFydHNXaXRoKFwiV2FpdCB0aW1lZCBvdXQgYWZ0ZXJcIikpIHtcbiAgICAgICAgICBlbGVtZW50cyA9IFtdXG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXJyb3IuY29uc3RydWN0b3IubmFtZX0gLSAke2Vycm9yLm1lc3NhZ2V9IChhY2Nlc3NpYmlsaXR5IGlkOiAke3Rlc3RJZH0pYClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0eXBlb2YgZXJyb3J9IC0gJHtlcnJvcn0gKGFjY2Vzc2liaWxpdHkgaWQ6ICR7dGVzdElkfSlgKVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlbGVtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE1vcmUgdGhhbiAxIGVsZW1lbnRzICgke2VsZW1lbnRzLmxlbmd0aH0pIHdhcyBmb3VuZCBieSBhY2Nlc3NpYmlsaXR5IGlkOiAke3Rlc3RJZH1gKVxuICAgIH1cblxuICAgIGlmICghZWxlbWVudHNbMF0pIHtcbiAgICAgIGNvbnN0IGVsYXBzZWRTZWNvbmRzID0gKERhdGUubm93KCkgLSBzdGFydFRpbWUpIC8gMTAwMFxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFbGVtZW50IGNvdWxkbid0IGJlIGZvdW5kIGFmdGVyICR7ZWxhcHNlZFNlY29uZHMudG9GaXhlZCgyKX1zIGJ5IGFjY2Vzc2liaWxpdHkgaWQ6ICR7dGVzdElkfWApXG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnRzWzBdXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRlc3RJZFxuICAgKiBAcGFyYW0ge0ZpbmRBcmdzfSBbYXJnc11cbiAgICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwic2VsZW5pdW0td2ViZHJpdmVyXCIpLldlYkVsZW1lbnRbXT59XG4gICAqL1xuICBhc3luYyBhbGxCeUFjY2Vzc2liaWxpdHlJZCh0ZXN0SWQsIGFyZ3MgPSB7fSkge1xuICAgIGNvbnN0IHt2aXNpYmxlID0gdHJ1ZSwgdGltZW91dCwgLi4ucmVzdEFyZ3N9ID0gYXJnc1xuICAgIGNvbnN0IHJlc3RBcmdzS2V5cyA9IE9iamVjdC5rZXlzKHJlc3RBcmdzKS5maWx0ZXIoKGtleSkgPT4ga2V5ICE9PSBcInVzZUJhc2VTZWxlY3RvclwiKVxuICAgIGxldCBhY3R1YWxUaW1lb3V0XG5cbiAgICBpZiAodGltZW91dCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBhY3R1YWxUaW1lb3V0ID0gdGhpcy5fZHJpdmVyVGltZW91dHNcbiAgICB9IGVsc2Uge1xuICAgICAgYWN0dWFsVGltZW91dCA9IHRpbWVvdXRcbiAgICB9XG5cbiAgICBpZiAocmVzdEFyZ3NLZXlzLmxlbmd0aCA+IDApIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBhcmd1bWVudHM6ICR7cmVzdEFyZ3NLZXlzLmpvaW4oXCIsIFwiKX1gKVxuXG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKVxuICAgIGNvbnN0IGdldFRpbWVMZWZ0ID0gKCkgPT4gTWF0aC5tYXgoYWN0dWFsVGltZW91dCAtIChEYXRlLm5vdygpIC0gc3RhcnRUaW1lKSwgMClcbiAgICBjb25zdCBnZXRFbGVtZW50cyA9IGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZvdW5kRWxlbWVudHMgPSBhd2FpdCB0aGlzLmdldFdlYkRyaXZlcigpLmZpbmRFbGVtZW50cyhuZXcgQnkoXCJhY2Nlc3NpYmlsaXR5IGlkXCIsIHRlc3RJZCkpXG5cbiAgICAgIGlmICh2aXNpYmxlICE9PSB0cnVlICYmIHZpc2libGUgIT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBmb3VuZEVsZW1lbnRzXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGZpbHRlcmVkRWxlbWVudHMgPSBbXVxuXG4gICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZm91bmRFbGVtZW50cykge1xuICAgICAgICBjb25zdCBpc0Rpc3BsYXllZCA9IGF3YWl0IGVsZW1lbnQuaXNEaXNwbGF5ZWQoKVxuXG4gICAgICAgIGlmICh2aXNpYmxlICYmICFpc0Rpc3BsYXllZCkgY29udGludWVcbiAgICAgICAgaWYgKCF2aXNpYmxlICYmIGlzRGlzcGxheWVkKSBjb250aW51ZVxuXG4gICAgICAgIGZpbHRlcmVkRWxlbWVudHMucHVzaChlbGVtZW50KVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmlsdGVyZWRFbGVtZW50c1xuICAgIH1cbiAgICBsZXQgZWxlbWVudHMgPSBbXVxuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IHRpbWVMZWZ0ID0gYWN0dWFsVGltZW91dCA9PSAwID8gMCA6IGdldFRpbWVMZWZ0KClcblxuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKHRpbWVMZWZ0ID09IDApIHtcbiAgICAgICAgICBlbGVtZW50cyA9IGF3YWl0IGdldEVsZW1lbnRzKClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmdldFdlYkRyaXZlcigpLndhaXQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgZWxlbWVudHMgPSBhd2FpdCBnZXRFbGVtZW50cygpXG5cbiAgICAgICAgICAgIHJldHVybiBlbGVtZW50cy5sZW5ndGggPiAwXG4gICAgICAgICAgfSwgdGltZUxlZnQpXG4gICAgICAgIH1cblxuICAgICAgICBicmVha1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgJiYgZXJyb3IuY29uc3RydWN0b3IubmFtZSA9PT0gXCJUaW1lb3V0RXJyb3JcIiAmJiBnZXRUaW1lTGVmdCgpID4gMCkge1xuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkbid0IGdldCBlbGVtZW50cyB3aXRoIGFjY2Vzc2liaWxpdHkgaWQ6ICR7dGVzdElkfTogJHtlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IGVycm9yfWApXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnRzXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRlc3RJZFxuICAgKiBAcGFyYW0ge0ZpbmRBcmdzfSBbYXJnc11cbiAgICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwic2VsZW5pdW0td2ViZHJpdmVyXCIpLldlYkVsZW1lbnQ+fVxuICAgKi9cbiAgYXN5bmMgZmluZEJ5SWQodGVzdElkLCBhcmdzID0ge30pIHtcbiAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpXG4gICAgbGV0IGVsZW1lbnRzID0gW11cblxuICAgIHRyeSB7XG4gICAgICBlbGVtZW50cyA9IGF3YWl0IHRoaXMuYWxsQnlJZCh0ZXN0SWQsIGFyZ3MpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIFJlLXRocm93IHRvIHJlY292ZXIgc3RhY2sgdHJhY2VcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIGlmIChlcnJvci5tZXNzYWdlLnN0YXJ0c1dpdGgoXCJXYWl0IHRpbWVkIG91dCBhZnRlclwiKSkge1xuICAgICAgICAgIGVsZW1lbnRzID0gW11cbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtlcnJvci5jb25zdHJ1Y3Rvci5uYW1lfSAtICR7ZXJyb3IubWVzc2FnZX0gKGlkOiAke3Rlc3RJZH0pYClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0eXBlb2YgZXJyb3J9IC0gJHtlcnJvcn0gKGlkOiAke3Rlc3RJZH0pYClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxlbWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBNb3JlIHRoYW4gMSBlbGVtZW50cyAoJHtlbGVtZW50cy5sZW5ndGh9KSB3YXMgZm91bmQgYnkgaWQ6ICR7dGVzdElkfWApXG4gICAgfVxuXG4gICAgaWYgKCFlbGVtZW50c1swXSkge1xuICAgICAgY29uc3QgZWxhcHNlZFNlY29uZHMgPSAoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSkgLyAxMDAwXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVsZW1lbnQgY291bGRuJ3QgYmUgZm91bmQgYWZ0ZXIgJHtlbGFwc2VkU2Vjb25kcy50b0ZpeGVkKDIpfXMgYnkgaWQ6ICR7dGVzdElkfWApXG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnRzWzBdXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRlc3RJZFxuICAgKiBAcGFyYW0ge0ZpbmRBcmdzfSBbYXJnc11cbiAgICogQHJldHVybnMge1Byb21pc2U8aW1wb3J0KFwic2VsZW5pdW0td2ViZHJpdmVyXCIpLldlYkVsZW1lbnRbXT59XG4gICAqL1xuICBhc3luYyBhbGxCeUlkKHRlc3RJZCwgYXJncyA9IHt9KSB7XG4gICAgY29uc3Qge3Zpc2libGUgPSB0cnVlLCB0aW1lb3V0LCAuLi5yZXN0QXJnc30gPSBhcmdzXG4gICAgY29uc3QgcmVzdEFyZ3NLZXlzID0gT2JqZWN0LmtleXMocmVzdEFyZ3MpLmZpbHRlcigoa2V5KSA9PiBrZXkgIT09IFwidXNlQmFzZVNlbGVjdG9yXCIpXG4gICAgbGV0IGFjdHVhbFRpbWVvdXRcblxuICAgIGlmICh0aW1lb3V0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGFjdHVhbFRpbWVvdXQgPSB0aGlzLl9kcml2ZXJUaW1lb3V0c1xuICAgIH0gZWxzZSB7XG4gICAgICBhY3R1YWxUaW1lb3V0ID0gdGltZW91dFxuICAgIH1cblxuICAgIGlmIChyZXN0QXJnc0tleXMubGVuZ3RoID4gMCkgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGFyZ3VtZW50czogJHtyZXN0QXJnc0tleXMuam9pbihcIiwgXCIpfWApXG5cbiAgICBjb25zdCBzdGFydFRpbWUgPSBEYXRlLm5vdygpXG4gICAgY29uc3QgZ2V0VGltZUxlZnQgPSAoKSA9PiBNYXRoLm1heChhY3R1YWxUaW1lb3V0IC0gKERhdGUubm93KCkgLSBzdGFydFRpbWUpLCAwKVxuICAgIGNvbnN0IGdldEVsZW1lbnRzID0gYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZm91bmRFbGVtZW50cyA9IGF3YWl0IHRoaXMuZ2V0V2ViRHJpdmVyKCkuZmluZEVsZW1lbnRzKEJ5LmlkKHRlc3RJZCkpXG5cbiAgICAgIGlmICh2aXNpYmxlICE9PSB0cnVlICYmIHZpc2libGUgIT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBmb3VuZEVsZW1lbnRzXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGZpbHRlcmVkRWxlbWVudHMgPSBbXVxuXG4gICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZm91bmRFbGVtZW50cykge1xuICAgICAgICBjb25zdCBpc0Rpc3BsYXllZCA9IGF3YWl0IGVsZW1lbnQuaXNEaXNwbGF5ZWQoKVxuXG4gICAgICAgIGlmICh2aXNpYmxlICYmICFpc0Rpc3BsYXllZCkgY29udGludWVcbiAgICAgICAgaWYgKCF2aXNpYmxlICYmIGlzRGlzcGxheWVkKSBjb250aW51ZVxuXG4gICAgICAgIGZpbHRlcmVkRWxlbWVudHMucHVzaChlbGVtZW50KVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmlsdGVyZWRFbGVtZW50c1xuICAgIH1cbiAgICBsZXQgZWxlbWVudHMgPSBbXVxuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IHRpbWVMZWZ0ID0gYWN0dWFsVGltZW91dCA9PSAwID8gMCA6IGdldFRpbWVMZWZ0KClcblxuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKHRpbWVMZWZ0ID09IDApIHtcbiAgICAgICAgICBlbGVtZW50cyA9IGF3YWl0IGdldEVsZW1lbnRzKClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmdldFdlYkRyaXZlcigpLndhaXQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgZWxlbWVudHMgPSBhd2FpdCBnZXRFbGVtZW50cygpXG5cbiAgICAgICAgICAgIHJldHVybiBlbGVtZW50cy5sZW5ndGggPiAwXG4gICAgICAgICAgfSwgdGltZUxlZnQpXG4gICAgICAgIH1cblxuICAgICAgICBicmVha1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgJiYgZXJyb3IuY29uc3RydWN0b3IubmFtZSA9PT0gXCJUaW1lb3V0RXJyb3JcIiAmJiBnZXRUaW1lTGVmdCgpID4gMCkge1xuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkbid0IGdldCBlbGVtZW50cyB3aXRoIGlkOiAke3Rlc3RJZH06ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBlcnJvcn1gKVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBlbGVtZW50c1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgYW55Pn0gc2VydmVyQXJnc1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgYnVpbGRTZXJ2ZXJVcmwoc2VydmVyQXJncykge1xuICAgIGNvbnN0IGFkZHJlc3MgPSBzZXJ2ZXJBcmdzLmFkZHJlc3MgPz8gXCIxMjcuMC4wLjFcIlxuICAgIGNvbnN0IHBvcnQgPSBzZXJ2ZXJBcmdzLnBvcnQgPz8gNDcyM1xuICAgIGNvbnN0IGJhc2VQYXRoID0gc2VydmVyQXJncy5iYXNlUGF0aCA/IChzZXJ2ZXJBcmdzLmJhc2VQYXRoLnN0YXJ0c1dpdGgoXCIvXCIpID8gc2VydmVyQXJncy5iYXNlUGF0aCA6IGAvJHtzZXJ2ZXJBcmdzLmJhc2VQYXRofWApIDogXCJcIlxuXG4gICAgcmV0dXJuIGBodHRwOi8vJHthZGRyZXNzfToke3BvcnR9JHtiYXNlUGF0aH1gXG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} SeleniumDriverOptions
|
|
3
|
+
* @property {string} [browserName] Browser name used by the WebDriver session.
|
|
4
|
+
* @property {string[]} [chromeArguments] Chrome CLI arguments.
|
|
5
|
+
* @property {import("selenium-webdriver/chrome.js").Options} [chromeOptions] Preconfigured Chrome options instance.
|
|
6
|
+
* @property {Record<string, any>} [capabilities] Extra WebDriver capabilities.
|
|
7
|
+
* @property {Record<string, any>} [loggingPrefs] Logging preferences for browser logs.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Selenium WebDriver implementation.
|
|
11
|
+
*/
|
|
12
|
+
export default class SeleniumDriver extends WebDriverDriver {
|
|
13
|
+
}
|
|
14
|
+
export type SeleniumDriverOptions = {
|
|
15
|
+
/**
|
|
16
|
+
* Browser name used by the WebDriver session.
|
|
17
|
+
*/
|
|
18
|
+
browserName?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Chrome CLI arguments.
|
|
21
|
+
*/
|
|
22
|
+
chromeArguments?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Preconfigured Chrome options instance.
|
|
25
|
+
*/
|
|
26
|
+
chromeOptions?: import("selenium-webdriver/chrome.js").Options;
|
|
27
|
+
/**
|
|
28
|
+
* Extra WebDriver capabilities.
|
|
29
|
+
*/
|
|
30
|
+
capabilities?: Record<string, any>;
|
|
31
|
+
/**
|
|
32
|
+
* Logging preferences for browser logs.
|
|
33
|
+
*/
|
|
34
|
+
loggingPrefs?: Record<string, any>;
|
|
35
|
+
};
|
|
36
|
+
import WebDriverDriver from "./webdriver-driver.js";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Builder } from "selenium-webdriver";
|
|
2
|
+
import chrome from "selenium-webdriver/chrome.js";
|
|
3
|
+
import WebDriverDriver from "./webdriver-driver.js";
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} SeleniumDriverOptions
|
|
6
|
+
* @property {string} [browserName] Browser name used by the WebDriver session.
|
|
7
|
+
* @property {string[]} [chromeArguments] Chrome CLI arguments.
|
|
8
|
+
* @property {import("selenium-webdriver/chrome.js").Options} [chromeOptions] Preconfigured Chrome options instance.
|
|
9
|
+
* @property {Record<string, any>} [capabilities] Extra WebDriver capabilities.
|
|
10
|
+
* @property {Record<string, any>} [loggingPrefs] Logging preferences for browser logs.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Selenium WebDriver implementation.
|
|
14
|
+
*/
|
|
15
|
+
export default class SeleniumDriver extends WebDriverDriver {
|
|
16
|
+
/**
|
|
17
|
+
* @returns {Promise<void>}
|
|
18
|
+
*/
|
|
19
|
+
async start() {
|
|
20
|
+
const chromeOptions = this.options.chromeOptions ? this.options.chromeOptions : new chrome.Options();
|
|
21
|
+
const chromeArguments = this.options.chromeArguments ?? [
|
|
22
|
+
"--disable-dev-shm-usage",
|
|
23
|
+
"--disable-gpu",
|
|
24
|
+
"--headless=new",
|
|
25
|
+
"--no-sandbox",
|
|
26
|
+
"--window-size=1920,1080"
|
|
27
|
+
];
|
|
28
|
+
for (const argument of chromeArguments) {
|
|
29
|
+
chromeOptions.addArguments(argument);
|
|
30
|
+
}
|
|
31
|
+
const builder = new Builder().forBrowser(this.options.browserName ?? "chrome").setChromeOptions(chromeOptions);
|
|
32
|
+
const capabilities = builder.getCapabilities();
|
|
33
|
+
const loggingPrefs = this.options.loggingPrefs ?? { browser: "ALL" };
|
|
34
|
+
capabilities.set("goog:loggingPrefs", loggingPrefs);
|
|
35
|
+
if (this.options.capabilities) {
|
|
36
|
+
for (const [key, value] of Object.entries(this.options.capabilities)) {
|
|
37
|
+
capabilities.set(key, value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const webDriver = await builder.build();
|
|
41
|
+
this.setWebDriver(webDriver);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZW5pdW0tZHJpdmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RyaXZlcnMvc2VsZW5pdW0tZHJpdmVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxPQUFPLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQTtBQUMxQyxPQUFPLE1BQU0sTUFBTSw4QkFBOEIsQ0FBQTtBQUNqRCxPQUFPLGVBQWUsTUFBTSx1QkFBdUIsQ0FBQTtBQUVuRDs7Ozs7OztHQU9HO0FBRUg7O0dBRUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLGNBQWUsU0FBUSxlQUFlO0lBQ3pEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLEtBQUs7UUFDVCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQ3BHLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxJQUFJO1lBQ3RELHlCQUF5QjtZQUN6QixlQUFlO1lBQ2YsZ0JBQWdCO1lBQ2hCLGNBQWM7WUFDZCx5QkFBeUI7U0FDMUIsQ0FBQTtRQUVELEtBQUssTUFBTSxRQUFRLElBQUksZUFBZSxFQUFFLENBQUM7WUFDdkMsYUFBYSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUN0QyxDQUFDO1FBRUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLElBQUksUUFBUSxDQUFDLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLENBQUE7UUFDOUcsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLGVBQWUsRUFBRSxDQUFBO1FBRTlDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxJQUFJLEVBQUMsT0FBTyxFQUFFLEtBQUssRUFBQyxDQUFBO1FBQ2xFLFlBQVksQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUUsWUFBWSxDQUFDLENBQUE7UUFFbkQsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQzlCLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztnQkFDckUsWUFBWSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUE7WUFDOUIsQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLFNBQVMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQTtRQUV2QyxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFBO0lBQzlCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7QnVpbGRlcn0gZnJvbSBcInNlbGVuaXVtLXdlYmRyaXZlclwiXG5pbXBvcnQgY2hyb21lIGZyb20gXCJzZWxlbml1bS13ZWJkcml2ZXIvY2hyb21lLmpzXCJcbmltcG9ydCBXZWJEcml2ZXJEcml2ZXIgZnJvbSBcIi4vd2ViZHJpdmVyLWRyaXZlci5qc1wiXG5cbi8qKlxuICogQHR5cGVkZWYge29iamVjdH0gU2VsZW5pdW1Ecml2ZXJPcHRpb25zXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2Jyb3dzZXJOYW1lXSBCcm93c2VyIG5hbWUgdXNlZCBieSB0aGUgV2ViRHJpdmVyIHNlc3Npb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ1tdfSBbY2hyb21lQXJndW1lbnRzXSBDaHJvbWUgQ0xJIGFyZ3VtZW50cy5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwic2VsZW5pdW0td2ViZHJpdmVyL2Nocm9tZS5qc1wiKS5PcHRpb25zfSBbY2hyb21lT3B0aW9uc10gUHJlY29uZmlndXJlZCBDaHJvbWUgb3B0aW9ucyBpbnN0YW5jZS5cbiAqIEBwcm9wZXJ0eSB7UmVjb3JkPHN0cmluZywgYW55Pn0gW2NhcGFiaWxpdGllc10gRXh0cmEgV2ViRHJpdmVyIGNhcGFiaWxpdGllcy5cbiAqIEBwcm9wZXJ0eSB7UmVjb3JkPHN0cmluZywgYW55Pn0gW2xvZ2dpbmdQcmVmc10gTG9nZ2luZyBwcmVmZXJlbmNlcyBmb3IgYnJvd3NlciBsb2dzLlxuICovXG5cbi8qKlxuICogU2VsZW5pdW0gV2ViRHJpdmVyIGltcGxlbWVudGF0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTZWxlbml1bURyaXZlciBleHRlbmRzIFdlYkRyaXZlckRyaXZlciB7XG4gIC8qKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIHN0YXJ0KCkge1xuICAgIGNvbnN0IGNocm9tZU9wdGlvbnMgPSB0aGlzLm9wdGlvbnMuY2hyb21lT3B0aW9ucyA/IHRoaXMub3B0aW9ucy5jaHJvbWVPcHRpb25zIDogbmV3IGNocm9tZS5PcHRpb25zKClcbiAgICBjb25zdCBjaHJvbWVBcmd1bWVudHMgPSB0aGlzLm9wdGlvbnMuY2hyb21lQXJndW1lbnRzID8/IFtcbiAgICAgIFwiLS1kaXNhYmxlLWRldi1zaG0tdXNhZ2VcIixcbiAgICAgIFwiLS1kaXNhYmxlLWdwdVwiLFxuICAgICAgXCItLWhlYWRsZXNzPW5ld1wiLFxuICAgICAgXCItLW5vLXNhbmRib3hcIixcbiAgICAgIFwiLS13aW5kb3ctc2l6ZT0xOTIwLDEwODBcIlxuICAgIF1cblxuICAgIGZvciAoY29uc3QgYXJndW1lbnQgb2YgY2hyb21lQXJndW1lbnRzKSB7XG4gICAgICBjaHJvbWVPcHRpb25zLmFkZEFyZ3VtZW50cyhhcmd1bWVudClcbiAgICB9XG5cbiAgICBjb25zdCBidWlsZGVyID0gbmV3IEJ1aWxkZXIoKS5mb3JCcm93c2VyKHRoaXMub3B0aW9ucy5icm93c2VyTmFtZSA/PyBcImNocm9tZVwiKS5zZXRDaHJvbWVPcHRpb25zKGNocm9tZU9wdGlvbnMpXG4gICAgY29uc3QgY2FwYWJpbGl0aWVzID0gYnVpbGRlci5nZXRDYXBhYmlsaXRpZXMoKVxuXG4gICAgY29uc3QgbG9nZ2luZ1ByZWZzID0gdGhpcy5vcHRpb25zLmxvZ2dpbmdQcmVmcyA/PyB7YnJvd3NlcjogXCJBTExcIn1cbiAgICBjYXBhYmlsaXRpZXMuc2V0KFwiZ29vZzpsb2dnaW5nUHJlZnNcIiwgbG9nZ2luZ1ByZWZzKVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5jYXBhYmlsaXRpZXMpIHtcbiAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHRoaXMub3B0aW9ucy5jYXBhYmlsaXRpZXMpKSB7XG4gICAgICAgIGNhcGFiaWxpdGllcy5zZXQoa2V5LCB2YWx1ZSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB3ZWJEcml2ZXIgPSBhd2FpdCBidWlsZGVyLmJ1aWxkKClcblxuICAgIHRoaXMuc2V0V2ViRHJpdmVyKHdlYkRyaXZlcilcbiAgfVxufVxuIl19
|