@applitools/driver 1.11.36 → 1.11.38
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/capabilities.js +34 -27
- package/dist/context.js +15 -9
- package/dist/driver.js +398 -432
- package/dist/element.js +68 -44
- package/dist/fake/mock-driver.js +9 -12
- package/dist/fake/spec-driver.js +1 -1
- package/dist/user-agent.js +51 -12
- package/package.json +6 -6
- package/types/capabilities.d.ts +3 -4
- package/types/driver.d.ts +35 -51
- package/types/fake/mock-driver.d.ts +1 -1
- package/types/fake/spec-driver.d.ts +1 -1
- package/types/spec-driver.d.ts +3 -39
- package/types/types.d.ts +61 -0
- package/types/user-agent.d.ts +2 -12
- package/dist/user-agent-data.js +0 -33
- package/types/user-agent-data.d.ts +0 -13
package/dist/driver.js
CHANGED
|
@@ -29,19 +29,17 @@ 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");
|
|
33
32
|
const capabilities_1 = require("./capabilities");
|
|
34
33
|
const specUtils = __importStar(require("./spec-utils"));
|
|
35
34
|
const utils = __importStar(require("@applitools/utils"));
|
|
36
35
|
const snippets = require('@applitools/snippets');
|
|
37
|
-
// eslint-disable-next-line
|
|
38
36
|
class Driver {
|
|
39
37
|
constructor(options) {
|
|
40
38
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
41
|
-
this._driverInfo = {};
|
|
42
39
|
this._state = {};
|
|
43
40
|
this._customConfig = {};
|
|
44
41
|
this._customConfig = (_a = options.customConfig) !== null && _a !== void 0 ? _a : {};
|
|
42
|
+
this._guid = utils.general.guid();
|
|
45
43
|
this._spec = options.spec;
|
|
46
44
|
this._logger = (_c = (_b = options.logger) === null || _b === void 0 ? void 0 : _b.extend({ label: 'driver' })) !== null && _c !== void 0 ? _c : (0, logger_1.makeLogger)({ label: 'driver' });
|
|
47
45
|
this._target = (_f = (_e = (_d = this._spec).transformDriver) === null || _e === void 0 ? void 0 : _e.call(_d, options.driver)) !== null && _f !== void 0 ? _f : options.driver;
|
|
@@ -59,279 +57,339 @@ class Driver {
|
|
|
59
57
|
get target() {
|
|
60
58
|
return this._target;
|
|
61
59
|
}
|
|
60
|
+
get guid() {
|
|
61
|
+
return this._guid;
|
|
62
|
+
}
|
|
62
63
|
get currentContext() {
|
|
63
64
|
return this._currentContext;
|
|
64
65
|
}
|
|
65
66
|
get mainContext() {
|
|
66
67
|
return this._mainContext;
|
|
67
68
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.features;
|
|
71
|
-
}
|
|
72
|
-
get deviceName() {
|
|
73
|
-
var _a;
|
|
74
|
-
return (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.deviceName;
|
|
75
|
-
}
|
|
76
|
-
get platformName() {
|
|
77
|
-
var _a;
|
|
78
|
-
return (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.platformName;
|
|
79
|
-
}
|
|
80
|
-
get platformVersion() {
|
|
81
|
-
var _a;
|
|
82
|
-
return (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.platformVersion;
|
|
83
|
-
}
|
|
84
|
-
get browserName() {
|
|
85
|
-
var _a;
|
|
86
|
-
return (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.browserName;
|
|
87
|
-
}
|
|
88
|
-
get browserVersion() {
|
|
89
|
-
var _a;
|
|
90
|
-
return (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.browserVersion;
|
|
91
|
-
}
|
|
92
|
-
get userAgent() {
|
|
93
|
-
var _a;
|
|
94
|
-
return (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.userAgent;
|
|
95
|
-
}
|
|
96
|
-
get orientation() {
|
|
97
|
-
return this._driverInfo.orientation;
|
|
98
|
-
}
|
|
99
|
-
get pixelRatio() {
|
|
100
|
-
var _a;
|
|
101
|
-
return (_a = this._driverInfo.pixelRatio) !== null && _a !== void 0 ? _a : 1;
|
|
102
|
-
}
|
|
103
|
-
get viewportScale() {
|
|
104
|
-
var _a;
|
|
105
|
-
return (_a = this._driverInfo.viewportScale) !== null && _a !== void 0 ? _a : 1;
|
|
106
|
-
}
|
|
107
|
-
get statusBarSize() {
|
|
108
|
-
var _a;
|
|
109
|
-
return (_a = this._driverInfo.statusBarSize) !== null && _a !== void 0 ? _a : (this.isNative ? 0 : undefined);
|
|
110
|
-
}
|
|
111
|
-
get navigationBarSize() {
|
|
112
|
-
var _a;
|
|
113
|
-
return (_a = this._driverInfo.navigationBarSize) !== null && _a !== void 0 ? _a : (this.isNative ? 0 : undefined);
|
|
69
|
+
updateCurrentContext(context) {
|
|
70
|
+
this._currentContext = context;
|
|
114
71
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
72
|
+
async refresh() {
|
|
73
|
+
this._driverInfo = undefined;
|
|
74
|
+
this._environment = undefined;
|
|
75
|
+
this._viewport = undefined;
|
|
76
|
+
this._features = undefined;
|
|
77
|
+
this._helper = undefined;
|
|
78
|
+
this._state = {};
|
|
79
|
+
const spec = this._spec;
|
|
80
|
+
let currentContext = this.currentContext.target;
|
|
81
|
+
let contextInfo;
|
|
82
|
+
try {
|
|
83
|
+
contextInfo = await getContextInfo(currentContext);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
const path = [];
|
|
89
|
+
if (spec.parentContext) {
|
|
90
|
+
while (!contextInfo.isRoot) {
|
|
91
|
+
currentContext = await spec.parentContext(currentContext);
|
|
92
|
+
const contextReference = await findContextReference(currentContext, contextInfo);
|
|
93
|
+
if (!contextReference)
|
|
94
|
+
throw new Error('Unable to find out the chain of frames');
|
|
95
|
+
path.unshift(contextReference);
|
|
96
|
+
contextInfo = await getContextInfo(currentContext);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
currentContext = await spec.mainContext(currentContext);
|
|
101
|
+
path.push(...(await findContextPath(currentContext, contextInfo)));
|
|
102
|
+
}
|
|
103
|
+
this._currentContext = this._mainContext;
|
|
104
|
+
await this.switchToChildContext(...path);
|
|
105
|
+
return this;
|
|
106
|
+
function transformSelector(selector) {
|
|
107
|
+
return specUtils.transformSelector(spec, selector, { isWeb: true });
|
|
108
|
+
}
|
|
109
|
+
async function getContextInfo(context) {
|
|
110
|
+
const [documentElement, selector, isRoot, isCORS] = await spec.executeScript(context, snippets.getContextInfo);
|
|
111
|
+
return { documentElement, selector, isRoot, isCORS };
|
|
112
|
+
}
|
|
113
|
+
async function getChildContextsInfo(context) {
|
|
114
|
+
const framesInfo = await spec.executeScript(context, snippets.getChildFramesInfo);
|
|
115
|
+
return framesInfo.map(([contextElement, isCORS]) => ({
|
|
116
|
+
contextElement,
|
|
117
|
+
isCORS,
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
async function isEqualElements(context, element1, element2) {
|
|
121
|
+
return spec.executeScript(context, snippets.isEqualElements, [element1, element2]).catch(() => false);
|
|
122
|
+
}
|
|
123
|
+
async function findContextReference(context, contextInfo) {
|
|
124
|
+
if (contextInfo.selector) {
|
|
125
|
+
const contextElement = await spec.findElement(context, transformSelector({ type: 'xpath', selector: contextInfo.selector }));
|
|
126
|
+
if (contextElement)
|
|
127
|
+
return contextElement;
|
|
128
|
+
}
|
|
129
|
+
for (const childContextInfo of await getChildContextsInfo(context)) {
|
|
130
|
+
if (childContextInfo.isCORS !== contextInfo.isCORS)
|
|
131
|
+
continue;
|
|
132
|
+
const childContext = await spec.childContext(context, childContextInfo.contextElement);
|
|
133
|
+
const contentDocument = await spec.findElement(childContext, transformSelector('html'));
|
|
134
|
+
const isWantedContext = await isEqualElements(childContext, contentDocument, contextInfo.documentElement);
|
|
135
|
+
await spec.parentContext(childContext);
|
|
136
|
+
if (isWantedContext)
|
|
137
|
+
return childContextInfo.contextElement;
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
async function findContextPath(context, contextInfo, contextPath = []) {
|
|
142
|
+
const contentDocument = await spec.findElement(context, transformSelector('html'));
|
|
143
|
+
if (await isEqualElements(context, contentDocument, contextInfo.documentElement)) {
|
|
144
|
+
return contextPath;
|
|
145
|
+
}
|
|
146
|
+
for (const childContextInfo of await getChildContextsInfo(context)) {
|
|
147
|
+
const childContext = await spec.childContext(context, childContextInfo.contextElement);
|
|
148
|
+
const possibleContextPath = [...contextPath, childContextInfo.contextElement];
|
|
149
|
+
const wantedContextPath = await findContextPath(childContext, contextInfo, possibleContextPath);
|
|
150
|
+
await spec.mainContext(context);
|
|
151
|
+
if (wantedContextPath)
|
|
152
|
+
return wantedContextPath;
|
|
153
|
+
for (const contextElement of contextPath) {
|
|
154
|
+
await spec.childContext(context, contextElement);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
118
158
|
}
|
|
119
|
-
|
|
159
|
+
async getDriverInfo({ force } = {}) {
|
|
120
160
|
var _a, _b, _c;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
get isEmulation() {
|
|
127
|
-
var _a, _b;
|
|
128
|
-
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isEmulation) !== null && _b !== void 0 ? _b : false;
|
|
129
|
-
}
|
|
130
|
-
get isMobile() {
|
|
131
|
-
var _a, _b;
|
|
132
|
-
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isMobile) !== null && _b !== void 0 ? _b : false;
|
|
133
|
-
}
|
|
134
|
-
get isIOS() {
|
|
135
|
-
var _a, _b;
|
|
136
|
-
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isIOS) !== null && _b !== void 0 ? _b : (!!this.platformName && /iOS/i.test(this.platformName));
|
|
137
|
-
}
|
|
138
|
-
get isAndroid() {
|
|
139
|
-
var _a, _b;
|
|
140
|
-
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isAndroid) !== null && _b !== void 0 ? _b : (!!this.platformName && /Android/i.test(this.platformName));
|
|
141
|
-
}
|
|
142
|
-
get isMac() {
|
|
143
|
-
var _a, _b;
|
|
144
|
-
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isMac) !== null && _b !== void 0 ? _b : (!!this.platformName && /mac\s?OS/i.test(this.platformName));
|
|
145
|
-
}
|
|
146
|
-
get isWindows() {
|
|
147
|
-
var _a, _b;
|
|
148
|
-
return (_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isWindows) !== null && _b !== void 0 ? _b : (!!this.platformName && /Windows/i.test(this.platformName));
|
|
149
|
-
}
|
|
150
|
-
get isChromium() {
|
|
151
|
-
var _a, _b;
|
|
152
|
-
return ((_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isChromium) !== null && _b !== void 0 ? _b : (!!this.browserName &&
|
|
153
|
-
(/(chrome)/i.test(this.browserName) || (/edge/i.test(this.browserName) && Number(this.browserVersion) > 44))));
|
|
154
|
-
}
|
|
155
|
-
get isIE() {
|
|
156
|
-
return !!this.browserName && /(internet explorer|ie)/i.test(this.browserName);
|
|
157
|
-
}
|
|
158
|
-
get isEdgeLegacy() {
|
|
159
|
-
return !!this.browserName && /edge/i.test(this.browserName) && Number(this.browserVersion) <= 44;
|
|
160
|
-
}
|
|
161
|
-
get isECClient() {
|
|
162
|
-
var _a;
|
|
163
|
-
return !!((_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.isECClient);
|
|
161
|
+
if (!this._driverInfo || force) {
|
|
162
|
+
this._driverInfo = (_c = (await ((_b = (_a = this._spec).getDriverInfo) === null || _b === void 0 ? void 0 : _b.call(_a, this.target)))) !== null && _c !== void 0 ? _c : {};
|
|
163
|
+
this._logger.log('Extracted driver info', this._driverInfo);
|
|
164
|
+
}
|
|
165
|
+
return this._driverInfo;
|
|
164
166
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
+
async getCapabilities({ force } = {}) {
|
|
168
|
+
var _a, _b, _c, _d, _e;
|
|
169
|
+
if (((_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.capabilities) === undefined || force) {
|
|
170
|
+
(_b = this._driverInfo) !== null && _b !== void 0 ? _b : (this._driverInfo = {});
|
|
171
|
+
this._driverInfo.capabilities = (_e = (await ((_d = (_c = this._spec).getCapabilities) === null || _d === void 0 ? void 0 : _d.call(_c, this.target)))) !== null && _e !== void 0 ? _e : null;
|
|
172
|
+
this._logger.log('Extracted driver capabilities', this._driverInfo.capabilities);
|
|
173
|
+
}
|
|
174
|
+
return this._driverInfo.capabilities;
|
|
167
175
|
}
|
|
168
|
-
|
|
169
|
-
var _a;
|
|
170
|
-
|
|
176
|
+
async getUserAgent({ force } = {}) {
|
|
177
|
+
var _a, _b, _c, _d, _e;
|
|
178
|
+
var _f;
|
|
179
|
+
if (((_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.userAgent) === undefined || force) {
|
|
180
|
+
(_b = this._driverInfo) !== null && _b !== void 0 ? _b : (this._driverInfo = {});
|
|
181
|
+
(_c = (_f = this._driverInfo).userAgent) !== null && _c !== void 0 ? _c : (_f.userAgent = (_d = (await this.currentContext.executePoll(snippets.getUserAgent))) !== null && _d !== void 0 ? _d : null);
|
|
182
|
+
this._logger.log('Extracted user agent', this._driverInfo.userAgent);
|
|
183
|
+
}
|
|
184
|
+
return (_e = this._driverInfo.userAgent) !== null && _e !== void 0 ? _e : null;
|
|
171
185
|
}
|
|
172
|
-
|
|
186
|
+
async getUserAgentLegacy({ force } = {}) {
|
|
173
187
|
var _a;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
(_l = (await this.getOrientation().catch(() => undefined))) !== null && _l !== void 0 ? _l : this._driverInfo.orientation;
|
|
193
|
-
const world = await this.getCurrentWorld();
|
|
194
|
-
if (world) {
|
|
195
|
-
const [home] = (await this.getWorlds());
|
|
196
|
-
this._driverInfo.isWebView = world !== home;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (this.isWeb) {
|
|
200
|
-
const browserInfo = await this.currentContext.executePoll(snippets.getBrowserInfo);
|
|
201
|
-
(_m = (_20 = this._driverInfo).userAgent) !== null && _m !== void 0 ? _m : (_20.userAgent = browserInfo.userAgent);
|
|
202
|
-
(_o = (_21 = this._driverInfo).pixelRatio) !== null && _o !== void 0 ? _o : (_21.pixelRatio = browserInfo.pixelRatio);
|
|
203
|
-
(_p = (_22 = this._driverInfo).viewportScale) !== null && _p !== void 0 ? _p : (_22.viewportScale = browserInfo.viewportScale);
|
|
204
|
-
if (browserInfo.userAgentData && this.isChromium) {
|
|
205
|
-
if (this.isWindows && Number.parseInt(this.browserVersion) >= 107) {
|
|
206
|
-
this._driverInfo.platformVersion = (_q = browserInfo.platformVersion) !== null && _q !== void 0 ? _q : this._driverInfo.platformVersion;
|
|
207
|
-
}
|
|
208
|
-
else if (this.isMac && Number.parseInt(this.browserVersion) >= 90) {
|
|
209
|
-
this._driverInfo.platformVersion = (_r = browserInfo.platformVersion) !== null && _r !== void 0 ? _r : this._driverInfo.platformVersion;
|
|
188
|
+
const userAgent = await this.getUserAgent({ force });
|
|
189
|
+
return utils.types.isObject(userAgent) ? (_a = userAgent === null || userAgent === void 0 ? void 0 : userAgent.legacy) !== null && _a !== void 0 ? _a : null : userAgent;
|
|
190
|
+
}
|
|
191
|
+
async getEnvironment() {
|
|
192
|
+
var _a, _b, _c, _d;
|
|
193
|
+
var _e;
|
|
194
|
+
if (!this._environment) {
|
|
195
|
+
const driverInfo = await this.getDriverInfo();
|
|
196
|
+
this._environment = { ...driverInfo.environment };
|
|
197
|
+
const capabilities = await this.getCapabilities();
|
|
198
|
+
const capabilitiesEnvironment = capabilities ? (0, capabilities_1.extractCapabilitiesEnvironment)(capabilities) : null;
|
|
199
|
+
this._logger.log('Extracted capabilities environment', capabilitiesEnvironment);
|
|
200
|
+
this._environment = { ...this._environment, ...capabilitiesEnvironment };
|
|
201
|
+
if (this._environment.isMobile && !this._environment.browserName) {
|
|
202
|
+
const world = await this.getCurrentWorld();
|
|
203
|
+
if (!!(world === null || world === void 0 ? void 0 : world.includes('WEBVIEW'))) {
|
|
204
|
+
this._environment.isNative = true;
|
|
205
|
+
this._environment.isWeb = true;
|
|
210
206
|
}
|
|
211
207
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
this.
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
this._driverInfo.platformVersion =
|
|
229
|
-
(_5 = (_4 = userAgentDataInfo === null || userAgentDataInfo === void 0 ? void 0 : userAgentDataInfo.platformVersion) !== null && _4 !== void 0 ? _4 : userAgentInfo.platformVersion) !== null && _5 !== void 0 ? _5 : this._driverInfo.platformVersion;
|
|
230
|
-
}
|
|
208
|
+
(_a = (_e = this._environment).isWeb) !== null && _a !== void 0 ? _a : (_e.isWeb = !this._environment.isNative);
|
|
209
|
+
if (this._environment.isWeb) {
|
|
210
|
+
const userAgent = await this.getUserAgent();
|
|
211
|
+
const userAgentEnvironment = userAgent ? (0, user_agent_1.extractUserAgentEnvironment)(userAgent) : null;
|
|
212
|
+
this._logger.log('Extracted user agent environment', userAgentEnvironment);
|
|
213
|
+
this._environment = {
|
|
214
|
+
...this._environment,
|
|
215
|
+
...userAgentEnvironment,
|
|
216
|
+
// NOTE: not really necessary, but some user agents for mobile devices (iPads) may return a wrong platform info
|
|
217
|
+
...(this._environment.isMobile
|
|
218
|
+
? {
|
|
219
|
+
platformName: (_b = this._environment.platformName) !== null && _b !== void 0 ? _b : userAgentEnvironment === null || userAgentEnvironment === void 0 ? void 0 : userAgentEnvironment.platformName,
|
|
220
|
+
platformVersion: (_c = this._environment.platformVersion) !== null && _c !== void 0 ? _c : userAgentEnvironment === null || userAgentEnvironment === void 0 ? void 0 : userAgentEnvironment.platformVersion,
|
|
221
|
+
}
|
|
222
|
+
: {}),
|
|
223
|
+
};
|
|
231
224
|
}
|
|
232
|
-
if (
|
|
233
|
-
this.
|
|
234
|
-
this.
|
|
225
|
+
if (this._environment.browserName) {
|
|
226
|
+
this._environment.isIE = /(internet explorer|ie)/i.test(this._environment.browserName);
|
|
227
|
+
this._environment.isEdgeLegacy =
|
|
228
|
+
/edge/i.test(this._environment.browserName) && Number(this._environment.browserVersion) <= 44;
|
|
229
|
+
this._environment.isEdge =
|
|
230
|
+
/edge/i.test(this._environment.browserName) && Number(this._environment.browserVersion) > 44;
|
|
231
|
+
this._environment.isChrome = /chrome/i.test(this._environment.browserName);
|
|
232
|
+
this._environment.isChromium = this._environment.isChrome || this._environment.isEdge;
|
|
235
233
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// this value always excludes the height of the navigation bar, and sometimes it also excludes the height of the status bar
|
|
242
|
-
let windowSize = await this._spec.getWindowSize(this.target);
|
|
243
|
-
(_8 = (_29 = this._driverInfo).displaySize) !== null && _8 !== void 0 ? _8 : (_29.displaySize = windowSize);
|
|
244
|
-
if (((_9 = this.orientation) === null || _9 === void 0 ? void 0 : _9.startsWith('landscape')) &&
|
|
245
|
-
this._driverInfo.displaySize.height > this._driverInfo.displaySize.width) {
|
|
246
|
-
this._driverInfo.displaySize = {
|
|
247
|
-
width: this._driverInfo.displaySize.height,
|
|
248
|
-
height: this._driverInfo.displaySize.width,
|
|
249
|
-
};
|
|
234
|
+
if (this._environment.platformName) {
|
|
235
|
+
this._environment.isWindows = /Windows/i.test(this._environment.platformName);
|
|
236
|
+
this._environment.isMac = /mac\s?OS/i.test(this._environment.platformName);
|
|
237
|
+
this._environment.isAndroid = /Android/i.test(this._environment.platformName);
|
|
238
|
+
this._environment.isIOS = /iOS/i.test(this._environment.platformName);
|
|
250
239
|
}
|
|
251
|
-
if (this.
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
240
|
+
if (!this._environment.isMobile &&
|
|
241
|
+
this._environment.isWeb &&
|
|
242
|
+
(this._environment.isAndroid || this._environment.isIOS)) {
|
|
243
|
+
this._environment.isMobile = true;
|
|
244
|
+
this._environment.isEmulation = this._environment.isChromium;
|
|
245
|
+
}
|
|
246
|
+
this._environment.isEC =
|
|
247
|
+
this._environment.isECClient || /exec-wus.applitools.com/.test((_d = (await this.getDriverUrl())) !== null && _d !== void 0 ? _d : '');
|
|
248
|
+
this._logger.log('Extracted environment', this._environment);
|
|
249
|
+
}
|
|
250
|
+
return this._environment;
|
|
251
|
+
}
|
|
252
|
+
async getViewport() {
|
|
253
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
254
|
+
var _t, _u, _v, _w, _x, _y, _z, _0, _1;
|
|
255
|
+
if (!this._viewport) {
|
|
256
|
+
const environment = await this.getEnvironment();
|
|
257
|
+
const driverInfo = await this.getDriverInfo();
|
|
258
|
+
this._viewport = { ...driverInfo.viewport };
|
|
259
|
+
if (environment.isMobile) {
|
|
260
|
+
if (!this._viewport.orientation) {
|
|
261
|
+
const orientation = await this.getOrientation();
|
|
262
|
+
if (orientation)
|
|
263
|
+
this._viewport.orientation = orientation;
|
|
262
264
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
265
|
+
}
|
|
266
|
+
if (environment.isNative) {
|
|
267
|
+
const capabilities = await this.getCapabilities();
|
|
268
|
+
const capabilitiesViewport = capabilities ? (0, capabilities_1.extractCapabilitiesViewport)(capabilities) : null;
|
|
269
|
+
this._logger.log('Extracted capabilities viewport', capabilitiesViewport);
|
|
270
|
+
this._viewport = { ...capabilitiesViewport, ...this._viewport };
|
|
271
|
+
(_a = (_t = this._viewport).pixelRatio) !== null && _a !== void 0 ? _a : (_t.pixelRatio = 1);
|
|
272
|
+
// this value always excludes the height of the navigation bar, and sometimes it also excludes the height of the status bar
|
|
273
|
+
let windowSize = await this._spec.getWindowSize(this.target);
|
|
274
|
+
(_b = (_u = this._viewport).displaySize) !== null && _b !== void 0 ? _b : (_u.displaySize = windowSize);
|
|
275
|
+
if (((_c = this._viewport.orientation) === null || _c === void 0 ? void 0 : _c.startsWith('landscape')) &&
|
|
276
|
+
this._viewport.displaySize.height > this._viewport.displaySize.width) {
|
|
277
|
+
this._viewport.displaySize = utils.geometry.rotate(this._viewport.displaySize, 90);
|
|
278
|
+
}
|
|
279
|
+
if (environment.isAndroid) {
|
|
280
|
+
// bar sizes could be extracted only on android
|
|
281
|
+
const { statusBar, navigationBar } = (_f = (await ((_e = (_d = this._spec).getSystemBars) === null || _e === void 0 ? void 0 : _e.call(_d, this.target).catch(() => undefined)))) !== null && _f !== void 0 ? _f : {};
|
|
282
|
+
if (statusBar === null || statusBar === void 0 ? void 0 : statusBar.visible) {
|
|
283
|
+
this._logger.log('Driver status bar', statusBar);
|
|
284
|
+
const statusBarSize = statusBar.height;
|
|
285
|
+
// when status bar is overlapping content on android it returns status bar height equal to display height
|
|
286
|
+
if (statusBarSize < this._viewport.displaySize.height) {
|
|
287
|
+
this._viewport.statusBarSize = Math.max((_g = this._viewport.statusBarSize) !== null && _g !== void 0 ? _g : 0, statusBarSize);
|
|
288
|
+
}
|
|
274
289
|
}
|
|
275
|
-
|
|
276
|
-
this.
|
|
290
|
+
if (navigationBar === null || navigationBar === void 0 ? void 0 : navigationBar.visible) {
|
|
291
|
+
this._logger.log('Driver navigation size', navigationBar);
|
|
292
|
+
// if navigation bar is placed on the right side is screen the the orientation is landscape-secondary
|
|
293
|
+
if (navigationBar.x > 0)
|
|
294
|
+
this._viewport.orientation = 'landscape-secondary';
|
|
295
|
+
// navigation bar size could be its height or width depending on screen orientation
|
|
296
|
+
const navigationBarSize = navigationBar[((_h = this._viewport.orientation) === null || _h === void 0 ? void 0 : _h.startsWith('landscape')) ? 'width' : 'height'];
|
|
297
|
+
// when navigation bar is invisible on android it returns navigation bar size equal to display size
|
|
298
|
+
if (navigationBarSize <
|
|
299
|
+
this._viewport.displaySize[((_j = this._viewport.orientation) === null || _j === void 0 ? void 0 : _j.startsWith('landscape')) ? 'width' : 'height']) {
|
|
300
|
+
this._viewport.navigationBarSize = Math.max((_k = this._viewport.navigationBarSize) !== null && _k !== void 0 ? _k : 0, navigationBarSize);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
this._viewport.navigationBarSize = 0;
|
|
304
|
+
}
|
|
277
305
|
}
|
|
306
|
+
// bar sizes have to be scaled on android
|
|
307
|
+
(_v = this._viewport).statusBarSize && (_v.statusBarSize = this._viewport.statusBarSize / this._viewport.pixelRatio);
|
|
308
|
+
(_w = this._viewport).navigationBarSize && (_w.navigationBarSize = this._viewport.navigationBarSize / this._viewport.pixelRatio);
|
|
309
|
+
windowSize = utils.geometry.scale(windowSize, 1 / this._viewport.pixelRatio);
|
|
310
|
+
(_x = this._viewport).displaySize && (_x.displaySize = utils.geometry.scale(this._viewport.displaySize, 1 / this._viewport.pixelRatio));
|
|
278
311
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
windowSize = utils.geometry.scale(windowSize, 1 / this.pixelRatio);
|
|
283
|
-
(_32 = this._driverInfo).displaySize && (_32.displaySize = utils.geometry.scale(this._driverInfo.displaySize, 1 / this.pixelRatio));
|
|
284
|
-
}
|
|
285
|
-
if (this.isIOS) {
|
|
286
|
-
if ((_16 = this.orientation) === null || _16 === void 0 ? void 0 : _16.startsWith('landscape'))
|
|
287
|
-
this._driverInfo.statusBarSize = 0;
|
|
288
|
-
}
|
|
289
|
-
// calculate viewport location
|
|
290
|
-
(_17 = (_33 = this._driverInfo).viewportLocation) !== null && _17 !== void 0 ? _17 : (_33.viewportLocation = {
|
|
291
|
-
x: this.orientation === 'landscape' ? this.navigationBarSize : 0,
|
|
292
|
-
y: this.statusBarSize,
|
|
293
|
-
});
|
|
294
|
-
// calculate viewport size
|
|
295
|
-
if (!this._driverInfo.viewportSize) {
|
|
296
|
-
this._driverInfo.viewportSize = { ...this._driverInfo.displaySize };
|
|
297
|
-
this._driverInfo.viewportSize.height -= this.statusBarSize;
|
|
298
|
-
if (this.isAndroid) {
|
|
299
|
-
this._driverInfo.viewportSize[((_18 = this.orientation) === null || _18 === void 0 ? void 0 : _18.startsWith('landscape')) ? 'width' : 'height'] -=
|
|
300
|
-
this.navigationBarSize;
|
|
312
|
+
if (environment.isIOS) {
|
|
313
|
+
if ((_l = this._viewport.orientation) === null || _l === void 0 ? void 0 : _l.startsWith('landscape'))
|
|
314
|
+
this._viewport.statusBarSize = 0;
|
|
301
315
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
type: '-ios class chain',
|
|
308
|
-
selector: '**/XCUIElementTypeNavigationBar',
|
|
316
|
+
(_m = (_y = this._viewport).statusBarSize) !== null && _m !== void 0 ? _m : (_y.statusBarSize = 0);
|
|
317
|
+
// calculate viewport location
|
|
318
|
+
(_o = (_z = this._viewport).viewportLocation) !== null && _o !== void 0 ? _o : (_z.viewportLocation = {
|
|
319
|
+
x: this._viewport.orientation === 'landscape' ? (_p = this._viewport.navigationBarSize) !== null && _p !== void 0 ? _p : 0 : 0,
|
|
320
|
+
y: this._viewport.statusBarSize,
|
|
309
321
|
});
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
this.
|
|
314
|
-
|
|
322
|
+
// calculate viewport size
|
|
323
|
+
if (!this._viewport.viewportSize) {
|
|
324
|
+
this._viewport.viewportSize = { ...this._viewport.displaySize };
|
|
325
|
+
this._viewport.viewportSize.height -= this._viewport.statusBarSize;
|
|
326
|
+
if (environment.isAndroid) {
|
|
327
|
+
this._viewport.viewportSize[((_q = this._viewport.orientation) === null || _q === void 0 ? void 0 : _q.startsWith('landscape')) ? 'width' : 'height'] -=
|
|
328
|
+
this._viewport.navigationBarSize;
|
|
329
|
+
}
|
|
315
330
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
331
|
+
// calculate safe area
|
|
332
|
+
if (!environment.isWeb && environment.isIOS && !this._viewport.safeArea) {
|
|
333
|
+
this._viewport.safeArea = { x: 0, y: 0, ...this._viewport.displaySize };
|
|
334
|
+
const topElement = await this.element({
|
|
335
|
+
type: '-ios class chain',
|
|
336
|
+
selector: '**/XCUIElementTypeNavigationBar',
|
|
337
|
+
});
|
|
338
|
+
if (topElement) {
|
|
339
|
+
const topRegion = await this._spec.getElementRegion(this.target, topElement.target);
|
|
340
|
+
const topOffset = topRegion.y + topRegion.height;
|
|
341
|
+
this._viewport.safeArea.y = topOffset;
|
|
342
|
+
this._viewport.safeArea.height -= topOffset;
|
|
343
|
+
}
|
|
344
|
+
const bottomElement = await this.element({
|
|
345
|
+
type: '-ios class chain',
|
|
346
|
+
selector: '**/XCUIElementTypeTabBar',
|
|
347
|
+
});
|
|
348
|
+
if (bottomElement) {
|
|
349
|
+
const bottomRegion = await this._spec.getElementRegion(this.target, bottomElement.target);
|
|
350
|
+
const bottomOffset = bottomRegion.height;
|
|
351
|
+
this._viewport.safeArea.height -= bottomOffset;
|
|
352
|
+
}
|
|
324
353
|
}
|
|
325
354
|
}
|
|
355
|
+
if (environment.isWeb) {
|
|
356
|
+
const browserViewport = await this.execute(snippets.getViewport);
|
|
357
|
+
this._viewport = { ...browserViewport, ...this._viewport };
|
|
358
|
+
}
|
|
359
|
+
(_r = (_0 = this._viewport).pixelRatio) !== null && _r !== void 0 ? _r : (_0.pixelRatio = 1);
|
|
360
|
+
(_s = (_1 = this._viewport).viewportScale) !== null && _s !== void 0 ? _s : (_1.viewportScale = 1);
|
|
361
|
+
this._logger.log('Extracted viewport', this._viewport);
|
|
326
362
|
}
|
|
327
|
-
|
|
328
|
-
|
|
363
|
+
return this._viewport;
|
|
364
|
+
}
|
|
365
|
+
async getFeatures() {
|
|
366
|
+
var _a;
|
|
367
|
+
var _b;
|
|
368
|
+
if (!this._features) {
|
|
369
|
+
const driverInfo = await this.getDriverInfo();
|
|
370
|
+
this._features = { ...driverInfo.features };
|
|
371
|
+
const environment = await this.getEnvironment();
|
|
372
|
+
(_a = (_b = this._features).allCookies) !== null && _a !== void 0 ? _a : (_b.allCookies = environment.isChromium || !environment.isMobile);
|
|
373
|
+
this._logger.log('Extracted driver features', this._features);
|
|
374
|
+
}
|
|
375
|
+
return this._features;
|
|
376
|
+
}
|
|
377
|
+
async getSessionId() {
|
|
378
|
+
var _a;
|
|
379
|
+
const driverInfo = await this.getDriverInfo();
|
|
380
|
+
return (_a = driverInfo.sessionId) !== null && _a !== void 0 ? _a : null;
|
|
381
|
+
}
|
|
382
|
+
async getDriverUrl() {
|
|
383
|
+
var _a;
|
|
384
|
+
const driverInfo = await this.getDriverInfo();
|
|
385
|
+
return (_a = driverInfo.remoteHostname) !== null && _a !== void 0 ? _a : null;
|
|
329
386
|
}
|
|
330
387
|
async getHelper() {
|
|
331
388
|
var _a, _b, _c;
|
|
332
389
|
if (this._helper === undefined) {
|
|
333
|
-
|
|
334
|
-
this.
|
|
390
|
+
const environment = await this.getEnvironment();
|
|
391
|
+
this._logger.log(`Extracting helper for ${environment.isIOS ? 'ios' : 'android'}`);
|
|
392
|
+
this._helper = environment.isIOS
|
|
335
393
|
? await helper_ios_1.HelperIOS.make({ spec: this._spec, driver: this, logger: this._logger })
|
|
336
394
|
: await helper_android_1.HelperAndroid.make({ spec: this._spec, driver: this, logger: this._logger });
|
|
337
395
|
this._logger.log(`Extracted helper of type ${(_a = this._helper) === null || _a === void 0 ? void 0 : _a.name}`);
|
|
@@ -342,12 +400,15 @@ class Driver {
|
|
|
342
400
|
async extractBrokerUrl() {
|
|
343
401
|
var _a;
|
|
344
402
|
var _b;
|
|
345
|
-
|
|
403
|
+
const environment = await this.getEnvironment();
|
|
404
|
+
if (!environment.isNative)
|
|
346
405
|
return null;
|
|
347
406
|
this._logger.log('Broker url extraction is started');
|
|
348
|
-
(_a = (_b = this._state).nmlElement) !== null && _a !== void 0 ? _a : (_b.nmlElement = await this.
|
|
349
|
-
if (!this._state.nmlElement)
|
|
407
|
+
(_a = (_b = this._state).nmlElement) !== null && _a !== void 0 ? _a : (_b.nmlElement = await this.waitFor({ type: 'accessibility id', selector: 'Applitools_View' }, { timeout: 10000 }));
|
|
408
|
+
if (!this._state.nmlElement) {
|
|
409
|
+
this._logger.log('Broker url extraction is failed due to absence of nml element');
|
|
350
410
|
return null;
|
|
411
|
+
}
|
|
351
412
|
try {
|
|
352
413
|
let result;
|
|
353
414
|
do {
|
|
@@ -367,53 +428,15 @@ class Driver {
|
|
|
367
428
|
return this.extractBrokerUrl();
|
|
368
429
|
}
|
|
369
430
|
}
|
|
370
|
-
|
|
371
|
-
//
|
|
372
|
-
// Since "context" is an overloaded term from frames, we have decided to use
|
|
373
|
-
// the concept of a "world" when switching between mobile app contexts (e.g., native and webview(s))
|
|
374
|
-
//
|
|
375
|
-
// Notes:
|
|
376
|
-
// - two new functions need to be added to a spec driver for this to work (`getCurrentWorld` and `switchWorld`)
|
|
377
|
-
// - you can see a reference implementation of this in spec-driver-webdriverio
|
|
378
|
-
// - if a world id is provided it will be used for switching
|
|
379
|
-
// - if a world id is not provided, the first non-native world will be used
|
|
380
|
-
// (regardless of which world the driver is currently switched into)
|
|
381
|
-
// - before switching, the current world context is stored so it can switched back to later
|
|
382
|
-
// (with the `restoreState` option)
|
|
383
|
-
// - the native app world can be switched to (with the `goHome` option)
|
|
384
|
-
async switchWorld(options) {
|
|
431
|
+
async getSessionMetadata() {
|
|
385
432
|
var _a, _b;
|
|
386
|
-
if ((options === null || options === void 0 ? void 0 : options.restoreState) && !this._state.world)
|
|
387
|
-
return;
|
|
388
|
-
if (!this._spec.getCurrentWorld || !this._spec.switchWorld) {
|
|
389
|
-
this._logger.warn('world switching not implemented in the spec driver, skipping');
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
this._logger.log('switchWorld called with', options ? options : 'no options');
|
|
393
|
-
const current = (await this.getCurrentWorld());
|
|
394
|
-
if (!this._state.world) {
|
|
395
|
-
this._logger.log('storing current world id for future restoration', current);
|
|
396
|
-
this._state.world = current;
|
|
397
|
-
}
|
|
398
|
-
let world;
|
|
399
|
-
if (options === null || options === void 0 ? void 0 : options.id)
|
|
400
|
-
world = options.id;
|
|
401
|
-
else if (options === null || options === void 0 ? void 0 : options.restoreState)
|
|
402
|
-
world = this._state.world;
|
|
403
|
-
else {
|
|
404
|
-
const [home, next] = (await this.getWorlds());
|
|
405
|
-
if (options === null || options === void 0 ? void 0 : options.goHome)
|
|
406
|
-
world = home;
|
|
407
|
-
else
|
|
408
|
-
world = next;
|
|
409
|
-
}
|
|
410
|
-
this._logger.log('switching world with', world);
|
|
411
433
|
try {
|
|
412
|
-
await ((_b = (_a = this._spec).
|
|
413
|
-
|
|
434
|
+
const metadata = await ((_b = (_a = this._spec).getSessionMetadata) === null || _b === void 0 ? void 0 : _b.call(_a, this.target));
|
|
435
|
+
this._logger.log('Extracted session metadata', metadata);
|
|
436
|
+
return metadata;
|
|
414
437
|
}
|
|
415
|
-
catch (
|
|
416
|
-
|
|
438
|
+
catch (err) {
|
|
439
|
+
this._logger.warn('Failed to extract session metadata due to the error', err);
|
|
417
440
|
}
|
|
418
441
|
}
|
|
419
442
|
async getWorlds() {
|
|
@@ -422,7 +445,7 @@ class Driver {
|
|
|
422
445
|
this._logger.log('Extracting worlds');
|
|
423
446
|
try {
|
|
424
447
|
let worlds = [];
|
|
425
|
-
for (let attempt = 0; worlds.length <= 1 && attempt <
|
|
448
|
+
for (let attempt = 0; worlds.length <= 1 && attempt < 3; ++attempt) {
|
|
426
449
|
if (attempt > 0)
|
|
427
450
|
await utils.general.sleep(500);
|
|
428
451
|
worlds = await this._spec.getWorlds(this.target);
|
|
@@ -436,12 +459,11 @@ class Driver {
|
|
|
436
459
|
}
|
|
437
460
|
}
|
|
438
461
|
async getCurrentWorld() {
|
|
439
|
-
var _a, _b;
|
|
440
462
|
if (!this._spec.getCurrentWorld)
|
|
441
463
|
return null;
|
|
442
464
|
try {
|
|
443
465
|
this._logger.log('Extracting current world');
|
|
444
|
-
const current = await
|
|
466
|
+
const current = await this._spec.getCurrentWorld(this.target);
|
|
445
467
|
this._logger.log('Current world was extracted', current);
|
|
446
468
|
return current;
|
|
447
469
|
}
|
|
@@ -450,85 +472,20 @@ class Driver {
|
|
|
450
472
|
return null;
|
|
451
473
|
}
|
|
452
474
|
}
|
|
453
|
-
async
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
if (this.isNative)
|
|
460
|
-
return this.currentContext;
|
|
461
|
-
const spec = this._spec;
|
|
462
|
-
let currentContext = this.currentContext.target;
|
|
463
|
-
let contextInfo = await getContextInfo(currentContext);
|
|
464
|
-
const path = [];
|
|
465
|
-
if (spec.parentContext) {
|
|
466
|
-
while (!contextInfo.isRoot) {
|
|
467
|
-
currentContext = await spec.parentContext(currentContext);
|
|
468
|
-
const contextReference = await findContextReference(currentContext, contextInfo);
|
|
469
|
-
if (!contextReference)
|
|
470
|
-
throw new Error('Unable to find out the chain of frames');
|
|
471
|
-
path.unshift(contextReference);
|
|
472
|
-
contextInfo = await getContextInfo(currentContext);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
else {
|
|
476
|
-
currentContext = await spec.mainContext(currentContext);
|
|
477
|
-
path.push(...(await findContextPath(currentContext, contextInfo)));
|
|
478
|
-
}
|
|
479
|
-
this._currentContext = this._mainContext;
|
|
480
|
-
return this.switchToChildContext(...path);
|
|
481
|
-
function transformSelector(selector) {
|
|
482
|
-
return specUtils.transformSelector(spec, selector, { isWeb: true });
|
|
483
|
-
}
|
|
484
|
-
async function getContextInfo(context) {
|
|
485
|
-
const [documentElement, selector, isRoot, isCORS] = await spec.executeScript(context, snippets.getContextInfo);
|
|
486
|
-
return { documentElement, selector, isRoot, isCORS };
|
|
487
|
-
}
|
|
488
|
-
async function getChildContextsInfo(context) {
|
|
489
|
-
const framesInfo = await spec.executeScript(context, snippets.getChildFramesInfo);
|
|
490
|
-
return framesInfo.map(([contextElement, isCORS]) => ({
|
|
491
|
-
contextElement,
|
|
492
|
-
isCORS,
|
|
493
|
-
}));
|
|
494
|
-
}
|
|
495
|
-
async function isEqualElements(context, element1, element2) {
|
|
496
|
-
return spec.executeScript(context, snippets.isEqualElements, [element1, element2]).catch(() => false);
|
|
475
|
+
async switchWorld(name) {
|
|
476
|
+
name !== null && name !== void 0 ? name : (name = 'NATIVE_APP');
|
|
477
|
+
this._logger.log('Switching world to', name);
|
|
478
|
+
if (!this._spec.switchWorld) {
|
|
479
|
+
this._logger.error('Unable to switch world due to missed implementation');
|
|
480
|
+
throw new Error('Unable to switch world due to missed implementation');
|
|
497
481
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
if (contextElement)
|
|
502
|
-
return contextElement;
|
|
503
|
-
}
|
|
504
|
-
for (const childContextInfo of await getChildContextsInfo(context)) {
|
|
505
|
-
if (childContextInfo.isCORS !== contextInfo.isCORS)
|
|
506
|
-
continue;
|
|
507
|
-
const childContext = await spec.childContext(context, childContextInfo.contextElement);
|
|
508
|
-
const contentDocument = await spec.findElement(childContext, transformSelector('html'));
|
|
509
|
-
const isWantedContext = await isEqualElements(childContext, contentDocument, contextInfo.documentElement);
|
|
510
|
-
await spec.parentContext(childContext);
|
|
511
|
-
if (isWantedContext)
|
|
512
|
-
return childContextInfo.contextElement;
|
|
513
|
-
}
|
|
514
|
-
return null;
|
|
482
|
+
try {
|
|
483
|
+
await this._spec.switchWorld(this.target, name);
|
|
484
|
+
this.refresh();
|
|
515
485
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
return contextPath;
|
|
520
|
-
}
|
|
521
|
-
for (const childContextInfo of await getChildContextsInfo(context)) {
|
|
522
|
-
const childContext = await spec.childContext(context, childContextInfo.contextElement);
|
|
523
|
-
const possibleContextPath = [...contextPath, childContextInfo.contextElement];
|
|
524
|
-
const wantedContextPath = await findContextPath(childContext, contextInfo, possibleContextPath);
|
|
525
|
-
await spec.mainContext(context);
|
|
526
|
-
if (wantedContextPath)
|
|
527
|
-
return wantedContextPath;
|
|
528
|
-
for (const contextElement of contextPath) {
|
|
529
|
-
await spec.childContext(context, contextElement);
|
|
530
|
-
}
|
|
531
|
-
}
|
|
486
|
+
catch (error) {
|
|
487
|
+
this._logger.error('Unable to switch world due to the error', error);
|
|
488
|
+
throw new Error(`Unable to switch world, the original error was: ${error.message}`);
|
|
532
489
|
}
|
|
533
490
|
}
|
|
534
491
|
async switchTo(context) {
|
|
@@ -578,14 +535,16 @@ class Driver {
|
|
|
578
535
|
}
|
|
579
536
|
}
|
|
580
537
|
async switchToMainContext() {
|
|
581
|
-
|
|
538
|
+
const environment = await this.getEnvironment();
|
|
539
|
+
if (environment.isNative)
|
|
582
540
|
throw new Error('Contexts are supported only for web drivers');
|
|
583
541
|
this._logger.log('Switching to the main context');
|
|
584
542
|
await this._spec.mainContext(this.currentContext.target);
|
|
585
543
|
return (this._currentContext = this._mainContext);
|
|
586
544
|
}
|
|
587
545
|
async switchToParentContext(elevation = 1) {
|
|
588
|
-
|
|
546
|
+
const environment = await this.getEnvironment();
|
|
547
|
+
if (environment.isNative)
|
|
589
548
|
throw new Error('Contexts are supported only for web drivers');
|
|
590
549
|
this._logger.log('Switching to a parent context with elevation:', elevation);
|
|
591
550
|
if (this.currentContext.path.length <= elevation) {
|
|
@@ -609,7 +568,8 @@ class Driver {
|
|
|
609
568
|
return this.currentContext;
|
|
610
569
|
}
|
|
611
570
|
async switchToChildContext(...references) {
|
|
612
|
-
|
|
571
|
+
const environment = await this.getEnvironment();
|
|
572
|
+
if (environment.isNative)
|
|
613
573
|
throw new Error('Contexts are supported only for web drivers');
|
|
614
574
|
this._logger.log('Switching to a child context with depth:', references.length);
|
|
615
575
|
for (const reference of references) {
|
|
@@ -621,19 +581,19 @@ class Driver {
|
|
|
621
581
|
return this.currentContext;
|
|
622
582
|
}
|
|
623
583
|
async normalizeRegion(region) {
|
|
624
|
-
|
|
584
|
+
const environment = await this.getEnvironment();
|
|
585
|
+
if (environment.isWeb)
|
|
625
586
|
return region;
|
|
587
|
+
const viewport = await this.getViewport();
|
|
626
588
|
let normalizedRegion = region;
|
|
627
|
-
if (
|
|
628
|
-
normalizedRegion = utils.geometry.scale(normalizedRegion, 1 /
|
|
589
|
+
if (environment.isAndroid) {
|
|
590
|
+
normalizedRegion = utils.geometry.scale(normalizedRegion, 1 / viewport.pixelRatio);
|
|
629
591
|
}
|
|
630
|
-
if (
|
|
631
|
-
|
|
632
|
-
utils.geometry.isIntersected(normalizedRegion, this._driverInfo.safeArea)) {
|
|
633
|
-
normalizedRegion = utils.geometry.intersect(normalizedRegion, this._driverInfo.safeArea);
|
|
592
|
+
if (environment.isIOS && viewport.safeArea && utils.geometry.isIntersected(normalizedRegion, viewport.safeArea)) {
|
|
593
|
+
normalizedRegion = utils.geometry.intersect(normalizedRegion, viewport.safeArea);
|
|
634
594
|
}
|
|
635
|
-
if (
|
|
636
|
-
normalizedRegion = utils.geometry.offsetNegative(normalizedRegion,
|
|
595
|
+
if (viewport.viewportLocation) {
|
|
596
|
+
normalizedRegion = utils.geometry.offsetNegative(normalizedRegion, viewport.viewportLocation);
|
|
637
597
|
}
|
|
638
598
|
if (normalizedRegion.y < 0) {
|
|
639
599
|
normalizedRegion.height += normalizedRegion.y;
|
|
@@ -645,18 +605,6 @@ class Driver {
|
|
|
645
605
|
await context.focus();
|
|
646
606
|
return context.getRegionInViewport(region);
|
|
647
607
|
}
|
|
648
|
-
async element(selector) {
|
|
649
|
-
return this.currentContext.element(selector);
|
|
650
|
-
}
|
|
651
|
-
async elements(selector) {
|
|
652
|
-
return this.currentContext.elements(selector);
|
|
653
|
-
}
|
|
654
|
-
async waitFor(selector, options) {
|
|
655
|
-
return this.currentContext.waitFor(selector, options);
|
|
656
|
-
}
|
|
657
|
-
async execute(script, arg) {
|
|
658
|
-
return this.currentContext.execute(script, arg);
|
|
659
|
-
}
|
|
660
608
|
async takeScreenshot() {
|
|
661
609
|
const image = await this._spec.takeScreenshot(this.target);
|
|
662
610
|
if (utils.types.isString(image)) {
|
|
@@ -664,25 +612,20 @@ class Driver {
|
|
|
664
612
|
}
|
|
665
613
|
return image;
|
|
666
614
|
}
|
|
667
|
-
async getViewportRegion() {
|
|
668
|
-
var _a, _b;
|
|
669
|
-
return {
|
|
670
|
-
...((_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.viewportLocation) !== null && _b !== void 0 ? _b : { x: 0, y: 0 }),
|
|
671
|
-
...(await this.getViewportSize()),
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
615
|
async getViewportSize() {
|
|
675
616
|
var _a;
|
|
617
|
+
const environment = await this.getEnvironment();
|
|
676
618
|
let size;
|
|
677
|
-
if (
|
|
678
|
-
|
|
619
|
+
if (environment.isNative && !environment.isWeb) {
|
|
620
|
+
const viewport = await this.getViewport();
|
|
621
|
+
if (viewport.viewportSize) {
|
|
679
622
|
this._logger.log('Extracting viewport size from native driver using cached value');
|
|
680
|
-
size =
|
|
623
|
+
size = viewport.viewportSize;
|
|
681
624
|
}
|
|
682
625
|
else {
|
|
683
626
|
this._logger.log('Extracting viewport size from native driver');
|
|
684
|
-
size = await this.getDisplaySize();
|
|
685
|
-
size.height -=
|
|
627
|
+
size = (await this.getDisplaySize());
|
|
628
|
+
size.height -= (_a = viewport.statusBarSize) !== null && _a !== void 0 ? _a : 0;
|
|
686
629
|
}
|
|
687
630
|
this._logger.log(`Rounding viewport size using`, this._customConfig.useCeilForViewportSize ? 'ceil' : 'round');
|
|
688
631
|
if (this._customConfig.useCeilForViewportSize) {
|
|
@@ -698,13 +641,15 @@ class Driver {
|
|
|
698
641
|
}
|
|
699
642
|
else {
|
|
700
643
|
this._logger.log('Extracting viewport size from web driver using js snippet');
|
|
701
|
-
|
|
644
|
+
const viewport = await this.mainContext.execute(snippets.getViewport);
|
|
645
|
+
size = viewport.viewportSize;
|
|
702
646
|
}
|
|
703
647
|
this._logger.log('Extracted viewport size', size);
|
|
704
648
|
return size;
|
|
705
649
|
}
|
|
706
650
|
async setViewportSize(size) {
|
|
707
|
-
|
|
651
|
+
const environment = await this.getEnvironment();
|
|
652
|
+
if (environment.isMobile)
|
|
708
653
|
return;
|
|
709
654
|
if (this._spec.setViewportSize) {
|
|
710
655
|
this._logger.log('Setting viewport size to', size, 'using spec method');
|
|
@@ -739,30 +684,34 @@ class Driver {
|
|
|
739
684
|
throw new Error('Failed to set viewport size!');
|
|
740
685
|
}
|
|
741
686
|
async getDisplaySize() {
|
|
742
|
-
var _a
|
|
743
|
-
|
|
687
|
+
var _a;
|
|
688
|
+
const environment = await this.getEnvironment();
|
|
689
|
+
if (!environment.isNative)
|
|
744
690
|
return undefined;
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
691
|
+
const viewport = await this.getViewport();
|
|
692
|
+
if (viewport === null || viewport === void 0 ? void 0 : viewport.displaySize) {
|
|
693
|
+
this._logger.log('Extracting display size from native driver using cached value', viewport.displaySize);
|
|
694
|
+
return viewport.displaySize;
|
|
748
695
|
}
|
|
749
696
|
let size = await this._spec.getWindowSize(this.target);
|
|
750
|
-
if (((
|
|
697
|
+
if (((_a = (await this.getOrientation())) === null || _a === void 0 ? void 0 : _a.startsWith('landscape')) && size.height > size.width) {
|
|
751
698
|
size = { width: size.height, height: size.width };
|
|
752
699
|
}
|
|
753
|
-
const normalizedSize =
|
|
700
|
+
const normalizedSize = environment.isAndroid ? utils.geometry.scale(size, 1 / viewport.pixelRatio) : size;
|
|
754
701
|
this._logger.log('Extracted and normalized display size:', normalizedSize);
|
|
755
702
|
return normalizedSize;
|
|
756
703
|
}
|
|
757
704
|
async getOrientation() {
|
|
758
|
-
|
|
705
|
+
var _a, _b;
|
|
706
|
+
const environment = await this.getEnvironment();
|
|
707
|
+
if (!environment.isMobile)
|
|
759
708
|
return undefined;
|
|
760
|
-
if (
|
|
709
|
+
if (environment.isAndroid) {
|
|
761
710
|
this._logger.log('Extracting device orientation using adb command on android');
|
|
762
711
|
const rotation = await this.execute('mobile:shell', {
|
|
763
712
|
command: "dumpsys window | grep 'mCurrentRotation' | cut -d = -f2",
|
|
764
713
|
})
|
|
765
|
-
.then(
|
|
714
|
+
.then(rotation => { var _a; return (_a = rotation === null || rotation === void 0 ? void 0 : rotation.trim) === null || _a === void 0 ? void 0 : _a.call(rotation); })
|
|
766
715
|
.catch(() => null);
|
|
767
716
|
if (rotation) {
|
|
768
717
|
let orientation = undefined;
|
|
@@ -779,44 +728,63 @@ class Driver {
|
|
|
779
728
|
}
|
|
780
729
|
}
|
|
781
730
|
this._logger.log('Extracting device orientation');
|
|
782
|
-
const orientation = await this._spec.getOrientation(this.target);
|
|
731
|
+
const orientation = await ((_b = (_a = this._spec).getOrientation) === null || _b === void 0 ? void 0 : _b.call(_a, this.target));
|
|
783
732
|
this._logger.log('Extracted device orientation:', orientation);
|
|
784
733
|
return orientation;
|
|
785
734
|
}
|
|
786
735
|
async setOrientation(orientation) {
|
|
787
|
-
|
|
736
|
+
const environment = await this.getEnvironment();
|
|
737
|
+
if (!environment.isMobile)
|
|
788
738
|
return undefined;
|
|
789
739
|
this._logger.log('Set device orientation:', orientation);
|
|
790
740
|
await this._spec.setOrientation(this.target, orientation);
|
|
791
741
|
}
|
|
792
742
|
async getCookies() {
|
|
793
|
-
var _a, _b, _c
|
|
794
|
-
|
|
795
|
-
|
|
743
|
+
var _a, _b, _c;
|
|
744
|
+
const environment = await this.getEnvironment();
|
|
745
|
+
const features = await this.getFeatures();
|
|
746
|
+
if (environment.isNative || !features.allCookies)
|
|
796
747
|
return [];
|
|
797
748
|
try {
|
|
798
|
-
|
|
749
|
+
const cookies = await ((_b = (_a = this._spec).getCookies) === null || _b === void 0 ? void 0 : _b.call(_a, this.target));
|
|
750
|
+
this._logger.log('Extracted driver cookies', cookies);
|
|
751
|
+
return cookies !== null && cookies !== void 0 ? cookies : [];
|
|
799
752
|
}
|
|
800
753
|
catch (error) {
|
|
801
|
-
|
|
802
|
-
this.
|
|
754
|
+
this._logger.error('Error while extracting driver cookies', error);
|
|
755
|
+
(_c = this._features) !== null && _c !== void 0 ? _c : (this._features = {});
|
|
756
|
+
this._features.allCookies = false;
|
|
803
757
|
throw error;
|
|
804
758
|
}
|
|
805
759
|
}
|
|
806
760
|
async getTitle() {
|
|
807
|
-
|
|
761
|
+
const environment = await this.getEnvironment();
|
|
762
|
+
if (environment.isNative)
|
|
808
763
|
return undefined;
|
|
809
764
|
const title = await this._spec.getTitle(this.target);
|
|
810
765
|
this._logger.log('Extracted title:', title);
|
|
811
766
|
return title;
|
|
812
767
|
}
|
|
813
768
|
async getUrl() {
|
|
814
|
-
|
|
769
|
+
const environment = await this.getEnvironment();
|
|
770
|
+
if (environment.isNative)
|
|
815
771
|
return undefined;
|
|
816
772
|
const url = await this._spec.getUrl(this.target);
|
|
817
773
|
this._logger.log('Extracted url:', url);
|
|
818
774
|
return url;
|
|
819
775
|
}
|
|
776
|
+
async element(selector) {
|
|
777
|
+
return this.currentContext.element(selector);
|
|
778
|
+
}
|
|
779
|
+
async elements(selector) {
|
|
780
|
+
return this.currentContext.elements(selector);
|
|
781
|
+
}
|
|
782
|
+
async waitFor(selector, options) {
|
|
783
|
+
return this.currentContext.waitFor(selector, options);
|
|
784
|
+
}
|
|
785
|
+
async execute(script, arg) {
|
|
786
|
+
return this.currentContext.execute(script, arg);
|
|
787
|
+
}
|
|
820
788
|
async visit(url) {
|
|
821
789
|
var _a, _b;
|
|
822
790
|
await ((_b = (_a = this._spec).visit) === null || _b === void 0 ? void 0 : _b.call(_a, this.target, url));
|
|
@@ -829,8 +797,6 @@ function isDriver(driver, spec) {
|
|
|
829
797
|
exports.isDriver = isDriver;
|
|
830
798
|
async function makeDriver(options) {
|
|
831
799
|
const driver = options.driver instanceof Driver ? options.driver : new Driver(options);
|
|
832
|
-
|
|
833
|
-
await driver.refreshContexts();
|
|
834
|
-
return driver;
|
|
800
|
+
return driver.refresh();
|
|
835
801
|
}
|
|
836
802
|
exports.makeDriver = makeDriver;
|