@appium/driver-test-support 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/e2e-suite.d.ts +12 -12
- package/build/lib/e2e-suite.d.ts.map +1 -1
- package/build/lib/e2e-suite.js +404 -376
- package/build/lib/e2e-suite.js.map +1 -0
- package/build/lib/helpers.js +62 -40
- package/build/lib/helpers.js.map +1 -0
- package/build/lib/index.d.ts +3 -3
- package/build/lib/index.d.ts.map +1 -1
- package/build/lib/index.js +30 -45
- package/build/lib/index.js.map +1 -0
- package/build/lib/unit-suite.d.ts +4 -6
- package/build/lib/unit-suite.d.ts.map +1 -1
- package/build/lib/unit-suite.js +560 -544
- package/build/lib/unit-suite.js.map +1 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/lib/e2e-suite.js +13 -7
- package/lib/index.js +8 -3
- package/lib/unit-suite.js +8 -3
- package/package.json +10 -15
package/build/lib/e2e-suite.js
CHANGED
|
@@ -1,389 +1,417 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "__esModule", {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
require("
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
function createSessionHelpers(port, address = _helpers.TEST_HOST) {
|
|
30
|
-
const createAppiumTestURL = (0, _helpers.createAppiumURL)(address, port);
|
|
31
|
-
const createSessionURL = createAppiumTestURL(_lodash.default, '');
|
|
32
|
-
const newSessionURL = createAppiumTestURL('', 'session');
|
|
33
|
-
return {
|
|
34
|
-
newSessionURL,
|
|
35
|
-
createAppiumTestURL,
|
|
36
|
-
postCommand: async (sessionId, cmdName, data = {}, config = {}) => {
|
|
37
|
-
var _response$data;
|
|
38
|
-
|
|
39
|
-
const url = createAppiumTestURL(sessionId, cmdName);
|
|
40
|
-
const response = await _axios.default.post(url, data, config);
|
|
41
|
-
return (_response$data = response.data) === null || _response$data === void 0 ? void 0 : _response$data.value;
|
|
42
|
-
},
|
|
43
|
-
getCommand: async (sessionIdOrCmdName, cmdNameOrConfig, config = {}) => {
|
|
44
|
-
var _response$data2;
|
|
45
|
-
|
|
46
|
-
if (!_lodash.default.isString(cmdNameOrConfig)) {
|
|
47
|
-
config = cmdNameOrConfig;
|
|
48
|
-
cmdNameOrConfig = sessionIdOrCmdName;
|
|
49
|
-
sessionIdOrCmdName = '';
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const response = await (0, _axios.default)({
|
|
53
|
-
url: createAppiumTestURL(sessionIdOrCmdName, cmdNameOrConfig),
|
|
54
|
-
validateStatus: null,
|
|
55
|
-
...config
|
|
56
|
-
});
|
|
57
|
-
return (_response$data2 = response.data) === null || _response$data2 === void 0 ? void 0 : _response$data2.value;
|
|
58
|
-
},
|
|
59
|
-
startSession: async (data, config = {}) => {
|
|
60
|
-
var _response$data3;
|
|
61
|
-
|
|
62
|
-
data = _lodash.default.defaultsDeep(data, {
|
|
63
|
-
capabilities: {
|
|
64
|
-
alwaysMatch: {},
|
|
65
|
-
firstMatch: [{}]
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
const response = await _axios.default.post(newSessionURL, data, config);
|
|
69
|
-
return (_response$data3 = response.data) === null || _response$data3 === void 0 ? void 0 : _response$data3.value;
|
|
70
|
-
},
|
|
71
|
-
endSession: async sessionId => await _axios.default.delete(createSessionURL(sessionId), {
|
|
72
|
-
validateStatus: null
|
|
73
|
-
}),
|
|
74
|
-
getSession: async sessionId => {
|
|
75
|
-
var _response$data4;
|
|
76
|
-
|
|
77
|
-
const response = await (0, _axios.default)({
|
|
78
|
-
url: createSessionURL(sessionId),
|
|
79
|
-
validateStatus: null
|
|
80
|
-
});
|
|
81
|
-
return (_response$data4 = response.data) === null || _response$data4 === void 0 ? void 0 : _response$data4.value;
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function driverE2ETestSuite(DriverClass, defaultCaps = {}) {
|
|
87
|
-
let address = defaultCaps['appium:address'] ?? _helpers.TEST_HOST;
|
|
88
|
-
let port = defaultCaps['appium:port'];
|
|
89
|
-
const className = DriverClass.name || '(unknown driver)';
|
|
90
|
-
describe(`BaseDriver E2E (as ${className})`, function () {
|
|
91
|
-
let baseServer;
|
|
92
|
-
let d;
|
|
93
|
-
let newSessionURL;
|
|
94
|
-
let startSession;
|
|
95
|
-
let getSession;
|
|
96
|
-
let endSession;
|
|
97
|
-
let getCommand;
|
|
98
|
-
let postCommand;
|
|
99
|
-
before(async function () {
|
|
100
|
-
port = port ?? (await (0, _helpers.getTestPort)());
|
|
101
|
-
defaultCaps = { ...defaultCaps,
|
|
102
|
-
'appium:port': port
|
|
103
|
-
};
|
|
104
|
-
d = new DriverClass({
|
|
105
|
-
port,
|
|
106
|
-
address
|
|
107
|
-
});
|
|
108
|
-
baseServer = await (0, _driver.server)({
|
|
109
|
-
routeConfiguringFunction: (0, _driver.routeConfiguringFunction)(d),
|
|
110
|
-
port,
|
|
111
|
-
hostname: address,
|
|
112
|
-
cliArgs: {}
|
|
113
|
-
});
|
|
114
|
-
({
|
|
115
|
-
startSession,
|
|
116
|
-
getSession,
|
|
117
|
-
endSession,
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.driverE2ETestSuite = exports.createSessionHelpers = void 0;
|
|
7
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
8
|
+
const driver_1 = require("appium/driver");
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const bluebird_1 = __importDefault(require("bluebird"));
|
|
11
|
+
const helpers_1 = require("./helpers");
|
|
12
|
+
const chai_1 = __importDefault(require("chai"));
|
|
13
|
+
const sinon_1 = __importDefault(require("sinon"));
|
|
14
|
+
const should = chai_1.default.should();
|
|
15
|
+
/**
|
|
16
|
+
* Creates some helper functions for E2E tests to manage sessions.
|
|
17
|
+
* @template [CommandData=unknown]
|
|
18
|
+
* @template [ResponseData=any]
|
|
19
|
+
* @param {number} port - Port on which the server is running. Typically this will be retrieved via `get-port` beforehand
|
|
20
|
+
* @param {string} [address] - Address/host on which the server is running. Defaults to {@linkcode TEST_HOST}
|
|
21
|
+
* @returns {SessionHelpers<CommandData, ResponseData>}
|
|
22
|
+
*/
|
|
23
|
+
function createSessionHelpers(port, address = helpers_1.TEST_HOST) {
|
|
24
|
+
const createAppiumTestURL =
|
|
25
|
+
/** @type {import('lodash').CurriedFunction2<string,string,string>} */ ((0, helpers_1.createAppiumURL)(address, port));
|
|
26
|
+
const createSessionURL = createAppiumTestURL(lodash_1.default, '');
|
|
27
|
+
const newSessionURL = createAppiumTestURL('', 'session');
|
|
28
|
+
return /** @type {SessionHelpers<CommandData, ResponseData>} */ ({
|
|
118
29
|
newSessionURL,
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
30
|
+
createAppiumTestURL,
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @param {string} sessionId
|
|
34
|
+
* @param {string} cmdName
|
|
35
|
+
* @param {any} [data]
|
|
36
|
+
* @param {AxiosRequestConfig} [config]
|
|
37
|
+
* @returns {Promise<any>}
|
|
38
|
+
*/
|
|
39
|
+
postCommand: async (sessionId, cmdName, data = {}, config = {}) => {
|
|
40
|
+
const url = createAppiumTestURL(sessionId, cmdName);
|
|
41
|
+
const response = await axios_1.default.post(url, data, config);
|
|
42
|
+
return response.data?.value;
|
|
43
|
+
},
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @param {string} sessionIdOrCmdName
|
|
47
|
+
* @param {string|AxiosRequestConfig} cmdNameOrConfig
|
|
48
|
+
* @param {AxiosRequestConfig} [config]
|
|
49
|
+
* @returns {Promise<any>}
|
|
50
|
+
*/
|
|
51
|
+
getCommand: async (sessionIdOrCmdName, cmdNameOrConfig, config = {}) => {
|
|
52
|
+
if (!lodash_1.default.isString(cmdNameOrConfig)) {
|
|
53
|
+
config = cmdNameOrConfig;
|
|
54
|
+
cmdNameOrConfig = sessionIdOrCmdName;
|
|
55
|
+
sessionIdOrCmdName = '';
|
|
137
56
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const {
|
|
180
|
-
status,
|
|
181
|
-
data
|
|
182
|
-
} = await endSession(sessionIds[0]);
|
|
183
|
-
status.should.equal(200);
|
|
184
|
-
should.equal(data.value, null);
|
|
185
|
-
});
|
|
186
|
-
it('should create session and retrieve a session id, then delete it', async function () {
|
|
187
|
-
let {
|
|
188
|
-
status,
|
|
189
|
-
data
|
|
190
|
-
} = await _axios.default.post(newSessionURL, {
|
|
191
|
-
capabilities: {
|
|
192
|
-
alwaysMatch: defaultCaps
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
status.should.equal(200);
|
|
196
|
-
should.exist(data.value.sessionId);
|
|
197
|
-
data.value.capabilities.platformName.should.equal(defaultCaps.platformName);
|
|
198
|
-
data.value.capabilities.deviceName.should.equal(defaultCaps['appium:deviceName']);
|
|
199
|
-
({
|
|
200
|
-
status,
|
|
201
|
-
data
|
|
202
|
-
} = await endSession(d.sessionId));
|
|
203
|
-
status.should.equal(200);
|
|
204
|
-
should.equal(data.value, null);
|
|
205
|
-
should.equal(d.sessionId, null);
|
|
206
|
-
});
|
|
57
|
+
const response = await (0, axios_1.default)({
|
|
58
|
+
url: createAppiumTestURL(sessionIdOrCmdName, cmdNameOrConfig),
|
|
59
|
+
validateStatus: null,
|
|
60
|
+
...config,
|
|
61
|
+
});
|
|
62
|
+
return response.data?.value;
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
* @param {NewSessionData} data
|
|
67
|
+
* @param {AxiosRequestConfig} [config]
|
|
68
|
+
*/
|
|
69
|
+
startSession: async (data, config = {}) => {
|
|
70
|
+
data = lodash_1.default.defaultsDeep(data, {
|
|
71
|
+
capabilities: {
|
|
72
|
+
alwaysMatch: {},
|
|
73
|
+
firstMatch: [{}],
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
const response = await axios_1.default.post(newSessionURL, data, config);
|
|
77
|
+
return response.data?.value;
|
|
78
|
+
},
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @param {string} sessionId
|
|
82
|
+
*/
|
|
83
|
+
endSession: async (sessionId) => await axios_1.default.delete(createSessionURL(sessionId), {
|
|
84
|
+
validateStatus: null,
|
|
85
|
+
}),
|
|
86
|
+
/**
|
|
87
|
+
* @param {string} sessionId
|
|
88
|
+
* @returns {Promise<any>}
|
|
89
|
+
*/
|
|
90
|
+
getSession: async (sessionId) => {
|
|
91
|
+
const response = await (0, axios_1.default)({
|
|
92
|
+
url: createSessionURL(sessionId),
|
|
93
|
+
validateStatus: null,
|
|
94
|
+
});
|
|
95
|
+
return response.data?.value;
|
|
96
|
+
},
|
|
207
97
|
});
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
});
|
|
253
|
-
await _bluebird.default.delay(400);
|
|
254
|
-
const value = await getSession(sessionId);
|
|
255
|
-
should.equal(value.error, 'invalid session id');
|
|
256
|
-
should.equal(d.sessionId, null);
|
|
257
|
-
const resp = (await endSession(newSession.sessionId)).data.value;
|
|
258
|
-
should.equal(resp === null || resp === void 0 ? void 0 : resp.error, 'invalid session id');
|
|
259
|
-
});
|
|
260
|
-
it('should not timeout with commandTimeout of false', async function () {
|
|
261
|
-
let newSession = await startTimeoutSession(0.1);
|
|
262
|
-
let start = Date.now();
|
|
263
|
-
const value = await postCommand(d.sessionId, 'elements', {
|
|
264
|
-
using: 'name',
|
|
265
|
-
value: 'foo'
|
|
266
|
-
});
|
|
267
|
-
(Date.now() - start).should.be.above(150);
|
|
268
|
-
value.should.eql(['foo']);
|
|
269
|
-
await endSession(newSession.sessionId);
|
|
270
|
-
});
|
|
271
|
-
it('should not timeout with commandTimeout of 0', async function () {
|
|
272
|
-
var _value$platformName;
|
|
273
|
-
|
|
274
|
-
d.newCommandTimeoutMs = 2;
|
|
275
|
-
let newSession = await startTimeoutSession(0);
|
|
276
|
-
await postCommand(d.sessionId, 'element', {
|
|
277
|
-
using: 'name',
|
|
278
|
-
value: 'foo'
|
|
279
|
-
});
|
|
280
|
-
await _bluebird.default.delay(400);
|
|
281
|
-
const value = await getSession(d.sessionId);
|
|
282
|
-
(_value$platformName = value.platformName) === null || _value$platformName === void 0 ? void 0 : _value$platformName.should.equal(defaultCaps.platformName);
|
|
283
|
-
const resp = (await endSession(newSession.sessionId)).data.value;
|
|
284
|
-
should.equal(resp, null);
|
|
285
|
-
d.newCommandTimeoutMs = 60 * 1000;
|
|
286
|
-
});
|
|
287
|
-
it('should not timeout if its just the command taking awhile', async function () {
|
|
288
|
-
let newSession = await startTimeoutSession(0.25);
|
|
289
|
-
const {
|
|
290
|
-
sessionId
|
|
291
|
-
} = d;
|
|
292
|
-
await postCommand(d.sessionId, 'element', {
|
|
293
|
-
using: 'name',
|
|
294
|
-
value: 'foo'
|
|
98
|
+
}
|
|
99
|
+
exports.createSessionHelpers = createSessionHelpers;
|
|
100
|
+
/**
|
|
101
|
+
* Creates E2E test suites for a driver.
|
|
102
|
+
* @template {Driver} P
|
|
103
|
+
* @param {DriverClass<P>} DriverClass
|
|
104
|
+
* @param {Partial<BaseNSCapabilities>} [defaultCaps]
|
|
105
|
+
*/
|
|
106
|
+
function driverE2ETestSuite(DriverClass, defaultCaps = {}) {
|
|
107
|
+
let address = defaultCaps['appium:address'] ?? helpers_1.TEST_HOST;
|
|
108
|
+
let port = defaultCaps['appium:port'];
|
|
109
|
+
const className = DriverClass.name || '(unknown driver)';
|
|
110
|
+
describe(`BaseDriver E2E (as ${className})`, function () {
|
|
111
|
+
let baseServer;
|
|
112
|
+
/** @type {P} */
|
|
113
|
+
let d;
|
|
114
|
+
/**
|
|
115
|
+
* This URL creates a new session
|
|
116
|
+
* @type {string}
|
|
117
|
+
**/
|
|
118
|
+
let newSessionURL;
|
|
119
|
+
/** @type {SessionHelpers['startSession']} */
|
|
120
|
+
let startSession;
|
|
121
|
+
/** @type {SessionHelpers['getSession']} */
|
|
122
|
+
let getSession;
|
|
123
|
+
/** @type {SessionHelpers['endSession']} */
|
|
124
|
+
let endSession;
|
|
125
|
+
/** @type {SessionHelpers['getCommand']} */
|
|
126
|
+
let getCommand;
|
|
127
|
+
/** @type {SessionHelpers['postCommand']} */
|
|
128
|
+
let postCommand;
|
|
129
|
+
before(async function () {
|
|
130
|
+
port = port ?? (await (0, helpers_1.getTestPort)());
|
|
131
|
+
defaultCaps = { ...defaultCaps };
|
|
132
|
+
d = new DriverClass({ port, address });
|
|
133
|
+
baseServer = await (0, driver_1.server)({
|
|
134
|
+
routeConfiguringFunction: (0, driver_1.routeConfiguringFunction)(d),
|
|
135
|
+
port,
|
|
136
|
+
hostname: address,
|
|
137
|
+
// @ts-expect-error
|
|
138
|
+
cliArgs: {},
|
|
139
|
+
});
|
|
140
|
+
({ startSession, getSession, endSession, newSessionURL, getCommand, postCommand } =
|
|
141
|
+
createSessionHelpers(port, address));
|
|
295
142
|
});
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
value.error.should.equal('invalid session id');
|
|
299
|
-
should.equal(d.sessionId, null);
|
|
300
|
-
const resp = (await endSession(newSession.sessionId)).data.value;
|
|
301
|
-
resp.error.should.equal('invalid session id');
|
|
302
|
-
});
|
|
303
|
-
it('should not have a timer running before or after a session', async function () {
|
|
304
|
-
should.not.exist(d.noCommandTimer);
|
|
305
|
-
let newSession = await startTimeoutSession(0.25);
|
|
306
|
-
newSession.sessionId.should.equal(d.sessionId);
|
|
307
|
-
should.exist(d.noCommandTimer);
|
|
308
|
-
await endSession(newSession.sessionId);
|
|
309
|
-
should.not.exist(d.noCommandTimer);
|
|
310
|
-
});
|
|
311
|
-
});
|
|
312
|
-
describe('settings api', function () {
|
|
313
|
-
before(function () {
|
|
314
|
-
d.settings = new _driver.DeviceSettings({
|
|
315
|
-
ignoreUnimportantViews: false
|
|
143
|
+
after(async function () {
|
|
144
|
+
await baseServer.close();
|
|
316
145
|
});
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
146
|
+
describe('session handling', function () {
|
|
147
|
+
it('should handle idempotency while creating sessions', async function () {
|
|
148
|
+
const sessionIds = [];
|
|
149
|
+
let times = 0;
|
|
150
|
+
do {
|
|
151
|
+
const { sessionId } = await startSession({
|
|
152
|
+
capabilities: { alwaysMatch: defaultCaps },
|
|
153
|
+
}, {
|
|
154
|
+
headers: {
|
|
155
|
+
'X-Idempotency-Key': '123456',
|
|
156
|
+
},
|
|
157
|
+
// XXX: I'm not sure what these are, as they are not documented axios options,
|
|
158
|
+
// nor are they mentioned in our source
|
|
159
|
+
// @ts-expect-error
|
|
160
|
+
simple: false,
|
|
161
|
+
resolveWithFullResponse: true,
|
|
162
|
+
});
|
|
163
|
+
sessionIds.push(sessionId);
|
|
164
|
+
times++;
|
|
165
|
+
} while (times < 2);
|
|
166
|
+
lodash_1.default.uniq(sessionIds).length.should.equal(1);
|
|
167
|
+
const { status, data } = await endSession(sessionIds[0]);
|
|
168
|
+
status.should.equal(200);
|
|
169
|
+
should.equal(data.value, null);
|
|
170
|
+
});
|
|
171
|
+
it('should handle idempotency while creating parallel sessions', async function () {
|
|
172
|
+
const reqs = [];
|
|
173
|
+
let times = 0;
|
|
174
|
+
do {
|
|
175
|
+
reqs.push(startSession({
|
|
176
|
+
capabilities: {
|
|
177
|
+
alwaysMatch: defaultCaps,
|
|
178
|
+
},
|
|
179
|
+
}, {
|
|
180
|
+
headers: {
|
|
181
|
+
'X-Idempotency-Key': '12345',
|
|
182
|
+
},
|
|
183
|
+
}));
|
|
184
|
+
times++;
|
|
185
|
+
} while (times < 2);
|
|
186
|
+
const sessionIds = lodash_1.default.map(await bluebird_1.default.all(reqs), 'sessionId');
|
|
187
|
+
lodash_1.default.uniq(sessionIds).length.should.equal(1);
|
|
188
|
+
const { status, data } = await endSession(sessionIds[0]);
|
|
189
|
+
status.should.equal(200);
|
|
190
|
+
should.equal(data.value, null);
|
|
191
|
+
});
|
|
192
|
+
it('should create session and retrieve a session id, then delete it', async function () {
|
|
193
|
+
let { status, data } = await axios_1.default.post(newSessionURL, {
|
|
194
|
+
capabilities: {
|
|
195
|
+
alwaysMatch: defaultCaps,
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
status.should.equal(200);
|
|
199
|
+
should.exist(data.value.sessionId);
|
|
200
|
+
data.value.capabilities.platformName.should.equal(defaultCaps.platformName);
|
|
201
|
+
data.value.capabilities.deviceName.should.equal(defaultCaps['appium:deviceName']);
|
|
202
|
+
({ status, data } = await endSession(/** @type {string} */ (d.sessionId)));
|
|
203
|
+
status.should.equal(200);
|
|
204
|
+
should.equal(data.value, null);
|
|
205
|
+
should.equal(d.sessionId, null);
|
|
206
|
+
});
|
|
341
207
|
});
|
|
342
|
-
|
|
343
|
-
|
|
208
|
+
it.skip('should throw NYI for commands not implemented', async function () { });
|
|
209
|
+
describe('command timeouts', function () {
|
|
210
|
+
let originalFindElement, originalFindElements;
|
|
211
|
+
/**
|
|
212
|
+
* @param {number} [timeout]
|
|
213
|
+
*/
|
|
214
|
+
async function startTimeoutSession(timeout) {
|
|
215
|
+
const caps = lodash_1.default.cloneDeep(defaultCaps);
|
|
216
|
+
caps['appium:newCommandTimeout'] = timeout;
|
|
217
|
+
return await startSession({ capabilities: { alwaysMatch: caps } });
|
|
218
|
+
}
|
|
219
|
+
before(function () {
|
|
220
|
+
originalFindElement = d.findElement;
|
|
221
|
+
d.findElement = function () {
|
|
222
|
+
return 'foo';
|
|
223
|
+
}.bind(d);
|
|
224
|
+
originalFindElements = d.findElements;
|
|
225
|
+
d.findElements = async function () {
|
|
226
|
+
await bluebird_1.default.delay(200);
|
|
227
|
+
return ['foo'];
|
|
228
|
+
}.bind(d);
|
|
229
|
+
});
|
|
230
|
+
after(function () {
|
|
231
|
+
d.findElement = originalFindElement;
|
|
232
|
+
d.findElements = originalFindElements;
|
|
233
|
+
});
|
|
234
|
+
it('should set a default commandTimeout', async function () {
|
|
235
|
+
let newSession = await startTimeoutSession();
|
|
236
|
+
d.newCommandTimeoutMs.should.be.above(0);
|
|
237
|
+
await endSession(newSession.sessionId);
|
|
238
|
+
});
|
|
239
|
+
it('should timeout on commands using commandTimeout cap', async function () {
|
|
240
|
+
let newSession = await startTimeoutSession(0.25);
|
|
241
|
+
const sessionId = /** @type {string} */ (d.sessionId);
|
|
242
|
+
await postCommand(sessionId, 'element', {
|
|
243
|
+
using: 'name',
|
|
244
|
+
value: 'foo',
|
|
245
|
+
});
|
|
246
|
+
await bluebird_1.default.delay(400);
|
|
247
|
+
const value = await getSession(sessionId);
|
|
248
|
+
should.equal(value.error, 'invalid session id');
|
|
249
|
+
should.equal(d.sessionId, null);
|
|
250
|
+
const resp = (await endSession(newSession.sessionId)).data.value;
|
|
251
|
+
should.equal(resp?.error, 'invalid session id');
|
|
252
|
+
});
|
|
253
|
+
it('should not timeout with commandTimeout of false', async function () {
|
|
254
|
+
let newSession = await startTimeoutSession(0.1);
|
|
255
|
+
let start = Date.now();
|
|
256
|
+
const value = await postCommand(/** @type {string} */ (d.sessionId), 'elements', {
|
|
257
|
+
using: 'name',
|
|
258
|
+
value: 'foo',
|
|
259
|
+
});
|
|
260
|
+
(Date.now() - start).should.be.above(150);
|
|
261
|
+
value.should.eql(['foo']);
|
|
262
|
+
await endSession(newSession.sessionId);
|
|
263
|
+
});
|
|
264
|
+
it('should not timeout with commandTimeout of 0', async function () {
|
|
265
|
+
d.newCommandTimeoutMs = 2;
|
|
266
|
+
let newSession = await startTimeoutSession(0);
|
|
267
|
+
await postCommand(/** @type {string} */ (d.sessionId), 'element', {
|
|
268
|
+
using: 'name',
|
|
269
|
+
value: 'foo',
|
|
270
|
+
});
|
|
271
|
+
await bluebird_1.default.delay(400);
|
|
272
|
+
const value = await getSession(/** @type {string} */ (d.sessionId));
|
|
273
|
+
value.platformName?.should.equal(defaultCaps.platformName);
|
|
274
|
+
const resp = (await endSession(newSession.sessionId)).data.value;
|
|
275
|
+
should.equal(resp, null);
|
|
276
|
+
d.newCommandTimeoutMs = 60 * 1000;
|
|
277
|
+
});
|
|
278
|
+
it('should not timeout if its just the command taking awhile', async function () {
|
|
279
|
+
let newSession = await startTimeoutSession(0.25);
|
|
280
|
+
// XXX: race condition: we must build this URL before ...something happens...
|
|
281
|
+
// which causes `d.sessionId` to be missing
|
|
282
|
+
const { sessionId } = d;
|
|
283
|
+
await postCommand(/** @type {string} */ (d.sessionId), 'element', {
|
|
284
|
+
using: 'name',
|
|
285
|
+
value: 'foo',
|
|
286
|
+
});
|
|
287
|
+
await bluebird_1.default.delay(400);
|
|
288
|
+
const value = await getSession(/** @type {string} */ (sessionId));
|
|
289
|
+
/** @type {string} */ (value.error).should.equal('invalid session id');
|
|
290
|
+
should.equal(d.sessionId, null);
|
|
291
|
+
const resp = (await endSession(newSession.sessionId)).data.value;
|
|
292
|
+
/** @type {string} */ ( /** @type { {error: string} } */(resp).error).should.equal('invalid session id');
|
|
293
|
+
});
|
|
294
|
+
it('should not have a timer running before or after a session', async function () {
|
|
295
|
+
// @ts-expect-error
|
|
296
|
+
should.not.exist(d.noCommandTimer);
|
|
297
|
+
let newSession = await startTimeoutSession(0.25);
|
|
298
|
+
newSession.sessionId.should.equal(d.sessionId);
|
|
299
|
+
// @ts-expect-error
|
|
300
|
+
should.exist(d.noCommandTimer);
|
|
301
|
+
await endSession(newSession.sessionId);
|
|
302
|
+
// @ts-expect-error
|
|
303
|
+
should.not.exist(d.noCommandTimer);
|
|
304
|
+
});
|
|
344
305
|
});
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
306
|
+
describe('settings api', function () {
|
|
307
|
+
before(function () {
|
|
308
|
+
d.settings = new driver_1.DeviceSettings({ ignoreUnimportantViews: false });
|
|
309
|
+
});
|
|
310
|
+
it('should be able to get settings object', function () {
|
|
311
|
+
d.settings.getSettings().ignoreUnimportantViews.should.be.false;
|
|
312
|
+
});
|
|
313
|
+
it('should not reject when `updateSettings` method is not provided', async function () {
|
|
314
|
+
await d.settings.update({ ignoreUnimportantViews: true }).should.not.be.rejected;
|
|
315
|
+
});
|
|
316
|
+
it('should reject for invalid update object', async function () {
|
|
317
|
+
await d.settings
|
|
318
|
+
// @ts-expect-error
|
|
319
|
+
.update('invalid json')
|
|
320
|
+
.should.be.rejectedWith('JSON');
|
|
321
|
+
});
|
|
349
322
|
});
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
323
|
+
describe('unexpected exits', function () {
|
|
324
|
+
/** @type {import('sinon').SinonSandbox} */
|
|
325
|
+
let sandbox;
|
|
326
|
+
beforeEach(function () {
|
|
327
|
+
sandbox = sinon_1.default.createSandbox();
|
|
328
|
+
});
|
|
329
|
+
afterEach(function () {
|
|
330
|
+
sandbox.restore();
|
|
331
|
+
});
|
|
332
|
+
it('should reject a current command when the driver crashes', async function () {
|
|
333
|
+
sandbox.stub(d, 'getStatus').callsFake(async function () {
|
|
334
|
+
await bluebird_1.default.delay(5000);
|
|
335
|
+
});
|
|
336
|
+
const reqPromise = getCommand('status', { validateStatus: null });
|
|
337
|
+
// make sure that the request gets to the server before our shutdown
|
|
338
|
+
await bluebird_1.default.delay(100);
|
|
339
|
+
const shutdownEventPromise = new bluebird_1.default((resolve, reject) => {
|
|
340
|
+
setTimeout(() => reject(new Error('onUnexpectedShutdown event is expected to be fired within 5 seconds timeout')), 5000);
|
|
341
|
+
d.onUnexpectedShutdown(resolve);
|
|
342
|
+
});
|
|
343
|
+
d.startUnexpectedShutdown(new Error('Crashytimes'));
|
|
344
|
+
const value = await reqPromise;
|
|
345
|
+
value.message.should.contain('Crashytimes');
|
|
346
|
+
await shutdownEventPromise;
|
|
347
|
+
});
|
|
362
348
|
});
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
349
|
+
describe('event timings', function () {
|
|
350
|
+
it('should not add timings if not using opt-in cap', async function () {
|
|
351
|
+
const session = await startSession({ capabilities: { alwaysMatch: defaultCaps } });
|
|
352
|
+
const res = await getSession(session.sessionId);
|
|
353
|
+
should.not.exist(res.events);
|
|
354
|
+
await endSession(session.sessionId);
|
|
355
|
+
});
|
|
356
|
+
it('should add start session timings', async function () {
|
|
357
|
+
const caps = { ...defaultCaps, 'appium:eventTimings': true };
|
|
358
|
+
const session = await startSession({ capabilities: { alwaysMatch: caps } });
|
|
359
|
+
const res = await getSession(session.sessionId);
|
|
360
|
+
should.exist(res.events);
|
|
361
|
+
should.exist(res.events?.newSessionRequested);
|
|
362
|
+
should.exist(res.events?.newSessionStarted);
|
|
363
|
+
res.events?.newSessionRequested[0].should.be.a('number');
|
|
364
|
+
res.events?.newSessionStarted[0].should.be.a('number');
|
|
365
|
+
await endSession(session.sessionId);
|
|
366
|
+
});
|
|
377
367
|
});
|
|
378
|
-
const res = await getSession(session.sessionId);
|
|
379
|
-
should.exist(res.events);
|
|
380
|
-
should.exist((_res$events = res.events) === null || _res$events === void 0 ? void 0 : _res$events.newSessionRequested);
|
|
381
|
-
should.exist((_res$events2 = res.events) === null || _res$events2 === void 0 ? void 0 : _res$events2.newSessionStarted);
|
|
382
|
-
(_res$events3 = res.events) === null || _res$events3 === void 0 ? void 0 : _res$events3.newSessionRequested[0].should.be.a('number');
|
|
383
|
-
(_res$events4 = res.events) === null || _res$events4 === void 0 ? void 0 : _res$events4.newSessionStarted[0].should.be.a('number');
|
|
384
|
-
await endSession(session.sessionId);
|
|
385
|
-
});
|
|
386
368
|
});
|
|
387
|
-
});
|
|
388
369
|
}
|
|
389
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJzaG91bGQiLCJjaGFpIiwiY3JlYXRlU2Vzc2lvbkhlbHBlcnMiLCJwb3J0IiwiYWRkcmVzcyIsIlRFU1RfSE9TVCIsImNyZWF0ZUFwcGl1bVRlc3RVUkwiLCJjcmVhdGVBcHBpdW1VUkwiLCJjcmVhdGVTZXNzaW9uVVJMIiwiXyIsIm5ld1Nlc3Npb25VUkwiLCJwb3N0Q29tbWFuZCIsInNlc3Npb25JZCIsImNtZE5hbWUiLCJkYXRhIiwiY29uZmlnIiwidXJsIiwicmVzcG9uc2UiLCJheGlvcyIsInBvc3QiLCJ2YWx1ZSIsImdldENvbW1hbmQiLCJzZXNzaW9uSWRPckNtZE5hbWUiLCJjbWROYW1lT3JDb25maWciLCJpc1N0cmluZyIsInZhbGlkYXRlU3RhdHVzIiwic3RhcnRTZXNzaW9uIiwiZGVmYXVsdHNEZWVwIiwiY2FwYWJpbGl0aWVzIiwiYWx3YXlzTWF0Y2giLCJmaXJzdE1hdGNoIiwiZW5kU2Vzc2lvbiIsImRlbGV0ZSIsImdldFNlc3Npb24iLCJkcml2ZXJFMkVUZXN0U3VpdGUiLCJEcml2ZXJDbGFzcyIsImRlZmF1bHRDYXBzIiwiY2xhc3NOYW1lIiwibmFtZSIsImRlc2NyaWJlIiwiYmFzZVNlcnZlciIsImQiLCJiZWZvcmUiLCJnZXRUZXN0UG9ydCIsInNlcnZlciIsInJvdXRlQ29uZmlndXJpbmdGdW5jdGlvbiIsImhvc3RuYW1lIiwiY2xpQXJncyIsImFmdGVyIiwiY2xvc2UiLCJpdCIsInNlc3Npb25JZHMiLCJ0aW1lcyIsImhlYWRlcnMiLCJzaW1wbGUiLCJyZXNvbHZlV2l0aEZ1bGxSZXNwb25zZSIsInB1c2giLCJ1bmlxIiwibGVuZ3RoIiwiZXF1YWwiLCJzdGF0dXMiLCJyZXFzIiwibWFwIiwiQiIsImFsbCIsImV4aXN0IiwicGxhdGZvcm1OYW1lIiwiZGV2aWNlTmFtZSIsInNraXAiLCJvcmlnaW5hbEZpbmRFbGVtZW50Iiwib3JpZ2luYWxGaW5kRWxlbWVudHMiLCJzdGFydFRpbWVvdXRTZXNzaW9uIiwidGltZW91dCIsImNhcHMiLCJjbG9uZURlZXAiLCJmaW5kRWxlbWVudCIsImJpbmQiLCJmaW5kRWxlbWVudHMiLCJkZWxheSIsIm5ld1Nlc3Npb24iLCJuZXdDb21tYW5kVGltZW91dE1zIiwiYmUiLCJhYm92ZSIsInVzaW5nIiwiZXJyb3IiLCJyZXNwIiwic3RhcnQiLCJEYXRlIiwibm93IiwiZXFsIiwibm90Iiwibm9Db21tYW5kVGltZXIiLCJzZXR0aW5ncyIsIkRldmljZVNldHRpbmdzIiwiaWdub3JlVW5pbXBvcnRhbnRWaWV3cyIsImdldFNldHRpbmdzIiwiZmFsc2UiLCJ1cGRhdGUiLCJyZWplY3RlZCIsInJlamVjdGVkV2l0aCIsInNhbmRib3giLCJiZWZvcmVFYWNoIiwic2lub24iLCJjcmVhdGVTYW5kYm94IiwiYWZ0ZXJFYWNoIiwicmVzdG9yZSIsInN0dWIiLCJjYWxsc0Zha2UiLCJyZXFQcm9taXNlIiwic2h1dGRvd25FdmVudFByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0Iiwic2V0VGltZW91dCIsIkVycm9yIiwib25VbmV4cGVjdGVkU2h1dGRvd24iLCJzdGFydFVuZXhwZWN0ZWRTaHV0ZG93biIsIm1lc3NhZ2UiLCJjb250YWluIiwic2Vzc2lvbiIsInJlcyIsImV2ZW50cyIsIm5ld1Nlc3Npb25SZXF1ZXN0ZWQiLCJuZXdTZXNzaW9uU3RhcnRlZCIsImEiXSwic291cmNlcyI6WyIuLi8uLi9saWIvZTJlLXN1aXRlLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQge3NlcnZlciwgcm91dGVDb25maWd1cmluZ0Z1bmN0aW9uLCBEZXZpY2VTZXR0aW5nc30gZnJvbSAnYXBwaXVtL2RyaXZlcic7XG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuaW1wb3J0IEIgZnJvbSAnYmx1ZWJpcmQnO1xuaW1wb3J0IHtURVNUX0hPU1QsIGdldFRlc3RQb3J0LCBjcmVhdGVBcHBpdW1VUkx9IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQgY2hhaSBmcm9tICdjaGFpJztcbmltcG9ydCBzaW5vbiBmcm9tICdzaW5vbic7XG5cbmNvbnN0IHNob3VsZCA9IGNoYWkuc2hvdWxkKCk7XG5cbi8qKlxuICogQ3JlYXRlcyBzb21lIGhlbHBlciBmdW5jdGlvbnMgZm9yIEUyRSB0ZXN0cyB0byBtYW5hZ2Ugc2Vzc2lvbnMuXG4gKiBAdGVtcGxhdGUgW0NvbW1hbmREYXRhPXVua25vd25dXG4gKiBAdGVtcGxhdGUgW1Jlc3BvbnNlRGF0YT1hbnldXG4gKiBAcGFyYW0ge251bWJlcn0gcG9ydCAtIFBvcnQgb24gd2hpY2ggdGhlIHNlcnZlciBpcyBydW5uaW5nLiBUeXBpY2FsbHkgdGhpcyB3aWxsIGJlIHJldHJpZXZlZCB2aWEgYGdldC1wb3J0YCBiZWZvcmVoYW5kXG4gKiBAcGFyYW0ge3N0cmluZ30gW2FkZHJlc3NdIC0gQWRkcmVzcy9ob3N0IG9uIHdoaWNoIHRoZSBzZXJ2ZXIgaXMgcnVubmluZy4gRGVmYXVsdHMgdG8ge0BsaW5rY29kZSBURVNUX0hPU1R9XG4gKiBAcmV0dXJucyB7U2Vzc2lvbkhlbHBlcnM8Q29tbWFuZERhdGEsIFJlc3BvbnNlRGF0YT59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTZXNzaW9uSGVscGVycyhwb3J0LCBhZGRyZXNzID0gVEVTVF9IT1NUKSB7XG4gIGNvbnN0IGNyZWF0ZUFwcGl1bVRlc3RVUkwgPVxuICAgIC8qKiBAdHlwZSB7aW1wb3J0KCdsb2Rhc2gnKS5DdXJyaWVkRnVuY3Rpb24yPHN0cmluZyxzdHJpbmcsc3RyaW5nPn0gKi8gKFxuICAgICAgY3JlYXRlQXBwaXVtVVJMKGFkZHJlc3MsIHBvcnQpXG4gICAgKTtcblxuICBjb25zdCBjcmVhdGVTZXNzaW9uVVJMID0gY3JlYXRlQXBwaXVtVGVzdFVSTChfLCAnJyk7XG4gIGNvbnN0IG5ld1Nlc3Npb25VUkwgPSBjcmVhdGVBcHBpdW1UZXN0VVJMKCcnLCAnc2Vzc2lvbicpO1xuICByZXR1cm4gLyoqIEB0eXBlIHtTZXNzaW9uSGVscGVyczxDb21tYW5kRGF0YSwgUmVzcG9uc2VEYXRhPn0gKi8gKHtcbiAgICBuZXdTZXNzaW9uVVJMLFxuICAgIGNyZWF0ZUFwcGl1bVRlc3RVUkwsXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2Vzc2lvbklkXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNtZE5hbWVcbiAgICAgKiBAcGFyYW0ge2FueX0gW2RhdGFdXG4gICAgICogQHBhcmFtIHtBeGlvc1JlcXVlc3RDb25maWd9IFtjb25maWddXG4gICAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAgICAgKi9cbiAgICBwb3N0Q29tbWFuZDogYXN5bmMgKHNlc3Npb25JZCwgY21kTmFtZSwgZGF0YSA9IHt9LCBjb25maWcgPSB7fSkgPT4ge1xuICAgICAgY29uc3QgdXJsID0gY3JlYXRlQXBwaXVtVGVzdFVSTChzZXNzaW9uSWQsIGNtZE5hbWUpO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcy5wb3N0KHVybCwgZGF0YSwgY29uZmlnKTtcbiAgICAgIHJldHVybiByZXNwb25zZS5kYXRhPy52YWx1ZTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlc3Npb25JZE9yQ21kTmFtZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfEF4aW9zUmVxdWVzdENvbmZpZ30gY21kTmFtZU9yQ29uZmlnXG4gICAgICogQHBhcmFtIHtBeGlvc1JlcXVlc3RDb25maWd9IFtjb25maWddXG4gICAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAgICAgKi9cbiAgICBnZXRDb21tYW5kOiBhc3luYyAoc2Vzc2lvbklkT3JDbWROYW1lLCBjbWROYW1lT3JDb25maWcsIGNvbmZpZyA9IHt9KSA9PiB7XG4gICAgICBpZiAoIV8uaXNTdHJpbmcoY21kTmFtZU9yQ29uZmlnKSkge1xuICAgICAgICBjb25maWcgPSBjbWROYW1lT3JDb25maWc7XG4gICAgICAgIGNtZE5hbWVPckNvbmZpZyA9IHNlc3Npb25JZE9yQ21kTmFtZTtcbiAgICAgICAgc2Vzc2lvbklkT3JDbWROYW1lID0gJyc7XG4gICAgICB9XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGF4aW9zKHtcbiAgICAgICAgdXJsOiBjcmVhdGVBcHBpdW1UZXN0VVJMKHNlc3Npb25JZE9yQ21kTmFtZSwgY21kTmFtZU9yQ29uZmlnKSxcbiAgICAgICAgdmFsaWRhdGVTdGF0dXM6IG51bGwsXG4gICAgICAgIC4uLmNvbmZpZyxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGE/LnZhbHVlO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge05ld1Nlc3Npb25EYXRhfSBkYXRhXG4gICAgICogQHBhcmFtIHtBeGlvc1JlcXVlc3RDb25maWd9IFtjb25maWddXG4gICAgICovXG4gICAgc3RhcnRTZXNzaW9uOiBhc3luYyAoZGF0YSwgY29uZmlnID0ge30pID0+IHtcbiAgICAgIGRhdGEgPSBfLmRlZmF1bHRzRGVlcChkYXRhLCB7XG4gICAgICAgIGNhcGFiaWxpdGllczoge1xuICAgICAgICAgIGFsd2F5c01hdGNoOiB7fSxcbiAgICAgICAgICBmaXJzdE1hdGNoOiBbe31dLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGF4aW9zLnBvc3QobmV3U2Vzc2lvblVSTCwgZGF0YSwgY29uZmlnKTtcbiAgICAgIHJldHVybiByZXNwb25zZS5kYXRhPy52YWx1ZTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlc3Npb25JZFxuICAgICAqL1xuICAgIGVuZFNlc3Npb246IGFzeW5jIChzZXNzaW9uSWQpID0+XG4gICAgICBhd2FpdCBheGlvcy5kZWxldGUoY3JlYXRlU2Vzc2lvblVSTChzZXNzaW9uSWQpLCB7XG4gICAgICAgIHZhbGlkYXRlU3RhdHVzOiBudWxsLFxuICAgICAgfSksXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlc3Npb25JZFxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gICAgICovXG4gICAgZ2V0U2Vzc2lvbjogYXN5bmMgKHNlc3Npb25JZCkgPT4ge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcyh7XG4gICAgICAgIHVybDogY3JlYXRlU2Vzc2lvblVSTChzZXNzaW9uSWQpLFxuICAgICAgICB2YWxpZGF0ZVN0YXR1czogbnVsbCxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGE/LnZhbHVlO1xuICAgIH0sXG4gIH0pO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgRTJFIHRlc3Qgc3VpdGVzIGZvciBhIGRyaXZlci5cbiAqIEB0ZW1wbGF0ZSB7RHJpdmVyfSBQXG4gKiBAcGFyYW0ge0RyaXZlckNsYXNzPFA+fSBEcml2ZXJDbGFzc1xuICogQHBhcmFtIHtBcHBpdW1XM0NDYXBhYmlsaXRpZXN9IFtkZWZhdWx0Q2Fwc11cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRyaXZlckUyRVRlc3RTdWl0ZShEcml2ZXJDbGFzcywgZGVmYXVsdENhcHMgPSB7fSkge1xuICBsZXQgYWRkcmVzcyA9IGRlZmF1bHRDYXBzWydhcHBpdW06YWRkcmVzcyddID8/IFRFU1RfSE9TVDtcbiAgbGV0IHBvcnQgPSBkZWZhdWx0Q2Fwc1snYXBwaXVtOnBvcnQnXTtcbiAgY29uc3QgY2xhc3NOYW1lID0gRHJpdmVyQ2xhc3MubmFtZSB8fCAnKHVua25vd24gZHJpdmVyKSc7XG5cbiAgZGVzY3JpYmUoYEJhc2VEcml2ZXIgRTJFIChhcyAke2NsYXNzTmFtZX0pYCwgZnVuY3Rpb24gKCkge1xuICAgIGxldCBiYXNlU2VydmVyO1xuICAgIC8qKiBAdHlwZSB7UH0gKi9cbiAgICBsZXQgZDtcbiAgICAvKipcbiAgICAgKiBUaGlzIFVSTCBjcmVhdGVzIGEgbmV3IHNlc3Npb25cbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqKi9cbiAgICBsZXQgbmV3U2Vzc2lvblVSTDtcblxuICAgIC8qKiBAdHlwZSB7U2Vzc2lvbkhlbHBlcnNbJ3N0YXJ0U2Vzc2lvbiddfSAqL1xuICAgIGxldCBzdGFydFNlc3Npb247XG4gICAgLyoqIEB0eXBlIHtTZXNzaW9uSGVscGVyc1snZ2V0U2Vzc2lvbiddfSAqL1xuICAgIGxldCBnZXRTZXNzaW9uO1xuICAgIC8qKiBAdHlwZSB7U2Vzc2lvbkhlbHBlcnNbJ2VuZFNlc3Npb24nXX0gKi9cbiAgICBsZXQgZW5kU2Vzc2lvbjtcbiAgICAvKiogQHR5cGUge1Nlc3Npb25IZWxwZXJzWydnZXRDb21tYW5kJ119ICovXG4gICAgbGV0IGdldENvbW1hbmQ7XG4gICAgLyoqIEB0eXBlIHtTZXNzaW9uSGVscGVyc1sncG9zdENvbW1hbmQnXX0gKi9cbiAgICBsZXQgcG9zdENvbW1hbmQ7XG4gICAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHBvcnQgPSBwb3J0ID8/IChhd2FpdCBnZXRUZXN0UG9ydCgpKTtcbiAgICAgIGRlZmF1bHRDYXBzID0gey4uLmRlZmF1bHRDYXBzLCAnYXBwaXVtOnBvcnQnOiBwb3J0fTtcbiAgICAgIGQgPSBuZXcgRHJpdmVyQ2xhc3Moe3BvcnQsIGFkZHJlc3N9KTtcbiAgICAgIGJhc2VTZXJ2ZXIgPSBhd2FpdCBzZXJ2ZXIoe1xuICAgICAgICByb3V0ZUNvbmZpZ3VyaW5nRnVuY3Rpb246IHJvdXRlQ29uZmlndXJpbmdGdW5jdGlvbihkKSxcbiAgICAgICAgcG9ydCxcbiAgICAgICAgaG9zdG5hbWU6IGFkZHJlc3MsXG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgY2xpQXJnczoge30sXG4gICAgICB9KTtcbiAgICAgICh7c3RhcnRTZXNzaW9uLCBnZXRTZXNzaW9uLCBlbmRTZXNzaW9uLCBuZXdTZXNzaW9uVVJMLCBnZXRDb21tYW5kLCBwb3N0Q29tbWFuZH0gPVxuICAgICAgICBjcmVhdGVTZXNzaW9uSGVscGVycyhwb3J0LCBhZGRyZXNzKSk7XG4gICAgfSk7XG5cbiAgICBhZnRlcihhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCBiYXNlU2VydmVyLmNsb3NlKCk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnc2Vzc2lvbiBoYW5kbGluZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGl0KCdzaG91bGQgaGFuZGxlIGlkZW1wb3RlbmN5IHdoaWxlIGNyZWF0aW5nIHNlc3Npb25zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBzZXNzaW9uSWRzID0gW107XG4gICAgICAgIGxldCB0aW1lcyA9IDA7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICBjb25zdCB7c2Vzc2lvbklkfSA9IGF3YWl0IHN0YXJ0U2Vzc2lvbihcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgY2FwYWJpbGl0aWVzOiB7YWx3YXlzTWF0Y2g6IGRlZmF1bHRDYXBzfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAnWC1JZGVtcG90ZW5jeS1LZXknOiAnMTIzNDU2JyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgLy8gWFhYOiBJJ20gbm90IHN1cmUgd2hhdCB0aGVzZSBhcmUsIGFzIHRoZXkgYXJlIG5vdCBkb2N1bWVudGVkIGF4aW9zIG9wdGlvbnMsXG4gICAgICAgICAgICAgIC8vIG5vciBhcmUgdGhleSBtZW50aW9uZWQgaW4gb3VyIHNvdXJjZVxuICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgICAgICAgIHNpbXBsZTogZmFsc2UsXG4gICAgICAgICAgICAgIHJlc29sdmVXaXRoRnVsbFJlc3BvbnNlOiB0cnVlLFxuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBzZXNzaW9uSWRzLnB1c2goc2Vzc2lvbklkKTtcbiAgICAgICAgICB0aW1lcysrO1xuICAgICAgICB9IHdoaWxlICh0aW1lcyA8IDIpO1xuICAgICAgICBfLnVuaXEoc2Vzc2lvbklkcykubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgICBjb25zdCB7c3RhdHVzLCBkYXRhfSA9IGF3YWl0IGVuZFNlc3Npb24oc2Vzc2lvbklkc1swXSk7XG4gICAgICAgIHN0YXR1cy5zaG91bGQuZXF1YWwoMjAwKTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKGRhdGEudmFsdWUsIG51bGwpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgaGFuZGxlIGlkZW1wb3RlbmN5IHdoaWxlIGNyZWF0aW5nIHBhcmFsbGVsIHNlc3Npb25zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCByZXFzID0gW107XG4gICAgICAgIGxldCB0aW1lcyA9IDA7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICByZXFzLnB1c2goXG4gICAgICAgICAgICBzdGFydFNlc3Npb24oXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjYXBhYmlsaXRpZXM6IHtcbiAgICAgICAgICAgICAgICAgIGFsd2F5c01hdGNoOiBkZWZhdWx0Q2FwcyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgICAgJ1gtSWRlbXBvdGVuY3ktS2V5JzogJzEyMzQ1JyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aW1lcysrO1xuICAgICAgICB9IHdoaWxlICh0aW1lcyA8IDIpO1xuICAgICAgICBjb25zdCBzZXNzaW9uSWRzID0gXy5tYXAoYXdhaXQgQi5hbGwocmVxcyksICdzZXNzaW9uSWQnKTtcbiAgICAgICAgXy51bmlxKHNlc3Npb25JZHMpLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgICAgY29uc3Qge3N0YXR1cywgZGF0YX0gPSBhd2FpdCBlbmRTZXNzaW9uKHNlc3Npb25JZHNbMF0pO1xuICAgICAgICBzdGF0dXMuc2hvdWxkLmVxdWFsKDIwMCk7XG4gICAgICAgIHNob3VsZC5lcXVhbChkYXRhLnZhbHVlLCBudWxsKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGNyZWF0ZSBzZXNzaW9uIGFuZCByZXRyaWV2ZSBhIHNlc3Npb24gaWQsIHRoZW4gZGVsZXRlIGl0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQge3N0YXR1cywgZGF0YX0gPSBhd2FpdCBheGlvcy5wb3N0KG5ld1Nlc3Npb25VUkwsIHtcbiAgICAgICAgICBjYXBhYmlsaXRpZXM6IHtcbiAgICAgICAgICAgIGFsd2F5c01hdGNoOiBkZWZhdWx0Q2FwcyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICBzdGF0dXMuc2hvdWxkLmVxdWFsKDIwMCk7XG4gICAgICAgIHNob3VsZC5leGlzdChkYXRhLnZhbHVlLnNlc3Npb25JZCk7XG4gICAgICAgIGRhdGEudmFsdWUuY2FwYWJpbGl0aWVzLnBsYXRmb3JtTmFtZS5zaG91bGQuZXF1YWwoZGVmYXVsdENhcHMucGxhdGZvcm1OYW1lKTtcbiAgICAgICAgZGF0YS52YWx1ZS5jYXBhYmlsaXRpZXMuZGV2aWNlTmFtZS5zaG91bGQuZXF1YWwoZGVmYXVsdENhcHNbJ2FwcGl1bTpkZXZpY2VOYW1lJ10pO1xuXG4gICAgICAgICh7c3RhdHVzLCBkYXRhfSA9IGF3YWl0IGVuZFNlc3Npb24oLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkLnNlc3Npb25JZCkpKTtcblxuICAgICAgICBzdGF0dXMuc2hvdWxkLmVxdWFsKDIwMCk7XG4gICAgICAgIHNob3VsZC5lcXVhbChkYXRhLnZhbHVlLCBudWxsKTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKGQuc2Vzc2lvbklkLCBudWxsKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQuc2tpcCgnc2hvdWxkIHRocm93IE5ZSSBmb3IgY29tbWFuZHMgbm90IGltcGxlbWVudGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge30pO1xuXG4gICAgZGVzY3JpYmUoJ2NvbW1hbmQgdGltZW91dHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgb3JpZ2luYWxGaW5kRWxlbWVudCwgb3JpZ2luYWxGaW5kRWxlbWVudHM7XG5cbiAgICAgIC8qKlxuICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFt0aW1lb3V0XVxuICAgICAgICovXG4gICAgICBhc3luYyBmdW5jdGlvbiBzdGFydFRpbWVvdXRTZXNzaW9uKHRpbWVvdXQpIHtcbiAgICAgICAgY29uc3QgY2FwcyA9IF8uY2xvbmVEZWVwKGRlZmF1bHRDYXBzKTtcbiAgICAgICAgY2Fwc1snYXBwaXVtOm5ld0NvbW1hbmRUaW1lb3V0J10gPSB0aW1lb3V0O1xuICAgICAgICByZXR1cm4gYXdhaXQgc3RhcnRTZXNzaW9uKHtjYXBhYmlsaXRpZXM6IHthbHdheXNNYXRjaDogY2Fwc319KTtcbiAgICAgIH1cblxuICAgICAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgb3JpZ2luYWxGaW5kRWxlbWVudCA9IGQuZmluZEVsZW1lbnQ7XG4gICAgICAgIGQuZmluZEVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuICdmb28nO1xuICAgICAgICB9LmJpbmQoZCk7XG5cbiAgICAgICAgb3JpZ2luYWxGaW5kRWxlbWVudHMgPSBkLmZpbmRFbGVtZW50cztcbiAgICAgICAgZC5maW5kRWxlbWVudHMgPSBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYXdhaXQgQi5kZWxheSgyMDApO1xuICAgICAgICAgIHJldHVybiBbJ2ZvbyddO1xuICAgICAgICB9LmJpbmQoZCk7XG4gICAgICB9KTtcblxuICAgICAgYWZ0ZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICBkLmZpbmRFbGVtZW50ID0gb3JpZ2luYWxGaW5kRWxlbWVudDtcbiAgICAgICAgZC5maW5kRWxlbWVudHMgPSBvcmlnaW5hbEZpbmRFbGVtZW50cztcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHNldCBhIGRlZmF1bHQgY29tbWFuZFRpbWVvdXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBuZXdTZXNzaW9uID0gYXdhaXQgc3RhcnRUaW1lb3V0U2Vzc2lvbigpO1xuICAgICAgICBkLm5ld0NvbW1hbmRUaW1lb3V0TXMuc2hvdWxkLmJlLmFib3ZlKDApO1xuICAgICAgICBhd2FpdCBlbmRTZXNzaW9uKG5ld1Nlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRpbWVvdXQgb24gY29tbWFuZHMgdXNpbmcgY29tbWFuZFRpbWVvdXQgY2FwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQgbmV3U2Vzc2lvbiA9IGF3YWl0IHN0YXJ0VGltZW91dFNlc3Npb24oMC4yNSk7XG4gICAgICAgIGNvbnN0IHNlc3Npb25JZCA9IC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoZC5zZXNzaW9uSWQpO1xuICAgICAgICBhd2FpdCBwb3N0Q29tbWFuZChzZXNzaW9uSWQsICdlbGVtZW50Jywge1xuICAgICAgICAgIHVzaW5nOiAnbmFtZScsXG4gICAgICAgICAgdmFsdWU6ICdmb28nLFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgQi5kZWxheSg0MDApO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IGdldFNlc3Npb24oc2Vzc2lvbklkKTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKHZhbHVlLmVycm9yLCAnaW52YWxpZCBzZXNzaW9uIGlkJyk7XG4gICAgICAgIHNob3VsZC5lcXVhbChkLnNlc3Npb25JZCwgbnVsbCk7XG4gICAgICAgIGNvbnN0IHJlc3AgPSAoYXdhaXQgZW5kU2Vzc2lvbihuZXdTZXNzaW9uLnNlc3Npb25JZCkpLmRhdGEudmFsdWU7XG4gICAgICAgIHNob3VsZC5lcXVhbChyZXNwPy5lcnJvciwgJ2ludmFsaWQgc2Vzc2lvbiBpZCcpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgbm90IHRpbWVvdXQgd2l0aCBjb21tYW5kVGltZW91dCBvZiBmYWxzZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbGV0IG5ld1Nlc3Npb24gPSBhd2FpdCBzdGFydFRpbWVvdXRTZXNzaW9uKDAuMSk7XG4gICAgICAgIGxldCBzdGFydCA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgcG9zdENvbW1hbmQoLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkLnNlc3Npb25JZCksICdlbGVtZW50cycsIHtcbiAgICAgICAgICB1c2luZzogJ25hbWUnLFxuICAgICAgICAgIHZhbHVlOiAnZm9vJyxcbiAgICAgICAgfSk7XG4gICAgICAgIChEYXRlLm5vdygpIC0gc3RhcnQpLnNob3VsZC5iZS5hYm92ZSgxNTApO1xuICAgICAgICB2YWx1ZS5zaG91bGQuZXFsKFsnZm9vJ10pO1xuICAgICAgICBhd2FpdCBlbmRTZXNzaW9uKG5ld1Nlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG5vdCB0aW1lb3V0IHdpdGggY29tbWFuZFRpbWVvdXQgb2YgMCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZC5uZXdDb21tYW5kVGltZW91dE1zID0gMjtcbiAgICAgICAgbGV0IG5ld1Nlc3Npb24gPSBhd2FpdCBzdGFydFRpbWVvdXRTZXNzaW9uKDApO1xuXG4gICAgICAgIGF3YWl0IHBvc3RDb21tYW5kKC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoZC5zZXNzaW9uSWQpLCAnZWxlbWVudCcsIHtcbiAgICAgICAgICB1c2luZzogJ25hbWUnLFxuICAgICAgICAgIHZhbHVlOiAnZm9vJyxcbiAgICAgICAgfSk7XG4gICAgICAgIGF3YWl0IEIuZGVsYXkoNDAwKTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCBnZXRTZXNzaW9uKC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAoZC5zZXNzaW9uSWQpKTtcbiAgICAgICAgdmFsdWUucGxhdGZvcm1OYW1lPy5zaG91bGQuZXF1YWwoZGVmYXVsdENhcHMucGxhdGZvcm1OYW1lKTtcbiAgICAgICAgY29uc3QgcmVzcCA9IChhd2FpdCBlbmRTZXNzaW9uKG5ld1Nlc3Npb24uc2Vzc2lvbklkKSkuZGF0YS52YWx1ZTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKHJlc3AsIG51bGwpO1xuXG4gICAgICAgIGQubmV3Q29tbWFuZFRpbWVvdXRNcyA9IDYwICogMTAwMDtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG5vdCB0aW1lb3V0IGlmIGl0cyBqdXN0IHRoZSBjb21tYW5kIHRha2luZyBhd2hpbGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBuZXdTZXNzaW9uID0gYXdhaXQgc3RhcnRUaW1lb3V0U2Vzc2lvbigwLjI1KTtcbiAgICAgICAgLy8gWFhYOiByYWNlIGNvbmRpdGlvbjogd2UgbXVzdCBidWlsZCB0aGlzIFVSTCBiZWZvcmUgLi4uc29tZXRoaW5nIGhhcHBlbnMuLi5cbiAgICAgICAgLy8gd2hpY2ggY2F1c2VzIGBkLnNlc3Npb25JZGAgdG8gYmUgbWlzc2luZ1xuICAgICAgICBjb25zdCB7c2Vzc2lvbklkfSA9IGQ7XG5cbiAgICAgICAgYXdhaXQgcG9zdENvbW1hbmQoLyoqIEB0eXBlIHtzdHJpbmd9ICovIChkLnNlc3Npb25JZCksICdlbGVtZW50Jywge1xuICAgICAgICAgIHVzaW5nOiAnbmFtZScsXG4gICAgICAgICAgdmFsdWU6ICdmb28nLFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgQi5kZWxheSg0MDApO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IGdldFNlc3Npb24oLyoqIEB0eXBlIHtzdHJpbmd9ICovIChzZXNzaW9uSWQpKTtcbiAgICAgICAgdmFsdWUuZXJyb3Iuc2hvdWxkLmVxdWFsKCdpbnZhbGlkIHNlc3Npb24gaWQnKTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKGQuc2Vzc2lvbklkLCBudWxsKTtcbiAgICAgICAgY29uc3QgcmVzcCA9IChhd2FpdCBlbmRTZXNzaW9uKG5ld1Nlc3Npb24uc2Vzc2lvbklkKSkuZGF0YS52YWx1ZTtcbiAgICAgICAgLyoqIEB0eXBlIHtzdHJpbmd9ICovICgvKiogQHR5cGUgeyB7ZXJyb3I6IHN0cmluZ30gfSAqLyAocmVzcCkuZXJyb3IpLnNob3VsZC5lcXVhbChcbiAgICAgICAgICAnaW52YWxpZCBzZXNzaW9uIGlkJ1xuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgbm90IGhhdmUgYSB0aW1lciBydW5uaW5nIGJlZm9yZSBvciBhZnRlciBhIHNlc3Npb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgc2hvdWxkLm5vdC5leGlzdChkLm5vQ29tbWFuZFRpbWVyKTtcbiAgICAgICAgbGV0IG5ld1Nlc3Npb24gPSBhd2FpdCBzdGFydFRpbWVvdXRTZXNzaW9uKDAuMjUpO1xuICAgICAgICBuZXdTZXNzaW9uLnNlc3Npb25JZC5zaG91bGQuZXF1YWwoZC5zZXNzaW9uSWQpO1xuICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgIHNob3VsZC5leGlzdChkLm5vQ29tbWFuZFRpbWVyKTtcbiAgICAgICAgYXdhaXQgZW5kU2Vzc2lvbihuZXdTZXNzaW9uLnNlc3Npb25JZCk7XG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgc2hvdWxkLm5vdC5leGlzdChkLm5vQ29tbWFuZFRpbWVyKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3NldHRpbmdzIGFwaScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGQuc2V0dGluZ3MgPSBuZXcgRGV2aWNlU2V0dGluZ3Moe2lnbm9yZVVuaW1wb3J0YW50Vmlld3M6IGZhbHNlfSk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgYmUgYWJsZSB0byBnZXQgc2V0dGluZ3Mgb2JqZWN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICBkLnNldHRpbmdzLmdldFNldHRpbmdzKCkuaWdub3JlVW5pbXBvcnRhbnRWaWV3cy5zaG91bGQuYmUuZmFsc2U7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgbm90IHJlamVjdCB3aGVuIGB1cGRhdGVTZXR0aW5nc2AgbWV0aG9kIGlzIG5vdCBwcm92aWRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXdhaXQgZC5zZXR0aW5ncy51cGRhdGUoe2lnbm9yZVVuaW1wb3J0YW50Vmlld3M6IHRydWV9KS5zaG91bGQubm90LmJlLnJlamVjdGVkO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIHJlamVjdCBmb3IgaW52YWxpZCB1cGRhdGUgb2JqZWN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBhd2FpdCBkLnNldHRpbmdzXG4gICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgIC51cGRhdGUoJ2ludmFsaWQganNvbicpXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0pTT04nKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3VuZXhwZWN0ZWQgZXhpdHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvKiogQHR5cGUge2ltcG9ydCgnc2lub24nKS5TaW5vblNhbmRib3h9ICovXG4gICAgICBsZXQgc2FuZGJveDtcbiAgICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBzYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgICAgfSk7XG5cbiAgICAgIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNhbmRib3gucmVzdG9yZSgpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgY3VycmVudCBjb21tYW5kIHdoZW4gdGhlIGRyaXZlciBjcmFzaGVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBzYW5kYm94LnN0dWIoZCwgJ2dldFN0YXR1cycpLmNhbGxzRmFrZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYXdhaXQgQi5kZWxheSg1MDAwKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHJlcVByb21pc2UgPSBnZXRDb21tYW5kKCdzdGF0dXMnLCB7dmFsaWRhdGVTdGF0dXM6IG51bGx9KTtcbiAgICAgICAgLy8gbWFrZSBzdXJlIHRoYXQgdGhlIHJlcXVlc3QgZ2V0cyB0byB0aGUgc2VydmVyIGJlZm9yZSBvdXIgc2h1dGRvd25cbiAgICAgICAgYXdhaXQgQi5kZWxheSgxMDApO1xuICAgICAgICBjb25zdCBzaHV0ZG93bkV2ZW50UHJvbWlzZSA9IG5ldyBCKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICBzZXRUaW1lb3V0KFxuICAgICAgICAgICAgKCkgPT5cbiAgICAgICAgICAgICAgcmVqZWN0KFxuICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICdvblVuZXhwZWN0ZWRTaHV0ZG93biBldmVudCBpcyBleHBlY3RlZCB0byBiZSBmaXJlZCB3aXRoaW4gNSBzZWNvbmRzIHRpbWVvdXQnXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgNTAwMFxuICAgICAgICAgICk7XG4gICAgICAgICAgZC5vblVuZXhwZWN0ZWRTaHV0ZG93bihyZXNvbHZlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGQuc3RhcnRVbmV4cGVjdGVkU2h1dGRvd24obmV3IEVycm9yKCdDcmFzaHl0aW1lcycpKTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCByZXFQcm9taXNlO1xuICAgICAgICB2YWx1ZS5tZXNzYWdlLnNob3VsZC5jb250YWluKCdDcmFzaHl0aW1lcycpO1xuICAgICAgICBhd2FpdCBzaHV0ZG93bkV2ZW50UHJvbWlzZTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ2V2ZW50IHRpbWluZ3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpdCgnc2hvdWxkIG5vdCBhZGQgdGltaW5ncyBpZiBub3QgdXNpbmcgb3B0LWluIGNhcCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IHN0YXJ0U2Vzc2lvbih7Y2FwYWJpbGl0aWVzOiB7YWx3YXlzTWF0Y2g6IGRlZmF1bHRDYXBzfX0pO1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBnZXRTZXNzaW9uKHNlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgICAgc2hvdWxkLm5vdC5leGlzdChyZXMuZXZlbnRzKTtcbiAgICAgICAgYXdhaXQgZW5kU2Vzc2lvbihzZXNzaW9uLnNlc3Npb25JZCk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgYWRkIHN0YXJ0IHNlc3Npb24gdGltaW5ncycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY2FwcyA9IHsuLi5kZWZhdWx0Q2FwcywgJ2FwcGl1bTpldmVudFRpbWluZ3MnOiB0cnVlfTtcbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IHN0YXJ0U2Vzc2lvbih7Y2FwYWJpbGl0aWVzOiB7YWx3YXlzTWF0Y2g6IGNhcHN9fSk7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGdldFNlc3Npb24oc2Vzc2lvbi5zZXNzaW9uSWQpO1xuICAgICAgICBzaG91bGQuZXhpc3QocmVzLmV2ZW50cyk7XG4gICAgICAgIHNob3VsZC5leGlzdChyZXMuZXZlbnRzPy5uZXdTZXNzaW9uUmVxdWVzdGVkKTtcbiAgICAgICAgc2hvdWxkLmV4aXN0KHJlcy5ldmVudHM/Lm5ld1Nlc3Npb25TdGFydGVkKTtcbiAgICAgICAgcmVzLmV2ZW50cz8ubmV3U2Vzc2lvblJlcXVlc3RlZFswXS5zaG91bGQuYmUuYSgnbnVtYmVyJyk7XG4gICAgICAgIHJlcy5ldmVudHM/Lm5ld1Nlc3Npb25TdGFydGVkWzBdLnNob3VsZC5iZS5hKCdudW1iZXInKTtcbiAgICAgICAgYXdhaXQgZW5kU2Vzc2lvbihzZXNzaW9uLnNlc3Npb25JZCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbi8qKlxuICogQSB7QGxpbmtjb2RlIERyaXZlckNsYXNzfSwgZXhjZXB0IHVzaW5nIHRoZSBiYXNlIHtAbGlua2NvZGUgRHJpdmVyfSB0eXBlIGluc3RlYWQgb2YgYEV4dGVybmFsRHJpdmVyYC5cbiAqIFRoaXMgYWxsb3dzIHRoZSBzdWl0ZSB0byB3b3JrIGZvciBgQmFzZURyaXZlcmAuXG4gKiBAdGVtcGxhdGUge0RyaXZlcn0gUFxuICogQHR5cGVkZWYge2ltcG9ydCgnQGFwcGl1bS90eXBlcycpLkRyaXZlckNsYXNzPFA+fSBEcml2ZXJDbGFzc1xuICovXG5cbi8qKlxuICogQHR5cGVkZWYge2ltcG9ydCgnQGFwcGl1bS90eXBlcycpLkNhcGFiaWxpdGllc30gQ2FwYWJpbGl0aWVzXG4gKiBAdHlwZWRlZiB7aW1wb3J0KCdAYXBwaXVtL3R5cGVzJykuRHJpdmVyfSBEcml2ZXJcbiAqIEB0eXBlZGVmIHtpbXBvcnQoJ0BhcHBpdW0vdHlwZXMnKS5Ecml2ZXJTdGF0aWN9IERyaXZlclN0YXRpY1xuICogQHR5cGVkZWYge2ltcG9ydCgnQGFwcGl1bS90eXBlcycpLkFwcGl1bVczQ0NhcGFiaWxpdGllc30gQXBwaXVtVzNDQ2FwYWJpbGl0aWVzXG4gKiBAdHlwZWRlZiB7aW1wb3J0KCdheGlvcycpLkF4aW9zUmVxdWVzdENvbmZpZ30gQXhpb3NSZXF1ZXN0Q29uZmlnXG4gKiBAdHlwZWRlZiB7aW1wb3J0KCdAYXBwaXVtL3R5cGVzJykuU2luZ3VsYXJTZXNzaW9uRGF0YX0gU2luZ3VsYXJTZXNzaW9uRGF0YVxuICovXG5cbi8qKlxuICogQHRlbXBsYXRlIFQsRFxuICogQHR5cGVkZWYge2ltcG9ydCgnYXhpb3MnKS5BeGlvc1Jlc3BvbnNlPFQsIEQ+fSBBeGlvc1Jlc3BvbnNlXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiBOZXdTZXNzaW9uRGF0YVxuICogQHByb3BlcnR5IHtpbXBvcnQoJ3R5cGUtZmVzdCcpLlJlcXVpcmVBdExlYXN0T25lPGltcG9ydCgnQGFwcGl1bS90eXBlcycpLlczQ0NhcGFiaWxpdGllcywgJ2ZpcnN0TWF0Y2gnfCdhbHdheXNNYXRjaCc+fSBjYXBhYmlsaXRpZXNcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIE5ld1Nlc3Npb25SZXNwb25zZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IHNlc3Npb25JZCxcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KCdAYXBwaXVtL3R5cGVzJykuQ2FwYWJpbGl0aWVzfSBjYXBhYmlsaXRpZXNcbiAqL1xuXG4vKipcbiAqIFNvbWUgRTJFIGhlbHBlcnMgZm9yIG1ha2luZyByZXF1ZXN0cyBhbmQgbWFuYWdpbmcgc2Vzc2lvbnNcbiAqIFNlZSB7QGxpbmtjb2RlIGNyZWF0ZVNlc3Npb25IZWxwZXJzfVxuICogQHRlbXBsYXRlIFtDb21tYW5kRGF0YT11bmtub3duXVxuICogQHRlbXBsYXRlIFtSZXNwb25zZURhdGE9YW55XVxuICogQHR5cGVkZWYgU2Vzc2lvbkhlbHBlcnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBuZXdTZXNzaW9uVVJMIC0gVVJMIHRvIGNyZWF0ZSBhIG5ldyBzZXNzaW9uLiBDYW4gYmUgdXNlZCB3aXRoIHJhdyBgYXhpb3NgIHJlcXVlc3RzIHRvIGZ1bGx5IGluc3BlY3QgcmF3IHJlc3BvbnNlLiAgTW9zdGx5LCB0aGlzIHdpbGwgbm90IGJlIHVzZWQuXG4gKiBAcHJvcGVydHkgeyhkYXRhOiBOZXdTZXNzaW9uRGF0YSwgY29uZmlnPzogQXhpb3NSZXF1ZXN0Q29uZmlnKSA9PiBQcm9taXNlPE5ld1Nlc3Npb25SZXNwb25zZT59IHN0YXJ0U2Vzc2lvbiAtIEJlZ2luIGEgc2Vzc2lvblxuICogQHByb3BlcnR5IHsoc2Vzc2lvbklkOiBzdHJpbmcpID0+IFByb21pc2U8QXhpb3NSZXNwb25zZTx7dmFsdWU6IHtlcnJvcj86IHN0cmluZ30/fSwge3ZhbGlkYXRlU3RhdHVzOiBudWxsfT4+fSBlbmRTZXNzaW9uIC0gRW5kIGEgc2Vzc2lvbi4gX05vdGU6IHJlc29sdmVzIHdpdGggcmF3IHJlc3BvbnNlIG9iamVjdF9cbiAqIEBwcm9wZXJ0eSB7KHNlc3Npb25JZDogc3RyaW5nKSA9PiBQcm9taXNlPFNpbmd1bGFyU2Vzc2lvbkRhdGE+fSBnZXRTZXNzaW9uIC0gR2V0IGluZm8gYWJvdXQgYSBzZXNzaW9uXG4gKiBAcHJvcGVydHkgeyhzZXNzaW9uSWQ6IHN0cmluZywgY21kTmFtZTogc3RyaW5nLCBkYXRhPzogQ29tbWFuZERhdGEsIGNvbmZpZz86IEF4aW9zUmVxdWVzdENvbmZpZykgPT4gUHJvbWlzZTxSZXNwb25zZURhdGE+fSBwb3N0Q29tbWFuZCAtIFNlbmQgYW4gYXJiaXRyYXJ5IGNvbW1hbmQgdmlhIGBQT1NUYC5cbiAqIEBwcm9wZXJ0eSB7KHNlc3Npb25JZE9yQ21kTmFtZTogc3RyaW5nLCBjbWROYW1lT3JDb25maWc6IHN0cmluZ3xBeGlvc1JlcXVlc3RDb25maWcsIGNvbmZpZz86IEF4aW9zUmVxdWVzdENvbmZpZykgPT4gUHJvbWlzZTxSZXNwb25zZURhdGE+fSBnZXRDb21tYW5kIC0gU2VuZCBhbiBhcmJpdHJhcnkgY29tbWFuZCB2aWEgYEdFVGAuIE9wdGlvbmFsIGBzZXNzaW9uSWRgLlxuICovXG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUVBLE1BQU1BLE1BQU0sR0FBR0MsYUFBQSxDQUFLRCxNQUFMLEVBQWY7O0FBVU8sU0FBU0Usb0JBQVQsQ0FBOEJDLElBQTlCLEVBQW9DQyxPQUFPLEdBQUdDLGtCQUE5QyxFQUF5RDtFQUM5RCxNQUFNQyxtQkFBbUIsR0FFckIsSUFBQUMsd0JBQUEsRUFBZ0JILE9BQWhCLEVBQXlCRCxJQUF6QixDQUZKO0VBS0EsTUFBTUssZ0JBQWdCLEdBQUdG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
|
|
370
|
+
exports.driverE2ETestSuite = driverE2ETestSuite;
|
|
371
|
+
/**
|
|
372
|
+
* A {@linkcode DriverClass}, except using the base {@linkcode Driver} type instead of `ExternalDriver`.
|
|
373
|
+
* This allows the suite to work for `BaseDriver`.
|
|
374
|
+
* @template {Driver} P
|
|
375
|
+
* @typedef {import('@appium/types').DriverClass<P>} DriverClass
|
|
376
|
+
*/
|
|
377
|
+
/**
|
|
378
|
+
* @typedef {import('@appium/types').Driver} Driver
|
|
379
|
+
* @typedef {import('@appium/types').Constraints} Constraints
|
|
380
|
+
* @typedef {import('@appium/types').DriverStatic} DriverStatic
|
|
381
|
+
* @typedef {import('@appium/types').StringRecord} StringRecord
|
|
382
|
+
* @typedef {import('@appium/types').BaseDriverCapConstraints} BaseDriverCapConstraints
|
|
383
|
+
* @typedef {import('@appium/types').BaseNSCapabilities} BaseNSCapabilities
|
|
384
|
+
* @typedef {import('axios').AxiosRequestConfig} AxiosRequestConfig
|
|
385
|
+
* @typedef {import('@appium/types').SingularSessionData} SingularSessionData
|
|
386
|
+
*/
|
|
387
|
+
/**
|
|
388
|
+
* @template T,D
|
|
389
|
+
* @typedef {import('axios').AxiosResponse<T, D>} AxiosResponse
|
|
390
|
+
*/
|
|
391
|
+
/**
|
|
392
|
+
* @template {Constraints} [C=BaseDriverCapConstraints]
|
|
393
|
+
* @template {StringRecord|void} [Extra=void]
|
|
394
|
+
* @typedef NewSessionData
|
|
395
|
+
* @property {import('type-fest').RequireAtLeastOne<import('@appium/types').W3CCapabilities<C, Extra>, 'firstMatch'|'alwaysMatch'>} capabilities
|
|
396
|
+
*/
|
|
397
|
+
/**
|
|
398
|
+
* @template {Constraints} [C=BaseDriverCapConstraints]
|
|
399
|
+
* @template {StringRecord|void} [Extra=void]
|
|
400
|
+
* @typedef NewSessionResponse
|
|
401
|
+
* @property {string} sessionId,
|
|
402
|
+
* @property {import('@appium/types').Capabilities<C, Extra>} capabilities
|
|
403
|
+
*/
|
|
404
|
+
/**
|
|
405
|
+
* Some E2E helpers for making requests and managing sessions
|
|
406
|
+
* See {@linkcode createSessionHelpers}
|
|
407
|
+
* @template [CommandData=unknown]
|
|
408
|
+
* @template [ResponseData=any]
|
|
409
|
+
* @typedef SessionHelpers
|
|
410
|
+
* @property {string} newSessionURL - URL to create a new session. Can be used with raw `axios` requests to fully inspect raw response. Mostly, this will not be used.
|
|
411
|
+
* @property {(data: NewSessionData, config?: AxiosRequestConfig) => Promise<NewSessionResponse>} startSession - Begin a session
|
|
412
|
+
* @property {(sessionId: string) => Promise<AxiosResponse<{value: {error?: string}?}, {validateStatus: null}>>} endSession - End a session. _Note: resolves with raw response object_
|
|
413
|
+
* @property {(sessionId: string) => Promise<SingularSessionData>} getSession - Get info about a session
|
|
414
|
+
* @property {(sessionId: string, cmdName: string, data?: CommandData, config?: AxiosRequestConfig) => Promise<ResponseData>} postCommand - Send an arbitrary command via `POST`.
|
|
415
|
+
* @property {(sessionIdOrCmdName: string, cmdNameOrConfig: string|AxiosRequestConfig, config?: AxiosRequestConfig) => Promise<ResponseData>} getCommand - Send an arbitrary command via `GET`. Optional `sessionId`.
|
|
416
|
+
*/
|
|
417
|
+
//# sourceMappingURL=e2e-suite.js.map
|