@applitools/driver 1.11.2 → 1.11.4
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/dist/context.js +123 -85
- package/dist/driver.js +67 -34
- package/dist/fake/mock-driver.js +8 -7
- package/dist/spec-utils.js +6 -2
- package/dist/user-agent-data.js +33 -0
- package/package.json +4 -4
- package/types/context.d.ts +10 -5
- package/types/driver.d.ts +3 -0
- package/types/selector.d.ts +2 -0
- package/types/spec-driver.d.ts +3 -0
- package/types/spec-utils.d.ts +1 -6
- package/types/user-agent-data.d.ts +13 -0
package/dist/context.js
CHANGED
|
@@ -104,6 +104,70 @@ class Context {
|
|
|
104
104
|
get isRef() {
|
|
105
105
|
return !this._target;
|
|
106
106
|
}
|
|
107
|
+
async _findElements(selector, options = {}) {
|
|
108
|
+
await this.focus();
|
|
109
|
+
const { parent, all, wait } = options;
|
|
110
|
+
const transformedSelector = specUtils.transformSelector(this._spec, selector, this.driver);
|
|
111
|
+
let elements = [];
|
|
112
|
+
if (wait) {
|
|
113
|
+
if (this._spec.waitForSelector) {
|
|
114
|
+
const element = await this._spec.waitForSelector(this.target, specUtils.transformSelector(this._spec, selector, this.driver), parent, wait);
|
|
115
|
+
if (element)
|
|
116
|
+
elements = [element];
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
let waiting = true;
|
|
120
|
+
const timeout = setTimeout(() => (waiting = false), wait.timeout);
|
|
121
|
+
while (waiting) {
|
|
122
|
+
const element = await this._spec.findElement(this.target, specUtils.transformSelector(this._spec, selector, this.driver), parent);
|
|
123
|
+
if (element) {
|
|
124
|
+
clearTimeout(timeout);
|
|
125
|
+
elements = [element];
|
|
126
|
+
}
|
|
127
|
+
await utils.general.sleep(wait.interval);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (all) {
|
|
132
|
+
elements = await this._spec.findElements(this.target, transformedSelector, parent);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const element = await this._spec.findElement(this.target, transformedSelector, parent);
|
|
136
|
+
if (element)
|
|
137
|
+
elements = [element];
|
|
138
|
+
}
|
|
139
|
+
if (specUtils.isCommonSelector(this._spec, selector)) {
|
|
140
|
+
if (elements.length > 0) {
|
|
141
|
+
if (selector.child) {
|
|
142
|
+
elements = await elements.reduce((result, element) => {
|
|
143
|
+
return result.then(async (result) => {
|
|
144
|
+
return result.concat(await this._findElements(selector.child, { parent: element, all, wait }));
|
|
145
|
+
});
|
|
146
|
+
}, Promise.resolve([]));
|
|
147
|
+
}
|
|
148
|
+
else if (selector.shadow) {
|
|
149
|
+
elements = await elements.reduce((result, element) => {
|
|
150
|
+
return result.then(async (result) => {
|
|
151
|
+
const root = await this._spec.executeScript(this.target, snippets.getShadowRoot, [element]);
|
|
152
|
+
return result.concat(root ? await this._findElements(selector.shadow, { parent: root, all, wait }) : []);
|
|
153
|
+
});
|
|
154
|
+
}, Promise.resolve([]));
|
|
155
|
+
}
|
|
156
|
+
else if (selector.frame) {
|
|
157
|
+
elements = await elements.reduce((result, element) => {
|
|
158
|
+
return result.then(async (result) => {
|
|
159
|
+
const context = await this.context(element);
|
|
160
|
+
return result.concat(await context._findElements(selector.frame, { all, wait }));
|
|
161
|
+
});
|
|
162
|
+
}, Promise.resolve([]));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (elements.length === 0 && selector.fallback) {
|
|
166
|
+
elements = await this._findElements(selector.fallback, parent);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return elements;
|
|
170
|
+
}
|
|
107
171
|
async init() {
|
|
108
172
|
if (this.isInitialized)
|
|
109
173
|
return this;
|
|
@@ -201,62 +265,21 @@ class Context {
|
|
|
201
265
|
});
|
|
202
266
|
}
|
|
203
267
|
}
|
|
204
|
-
async root(selector) {
|
|
205
|
-
var _a;
|
|
206
|
-
await this.focus();
|
|
207
|
-
const { contextSelectors, elementSelector } = specUtils.splitSelector(this._spec, selector);
|
|
208
|
-
let context = this;
|
|
209
|
-
for (const contextSelector of contextSelectors) {
|
|
210
|
-
try {
|
|
211
|
-
context = await context.context(contextSelector);
|
|
212
|
-
await context.focus();
|
|
213
|
-
}
|
|
214
|
-
catch {
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
if ((_a = this.driver.features) === null || _a === void 0 ? void 0 : _a.shadowSelector)
|
|
219
|
-
return { context, selector: elementSelector };
|
|
220
|
-
let root = null;
|
|
221
|
-
let element = null;
|
|
222
|
-
let currentSelector = elementSelector;
|
|
223
|
-
while (specUtils.isCommonSelector(this._spec, currentSelector) &&
|
|
224
|
-
specUtils.isSelector(this._spec, currentSelector.shadow)) {
|
|
225
|
-
element = await this._spec.findElement(this.target, specUtils.transformSelector(this._spec, currentSelector, this.driver), root);
|
|
226
|
-
if (!element)
|
|
227
|
-
return null;
|
|
228
|
-
root = await this._spec.executeScript(this.target, snippets.getShadowRoot, [element]);
|
|
229
|
-
if (!root)
|
|
230
|
-
return null;
|
|
231
|
-
currentSelector = currentSelector.shadow;
|
|
232
|
-
}
|
|
233
|
-
return {
|
|
234
|
-
context,
|
|
235
|
-
shadow: element && new element_1.Element({ spec: this._spec, context, element, logger: this._logger }),
|
|
236
|
-
selector: currentSelector,
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
268
|
async element(elementOrSelector) {
|
|
240
269
|
if (this._spec.isElement(elementOrSelector)) {
|
|
241
270
|
return new element_1.Element({ spec: this._spec, context: this, element: elementOrSelector, logger: this._logger });
|
|
242
271
|
}
|
|
243
|
-
else if (specUtils.isSelector(this._spec, elementOrSelector)) {
|
|
244
|
-
if (this.isRef) {
|
|
245
|
-
return new element_1.Element({ spec: this._spec, context: this, selector: elementOrSelector, logger: this._logger });
|
|
246
|
-
}
|
|
247
|
-
this._logger.log('Finding element by selector: ', elementOrSelector);
|
|
248
|
-
const root = await this.root(elementOrSelector);
|
|
249
|
-
if (!root)
|
|
250
|
-
return null;
|
|
251
|
-
const element = await this._spec.findElement(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), root.shadow && (await root.shadow.getShadowRoot()));
|
|
252
|
-
// TODO root.selector is not a full selector from context root to an element, but selector inside a shadow
|
|
253
|
-
return element
|
|
254
|
-
? new element_1.Element({ spec: this._spec, context: root.context, element, selector: root.selector, logger: this._logger })
|
|
255
|
-
: null;
|
|
256
|
-
}
|
|
257
|
-
else {
|
|
272
|
+
else if (!specUtils.isSelector(this._spec, elementOrSelector)) {
|
|
258
273
|
throw new TypeError('Cannot find element using argument of unknown type!');
|
|
259
274
|
}
|
|
275
|
+
if (this.isRef) {
|
|
276
|
+
return new element_1.Element({ spec: this._spec, context: this, selector: elementOrSelector, logger: this._logger });
|
|
277
|
+
}
|
|
278
|
+
this._logger.log('Finding element by selector: ', elementOrSelector);
|
|
279
|
+
const [element] = await this._findElements(elementOrSelector, { all: false });
|
|
280
|
+
return element
|
|
281
|
+
? new element_1.Element({ spec: this._spec, context: this, element, selector: elementOrSelector, logger: this._logger })
|
|
282
|
+
: null;
|
|
260
283
|
}
|
|
261
284
|
async elements(selectorOrElement) {
|
|
262
285
|
if (specUtils.isSelector(this._spec, selectorOrElement)) {
|
|
@@ -264,17 +287,13 @@ class Context {
|
|
|
264
287
|
return [new element_1.Element({ spec: this._spec, context: this, selector: selectorOrElement, logger: this._logger })];
|
|
265
288
|
}
|
|
266
289
|
this._logger.log('Finding elements by selector: ', selectorOrElement);
|
|
267
|
-
const
|
|
268
|
-
if (!root)
|
|
269
|
-
return [];
|
|
270
|
-
const elements = await this._spec.findElements(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), root.shadow && (await root.shadow.getShadowRoot()));
|
|
290
|
+
const elements = await this._findElements(selectorOrElement, { all: true });
|
|
271
291
|
return elements.map((element, index) => {
|
|
272
|
-
// TODO root.selector is not a full selector from context root to an element, but selector inside a shadow
|
|
273
292
|
return new element_1.Element({
|
|
274
293
|
spec: this._spec,
|
|
275
|
-
context:
|
|
294
|
+
context: this,
|
|
276
295
|
element,
|
|
277
|
-
selector:
|
|
296
|
+
selector: selectorOrElement,
|
|
278
297
|
index,
|
|
279
298
|
logger: this._logger,
|
|
280
299
|
});
|
|
@@ -288,34 +307,10 @@ class Context {
|
|
|
288
307
|
}
|
|
289
308
|
}
|
|
290
309
|
async waitFor(selector, options) {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
options = { state: 'exist', timeout: 10000, interval: 500, ...options };
|
|
296
|
-
if (this._spec.waitForSelector) {
|
|
297
|
-
const element = await this._spec.waitForSelector(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), (_a = root.shadow) === null || _a === void 0 ? void 0 : _a.target, options);
|
|
298
|
-
return element
|
|
299
|
-
? new element_1.Element({ spec: this._spec, context: root.context, element, selector: root.selector, logger: this._logger })
|
|
300
|
-
: null;
|
|
301
|
-
}
|
|
302
|
-
let waiting = true;
|
|
303
|
-
const timeout = setTimeout(() => (waiting = false), options.timeout);
|
|
304
|
-
while (waiting) {
|
|
305
|
-
const element = await this._spec.findElement(root.context.target, specUtils.transformSelector(this._spec, root.selector, this.driver), (_b = root.shadow) === null || _b === void 0 ? void 0 : _b.target);
|
|
306
|
-
if (element) {
|
|
307
|
-
clearTimeout(timeout);
|
|
308
|
-
return new element_1.Element({
|
|
309
|
-
spec: this._spec,
|
|
310
|
-
context: root.context,
|
|
311
|
-
element,
|
|
312
|
-
selector: root.selector,
|
|
313
|
-
logger: this._logger,
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
await utils.general.sleep(options.interval);
|
|
317
|
-
}
|
|
318
|
-
return null;
|
|
310
|
+
const [element] = await this._findElements(selector, {
|
|
311
|
+
wait: { state: 'exist', timeout: 10000, interval: 500, ...options },
|
|
312
|
+
});
|
|
313
|
+
return element ? new element_1.Element({ spec: this._spec, context: this, element, selector, logger: this._logger }) : null;
|
|
319
314
|
}
|
|
320
315
|
async execute(script, arg) {
|
|
321
316
|
await this.focus();
|
|
@@ -345,6 +340,49 @@ class Context {
|
|
|
345
340
|
}
|
|
346
341
|
}
|
|
347
342
|
}
|
|
343
|
+
async executePoll(script, arg) {
|
|
344
|
+
this._logger.log('Executing poll script');
|
|
345
|
+
const { main: mainScript, poll: pollScript } = utils.types.isString(script) || utils.types.isFunction(script) ? { main: script, poll: script } : script;
|
|
346
|
+
const { main: mainArg, poll: pollArg, executionTimeout = 60000, pollTimeout = 1000, } = !utils.types.has(arg, ['main', 'poll']) ? { main: arg, poll: arg } : arg;
|
|
347
|
+
let isExecutionTimedOut = false;
|
|
348
|
+
const executionTimer = setTimeout(() => (isExecutionTimedOut = true), executionTimeout);
|
|
349
|
+
try {
|
|
350
|
+
let response = deserialize(await this.execute(mainScript, mainArg));
|
|
351
|
+
let chunks = '';
|
|
352
|
+
while (!isExecutionTimedOut) {
|
|
353
|
+
if (response.status === 'ERROR') {
|
|
354
|
+
throw new Error(`Error during execute poll script: '${response.error}'`);
|
|
355
|
+
}
|
|
356
|
+
else if (response.status === 'SUCCESS') {
|
|
357
|
+
return response.value;
|
|
358
|
+
}
|
|
359
|
+
else if (response.status === 'SUCCESS_CHUNKED') {
|
|
360
|
+
chunks += response.value;
|
|
361
|
+
if (response.done)
|
|
362
|
+
return deserialize(chunks);
|
|
363
|
+
}
|
|
364
|
+
else if (response.status === 'WIP') {
|
|
365
|
+
await utils.general.sleep(pollTimeout);
|
|
366
|
+
}
|
|
367
|
+
this._logger.log('Polling...');
|
|
368
|
+
response = deserialize(await this.execute(pollScript, pollArg));
|
|
369
|
+
}
|
|
370
|
+
throw new Error('Poll script execution is timed out');
|
|
371
|
+
}
|
|
372
|
+
finally {
|
|
373
|
+
clearTimeout(executionTimer);
|
|
374
|
+
}
|
|
375
|
+
function deserialize(json) {
|
|
376
|
+
try {
|
|
377
|
+
return JSON.parse(json);
|
|
378
|
+
}
|
|
379
|
+
catch (err) {
|
|
380
|
+
const firstChars = json.slice(0, 100);
|
|
381
|
+
const lastChars = json.slice(-100);
|
|
382
|
+
throw new Error(`Response is not a valid JSON string. length: ${json.length}, first 100 chars: "${firstChars}", last 100 chars: "${lastChars}". error: ${err}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
348
386
|
async getContextElement() {
|
|
349
387
|
if (this.isMain)
|
|
350
388
|
return null;
|
package/dist/driver.js
CHANGED
|
@@ -29,10 +29,11 @@ const logger_1 = require("@applitools/logger");
|
|
|
29
29
|
const helper_ios_1 = require("./helper-ios");
|
|
30
30
|
const helper_android_1 = require("./helper-android");
|
|
31
31
|
const user_agent_1 = require("./user-agent");
|
|
32
|
+
const user_agent_data_1 = require("./user-agent-data");
|
|
32
33
|
const capabilities_1 = require("./capabilities");
|
|
34
|
+
const snippets = __importStar(require("@applitools/snippets"));
|
|
33
35
|
const utils = __importStar(require("@applitools/utils"));
|
|
34
36
|
const specUtils = __importStar(require("./spec-utils"));
|
|
35
|
-
const snippets = require('@applitools/snippets');
|
|
36
37
|
// eslint-disable-next-line
|
|
37
38
|
class Driver {
|
|
38
39
|
constructor(options) {
|
|
@@ -135,12 +136,24 @@ class Driver {
|
|
|
135
136
|
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isMobile) !== null && _b !== void 0 ? _b : false;
|
|
136
137
|
}
|
|
137
138
|
get isIOS() {
|
|
138
|
-
var _a;
|
|
139
|
-
return ((_a = this.
|
|
139
|
+
var _a, _b;
|
|
140
|
+
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isIOS) !== null && _b !== void 0 ? _b : /iOS/i.test(this.platformName);
|
|
140
141
|
}
|
|
141
142
|
get isAndroid() {
|
|
142
|
-
var _a;
|
|
143
|
-
return ((_a = this.
|
|
143
|
+
var _a, _b;
|
|
144
|
+
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isAndroid) !== null && _b !== void 0 ? _b : /Android/i.test(this.platformName);
|
|
145
|
+
}
|
|
146
|
+
get isMac() {
|
|
147
|
+
var _a, _b;
|
|
148
|
+
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isMac) !== null && _b !== void 0 ? _b : /mac\s?OS/i.test(this.platformName);
|
|
149
|
+
}
|
|
150
|
+
get isWindows() {
|
|
151
|
+
var _a, _b;
|
|
152
|
+
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isWindows) !== null && _b !== void 0 ? _b : /Windows/i.test(this.platformName);
|
|
153
|
+
}
|
|
154
|
+
get isChromium() {
|
|
155
|
+
var _a, _b;
|
|
156
|
+
return ((_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isChromium) !== null && _b !== void 0 ? _b : (/(chrome)/i.test(this.browserName) || (/edge/i.test(this.browserName) && Number(this.browserVersion) > 44)));
|
|
144
157
|
}
|
|
145
158
|
get isIE() {
|
|
146
159
|
return /(internet explorer|ie)/i.test(this.browserName);
|
|
@@ -152,8 +165,8 @@ class Driver {
|
|
|
152
165
|
this._currentContext = context;
|
|
153
166
|
}
|
|
154
167
|
async init() {
|
|
155
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
|
|
156
|
-
var
|
|
168
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18;
|
|
169
|
+
var _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34;
|
|
157
170
|
// NOTE: this is here because saucelabs does not provide right capabilities for the first call
|
|
158
171
|
await ((_b = (_a = this._spec).getCapabilities) === null || _b === void 0 ? void 0 : _b.call(_a, this.target));
|
|
159
172
|
const capabilities = await ((_d = (_c = this._spec).getCapabilities) === null || _d === void 0 ? void 0 : _d.call(_c, this.target));
|
|
@@ -168,34 +181,54 @@ class Driver {
|
|
|
168
181
|
this._driverInfo.isWebView = !!(world === null || world === void 0 ? void 0 : world.isWebView);
|
|
169
182
|
}
|
|
170
183
|
if (this.isWeb) {
|
|
171
|
-
|
|
172
|
-
(
|
|
173
|
-
(
|
|
184
|
+
const browserInfo = await this.currentContext.executePoll(snippets.getBrowserInfo);
|
|
185
|
+
(_h = (_19 = this._driverInfo).userAgent) !== null && _h !== void 0 ? _h : (_19.userAgent = browserInfo.userAgent);
|
|
186
|
+
(_j = (_20 = this._driverInfo).pixelRatio) !== null && _j !== void 0 ? _j : (_20.pixelRatio = browserInfo.pixelRatio);
|
|
187
|
+
(_k = (_21 = this._driverInfo).viewportScale) !== null && _k !== void 0 ? _k : (_21.viewportScale = browserInfo.viewportScale);
|
|
188
|
+
if (browserInfo.userAgentData) {
|
|
189
|
+
(_l = (_22 = this._driverInfo).isMobile) !== null && _l !== void 0 ? _l : (_22.isMobile = this._driverInfo.isMobile);
|
|
190
|
+
(_m = (_23 = this._driverInfo).isChromium) !== null && _m !== void 0 ? _m : (_23.isChromium = this._driverInfo.isChromium);
|
|
191
|
+
if (this.isChromium) {
|
|
192
|
+
if (this.isWindows && Number.parseInt(this.browserVersion) >= 107) {
|
|
193
|
+
this._driverInfo.platformVersion = (_o = browserInfo.platformVersion) !== null && _o !== void 0 ? _o : this._driverInfo.platformVersion;
|
|
194
|
+
}
|
|
195
|
+
else if (this.isMac && Number.parseInt(this.browserVersion) >= 90) {
|
|
196
|
+
this._driverInfo.platformVersion = (_p = browserInfo.platformVersion) !== null && _p !== void 0 ? _p : this._driverInfo.platformVersion;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
174
200
|
if (this._driverInfo.userAgent) {
|
|
175
201
|
const userAgentInfo = (0, user_agent_1.parseUserAgent)(this._driverInfo.userAgent);
|
|
176
|
-
|
|
177
|
-
this._driverInfo.
|
|
202
|
+
const userAgentDataInfo = browserInfo.userAgentData && (0, user_agent_data_1.parseUserAgentData)(browserInfo.userAgentData);
|
|
203
|
+
this._driverInfo.browserName =
|
|
204
|
+
(_r = (_q = userAgentInfo.browserName) !== null && _q !== void 0 ? _q : userAgentDataInfo.browserName) !== null && _r !== void 0 ? _r : this._driverInfo.browserName;
|
|
205
|
+
this._driverInfo.browserVersion =
|
|
206
|
+
(_t = (_s = userAgentInfo.browserVersion) !== null && _s !== void 0 ? _s : userAgentDataInfo.browserVersion) !== null && _t !== void 0 ? _t : this._driverInfo.browserVersion;
|
|
207
|
+
(_u = (_24 = this._driverInfo).isMobile) !== null && _u !== void 0 ? _u : (_24.isMobile = userAgentDataInfo === null || userAgentDataInfo === void 0 ? void 0 : userAgentDataInfo.isMobile);
|
|
208
|
+
(_v = (_25 = this._driverInfo).isChromium) !== null && _v !== void 0 ? _v : (_25.isChromium = userAgentDataInfo === null || userAgentDataInfo === void 0 ? void 0 : userAgentDataInfo.isChromium);
|
|
178
209
|
if (this._driverInfo.isMobile) {
|
|
179
|
-
(
|
|
180
|
-
(
|
|
210
|
+
(_w = (_26 = this._driverInfo).platformName) !== null && _w !== void 0 ? _w : (_26.platformName = (_x = userAgentDataInfo === null || userAgentDataInfo === void 0 ? void 0 : userAgentDataInfo.platformName) !== null && _x !== void 0 ? _x : userAgentInfo.platformName);
|
|
211
|
+
(_y = (_27 = this._driverInfo).platformVersion) !== null && _y !== void 0 ? _y : (_27.platformVersion = (_z = userAgentDataInfo === null || userAgentDataInfo === void 0 ? void 0 : userAgentDataInfo.platformVersion) !== null && _z !== void 0 ? _z : userAgentInfo.platformVersion);
|
|
181
212
|
}
|
|
182
213
|
else {
|
|
183
|
-
this._driverInfo.platformName =
|
|
184
|
-
|
|
214
|
+
this._driverInfo.platformName =
|
|
215
|
+
(_1 = (_0 = userAgentDataInfo === null || userAgentDataInfo === void 0 ? void 0 : userAgentDataInfo.platformName) !== null && _0 !== void 0 ? _0 : userAgentInfo.platformName) !== null && _1 !== void 0 ? _1 : this._driverInfo.platformName;
|
|
216
|
+
this._driverInfo.platformVersion =
|
|
217
|
+
(_3 = (_2 = userAgentDataInfo === null || userAgentDataInfo === void 0 ? void 0 : userAgentDataInfo.platformVersion) !== null && _2 !== void 0 ? _2 : userAgentInfo.platformVersion) !== null && _3 !== void 0 ? _3 : this._driverInfo.platformVersion;
|
|
185
218
|
}
|
|
186
219
|
}
|
|
187
|
-
if (!this.
|
|
220
|
+
if (!this.isMobile && (this.isAndroid || this.isIOS)) {
|
|
188
221
|
this._driverInfo.isMobile = true;
|
|
189
222
|
this._driverInfo.isEmulation = this._driverInfo.isChrome;
|
|
190
223
|
}
|
|
191
|
-
(
|
|
192
|
-
(
|
|
224
|
+
(_4 = (_28 = this._driverInfo).features) !== null && _4 !== void 0 ? _4 : (_28.features = {});
|
|
225
|
+
(_5 = (_29 = this._driverInfo.features).allCookies) !== null && _5 !== void 0 ? _5 : (_29.allCookies = this._driverInfo.isChrome || (/chrome/i.test(this._driverInfo.browserName) && !this._driverInfo.isMobile));
|
|
193
226
|
}
|
|
194
227
|
else {
|
|
195
228
|
// this value always excludes the height of the navigation bar, and sometimes it also excludes the height of the status bar
|
|
196
229
|
let windowSize = await this._spec.getWindowSize(this.target);
|
|
197
|
-
(
|
|
198
|
-
if (((
|
|
230
|
+
(_6 = (_30 = this._driverInfo).displaySize) !== null && _6 !== void 0 ? _6 : (_30.displaySize = windowSize);
|
|
231
|
+
if (((_7 = this.orientation) === null || _7 === void 0 ? void 0 : _7.startsWith('landscape')) &&
|
|
199
232
|
this._driverInfo.displaySize.height > this._driverInfo.displaySize.width) {
|
|
200
233
|
this._driverInfo.displaySize = {
|
|
201
234
|
width: this._driverInfo.displaySize.height,
|
|
@@ -204,14 +237,14 @@ class Driver {
|
|
|
204
237
|
}
|
|
205
238
|
if (this.isAndroid) {
|
|
206
239
|
// bar sizes could be extracted only on android
|
|
207
|
-
const systemBars = await ((
|
|
240
|
+
const systemBars = await ((_9 = (_8 = this._spec).getSystemBars) === null || _9 === void 0 ? void 0 : _9.call(_8, this.target).catch(() => null));
|
|
208
241
|
const { statusBar, navigationBar } = systemBars !== null && systemBars !== void 0 ? systemBars : {};
|
|
209
242
|
if (statusBar === null || statusBar === void 0 ? void 0 : statusBar.visible) {
|
|
210
243
|
this._logger.log('Driver status bar', statusBar);
|
|
211
244
|
const statusBarSize = statusBar.height;
|
|
212
245
|
// when status bar is overlapping content on android it returns status bar height equal to display height
|
|
213
246
|
if (statusBarSize < this._driverInfo.displaySize.height) {
|
|
214
|
-
this._driverInfo.statusBarSize = Math.max((
|
|
247
|
+
this._driverInfo.statusBarSize = Math.max((_10 = this._driverInfo.statusBarSize) !== null && _10 !== void 0 ? _10 : 0, statusBarSize);
|
|
215
248
|
}
|
|
216
249
|
}
|
|
217
250
|
if (navigationBar === null || navigationBar === void 0 ? void 0 : navigationBar.visible) {
|
|
@@ -220,28 +253,28 @@ class Driver {
|
|
|
220
253
|
if (navigationBar.x > 0)
|
|
221
254
|
this._driverInfo.orientation = 'landscape-secondary';
|
|
222
255
|
// navigation bar size could be its height or width depending on screen orientation
|
|
223
|
-
const navigationBarSize = navigationBar[((
|
|
256
|
+
const navigationBarSize = navigationBar[((_11 = this.orientation) === null || _11 === void 0 ? void 0 : _11.startsWith('landscape')) ? 'width' : 'height'];
|
|
224
257
|
// when navigation bar is invisible on android it returns navigation bar size equal to display size
|
|
225
258
|
if (navigationBarSize <
|
|
226
|
-
this._driverInfo.displaySize[((
|
|
227
|
-
this._driverInfo.navigationBarSize = Math.max((
|
|
259
|
+
this._driverInfo.displaySize[((_12 = this.orientation) === null || _12 === void 0 ? void 0 : _12.startsWith('landscape')) ? 'width' : 'height']) {
|
|
260
|
+
this._driverInfo.navigationBarSize = Math.max((_13 = this._driverInfo.navigationBarSize) !== null && _13 !== void 0 ? _13 : 0, navigationBarSize);
|
|
228
261
|
}
|
|
229
262
|
else {
|
|
230
263
|
this._driverInfo.navigationBarSize = 0;
|
|
231
264
|
}
|
|
232
265
|
}
|
|
233
266
|
// bar sizes have to be scaled on android
|
|
234
|
-
(
|
|
235
|
-
(
|
|
267
|
+
(_31 = this._driverInfo).statusBarSize && (_31.statusBarSize = this._driverInfo.statusBarSize / this.pixelRatio);
|
|
268
|
+
(_32 = this._driverInfo).navigationBarSize && (_32.navigationBarSize = this._driverInfo.navigationBarSize / this.pixelRatio);
|
|
236
269
|
windowSize = utils.geometry.scale(windowSize, 1 / this.pixelRatio);
|
|
237
|
-
(
|
|
270
|
+
(_33 = this._driverInfo).displaySize && (_33.displaySize = utils.geometry.scale(this._driverInfo.displaySize, 1 / this.pixelRatio));
|
|
238
271
|
}
|
|
239
272
|
if (this.isIOS) {
|
|
240
|
-
if ((
|
|
273
|
+
if ((_14 = this.orientation) === null || _14 === void 0 ? void 0 : _14.startsWith('landscape'))
|
|
241
274
|
this._driverInfo.statusBarSize = 0;
|
|
242
275
|
}
|
|
243
276
|
// calculate viewport location
|
|
244
|
-
(
|
|
277
|
+
(_15 = (_34 = this._driverInfo).viewportLocation) !== null && _15 !== void 0 ? _15 : (_34.viewportLocation = {
|
|
245
278
|
x: this.orientation === 'landscape' ? this.navigationBarSize : 0,
|
|
246
279
|
y: this.statusBarSize,
|
|
247
280
|
});
|
|
@@ -250,7 +283,7 @@ class Driver {
|
|
|
250
283
|
this._driverInfo.viewportSize = { ...this._driverInfo.displaySize };
|
|
251
284
|
this._driverInfo.viewportSize.height -= this.statusBarSize;
|
|
252
285
|
if (this.isAndroid) {
|
|
253
|
-
this._driverInfo.viewportSize[((
|
|
286
|
+
this._driverInfo.viewportSize[((_16 = this.orientation) === null || _16 === void 0 ? void 0 : _16.startsWith('landscape')) ? 'width' : 'height'] -=
|
|
254
287
|
this.navigationBarSize;
|
|
255
288
|
}
|
|
256
289
|
}
|
|
@@ -273,12 +306,12 @@ class Driver {
|
|
|
273
306
|
}
|
|
274
307
|
// TODO: if user opts into NML, skip initializing the helpers
|
|
275
308
|
// init helper lib
|
|
276
|
-
if (!((
|
|
309
|
+
if (!((_17 = this._customConfig) === null || _17 === void 0 ? void 0 : _17.disableHelper)) {
|
|
277
310
|
this._helper = this.isIOS
|
|
278
311
|
? await helper_ios_1.HelperIOS.make({ spec: this._spec, driver: this, logger: this._logger })
|
|
279
312
|
: await helper_android_1.HelperAndroid.make({ spec: this._spec, driver: this, logger: this._logger });
|
|
280
313
|
}
|
|
281
|
-
this._logger.log(`Helper set to ${(
|
|
314
|
+
this._logger.log(`Helper set to ${(_18 = this._helper) === null || _18 === void 0 ? void 0 : _18.name}`);
|
|
282
315
|
}
|
|
283
316
|
this._logger.log('Combined driver info', this._driverInfo);
|
|
284
317
|
return this;
|
package/dist/fake/mock-driver.js
CHANGED
|
@@ -117,16 +117,17 @@ class MockDriver {
|
|
|
117
117
|
}
|
|
118
118
|
return { x: scrollingElement.scrollPosition.x, y: scrollingElement.scrollPosition.y };
|
|
119
119
|
});
|
|
120
|
-
this.mockScript(snippets.getPixelRatio, () => {
|
|
121
|
-
return 1;
|
|
122
|
-
});
|
|
123
120
|
this.mockScript(snippets.getShadowRoot, ([element]) => {
|
|
124
121
|
return element;
|
|
125
122
|
});
|
|
126
|
-
this.mockScript(snippets.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
123
|
+
this.mockScript(snippets.getBrowserInfo, () => {
|
|
124
|
+
return JSON.stringify({
|
|
125
|
+
status: 'SUCCESS',
|
|
126
|
+
value: {
|
|
127
|
+
userAgent: this._ua !== undefined ? this._ua : this.info.isMobile ? DEFAULT_MOBILE_UA : DEFAULT_DESKTOP_UA,
|
|
128
|
+
pixelRatio: 1,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
130
131
|
});
|
|
131
132
|
this.mockScript(snippets.getViewportSize, () => {
|
|
132
133
|
return { width: this._window.rect.width, height: this._window.rect.height };
|
package/dist/spec-utils.js
CHANGED
|
@@ -34,7 +34,7 @@ exports.isSimpleCommonSelector = isSimpleCommonSelector;
|
|
|
34
34
|
function isCommonSelector(spec, selector) {
|
|
35
35
|
return (utils.types.isPlainObject(selector) &&
|
|
36
36
|
utils.types.has(selector, 'selector') &&
|
|
37
|
-
Object.keys(selector).every(key => ['selector', 'type', 'frame', 'shadow'].includes(key)) &&
|
|
37
|
+
Object.keys(selector).every(key => ['selector', 'type', 'frame', 'shadow', 'child', 'fallback'].includes(key)) &&
|
|
38
38
|
(utils.types.isString(selector.selector) || spec.isSelector(selector.selector)));
|
|
39
39
|
}
|
|
40
40
|
exports.isCommonSelector = isCommonSelector;
|
|
@@ -67,7 +67,11 @@ function splitSelector(spec, selector) {
|
|
|
67
67
|
activeSelector.selector = targetSelector.selector;
|
|
68
68
|
if (targetSelector.type)
|
|
69
69
|
activeSelector.type = targetSelector.type;
|
|
70
|
-
if (targetSelector.
|
|
70
|
+
if (targetSelector.child) {
|
|
71
|
+
activeSelector = activeSelector.child = {};
|
|
72
|
+
targetSelector = targetSelector.child;
|
|
73
|
+
}
|
|
74
|
+
else if (targetSelector.shadow) {
|
|
71
75
|
activeSelector = activeSelector.shadow = {};
|
|
72
76
|
targetSelector = targetSelector.shadow;
|
|
73
77
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseUserAgentData = void 0;
|
|
4
|
+
const WINDOWS_VERSIONS = {
|
|
5
|
+
'0.1.0': '7',
|
|
6
|
+
'0.2.0': '8',
|
|
7
|
+
'0.3.0': '8.1',
|
|
8
|
+
'10.0.0': '10',
|
|
9
|
+
'15.0.0': '11',
|
|
10
|
+
};
|
|
11
|
+
function parseUserAgentData(userAgentData) {
|
|
12
|
+
var _a, _b, _c;
|
|
13
|
+
const chromiumBrand = (_a = userAgentData.brands) === null || _a === void 0 ? void 0 : _a.find(brand => /Chromium/i.test(brand.brand));
|
|
14
|
+
const browserBrand = (_c = (_b = userAgentData.brands) === null || _b === void 0 ? void 0 : _b.find(brand => brand !== chromiumBrand && !/Not.?A.?Brand/i.test(brand.brand))) !== null && _c !== void 0 ? _c : chromiumBrand;
|
|
15
|
+
const info = {
|
|
16
|
+
browserName: browserBrand === null || browserBrand === void 0 ? void 0 : browserBrand.brand,
|
|
17
|
+
browserVersion: browserBrand === null || browserBrand === void 0 ? void 0 : browserBrand.version,
|
|
18
|
+
platformName: userAgentData.platform || undefined,
|
|
19
|
+
platformVersion: userAgentData.platformVersion || undefined,
|
|
20
|
+
deviceName: userAgentData.model || undefined,
|
|
21
|
+
isMobile: userAgentData.mobile,
|
|
22
|
+
isChromium: Boolean(chromiumBrand),
|
|
23
|
+
};
|
|
24
|
+
if (info.platformName === 'Windows') {
|
|
25
|
+
info.platformVersion = WINDOWS_VERSIONS[info.platformVersion];
|
|
26
|
+
}
|
|
27
|
+
else if (info.platformName === 'macOS') {
|
|
28
|
+
info.platformName = 'Mac OS X';
|
|
29
|
+
info.platformVersion = info.platformVersion.split(/[._]/, 2).join('.');
|
|
30
|
+
}
|
|
31
|
+
return info;
|
|
32
|
+
}
|
|
33
|
+
exports.parseUserAgentData = parseUserAgentData;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applitools/driver",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.4",
|
|
4
4
|
"description": "Applitools universal framework wrapper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"applitools",
|
|
@@ -87,9 +87,9 @@
|
|
|
87
87
|
}
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
|
-
"@applitools/logger": "1.1.
|
|
91
|
-
"@applitools/snippets": "2.4.
|
|
92
|
-
"@applitools/utils": "1.3.
|
|
90
|
+
"@applitools/logger": "1.1.29",
|
|
91
|
+
"@applitools/snippets": "2.4.7",
|
|
92
|
+
"@applitools/utils": "1.3.15",
|
|
93
93
|
"semver": "7.3.7"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
package/types/context.d.ts
CHANGED
|
@@ -47,19 +47,24 @@ export declare class Context<TDriver, TContext, TElement, TSelector> {
|
|
|
47
47
|
get isCurrent(): boolean;
|
|
48
48
|
get isInitialized(): boolean;
|
|
49
49
|
get isRef(): boolean;
|
|
50
|
+
private _findElements;
|
|
50
51
|
init(): Promise<this>;
|
|
51
52
|
focus(): Promise<this>;
|
|
52
53
|
equals(context: Context<TDriver, TContext, TElement, TSelector> | Element<TDriver, TContext, TElement, TSelector>): Promise<boolean>;
|
|
53
54
|
context(reference: ContextPlain<TDriver, TContext, TElement, TSelector>): Promise<Context<TDriver, TContext, TElement, TSelector>>;
|
|
54
|
-
root(selector: Selector<TSelector>): Promise<{
|
|
55
|
-
context: Context<TDriver, TContext, TElement, TSelector>;
|
|
56
|
-
shadow?: Element<TDriver, TContext, TElement, TSelector>;
|
|
57
|
-
selector: Selector<TSelector>;
|
|
58
|
-
}>;
|
|
59
55
|
element(elementOrSelector: TElement | Selector<TSelector>): Promise<Element<TDriver, TContext, TElement, TSelector>>;
|
|
60
56
|
elements(selectorOrElement: Selector<TSelector> | TElement): Promise<Element<TDriver, TContext, TElement, TSelector>[]>;
|
|
61
57
|
waitFor(selector: Selector<TSelector>, options?: WaitOptions): Promise<Element<TDriver, TContext, TElement, TSelector>>;
|
|
62
58
|
execute(script: ((args: any) => any) | string, arg?: any): Promise<any>;
|
|
59
|
+
executePoll(script: ((arg: any) => any) | string | {
|
|
60
|
+
main: ((arg: any) => any) | string;
|
|
61
|
+
poll: ((arg: any) => any) | string;
|
|
62
|
+
}, arg?: any | {
|
|
63
|
+
main: any;
|
|
64
|
+
poll: any;
|
|
65
|
+
executionTimeout?: number;
|
|
66
|
+
pollTimeout?: number;
|
|
67
|
+
}): Promise<any>;
|
|
63
68
|
getContextElement(): Promise<Element<TDriver, TContext, TElement, TSelector>>;
|
|
64
69
|
getScrollingElement(): Promise<Element<TDriver, TContext, TElement, TSelector>>;
|
|
65
70
|
setScrollingElement(scrollingElement: Element<TDriver, TContext, TElement, TSelector> | TElement | Selector<TSelector>): Promise<void>;
|
package/types/driver.d.ts
CHANGED
|
@@ -55,6 +55,9 @@ export declare class Driver<TDriver, TContext, TElement, TSelector> {
|
|
|
55
55
|
get isMobile(): boolean;
|
|
56
56
|
get isIOS(): boolean;
|
|
57
57
|
get isAndroid(): boolean;
|
|
58
|
+
get isMac(): boolean;
|
|
59
|
+
get isWindows(): boolean;
|
|
60
|
+
get isChromium(): boolean;
|
|
58
61
|
get isIE(): boolean;
|
|
59
62
|
get isEdgeLegacy(): boolean;
|
|
60
63
|
updateCurrentContext(context: Context<TDriver, TContext, TElement, TSelector>): void;
|
package/types/selector.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export declare type Selector<TSelector = never> = TSelector | string | {
|
|
2
2
|
selector: TSelector | string;
|
|
3
3
|
type?: string;
|
|
4
|
+
child?: Selector<TSelector>;
|
|
4
5
|
shadow?: Selector<TSelector>;
|
|
5
6
|
frame?: Selector<TSelector>;
|
|
7
|
+
fallback?: Selector<TSelector>;
|
|
6
8
|
};
|
|
7
9
|
export declare type CommonSelector = Selector;
|
package/types/spec-driver.d.ts
CHANGED
|
@@ -21,11 +21,14 @@ export declare type DriverInfo = {
|
|
|
21
21
|
navigationBarSize?: number;
|
|
22
22
|
isW3C?: boolean;
|
|
23
23
|
isChrome?: boolean;
|
|
24
|
+
isChromium?: boolean;
|
|
24
25
|
isEmulation?: boolean;
|
|
25
26
|
isMobile?: boolean;
|
|
26
27
|
isNative?: boolean;
|
|
27
28
|
isAndroid?: boolean;
|
|
28
29
|
isIOS?: boolean;
|
|
30
|
+
isMac?: boolean;
|
|
31
|
+
isWindows?: boolean;
|
|
29
32
|
isWebView?: boolean;
|
|
30
33
|
features?: {
|
|
31
34
|
shadowSelector?: boolean;
|
package/types/spec-utils.d.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { type SpecDriver } from './spec-driver';
|
|
2
2
|
import { type Selector } from './selector';
|
|
3
|
-
declare type CommonSelector<TSelector = never> =
|
|
4
|
-
selector: TSelector | string;
|
|
5
|
-
type?: string;
|
|
6
|
-
shadow?: CommonSelector<TSelector> | TSelector | string;
|
|
7
|
-
frame?: CommonSelector<TSelector> | TSelector | string;
|
|
8
|
-
};
|
|
3
|
+
declare type CommonSelector<TSelector = never> = Exclude<Selector<TSelector>, TSelector | string>;
|
|
9
4
|
export declare function isSimpleCommonSelector(selector: any): selector is CommonSelector;
|
|
10
5
|
export declare function isCommonSelector<TSelector>(spec: Pick<SpecDriver<unknown, unknown, unknown, TSelector>, 'isSelector'>, selector: any): selector is CommonSelector<TSelector>;
|
|
11
6
|
export declare function isSelector<TSelector>(spec: Pick<SpecDriver<unknown, unknown, unknown, TSelector>, 'isSelector'>, selector: any): selector is Selector<TSelector>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type DriverInfo } from './spec-driver';
|
|
2
|
+
declare type UserAgentData = {
|
|
3
|
+
brands: {
|
|
4
|
+
brand: string;
|
|
5
|
+
version: string;
|
|
6
|
+
}[];
|
|
7
|
+
platform: string;
|
|
8
|
+
platformVersion?: string;
|
|
9
|
+
model?: string;
|
|
10
|
+
mobile?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare function parseUserAgentData(userAgentData: UserAgentData): DriverInfo;
|
|
13
|
+
export {};
|