webdriverio 9.6.4 → 9.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/commands/browser.d.ts +3 -0
- package/build/commands/browser.d.ts.map +1 -1
- package/build/commands/mobile/getContext.d.ts +107 -0
- package/build/commands/mobile/getContext.d.ts.map +1 -0
- package/build/commands/mobile/getContexts.d.ts +158 -0
- package/build/commands/mobile/getContexts.d.ts.map +1 -0
- package/build/commands/mobile/switchContext.d.ts +112 -0
- package/build/commands/mobile/switchContext.d.ts.map +1 -0
- package/build/commands/mobile.d.ts +3 -0
- package/build/commands/mobile.d.ts.map +1 -1
- package/build/index.cjs +3 -3
- package/build/index.js +325 -65
- package/build/node.js +319 -65
- package/build/session/context.d.ts.map +1 -1
- package/build/types.d.ts +39 -0
- package/build/types.d.ts.map +1 -1
- package/package.json +4 -4
package/build/index.js
CHANGED
|
@@ -23,7 +23,7 @@ var __privateWrapper = (obj, member, setter, getter) => ({
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
// src/index.ts
|
|
26
|
-
import
|
|
26
|
+
import logger27 from "@wdio/logger";
|
|
27
27
|
import WebDriver, { DEFAULTS } from "webdriver";
|
|
28
28
|
import { validateConfig } from "@wdio/config";
|
|
29
29
|
import { enableFileLogging, wrapCommand as wrapCommand3 } from "@wdio/utils";
|
|
@@ -97,7 +97,7 @@ async function refetchElement(currentElement, commandName) {
|
|
|
97
97
|
import cssValue from "css-value";
|
|
98
98
|
import rgb2hex from "rgb2hex";
|
|
99
99
|
import GraphemeSplitter from "grapheme-splitter";
|
|
100
|
-
import
|
|
100
|
+
import logger26 from "@wdio/logger";
|
|
101
101
|
import isPlainObject from "is-plain-obj";
|
|
102
102
|
import { ELEMENT_KEY as ELEMENT_KEY18 } from "webdriver";
|
|
103
103
|
import { UNICODE_CHARACTERS as UNICODE_CHARACTERS2, asyncIterators, getBrowserObject as getBrowserObject34 } from "@wdio/utils";
|
|
@@ -120,6 +120,8 @@ __export(browser_exports, {
|
|
|
120
120
|
emulate: () => emulate,
|
|
121
121
|
execute: () => execute,
|
|
122
122
|
executeAsync: () => executeAsync,
|
|
123
|
+
getContext: () => getContext,
|
|
124
|
+
getContexts: () => getContexts,
|
|
123
125
|
getCookies: () => getCookies,
|
|
124
126
|
getPuppeteer: () => getPuppeteer,
|
|
125
127
|
getWindowSize: () => getWindowSize,
|
|
@@ -142,6 +144,7 @@ __export(browser_exports, {
|
|
|
142
144
|
setViewport: () => setViewport,
|
|
143
145
|
setWindowSize: () => setWindowSize,
|
|
144
146
|
swipe: () => swipe,
|
|
147
|
+
switchContext: () => switchContext,
|
|
145
148
|
switchFrame: () => switchFrame,
|
|
146
149
|
switchWindow: () => switchWindow,
|
|
147
150
|
tap: () => tap,
|
|
@@ -3134,7 +3137,7 @@ var _ContextManager = class _ContextManager extends SessionManager {
|
|
|
3134
3137
|
isNativeContext: __privateGet(this, _isNativeContext)
|
|
3135
3138
|
}));
|
|
3136
3139
|
__privateGet(this, _browser3).on("result", __privateMethod(this, _ContextManager_instances, onCommandResultBidiAndClassic_fn).bind(this));
|
|
3137
|
-
if (!this.isEnabled()) {
|
|
3140
|
+
if (!this.isEnabled() && !__privateGet(this, _browser3).isMobile) {
|
|
3138
3141
|
return;
|
|
3139
3142
|
}
|
|
3140
3143
|
__privateGet(this, _browser3).on("command", __privateMethod(this, _ContextManager_instances, onCommand_fn2).bind(this));
|
|
@@ -3288,15 +3291,15 @@ onCommand_fn2 = function(event) {
|
|
|
3288
3291
|
if (COMMANDS_REQUIRING_RESET.includes(event.command)) {
|
|
3289
3292
|
__privateSet(this, _currentContext, void 0);
|
|
3290
3293
|
}
|
|
3291
|
-
if (__privateGet(this, _browser3).isMobile && event.command === "
|
|
3294
|
+
if (__privateGet(this, _browser3).isMobile && event.command === "switchAppiumContext") {
|
|
3292
3295
|
__privateSet(this, _mobileContext, event.body.name);
|
|
3293
3296
|
}
|
|
3294
3297
|
};
|
|
3295
3298
|
onCommandResultMobile_fn = function(event) {
|
|
3296
|
-
if (event.command === "
|
|
3299
|
+
if (event.command === "getAppiumContext") {
|
|
3297
3300
|
this.setCurrentContext(event.result.value);
|
|
3298
3301
|
}
|
|
3299
|
-
if (event.command === "
|
|
3302
|
+
if (event.command === "switchAppiumContext" && event.result.value === null && __privateGet(this, _mobileContext)) {
|
|
3300
3303
|
this.setCurrentContext(__privateGet(this, _mobileContext));
|
|
3301
3304
|
}
|
|
3302
3305
|
};
|
|
@@ -4692,16 +4695,16 @@ _initialize3 = new WeakMap();
|
|
|
4692
4695
|
_requests = new WeakMap();
|
|
4693
4696
|
_lastNetworkId = new WeakMap();
|
|
4694
4697
|
_NetworkManager_instances = new WeakSet();
|
|
4695
|
-
beforeRequestSent_fn = function(
|
|
4698
|
+
beforeRequestSent_fn = function(log27) {
|
|
4696
4699
|
var _a;
|
|
4697
|
-
if (
|
|
4700
|
+
if (log27.navigation) {
|
|
4698
4701
|
return;
|
|
4699
4702
|
}
|
|
4700
|
-
const request = __privateMethod(this, _NetworkManager_instances, findRootRequest_fn).call(this,
|
|
4703
|
+
const request = __privateMethod(this, _NetworkManager_instances, findRootRequest_fn).call(this, log27.navigation);
|
|
4701
4704
|
if (!request) {
|
|
4702
4705
|
return;
|
|
4703
4706
|
}
|
|
4704
|
-
const { request: id, headers, cookies, url: url2 } =
|
|
4707
|
+
const { request: id, headers, cookies, url: url2 } = log27.request;
|
|
4705
4708
|
(_a = request.children) == null ? void 0 : _a.push({
|
|
4706
4709
|
id,
|
|
4707
4710
|
url: url2,
|
|
@@ -4717,52 +4720,52 @@ beforeRequestSent_fn = function(log24) {
|
|
|
4717
4720
|
sameSite: cookie.sameSite,
|
|
4718
4721
|
expiry: cookie.expiry
|
|
4719
4722
|
})),
|
|
4720
|
-
timestamp:
|
|
4723
|
+
timestamp: log27.timestamp
|
|
4721
4724
|
});
|
|
4722
4725
|
};
|
|
4723
|
-
navigationStarted_fn = function(
|
|
4726
|
+
navigationStarted_fn = function(log27) {
|
|
4724
4727
|
if (
|
|
4725
4728
|
/**
|
|
4726
4729
|
* we need a navigation id to identify the request
|
|
4727
4730
|
*/
|
|
4728
|
-
!
|
|
4731
|
+
!log27.navigation || /**
|
|
4729
4732
|
* ignore urls that users wouldn't navigate to
|
|
4730
4733
|
*/
|
|
4731
|
-
!SUPPORTED_NAVIGATION_PROTOCOLS.some((protocol) =>
|
|
4734
|
+
!SUPPORTED_NAVIGATION_PROTOCOLS.some((protocol) => log27.url.startsWith(protocol))
|
|
4732
4735
|
) {
|
|
4733
|
-
if (
|
|
4736
|
+
if (log27.navigation === null && log27.url === "") {
|
|
4734
4737
|
__privateSet(this, _lastNetworkId, UNKNOWN_NAVIGATION_ID);
|
|
4735
4738
|
return __privateGet(this, _requests).set(UNKNOWN_NAVIGATION_ID, {
|
|
4736
4739
|
url: "",
|
|
4737
4740
|
headers: {},
|
|
4738
|
-
timestamp:
|
|
4741
|
+
timestamp: log27.timestamp,
|
|
4739
4742
|
redirectChain: [],
|
|
4740
4743
|
children: []
|
|
4741
4744
|
});
|
|
4742
4745
|
}
|
|
4743
4746
|
return;
|
|
4744
4747
|
}
|
|
4745
|
-
__privateSet(this, _lastNetworkId,
|
|
4746
|
-
__privateGet(this, _requests).set(
|
|
4747
|
-
url:
|
|
4748
|
+
__privateSet(this, _lastNetworkId, log27.navigation);
|
|
4749
|
+
__privateGet(this, _requests).set(log27.navigation, {
|
|
4750
|
+
url: log27.url,
|
|
4748
4751
|
headers: {},
|
|
4749
|
-
timestamp:
|
|
4750
|
-
navigation:
|
|
4752
|
+
timestamp: log27.timestamp,
|
|
4753
|
+
navigation: log27.navigation,
|
|
4751
4754
|
redirectChain: [],
|
|
4752
4755
|
children: []
|
|
4753
4756
|
});
|
|
4754
4757
|
};
|
|
4755
|
-
fetchError_fn = function(
|
|
4758
|
+
fetchError_fn = function(log27) {
|
|
4756
4759
|
var _a;
|
|
4757
|
-
const response = __privateMethod(this, _NetworkManager_instances, findRootRequest_fn).call(this,
|
|
4760
|
+
const response = __privateMethod(this, _NetworkManager_instances, findRootRequest_fn).call(this, log27.navigation);
|
|
4758
4761
|
if (!response) {
|
|
4759
4762
|
return;
|
|
4760
4763
|
}
|
|
4761
|
-
const request = (_a = response.children) == null ? void 0 : _a.find((child) => child.id ===
|
|
4764
|
+
const request = (_a = response.children) == null ? void 0 : _a.find((child) => child.id === log27.request.request);
|
|
4762
4765
|
if (!request) {
|
|
4763
4766
|
return;
|
|
4764
4767
|
}
|
|
4765
|
-
request.error =
|
|
4768
|
+
request.error = log27.errorText;
|
|
4766
4769
|
};
|
|
4767
4770
|
findRootRequest_fn = function(navigationId) {
|
|
4768
4771
|
const response = __privateGet(this, _requests).get(navigationId || UNKNOWN_NAVIGATION_ID);
|
|
@@ -4772,23 +4775,23 @@ findRootRequest_fn = function(navigationId) {
|
|
|
4772
4775
|
const firstRequest = __privateGet(this, _requests).values().next().value;
|
|
4773
4776
|
return __privateGet(this, _lastNetworkId) ? __privateGet(this, _requests).get(__privateGet(this, _lastNetworkId)) || firstRequest : firstRequest;
|
|
4774
4777
|
};
|
|
4775
|
-
responseCompleted_fn = function(
|
|
4778
|
+
responseCompleted_fn = function(log27) {
|
|
4776
4779
|
var _a, _b, _c;
|
|
4777
|
-
const response = __privateMethod(this, _NetworkManager_instances, findRootRequest_fn).call(this,
|
|
4780
|
+
const response = __privateMethod(this, _NetworkManager_instances, findRootRequest_fn).call(this, log27.navigation);
|
|
4778
4781
|
if (!response) {
|
|
4779
4782
|
return;
|
|
4780
4783
|
}
|
|
4781
4784
|
if (!response.navigation && response.url === "") {
|
|
4782
|
-
response.url =
|
|
4783
|
-
response.navigation =
|
|
4785
|
+
response.url = log27.request.url;
|
|
4786
|
+
response.navigation = log27.navigation;
|
|
4784
4787
|
}
|
|
4785
|
-
if (
|
|
4786
|
-
if (response.url !==
|
|
4788
|
+
if (log27.navigation === response.navigation) {
|
|
4789
|
+
if (response.url !== log27.response.url) {
|
|
4787
4790
|
(_a = response.redirectChain) == null ? void 0 : _a.push(response.url);
|
|
4788
4791
|
}
|
|
4789
|
-
response.url =
|
|
4790
|
-
const { headers: requestHeaders } =
|
|
4791
|
-
const { fromCache, headers: responseHeaders, mimeType, status } =
|
|
4792
|
+
response.url = log27.response.url;
|
|
4793
|
+
const { headers: requestHeaders } = log27.request;
|
|
4794
|
+
const { fromCache, headers: responseHeaders, mimeType, status } = log27.response;
|
|
4792
4795
|
response.headers = headerListToObject(requestHeaders), response.response = {
|
|
4793
4796
|
fromCache,
|
|
4794
4797
|
headers: headerListToObject(responseHeaders),
|
|
@@ -4797,15 +4800,15 @@ responseCompleted_fn = function(log24) {
|
|
|
4797
4800
|
};
|
|
4798
4801
|
return;
|
|
4799
4802
|
}
|
|
4800
|
-
const request = (_b = response.children) == null ? void 0 : _b.find((child) => child.id ===
|
|
4803
|
+
const request = (_b = response.children) == null ? void 0 : _b.find((child) => child.id === log27.request.request);
|
|
4801
4804
|
if (!request) {
|
|
4802
4805
|
return;
|
|
4803
4806
|
}
|
|
4804
4807
|
request.response = {
|
|
4805
|
-
fromCache:
|
|
4806
|
-
headers: headerListToObject(
|
|
4807
|
-
mimeType:
|
|
4808
|
-
status:
|
|
4808
|
+
fromCache: log27.response.fromCache,
|
|
4809
|
+
headers: headerListToObject(log27.response.headers),
|
|
4810
|
+
mimeType: log27.response.mimeType,
|
|
4811
|
+
status: log27.response.status
|
|
4809
4812
|
};
|
|
4810
4813
|
(_c = response.children) == null ? void 0 : _c.push(request);
|
|
4811
4814
|
};
|
|
@@ -4855,14 +4858,14 @@ _browser8 = new WeakMap();
|
|
|
4855
4858
|
_initialize4 = new WeakMap();
|
|
4856
4859
|
_autoHandleDialog = new WeakMap();
|
|
4857
4860
|
_DialogManager_instances = new WeakSet();
|
|
4858
|
-
handleUserPrompt_fn = async function(
|
|
4861
|
+
handleUserPrompt_fn = async function(log27) {
|
|
4859
4862
|
if (__privateGet(this, _autoHandleDialog)) {
|
|
4860
4863
|
return __privateGet(this, _browser8).browsingContextHandleUserPrompt({
|
|
4861
4864
|
accept: false,
|
|
4862
|
-
context:
|
|
4865
|
+
context: log27.context
|
|
4863
4866
|
});
|
|
4864
4867
|
}
|
|
4865
|
-
const dialog = new Dialog(
|
|
4868
|
+
const dialog = new Dialog(log27, __privateGet(this, _browser8));
|
|
4866
4869
|
__privateGet(this, _browser8).emit("dialog", dialog);
|
|
4867
4870
|
};
|
|
4868
4871
|
/**
|
|
@@ -5797,6 +5800,263 @@ async function screenTap(browser, options) {
|
|
|
5797
5800
|
).move({ x, y }).down({ button: 0 }).pause(10).up({ button: 0 }).perform();
|
|
5798
5801
|
}
|
|
5799
5802
|
|
|
5803
|
+
// src/commands/mobile/getContext.ts
|
|
5804
|
+
import logger18 from "@wdio/logger";
|
|
5805
|
+
var log18 = logger18("webdriver");
|
|
5806
|
+
async function getContext(options) {
|
|
5807
|
+
const browser = this;
|
|
5808
|
+
if (!browser.isMobile) {
|
|
5809
|
+
throw new Error("The `getContext` command is only available for mobile platforms.");
|
|
5810
|
+
}
|
|
5811
|
+
const currentAppiumContext = await browser.getAppiumContext();
|
|
5812
|
+
if (!options || !(options == null ? void 0 : options.returnDetailedContext) || currentAppiumContext === "NATIVE_APP") {
|
|
5813
|
+
return currentAppiumContext;
|
|
5814
|
+
}
|
|
5815
|
+
delete options.returnDetailedContext;
|
|
5816
|
+
return getDetailedContext(browser, currentAppiumContext, options);
|
|
5817
|
+
}
|
|
5818
|
+
async function getDetailedContext(browser, currentAppiumContext, options) {
|
|
5819
|
+
const detailedContexts = await browser.getContexts({
|
|
5820
|
+
...{ options },
|
|
5821
|
+
// Defaults
|
|
5822
|
+
returnDetailedContexts: true,
|
|
5823
|
+
// We want to get back the detailed context information
|
|
5824
|
+
isAndroidWebviewVisible: true,
|
|
5825
|
+
// We only want to get back the visible webviews
|
|
5826
|
+
filterByCurrentAndroidApp: true,
|
|
5827
|
+
// We only want to get back the webviews that are attached to the current app
|
|
5828
|
+
returnAndroidDescriptionData: false
|
|
5829
|
+
// We don't want to get back the Android Webview description data
|
|
5830
|
+
});
|
|
5831
|
+
const parsedContexts = detailedContexts.filter((context) => context.id === currentAppiumContext);
|
|
5832
|
+
if (parsedContexts.length > 1) {
|
|
5833
|
+
log18.warn("We found more than 1 detailed context for the current context '".concat(currentAppiumContext, "'. We will return the first context."));
|
|
5834
|
+
return parsedContexts[0];
|
|
5835
|
+
} else if (parsedContexts.length === 0) {
|
|
5836
|
+
log18.warn("We did not get back any detailed context for the current context '".concat(currentAppiumContext, "'. We will return the current context as a string."));
|
|
5837
|
+
return currentAppiumContext;
|
|
5838
|
+
}
|
|
5839
|
+
return parsedContexts[0];
|
|
5840
|
+
}
|
|
5841
|
+
|
|
5842
|
+
// src/commands/mobile/getContexts.ts
|
|
5843
|
+
import logger19 from "@wdio/logger";
|
|
5844
|
+
var log19 = logger19("webdriver");
|
|
5845
|
+
async function getContexts(options) {
|
|
5846
|
+
const browser = this;
|
|
5847
|
+
if (!browser.isMobile) {
|
|
5848
|
+
throw new Error("The `getContexts` command is only available for mobile platforms.");
|
|
5849
|
+
}
|
|
5850
|
+
if (!options || !options.returnDetailedContexts) {
|
|
5851
|
+
log19.info("The standard Appium `contexts` method is used. If you want to get more detailed data, you can set `returnDetailedContexts` to `true`.");
|
|
5852
|
+
return browser.getAppiumContexts();
|
|
5853
|
+
}
|
|
5854
|
+
const defaultOptions = {
|
|
5855
|
+
androidWebviewConnectionRetryTime: 500,
|
|
5856
|
+
androidWebviewConnectTimeout: 5e3,
|
|
5857
|
+
filterByCurrentAndroidApp: false,
|
|
5858
|
+
isAndroidWebviewVisible: true,
|
|
5859
|
+
returnAndroidDescriptionData: false
|
|
5860
|
+
};
|
|
5861
|
+
return getCurrentContexts({ browser, ...{ ...defaultOptions, ...options } });
|
|
5862
|
+
}
|
|
5863
|
+
var CHROME_PACKAGE_NAME = "com.android.chrome";
|
|
5864
|
+
async function parsedAndroidContexts({
|
|
5865
|
+
contexts,
|
|
5866
|
+
filterByCurrentAndroidApp,
|
|
5867
|
+
isAttachedAndVisible,
|
|
5868
|
+
packageName
|
|
5869
|
+
}) {
|
|
5870
|
+
const currentWebviewName = "WEBVIEW_".concat(packageName);
|
|
5871
|
+
let parsedContexts = contexts;
|
|
5872
|
+
if (filterByCurrentAndroidApp) {
|
|
5873
|
+
parsedContexts = contexts.filter((context) => context.webviewName === currentWebviewName);
|
|
5874
|
+
}
|
|
5875
|
+
const result = [{ id: "NATIVE_APP" }];
|
|
5876
|
+
if (!parsedContexts || parsedContexts.length < 1) {
|
|
5877
|
+
return result;
|
|
5878
|
+
}
|
|
5879
|
+
parsedContexts.forEach(
|
|
5880
|
+
(context) => {
|
|
5881
|
+
var _a;
|
|
5882
|
+
return (_a = context.pages) == null ? void 0 : _a.filter((page) => {
|
|
5883
|
+
if (packageName === CHROME_PACKAGE_NAME) {
|
|
5884
|
+
return true;
|
|
5885
|
+
}
|
|
5886
|
+
if (page.type === "page" && page.description) {
|
|
5887
|
+
let descriptionObj;
|
|
5888
|
+
try {
|
|
5889
|
+
descriptionObj = JSON.parse(page.description);
|
|
5890
|
+
} catch (e) {
|
|
5891
|
+
return false;
|
|
5892
|
+
}
|
|
5893
|
+
return isAttachedAndVisible ? descriptionObj.attached === true && descriptionObj.visible === true : true;
|
|
5894
|
+
}
|
|
5895
|
+
return !isAttachedAndVisible;
|
|
5896
|
+
}).forEach((page) => {
|
|
5897
|
+
const {
|
|
5898
|
+
attached = false,
|
|
5899
|
+
empty = false,
|
|
5900
|
+
height = 0,
|
|
5901
|
+
never_attached: neverAttached = false,
|
|
5902
|
+
screenX = 0,
|
|
5903
|
+
screenY = 0,
|
|
5904
|
+
visible = false,
|
|
5905
|
+
width = 0
|
|
5906
|
+
} = JSON.parse(page.description || "{}");
|
|
5907
|
+
const pageData = {
|
|
5908
|
+
androidWebviewData: {
|
|
5909
|
+
attached,
|
|
5910
|
+
empty,
|
|
5911
|
+
height,
|
|
5912
|
+
neverAttached,
|
|
5913
|
+
screenX,
|
|
5914
|
+
screenY,
|
|
5915
|
+
visible,
|
|
5916
|
+
width
|
|
5917
|
+
},
|
|
5918
|
+
id: context.webviewName,
|
|
5919
|
+
title: page.title,
|
|
5920
|
+
url: page.url,
|
|
5921
|
+
packageName: context.info["Android-Package"],
|
|
5922
|
+
webviewPageId: page.id
|
|
5923
|
+
};
|
|
5924
|
+
result.push(pageData);
|
|
5925
|
+
});
|
|
5926
|
+
}
|
|
5927
|
+
);
|
|
5928
|
+
return result;
|
|
5929
|
+
}
|
|
5930
|
+
async function getCurrentContexts({
|
|
5931
|
+
browser,
|
|
5932
|
+
androidWebviewConnectionRetryTime,
|
|
5933
|
+
androidWebviewConnectTimeout,
|
|
5934
|
+
filterByCurrentAndroidApp,
|
|
5935
|
+
isAndroidWebviewVisible,
|
|
5936
|
+
returnAndroidDescriptionData
|
|
5937
|
+
}) {
|
|
5938
|
+
var _a;
|
|
5939
|
+
const contexts = await browser.execute("mobile: getContexts");
|
|
5940
|
+
if (browser.isIOS) {
|
|
5941
|
+
return contexts;
|
|
5942
|
+
}
|
|
5943
|
+
const packageName = await browser.getCurrentPackage();
|
|
5944
|
+
const startTime = Date.now();
|
|
5945
|
+
const retryInterval = androidWebviewConnectionRetryTime;
|
|
5946
|
+
let isPackageNameMissing = false;
|
|
5947
|
+
while (Date.now() - startTime < androidWebviewConnectTimeout) {
|
|
5948
|
+
const parsedContexts = await parsedAndroidContexts({
|
|
5949
|
+
contexts,
|
|
5950
|
+
filterByCurrentAndroidApp,
|
|
5951
|
+
isAttachedAndVisible: isAndroidWebviewVisible,
|
|
5952
|
+
packageName
|
|
5953
|
+
});
|
|
5954
|
+
const androidContext = parsedContexts.find((context) => context.packageName === packageName);
|
|
5955
|
+
isPackageNameMissing = !(androidContext == null ? void 0 : androidContext.packageName);
|
|
5956
|
+
const isAndroidWebviewDataMissing = androidContext && !("androidWebviewData" in androidContext);
|
|
5957
|
+
const isAndroidWebviewDataEmpty = androidContext && ((_a = androidContext.androidWebviewData) == null ? void 0 : _a.empty);
|
|
5958
|
+
if (packageName === CHROME_PACKAGE_NAME) {
|
|
5959
|
+
return parsedContexts;
|
|
5960
|
+
}
|
|
5961
|
+
if (!isPackageNameMissing && !isAndroidWebviewDataMissing && !isAndroidWebviewDataEmpty) {
|
|
5962
|
+
if (!returnAndroidDescriptionData) {
|
|
5963
|
+
parsedContexts.forEach((context) => {
|
|
5964
|
+
if ("androidWebviewData" in context) {
|
|
5965
|
+
delete context.androidWebviewData;
|
|
5966
|
+
}
|
|
5967
|
+
});
|
|
5968
|
+
}
|
|
5969
|
+
return parsedContexts;
|
|
5970
|
+
}
|
|
5971
|
+
await new Promise((resolve2) => setTimeout(resolve2, retryInterval));
|
|
5972
|
+
}
|
|
5973
|
+
throw new Error(
|
|
5974
|
+
"The packageName '".concat(packageName, "' ").concat(isPackageNameMissing ? "could not be found!" : "matches, but no webview with pages was loaded in this response: " + JSON.stringify(contexts) + "'")
|
|
5975
|
+
);
|
|
5976
|
+
}
|
|
5977
|
+
|
|
5978
|
+
// src/commands/mobile/switchContext.ts
|
|
5979
|
+
import logger20 from "@wdio/logger";
|
|
5980
|
+
var log20 = logger20("webdriver");
|
|
5981
|
+
async function switchContext(options) {
|
|
5982
|
+
const browser = this;
|
|
5983
|
+
if (!browser.isMobile) {
|
|
5984
|
+
throw new Error("The `switchContext` command is only available for mobile platforms.");
|
|
5985
|
+
}
|
|
5986
|
+
if (!options) {
|
|
5987
|
+
throw new Error("You need to provide at least a context name to switch to. See https://webdriver.io/docs/api/mobile/switchContext for more information.");
|
|
5988
|
+
}
|
|
5989
|
+
if (typeof options === "string") {
|
|
5990
|
+
log20.info("The standard Appium `context`-method is used. If you want to switch to a webview with a specific title or url, please provide an object with the `title` or `url` property. See https://webdriver.io/docs/api/mobile/switchContext for more information.");
|
|
5991
|
+
return browser.switchAppiumContext(options);
|
|
5992
|
+
}
|
|
5993
|
+
if (!options.title && !options.url) {
|
|
5994
|
+
throw new Error("You need to provide at least a `title` or `url` property to use full potential of the `switchContext` command. See https://webdriver.io/docs/api/mobile/switchContext for more information.");
|
|
5995
|
+
}
|
|
5996
|
+
return switchToContext({ browser, options });
|
|
5997
|
+
}
|
|
5998
|
+
async function switchToContext({ browser, options }) {
|
|
5999
|
+
var _a;
|
|
6000
|
+
const getContextsOptions = {
|
|
6001
|
+
returnDetailedContexts: true,
|
|
6002
|
+
filterByCurrentAndroidApp: false,
|
|
6003
|
+
isAndroidWebviewVisible: false,
|
|
6004
|
+
returnAndroidDescriptionData: true,
|
|
6005
|
+
...(options == null ? void 0 : options.androidWebviewConnectionRetryTime) && { androidWebviewConnectionRetryTime: options.androidWebviewConnectionRetryTime },
|
|
6006
|
+
...(options == null ? void 0 : options.androidWebviewConnectTimeout) && { androidWebviewConnectTimeout: options.androidWebviewConnectTimeout }
|
|
6007
|
+
};
|
|
6008
|
+
const contexts = await browser.getContexts(getContextsOptions);
|
|
6009
|
+
const identifier = browser.isIOS ? (_a = await browser.execute("mobile: activeAppInfo")) == null ? void 0 : _a.bundleId : await browser.getCurrentPackage();
|
|
6010
|
+
const { matchingContext, reasons } = findMatchingContext({ browser, contexts, identifier, ...(options == null ? void 0 : options.title) && { title: options.title }, ...(options == null ? void 0 : options.url) && { url: options.url } });
|
|
6011
|
+
if (!matchingContext) {
|
|
6012
|
+
throw new Error(reasons.join("\n"));
|
|
6013
|
+
}
|
|
6014
|
+
log20.info("WebdriverIO found a matching context:", JSON.stringify(matchingContext, null, 2));
|
|
6015
|
+
if (!browser.isIOS) {
|
|
6016
|
+
const webviewName = "WEBVIEW_".concat(identifier);
|
|
6017
|
+
await browser.switchAppiumContext(webviewName);
|
|
6018
|
+
}
|
|
6019
|
+
const switchFunction = browser.isIOS ? browser.switchAppiumContext.bind(browser) : browser.switchToWindow.bind(browser);
|
|
6020
|
+
const matchingContextId = browser.isIOS ? matchingContext.id : matchingContext.webviewPageId;
|
|
6021
|
+
return switchFunction(matchingContextId);
|
|
6022
|
+
}
|
|
6023
|
+
function findMatchingContext({
|
|
6024
|
+
browser: { isIOS },
|
|
6025
|
+
contexts,
|
|
6026
|
+
identifier,
|
|
6027
|
+
title,
|
|
6028
|
+
url: url2
|
|
6029
|
+
}) {
|
|
6030
|
+
const reasons = [];
|
|
6031
|
+
reasons.push("We parsed a total of ".concat(contexts.length, " Webviews but did not find a matching context. The reasons are:"));
|
|
6032
|
+
const matchingContext = contexts.find((context, index) => {
|
|
6033
|
+
var _a, _b, _c, _d;
|
|
6034
|
+
reasons.push("- Webview ".concat(index + 1, ": '").concat(context.id, "'"));
|
|
6035
|
+
if (context.id === "NATIVE_APP") {
|
|
6036
|
+
reasons.push(" - Skipped context because it is NATIVE_APP");
|
|
6037
|
+
return false;
|
|
6038
|
+
}
|
|
6039
|
+
const idMatch = isIOS ? context.bundleId === identifier : context.packageName === identifier;
|
|
6040
|
+
const titleMatches = title ? title instanceof RegExp ? title.test(context.title || "") : (_a = context.title) == null ? void 0 : _a.includes(title) : true;
|
|
6041
|
+
const urlMatches = url2 ? url2 instanceof RegExp ? url2.test(context.url || "") : (_b = context.url) == null ? void 0 : _b.includes(url2) : true;
|
|
6042
|
+
const additionalAndroidChecks = isIOS ? true : ((_c = context.androidWebviewData) == null ? void 0 : _c.attached) && ((_d = context.androidWebviewData) == null ? void 0 : _d.visible);
|
|
6043
|
+
if (!idMatch) {
|
|
6044
|
+
reasons.push(" - App ".concat(isIOS ? "bundleId" : "packageName", " '").concat(identifier, "' did not match: '").concat(context.id, "'"));
|
|
6045
|
+
}
|
|
6046
|
+
if (!titleMatches) {
|
|
6047
|
+
reasons.push(" - Title '".concat(title, "' did not match: '").concat(context.title, "'"));
|
|
6048
|
+
}
|
|
6049
|
+
if (!urlMatches) {
|
|
6050
|
+
reasons.push(" - URL '".concat(url2, "' did not match: '").concat(context.url, "'"));
|
|
6051
|
+
}
|
|
6052
|
+
if (!additionalAndroidChecks) {
|
|
6053
|
+
reasons.push(" - Additional Android checks failed");
|
|
6054
|
+
}
|
|
6055
|
+
return idMatch && titleMatches && urlMatches && additionalAndroidChecks;
|
|
6056
|
+
});
|
|
6057
|
+
return { matchingContext, reasons };
|
|
6058
|
+
}
|
|
6059
|
+
|
|
5800
6060
|
// src/commands/element.ts
|
|
5801
6061
|
var element_exports = {};
|
|
5802
6062
|
__export(element_exports, {
|
|
@@ -5881,9 +6141,9 @@ function clearValue() {
|
|
|
5881
6141
|
}
|
|
5882
6142
|
|
|
5883
6143
|
// src/commands/element/click.ts
|
|
5884
|
-
import
|
|
6144
|
+
import logger21 from "@wdio/logger";
|
|
5885
6145
|
import { getBrowserObject as getBrowserObject11 } from "@wdio/utils";
|
|
5886
|
-
var
|
|
6146
|
+
var log21 = logger21("webdriver");
|
|
5887
6147
|
function click(options) {
|
|
5888
6148
|
if (typeof options !== "undefined") {
|
|
5889
6149
|
if (typeof options !== "object" || Array.isArray(options)) {
|
|
@@ -5930,10 +6190,10 @@ async function actionClick(element, options) {
|
|
|
5930
6190
|
if (x || y) {
|
|
5931
6191
|
const { width, height } = await browser.getElementRect(element.elementId);
|
|
5932
6192
|
if (x && x < -Math.floor(width / 2) || x && x > Math.floor(width / 2)) {
|
|
5933
|
-
|
|
6193
|
+
log21.warn("x would cause a out of bounds error as it goes outside of element");
|
|
5934
6194
|
}
|
|
5935
6195
|
if (y && y < -Math.floor(height / 2) || y && y > Math.floor(height / 2)) {
|
|
5936
|
-
|
|
6196
|
+
log21.warn("y would cause a out of bounds error as it goes outside of element");
|
|
5937
6197
|
}
|
|
5938
6198
|
}
|
|
5939
6199
|
const clickNested = async () => {
|
|
@@ -6437,7 +6697,7 @@ async function isClickable() {
|
|
|
6437
6697
|
if (!await this.isDisplayed()) {
|
|
6438
6698
|
return false;
|
|
6439
6699
|
}
|
|
6440
|
-
if (this.isMobile &&
|
|
6700
|
+
if (this.isMobile && this.isNativeContext) {
|
|
6441
6701
|
throw new Error("Method not supported in mobile native environment. It is unlikely that you need to use this command.");
|
|
6442
6702
|
}
|
|
6443
6703
|
const browser = getBrowserObject20(this);
|
|
@@ -6789,18 +7049,18 @@ async function isStable() {
|
|
|
6789
7049
|
}
|
|
6790
7050
|
|
|
6791
7051
|
// src/commands/element/moveTo.ts
|
|
6792
|
-
import
|
|
7052
|
+
import logger22 from "@wdio/logger";
|
|
6793
7053
|
import { getBrowserObject as getBrowserObject25 } from "@wdio/utils";
|
|
6794
|
-
var
|
|
7054
|
+
var log22 = logger22("webdriver");
|
|
6795
7055
|
async function moveTo({ xOffset, yOffset } = {}) {
|
|
6796
7056
|
const browser = getBrowserObject25(this);
|
|
6797
7057
|
if (xOffset || yOffset) {
|
|
6798
7058
|
const { width, height } = await browser.getElementRect(this.elementId);
|
|
6799
7059
|
if (xOffset && xOffset < -Math.floor(width / 2) || xOffset && xOffset > Math.floor(width / 2)) {
|
|
6800
|
-
|
|
7060
|
+
log22.warn("xOffset would cause a out of bounds error as it goes outside of element");
|
|
6801
7061
|
}
|
|
6802
7062
|
if (yOffset && yOffset < -Math.floor(height / 2) || yOffset && yOffset > Math.floor(height / 2)) {
|
|
6803
|
-
|
|
7063
|
+
log22.warn("yOffset would cause a out of bounds error as it goes outside of element");
|
|
6804
7064
|
}
|
|
6805
7065
|
}
|
|
6806
7066
|
const moveToNested = async () => {
|
|
@@ -6884,10 +7144,10 @@ async function saveScreenshot2(filepath) {
|
|
|
6884
7144
|
}
|
|
6885
7145
|
|
|
6886
7146
|
// src/commands/element/scrollIntoView.ts
|
|
6887
|
-
import
|
|
7147
|
+
import logger23 from "@wdio/logger";
|
|
6888
7148
|
import { ELEMENT_KEY as ELEMENT_KEY17 } from "webdriver";
|
|
6889
7149
|
import { getBrowserObject as getBrowserObject28 } from "@wdio/utils";
|
|
6890
|
-
var
|
|
7150
|
+
var log23 = logger23("webdriverio");
|
|
6891
7151
|
async function scrollIntoView(options = { block: "start", inline: "nearest" }) {
|
|
6892
7152
|
const browser = getBrowserObject28(this);
|
|
6893
7153
|
if (browser.isMobile) {
|
|
@@ -6940,7 +7200,7 @@ async function scrollIntoView(options = { block: "start", inline: "nearest" }) {
|
|
|
6940
7200
|
deltaY = Math.round(deltaY - scrollY2);
|
|
6941
7201
|
await browser.action("wheel").scroll({ duration: 0, x: deltaX, y: deltaY, origin: this }).perform();
|
|
6942
7202
|
} catch (err) {
|
|
6943
|
-
|
|
7203
|
+
log23.warn(
|
|
6944
7204
|
'Failed to execute "scrollIntoView" using WebDriver Actions API: '.concat(err.message, "!\n") + "Re-attempting using `Element.scrollIntoView` via Web API."
|
|
6945
7205
|
);
|
|
6946
7206
|
await scrollIntoViewWeb.call(this, options);
|
|
@@ -7078,7 +7338,7 @@ async function setValue(value) {
|
|
|
7078
7338
|
}
|
|
7079
7339
|
|
|
7080
7340
|
// src/commands/element/shadow$$.ts
|
|
7081
|
-
import
|
|
7341
|
+
import logger24 from "@wdio/logger";
|
|
7082
7342
|
import { getBrowserObject as getBrowserObject29 } from "@wdio/utils";
|
|
7083
7343
|
import { SHADOW_ELEMENT_KEY } from "webdriver";
|
|
7084
7344
|
|
|
@@ -7414,7 +7674,7 @@ var createRoleBaseXpathSelector = (role) => {
|
|
|
7414
7674
|
};
|
|
7415
7675
|
|
|
7416
7676
|
// src/commands/element/shadow$$.ts
|
|
7417
|
-
var
|
|
7677
|
+
var log24 = logger24("webdriverio");
|
|
7418
7678
|
async function shadow$$(selector) {
|
|
7419
7679
|
const browser = getBrowserObject29(this);
|
|
7420
7680
|
try {
|
|
@@ -7424,7 +7684,7 @@ async function shadow$$(selector) {
|
|
|
7424
7684
|
const elements = await getElements.call(this, selector, res, { isShadowElement: true });
|
|
7425
7685
|
return enhanceElementsArray(elements, this, selector);
|
|
7426
7686
|
} catch (err) {
|
|
7427
|
-
|
|
7687
|
+
log24.warn(
|
|
7428
7688
|
"Failed to fetch element within shadow DOM using WebDriver command: ".concat(err.message, "!\n") + "Falling back to JavaScript shim."
|
|
7429
7689
|
);
|
|
7430
7690
|
return await this.$$(shadowFnFactory(selector, true));
|
|
@@ -7432,10 +7692,10 @@ async function shadow$$(selector) {
|
|
|
7432
7692
|
}
|
|
7433
7693
|
|
|
7434
7694
|
// src/commands/element/shadow$.ts
|
|
7435
|
-
import
|
|
7695
|
+
import logger25 from "@wdio/logger";
|
|
7436
7696
|
import { SHADOW_ELEMENT_KEY as SHADOW_ELEMENT_KEY2 } from "webdriver";
|
|
7437
7697
|
import { getBrowserObject as getBrowserObject30 } from "@wdio/utils";
|
|
7438
|
-
var
|
|
7698
|
+
var log25 = logger25("webdriverio");
|
|
7439
7699
|
async function shadow$(selector) {
|
|
7440
7700
|
const browser = getBrowserObject30(this);
|
|
7441
7701
|
try {
|
|
@@ -7444,7 +7704,7 @@ async function shadow$(selector) {
|
|
|
7444
7704
|
const res = await browser.findElementFromShadowRoot(shadowRoot[SHADOW_ELEMENT_KEY2], using, value);
|
|
7445
7705
|
return getElement.call(this, selector, res, { isShadowElement: true });
|
|
7446
7706
|
} catch (err) {
|
|
7447
|
-
|
|
7707
|
+
log25.warn(
|
|
7448
7708
|
"Failed to fetch element within shadow DOM using WebDriver command: ".concat(err.message, "!\n") + "Falling back to JavaScript shim."
|
|
7449
7709
|
);
|
|
7450
7710
|
return this.$(shadowFnFactory(selector));
|
|
@@ -7818,7 +8078,7 @@ function querySelectorAllDeep(findMany, s, r) {
|
|
|
7818
8078
|
}
|
|
7819
8079
|
|
|
7820
8080
|
// src/utils/index.ts
|
|
7821
|
-
var
|
|
8081
|
+
var log26 = logger26("webdriverio");
|
|
7822
8082
|
var INVALID_SELECTOR_ERROR = "selector needs to be typeof `string` or `function`";
|
|
7823
8083
|
var IGNORED_COMMAND_FILE_EXPORTS = ["SESSION_MOCKS", "CDP_SESSIONS"];
|
|
7824
8084
|
var scopes = {
|
|
@@ -7987,7 +8247,7 @@ async function findDeepElement(selector) {
|
|
|
7987
8247
|
})).then((elems) => elems.filter(([isIn]) => isIn).map(([, elem]) => elem));
|
|
7988
8248
|
return scopedNodes[0];
|
|
7989
8249
|
}, (err) => {
|
|
7990
|
-
|
|
8250
|
+
log26.warn("Failed to execute browser.browsingContextLocateNodes({ ... }) due to ".concat(err, ", falling back to regular WebDriver Classic command"));
|
|
7991
8251
|
return this && "elementId" in this && this.elementId ? this.findElementFromElement(this.elementId, using, value) : browser.findElement(using, value);
|
|
7992
8252
|
});
|
|
7993
8253
|
if (!deepElementResult) {
|
|
@@ -8025,7 +8285,7 @@ async function findDeepElements(selector) {
|
|
|
8025
8285
|
})).then((elems) => elems.filter(([isIn]) => isIn).map(([, elem]) => elem));
|
|
8026
8286
|
return scopedNodes;
|
|
8027
8287
|
}, (err) => {
|
|
8028
|
-
|
|
8288
|
+
log26.warn("Failed to execute browser.browsingContextLocateNodes({ ... }) due to ".concat(err, ", falling back to regular WebDriver Classic command"));
|
|
8029
8289
|
return this && "elementId" in this && this.elementId ? this.findElementsFromElement(this.elementId, using, value) : browser.findElements(using, value);
|
|
8030
8290
|
});
|
|
8031
8291
|
return deepElementResult;
|
|
@@ -8153,7 +8413,7 @@ async function getElementRect(scope) {
|
|
|
8153
8413
|
if (rectJs && typeof rectJs[key] === "number") {
|
|
8154
8414
|
rect[key] = Math.floor(rectJs[key]);
|
|
8155
8415
|
} else {
|
|
8156
|
-
|
|
8416
|
+
log26.error("getElementRect", { rect, rectJs, key });
|
|
8157
8417
|
throw new Error("Failed to receive element rects via execute command");
|
|
8158
8418
|
}
|
|
8159
8419
|
});
|
|
@@ -8599,7 +8859,7 @@ var remote = async function(params, remoteModifier) {
|
|
|
8599
8859
|
const keysToKeep = Object.keys(process.env.WDIO_WORKER_ID ? params : DEFAULTS);
|
|
8600
8860
|
const config = validateConfig(WDIO_DEFAULTS, params, keysToKeep);
|
|
8601
8861
|
await enableFileLogging(config.outputDir);
|
|
8602
|
-
|
|
8862
|
+
logger27.setLogLevelsConfig(config.logLevels, config.logLevel);
|
|
8603
8863
|
const modifier = (client, options2) => {
|
|
8604
8864
|
Object.assign(options2, Object.entries(config).reduce((a, [k, v]) => typeof v === "undefined" ? a : { ...a, [k]: v }, {}));
|
|
8605
8865
|
if (typeof remoteModifier === "function") {
|