@applitools/driver 1.11.37 → 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 +394 -430
- 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 +3 -3
- 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,7 +400,8 @@ 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
407
|
(_a = (_b = this._state).nmlElement) !== null && _a !== void 0 ? _a : (_b.nmlElement = await this.waitFor({ type: 'accessibility id', selector: 'Applitools_View' }, { timeout: 10000 }));
|
|
@@ -369,53 +428,15 @@ class Driver {
|
|
|
369
428
|
return this.extractBrokerUrl();
|
|
370
429
|
}
|
|
371
430
|
}
|
|
372
|
-
|
|
373
|
-
//
|
|
374
|
-
// Since "context" is an overloaded term from frames, we have decided to use
|
|
375
|
-
// the concept of a "world" when switching between mobile app contexts (e.g., native and webview(s))
|
|
376
|
-
//
|
|
377
|
-
// Notes:
|
|
378
|
-
// - two new functions need to be added to a spec driver for this to work (`getCurrentWorld` and `switchWorld`)
|
|
379
|
-
// - you can see a reference implementation of this in spec-driver-webdriverio
|
|
380
|
-
// - if a world id is provided it will be used for switching
|
|
381
|
-
// - if a world id is not provided, the first non-native world will be used
|
|
382
|
-
// (regardless of which world the driver is currently switched into)
|
|
383
|
-
// - before switching, the current world context is stored so it can switched back to later
|
|
384
|
-
// (with the `restoreState` option)
|
|
385
|
-
// - the native app world can be switched to (with the `goHome` option)
|
|
386
|
-
async switchWorld(options) {
|
|
431
|
+
async getSessionMetadata() {
|
|
387
432
|
var _a, _b;
|
|
388
|
-
if ((options === null || options === void 0 ? void 0 : options.restoreState) && !this._state.world)
|
|
389
|
-
return;
|
|
390
|
-
if (!this._spec.getCurrentWorld || !this._spec.switchWorld) {
|
|
391
|
-
this._logger.warn('world switching not implemented in the spec driver, skipping');
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
this._logger.log('switchWorld called with', options ? options : 'no options');
|
|
395
|
-
const current = (await this.getCurrentWorld());
|
|
396
|
-
if (!this._state.world) {
|
|
397
|
-
this._logger.log('storing current world id for future restoration', current);
|
|
398
|
-
this._state.world = current;
|
|
399
|
-
}
|
|
400
|
-
let world;
|
|
401
|
-
if (options === null || options === void 0 ? void 0 : options.id)
|
|
402
|
-
world = options.id;
|
|
403
|
-
else if (options === null || options === void 0 ? void 0 : options.restoreState)
|
|
404
|
-
world = this._state.world;
|
|
405
|
-
else {
|
|
406
|
-
const [home, next] = (await this.getWorlds());
|
|
407
|
-
if (options === null || options === void 0 ? void 0 : options.goHome)
|
|
408
|
-
world = home;
|
|
409
|
-
else
|
|
410
|
-
world = next;
|
|
411
|
-
}
|
|
412
|
-
this._logger.log('switching world with', world);
|
|
413
433
|
try {
|
|
414
|
-
await ((_b = (_a = this._spec).
|
|
415
|
-
|
|
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;
|
|
416
437
|
}
|
|
417
|
-
catch (
|
|
418
|
-
|
|
438
|
+
catch (err) {
|
|
439
|
+
this._logger.warn('Failed to extract session metadata due to the error', err);
|
|
419
440
|
}
|
|
420
441
|
}
|
|
421
442
|
async getWorlds() {
|
|
@@ -424,7 +445,7 @@ class Driver {
|
|
|
424
445
|
this._logger.log('Extracting worlds');
|
|
425
446
|
try {
|
|
426
447
|
let worlds = [];
|
|
427
|
-
for (let attempt = 0; worlds.length <= 1 && attempt <
|
|
448
|
+
for (let attempt = 0; worlds.length <= 1 && attempt < 3; ++attempt) {
|
|
428
449
|
if (attempt > 0)
|
|
429
450
|
await utils.general.sleep(500);
|
|
430
451
|
worlds = await this._spec.getWorlds(this.target);
|
|
@@ -438,12 +459,11 @@ class Driver {
|
|
|
438
459
|
}
|
|
439
460
|
}
|
|
440
461
|
async getCurrentWorld() {
|
|
441
|
-
var _a, _b;
|
|
442
462
|
if (!this._spec.getCurrentWorld)
|
|
443
463
|
return null;
|
|
444
464
|
try {
|
|
445
465
|
this._logger.log('Extracting current world');
|
|
446
|
-
const current = await
|
|
466
|
+
const current = await this._spec.getCurrentWorld(this.target);
|
|
447
467
|
this._logger.log('Current world was extracted', current);
|
|
448
468
|
return current;
|
|
449
469
|
}
|
|
@@ -452,85 +472,20 @@ class Driver {
|
|
|
452
472
|
return null;
|
|
453
473
|
}
|
|
454
474
|
}
|
|
455
|
-
async
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
if (this.isNative)
|
|
462
|
-
return this.currentContext;
|
|
463
|
-
const spec = this._spec;
|
|
464
|
-
let currentContext = this.currentContext.target;
|
|
465
|
-
let contextInfo = await getContextInfo(currentContext);
|
|
466
|
-
const path = [];
|
|
467
|
-
if (spec.parentContext) {
|
|
468
|
-
while (!contextInfo.isRoot) {
|
|
469
|
-
currentContext = await spec.parentContext(currentContext);
|
|
470
|
-
const contextReference = await findContextReference(currentContext, contextInfo);
|
|
471
|
-
if (!contextReference)
|
|
472
|
-
throw new Error('Unable to find out the chain of frames');
|
|
473
|
-
path.unshift(contextReference);
|
|
474
|
-
contextInfo = await getContextInfo(currentContext);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
else {
|
|
478
|
-
currentContext = await spec.mainContext(currentContext);
|
|
479
|
-
path.push(...(await findContextPath(currentContext, contextInfo)));
|
|
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');
|
|
480
481
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
return specUtils.transformSelector(spec, selector, { isWeb: true });
|
|
485
|
-
}
|
|
486
|
-
async function getContextInfo(context) {
|
|
487
|
-
const [documentElement, selector, isRoot, isCORS] = await spec.executeScript(context, snippets.getContextInfo);
|
|
488
|
-
return { documentElement, selector, isRoot, isCORS };
|
|
489
|
-
}
|
|
490
|
-
async function getChildContextsInfo(context) {
|
|
491
|
-
const framesInfo = await spec.executeScript(context, snippets.getChildFramesInfo);
|
|
492
|
-
return framesInfo.map(([contextElement, isCORS]) => ({
|
|
493
|
-
contextElement,
|
|
494
|
-
isCORS,
|
|
495
|
-
}));
|
|
496
|
-
}
|
|
497
|
-
async function isEqualElements(context, element1, element2) {
|
|
498
|
-
return spec.executeScript(context, snippets.isEqualElements, [element1, element2]).catch(() => false);
|
|
499
|
-
}
|
|
500
|
-
async function findContextReference(context, contextInfo) {
|
|
501
|
-
if (contextInfo.selector) {
|
|
502
|
-
const contextElement = await spec.findElement(context, transformSelector({ type: 'xpath', selector: contextInfo.selector }));
|
|
503
|
-
if (contextElement)
|
|
504
|
-
return contextElement;
|
|
505
|
-
}
|
|
506
|
-
for (const childContextInfo of await getChildContextsInfo(context)) {
|
|
507
|
-
if (childContextInfo.isCORS !== contextInfo.isCORS)
|
|
508
|
-
continue;
|
|
509
|
-
const childContext = await spec.childContext(context, childContextInfo.contextElement);
|
|
510
|
-
const contentDocument = await spec.findElement(childContext, transformSelector('html'));
|
|
511
|
-
const isWantedContext = await isEqualElements(childContext, contentDocument, contextInfo.documentElement);
|
|
512
|
-
await spec.parentContext(childContext);
|
|
513
|
-
if (isWantedContext)
|
|
514
|
-
return childContextInfo.contextElement;
|
|
515
|
-
}
|
|
516
|
-
return null;
|
|
482
|
+
try {
|
|
483
|
+
await this._spec.switchWorld(this.target, name);
|
|
484
|
+
this.refresh();
|
|
517
485
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
return contextPath;
|
|
522
|
-
}
|
|
523
|
-
for (const childContextInfo of await getChildContextsInfo(context)) {
|
|
524
|
-
const childContext = await spec.childContext(context, childContextInfo.contextElement);
|
|
525
|
-
const possibleContextPath = [...contextPath, childContextInfo.contextElement];
|
|
526
|
-
const wantedContextPath = await findContextPath(childContext, contextInfo, possibleContextPath);
|
|
527
|
-
await spec.mainContext(context);
|
|
528
|
-
if (wantedContextPath)
|
|
529
|
-
return wantedContextPath;
|
|
530
|
-
for (const contextElement of contextPath) {
|
|
531
|
-
await spec.childContext(context, contextElement);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
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}`);
|
|
534
489
|
}
|
|
535
490
|
}
|
|
536
491
|
async switchTo(context) {
|
|
@@ -580,14 +535,16 @@ class Driver {
|
|
|
580
535
|
}
|
|
581
536
|
}
|
|
582
537
|
async switchToMainContext() {
|
|
583
|
-
|
|
538
|
+
const environment = await this.getEnvironment();
|
|
539
|
+
if (environment.isNative)
|
|
584
540
|
throw new Error('Contexts are supported only for web drivers');
|
|
585
541
|
this._logger.log('Switching to the main context');
|
|
586
542
|
await this._spec.mainContext(this.currentContext.target);
|
|
587
543
|
return (this._currentContext = this._mainContext);
|
|
588
544
|
}
|
|
589
545
|
async switchToParentContext(elevation = 1) {
|
|
590
|
-
|
|
546
|
+
const environment = await this.getEnvironment();
|
|
547
|
+
if (environment.isNative)
|
|
591
548
|
throw new Error('Contexts are supported only for web drivers');
|
|
592
549
|
this._logger.log('Switching to a parent context with elevation:', elevation);
|
|
593
550
|
if (this.currentContext.path.length <= elevation) {
|
|
@@ -611,7 +568,8 @@ class Driver {
|
|
|
611
568
|
return this.currentContext;
|
|
612
569
|
}
|
|
613
570
|
async switchToChildContext(...references) {
|
|
614
|
-
|
|
571
|
+
const environment = await this.getEnvironment();
|
|
572
|
+
if (environment.isNative)
|
|
615
573
|
throw new Error('Contexts are supported only for web drivers');
|
|
616
574
|
this._logger.log('Switching to a child context with depth:', references.length);
|
|
617
575
|
for (const reference of references) {
|
|
@@ -623,19 +581,19 @@ class Driver {
|
|
|
623
581
|
return this.currentContext;
|
|
624
582
|
}
|
|
625
583
|
async normalizeRegion(region) {
|
|
626
|
-
|
|
584
|
+
const environment = await this.getEnvironment();
|
|
585
|
+
if (environment.isWeb)
|
|
627
586
|
return region;
|
|
587
|
+
const viewport = await this.getViewport();
|
|
628
588
|
let normalizedRegion = region;
|
|
629
|
-
if (
|
|
630
|
-
normalizedRegion = utils.geometry.scale(normalizedRegion, 1 /
|
|
589
|
+
if (environment.isAndroid) {
|
|
590
|
+
normalizedRegion = utils.geometry.scale(normalizedRegion, 1 / viewport.pixelRatio);
|
|
631
591
|
}
|
|
632
|
-
if (
|
|
633
|
-
|
|
634
|
-
utils.geometry.isIntersected(normalizedRegion, this._driverInfo.safeArea)) {
|
|
635
|
-
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);
|
|
636
594
|
}
|
|
637
|
-
if (
|
|
638
|
-
normalizedRegion = utils.geometry.offsetNegative(normalizedRegion,
|
|
595
|
+
if (viewport.viewportLocation) {
|
|
596
|
+
normalizedRegion = utils.geometry.offsetNegative(normalizedRegion, viewport.viewportLocation);
|
|
639
597
|
}
|
|
640
598
|
if (normalizedRegion.y < 0) {
|
|
641
599
|
normalizedRegion.height += normalizedRegion.y;
|
|
@@ -647,18 +605,6 @@ class Driver {
|
|
|
647
605
|
await context.focus();
|
|
648
606
|
return context.getRegionInViewport(region);
|
|
649
607
|
}
|
|
650
|
-
async element(selector) {
|
|
651
|
-
return this.currentContext.element(selector);
|
|
652
|
-
}
|
|
653
|
-
async elements(selector) {
|
|
654
|
-
return this.currentContext.elements(selector);
|
|
655
|
-
}
|
|
656
|
-
async waitFor(selector, options) {
|
|
657
|
-
return this.currentContext.waitFor(selector, options);
|
|
658
|
-
}
|
|
659
|
-
async execute(script, arg) {
|
|
660
|
-
return this.currentContext.execute(script, arg);
|
|
661
|
-
}
|
|
662
608
|
async takeScreenshot() {
|
|
663
609
|
const image = await this._spec.takeScreenshot(this.target);
|
|
664
610
|
if (utils.types.isString(image)) {
|
|
@@ -666,25 +612,20 @@ class Driver {
|
|
|
666
612
|
}
|
|
667
613
|
return image;
|
|
668
614
|
}
|
|
669
|
-
async getViewportRegion() {
|
|
670
|
-
var _a, _b;
|
|
671
|
-
return {
|
|
672
|
-
...((_b = (_a = this._driverInfo) === null || _a === void 0 ? void 0 : _a.viewportLocation) !== null && _b !== void 0 ? _b : { x: 0, y: 0 }),
|
|
673
|
-
...(await this.getViewportSize()),
|
|
674
|
-
};
|
|
675
|
-
}
|
|
676
615
|
async getViewportSize() {
|
|
677
616
|
var _a;
|
|
617
|
+
const environment = await this.getEnvironment();
|
|
678
618
|
let size;
|
|
679
|
-
if (
|
|
680
|
-
|
|
619
|
+
if (environment.isNative && !environment.isWeb) {
|
|
620
|
+
const viewport = await this.getViewport();
|
|
621
|
+
if (viewport.viewportSize) {
|
|
681
622
|
this._logger.log('Extracting viewport size from native driver using cached value');
|
|
682
|
-
size =
|
|
623
|
+
size = viewport.viewportSize;
|
|
683
624
|
}
|
|
684
625
|
else {
|
|
685
626
|
this._logger.log('Extracting viewport size from native driver');
|
|
686
|
-
size = await this.getDisplaySize();
|
|
687
|
-
size.height -=
|
|
627
|
+
size = (await this.getDisplaySize());
|
|
628
|
+
size.height -= (_a = viewport.statusBarSize) !== null && _a !== void 0 ? _a : 0;
|
|
688
629
|
}
|
|
689
630
|
this._logger.log(`Rounding viewport size using`, this._customConfig.useCeilForViewportSize ? 'ceil' : 'round');
|
|
690
631
|
if (this._customConfig.useCeilForViewportSize) {
|
|
@@ -700,13 +641,15 @@ class Driver {
|
|
|
700
641
|
}
|
|
701
642
|
else {
|
|
702
643
|
this._logger.log('Extracting viewport size from web driver using js snippet');
|
|
703
|
-
|
|
644
|
+
const viewport = await this.mainContext.execute(snippets.getViewport);
|
|
645
|
+
size = viewport.viewportSize;
|
|
704
646
|
}
|
|
705
647
|
this._logger.log('Extracted viewport size', size);
|
|
706
648
|
return size;
|
|
707
649
|
}
|
|
708
650
|
async setViewportSize(size) {
|
|
709
|
-
|
|
651
|
+
const environment = await this.getEnvironment();
|
|
652
|
+
if (environment.isMobile)
|
|
710
653
|
return;
|
|
711
654
|
if (this._spec.setViewportSize) {
|
|
712
655
|
this._logger.log('Setting viewport size to', size, 'using spec method');
|
|
@@ -741,30 +684,34 @@ class Driver {
|
|
|
741
684
|
throw new Error('Failed to set viewport size!');
|
|
742
685
|
}
|
|
743
686
|
async getDisplaySize() {
|
|
744
|
-
var _a
|
|
745
|
-
|
|
687
|
+
var _a;
|
|
688
|
+
const environment = await this.getEnvironment();
|
|
689
|
+
if (!environment.isNative)
|
|
746
690
|
return undefined;
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
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;
|
|
750
695
|
}
|
|
751
696
|
let size = await this._spec.getWindowSize(this.target);
|
|
752
|
-
if (((
|
|
697
|
+
if (((_a = (await this.getOrientation())) === null || _a === void 0 ? void 0 : _a.startsWith('landscape')) && size.height > size.width) {
|
|
753
698
|
size = { width: size.height, height: size.width };
|
|
754
699
|
}
|
|
755
|
-
const normalizedSize =
|
|
700
|
+
const normalizedSize = environment.isAndroid ? utils.geometry.scale(size, 1 / viewport.pixelRatio) : size;
|
|
756
701
|
this._logger.log('Extracted and normalized display size:', normalizedSize);
|
|
757
702
|
return normalizedSize;
|
|
758
703
|
}
|
|
759
704
|
async getOrientation() {
|
|
760
|
-
|
|
705
|
+
var _a, _b;
|
|
706
|
+
const environment = await this.getEnvironment();
|
|
707
|
+
if (!environment.isMobile)
|
|
761
708
|
return undefined;
|
|
762
|
-
if (
|
|
709
|
+
if (environment.isAndroid) {
|
|
763
710
|
this._logger.log('Extracting device orientation using adb command on android');
|
|
764
711
|
const rotation = await this.execute('mobile:shell', {
|
|
765
712
|
command: "dumpsys window | grep 'mCurrentRotation' | cut -d = -f2",
|
|
766
713
|
})
|
|
767
|
-
.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); })
|
|
768
715
|
.catch(() => null);
|
|
769
716
|
if (rotation) {
|
|
770
717
|
let orientation = undefined;
|
|
@@ -781,44 +728,63 @@ class Driver {
|
|
|
781
728
|
}
|
|
782
729
|
}
|
|
783
730
|
this._logger.log('Extracting device orientation');
|
|
784
|
-
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));
|
|
785
732
|
this._logger.log('Extracted device orientation:', orientation);
|
|
786
733
|
return orientation;
|
|
787
734
|
}
|
|
788
735
|
async setOrientation(orientation) {
|
|
789
|
-
|
|
736
|
+
const environment = await this.getEnvironment();
|
|
737
|
+
if (!environment.isMobile)
|
|
790
738
|
return undefined;
|
|
791
739
|
this._logger.log('Set device orientation:', orientation);
|
|
792
740
|
await this._spec.setOrientation(this.target, orientation);
|
|
793
741
|
}
|
|
794
742
|
async getCookies() {
|
|
795
|
-
var _a, _b, _c
|
|
796
|
-
|
|
797
|
-
|
|
743
|
+
var _a, _b, _c;
|
|
744
|
+
const environment = await this.getEnvironment();
|
|
745
|
+
const features = await this.getFeatures();
|
|
746
|
+
if (environment.isNative || !features.allCookies)
|
|
798
747
|
return [];
|
|
799
748
|
try {
|
|
800
|
-
|
|
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 : [];
|
|
801
752
|
}
|
|
802
753
|
catch (error) {
|
|
803
|
-
|
|
804
|
-
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;
|
|
805
757
|
throw error;
|
|
806
758
|
}
|
|
807
759
|
}
|
|
808
760
|
async getTitle() {
|
|
809
|
-
|
|
761
|
+
const environment = await this.getEnvironment();
|
|
762
|
+
if (environment.isNative)
|
|
810
763
|
return undefined;
|
|
811
764
|
const title = await this._spec.getTitle(this.target);
|
|
812
765
|
this._logger.log('Extracted title:', title);
|
|
813
766
|
return title;
|
|
814
767
|
}
|
|
815
768
|
async getUrl() {
|
|
816
|
-
|
|
769
|
+
const environment = await this.getEnvironment();
|
|
770
|
+
if (environment.isNative)
|
|
817
771
|
return undefined;
|
|
818
772
|
const url = await this._spec.getUrl(this.target);
|
|
819
773
|
this._logger.log('Extracted url:', url);
|
|
820
774
|
return url;
|
|
821
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
|
+
}
|
|
822
788
|
async visit(url) {
|
|
823
789
|
var _a, _b;
|
|
824
790
|
await ((_b = (_a = this._spec).visit) === null || _b === void 0 ? void 0 : _b.call(_a, this.target, url));
|
|
@@ -831,8 +797,6 @@ function isDriver(driver, spec) {
|
|
|
831
797
|
exports.isDriver = isDriver;
|
|
832
798
|
async function makeDriver(options) {
|
|
833
799
|
const driver = options.driver instanceof Driver ? options.driver : new Driver(options);
|
|
834
|
-
|
|
835
|
-
await driver.refreshContexts();
|
|
836
|
-
return driver;
|
|
800
|
+
return driver.refresh();
|
|
837
801
|
}
|
|
838
802
|
exports.makeDriver = makeDriver;
|