webdriverio 9.18.4 → 9.19.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.
@@ -1 +1 @@
1
- {"version":3,"file":"switchFrame.d.ts","sourceRoot":"","sources":["../../../src/commands/browser/switchFrame.ts"],"names":[],"mappings":"AAIA,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAIlF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAI7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,wBAAsB,WAAW,CAC7B,IAAI,EAAE,WAAW,CAAC,OAAO,EACzB,OAAO,EAAE,WAAW,CAAC,OAAO,GAAG,uBAAuB,GAAG,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,eAAe,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,GACjI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6PxB"}
1
+ {"version":3,"file":"switchFrame.d.ts","sourceRoot":"","sources":["../../../src/commands/browser/switchFrame.ts"],"names":[],"mappings":"AAIA,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAIlF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAK7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,wBAAsB,WAAW,CAC7B,IAAI,EAAE,WAAW,CAAC,OAAO,EACzB,OAAO,EAAE,WAAW,CAAC,OAAO,GAAG,uBAAuB,GAAG,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,eAAe,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,GACjI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwRxB"}
@@ -3,7 +3,7 @@ import type { LongPressOptions } from '../../types.js';
3
3
  *
4
4
  * Performs a long press gesture on the given element on the screen.
5
5
  *
6
- * This issues a WebDriver `action` command for the selected element. It is based on the `click` command.
6
+ * This issues a WebDriver `action` command for the selected element. It is based on the `click` command, except for iOS web context, there we use a script to simulate the long press due to the lack of support for long press gestures in webview.
7
7
  *
8
8
  * :::info
9
9
  *
@@ -1 +1 @@
1
- {"version":3,"file":"longPress.d.ts","sourceRoot":"","sources":["../../../src/commands/mobile/longPress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,SAAS,CACrB,IAAI,EAAE,WAAW,CAAC,OAAO,EACzB,OAAO,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,iBAwBtC"}
1
+ {"version":3,"file":"longPress.d.ts","sourceRoot":"","sources":["../../../src/commands/mobile/longPress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,SAAS,CACrB,IAAI,EAAE,WAAW,CAAC,OAAO,EACzB,OAAO,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,iBA+CtC"}
package/build/index.js CHANGED
@@ -3070,22 +3070,15 @@ onCommand_fn = function(ev) {
3070
3070
  };
3071
3071
 
3072
3072
  // src/utils/mobile.ts
3073
- var appiumKeys = ["app", "bundleId", "appPackage", "appActivity", "appWaitActivity", "appWaitPackage"];
3074
3073
  function getNativeContext({ capabilities, isMobile }) {
3075
3074
  var _a, _b;
3076
3075
  if (!capabilities || typeof capabilities !== "object" || !isMobile) {
3077
3076
  return false;
3078
3077
  }
3079
- const isAppiumAppCapPresent = (capabilities2) => {
3080
- return appiumKeys.some((key) => {
3081
- var _a2, _b2;
3082
- return capabilities2[key] !== void 0 || ((_a2 = capabilities2["appium:options"]) == null ? void 0 : _a2[key]) !== void 0 || ((_b2 = capabilities2["lt:options"]) == null ? void 0 : _b2[key]) !== void 0;
3083
- });
3084
- };
3085
3078
  const isBrowserNameFalse = !!(capabilities == null ? void 0 : capabilities.browserName) === false;
3086
3079
  const isAutoWebviewFalse = !// @ts-expect-error
3087
3080
  ((capabilities == null ? void 0 : capabilities.autoWebview) === true || capabilities["appium:autoWebview"] === true || ((_a = capabilities["appium:options"]) == null ? void 0 : _a.autoWebview) === true || ((_b = capabilities["lt:options"]) == null ? void 0 : _b.autoWebview) === true);
3088
- return isBrowserNameFalse && isAppiumAppCapPresent(capabilities) && isAutoWebviewFalse;
3081
+ return isBrowserNameFalse && isMobile && isAutoWebviewFalse;
3089
3082
  }
3090
3083
  function getMobileContext({ capabilities, isAndroid, isNativeContext }) {
3091
3084
  var _a;
@@ -3299,7 +3292,7 @@ _getContextSupport = new WeakMap();
3299
3292
  _ContextManager_instances = new WeakSet();
3300
3293
  onCommandResultBidiAndClassic_fn = function(event) {
3301
3294
  if (event.command === "closeWindow") {
3302
- const windowHandles = event.result.value;
3295
+ const windowHandles = event.result.value || [];
3303
3296
  if (windowHandles.length === 0) {
3304
3297
  throw new Error("All window handles were removed, causing WebdriverIO to close the session.");
3305
3298
  }
@@ -5235,8 +5228,35 @@ async function switchWindow(matcher) {
5235
5228
  // src/commands/browser/switchFrame.ts
5236
5229
  import logger14 from "@wdio/logger";
5237
5230
  import { ELEMENT_KEY as ELEMENT_KEY8 } from "webdriver";
5231
+
5232
+ // src/scripts/shadowDom.ts
5233
+ function findIframeInShadowDOM(fragment) {
5234
+ function findIframe(root) {
5235
+ const allElements = Array.from(root.querySelectorAll("iframe"));
5236
+ for (const el of allElements) {
5237
+ if (el instanceof HTMLIFrameElement && el.src.includes(fragment)) {
5238
+ return el;
5239
+ }
5240
+ }
5241
+ const shadowHosts = Array.from(root.querySelectorAll("*"));
5242
+ for (const host of shadowHosts) {
5243
+ const maybeShadowRoot = host.shadowRoot;
5244
+ if (maybeShadowRoot) {
5245
+ const result = findIframe(maybeShadowRoot);
5246
+ if (result) {
5247
+ return result;
5248
+ }
5249
+ }
5250
+ }
5251
+ return null;
5252
+ }
5253
+ return findIframe(document);
5254
+ }
5255
+
5256
+ // src/commands/browser/switchFrame.ts
5238
5257
  var log14 = logger14("webdriverio:switchFrame");
5239
5258
  async function switchFrame(context) {
5259
+ var _a;
5240
5260
  function isPossiblyUnresolvedElement(input) {
5241
5261
  return Boolean(input) && typeof input === "object" && typeof input.getElement === "function";
5242
5262
  }
@@ -5297,8 +5317,8 @@ async function switchFrame(context) {
5297
5317
  context: id
5298
5318
  }).catch(() => ({ nodes: [] }));
5299
5319
  return Promise.all(nodes.map(async (node) => {
5300
- var _a;
5301
- const html = "<iframe".concat(Object.entries(((_a = node.value) == null ? void 0 : _a.attributes) || {}).reduce((acc, [key, value]) => "".concat(acc, " ").concat(key, '="').concat(value, '"'), " "), "></iframe>");
5320
+ var _a2;
5321
+ const html = "<iframe".concat(Object.entries(((_a2 = node.value) == null ? void 0 : _a2.attributes) || {}).reduce((acc, [key, value]) => "".concat(acc, " ").concat(key, '="').concat(value, '"'), " "), "></iframe>");
5302
5322
  const args = [{ [ELEMENT_KEY8]: node.sharedId }];
5303
5323
  const userScript = (iframe) => iframe.contentWindow;
5304
5324
  const functionDeclaration = new Function("\n return (".concat(SCRIPT_PREFIX).concat(userScript.toString()).concat(SCRIPT_SUFFIX, ").apply(this, arguments);\n ")).toString();
@@ -5335,6 +5355,17 @@ async function switchFrame(context) {
5335
5355
  };
5336
5356
  }));
5337
5357
  }))).flat(Infinity);
5358
+ if (allFrames.length === 0) {
5359
+ const urlFragment = typeof context === "string" ? (_a = context.split("/").pop()) != null ? _a : "" : "";
5360
+ const iframeFound = await this.execute(findIframeInShadowDOM, urlFragment);
5361
+ if (iframeFound && typeof iframeFound === "object" && iframeFound[ELEMENT_KEY8]) {
5362
+ const iframeElement = await this.$(iframeFound);
5363
+ if (iframeElement) {
5364
+ return this.switchFrame(iframeElement);
5365
+ }
5366
+ }
5367
+ log14.warn('Shadow DOM iframe with src containing "'.concat(urlFragment, '" found, but could not be resolved into a WebdriverIO element.'));
5368
+ }
5338
5369
  let desiredFrame;
5339
5370
  let desiredContext = newContextId;
5340
5371
  const contextQueue = [];
@@ -8042,6 +8073,28 @@ function longPress(options) {
8042
8073
  y: 0
8043
8074
  };
8044
8075
  const { duration, x, y } = { ...defaultOptions, ...options };
8076
+ if (!browser.isNativeContext && browser.isIOS) {
8077
+ return browser.execute(
8078
+ (el, duration2) => {
8079
+ const touchStart = new TouchEvent("touchstart", {
8080
+ touches: [new Touch({ identifier: 0, target: el, clientX: 0, clientY: 0 })],
8081
+ bubbles: true,
8082
+ cancelable: true
8083
+ });
8084
+ el.dispatchEvent(touchStart);
8085
+ setTimeout(() => {
8086
+ const touchEnd = new TouchEvent("touchend", {
8087
+ changedTouches: [new Touch({ identifier: 0, target: el, clientX: 0, clientY: 0 })],
8088
+ bubbles: true,
8089
+ cancelable: true
8090
+ });
8091
+ el.dispatchEvent(touchEnd);
8092
+ }, duration2);
8093
+ },
8094
+ this,
8095
+ duration
8096
+ );
8097
+ }
8045
8098
  return this.click({ duration, x, y });
8046
8099
  }
8047
8100
 
package/build/node.js CHANGED
@@ -232,18 +232,14 @@ var SessionManager = class {
232
232
  };
233
233
 
234
234
  // src/utils/mobile.ts
235
- var appiumKeys = ["app", "bundleId", "appPackage", "appActivity", "appWaitActivity", "appWaitPackage"];
236
235
  function getNativeContext({ capabilities, isMobile }) {
237
236
  if (!capabilities || typeof capabilities !== "object" || !isMobile) {
238
237
  return false;
239
238
  }
240
- const isAppiumAppCapPresent = (capabilities2) => {
241
- return appiumKeys.some((key) => capabilities2[key] !== void 0 || capabilities2["appium:options"]?.[key] !== void 0 || capabilities2["lt:options"]?.[key] !== void 0);
242
- };
243
239
  const isBrowserNameFalse = !!capabilities?.browserName === false;
244
240
  const isAutoWebviewFalse = !// @ts-expect-error
245
241
  (capabilities?.autoWebview === true || capabilities["appium:autoWebview"] === true || capabilities["appium:options"]?.autoWebview === true || capabilities["lt:options"]?.autoWebview === true);
246
- return isBrowserNameFalse && isAppiumAppCapPresent(capabilities) && isAutoWebviewFalse;
242
+ return isBrowserNameFalse && isMobile && isAutoWebviewFalse;
247
243
  }
248
244
  function getMobileContext({ capabilities, isAndroid, isNativeContext }) {
249
245
  return isNativeContext ? "NATIVE_APP" : (
@@ -340,7 +336,7 @@ var ContextManager = class _ContextManager extends SessionManager {
340
336
  }
341
337
  #onCommandResultBidiAndClassic(event) {
342
338
  if (event.command === "closeWindow") {
343
- const windowHandles = event.result.value;
339
+ const windowHandles = event.result.value || [];
344
340
  if (windowHandles.length === 0) {
345
341
  throw new Error("All window handles were removed, causing WebdriverIO to close the session.");
346
342
  }
@@ -5286,6 +5282,7 @@ async function switchWindow(matcher) {
5286
5282
  // src/commands/browser/switchFrame.ts
5287
5283
  import logger15 from "@wdio/logger";
5288
5284
  import { ELEMENT_KEY as ELEMENT_KEY8 } from "webdriver";
5285
+ import findIframeInShadowDOM from "./scripts/shadowDom.js";
5289
5286
  var log15 = logger15("webdriverio:switchFrame");
5290
5287
  async function switchFrame(context) {
5291
5288
  function isPossiblyUnresolvedElement(input) {
@@ -5387,6 +5384,17 @@ async function switchFrame(context) {
5387
5384
  };
5388
5385
  }));
5389
5386
  }))).flat(Infinity);
5387
+ if (allFrames.length === 0) {
5388
+ const urlFragment = typeof context === "string" ? context.split("/").pop() ?? "" : "";
5389
+ const iframeFound = await this.execute(findIframeInShadowDOM, urlFragment);
5390
+ if (iframeFound && typeof iframeFound === "object" && iframeFound[ELEMENT_KEY8]) {
5391
+ const iframeElement = await this.$(iframeFound);
5392
+ if (iframeElement) {
5393
+ return this.switchFrame(iframeElement);
5394
+ }
5395
+ }
5396
+ log15.warn(`Shadow DOM iframe with src containing "${urlFragment}" found, but could not be resolved into a WebdriverIO element.`);
5397
+ }
5390
5398
  let desiredFrame;
5391
5399
  let desiredContext = newContextId;
5392
5400
  const contextQueue = [];
@@ -7768,6 +7776,28 @@ function longPress(options) {
7768
7776
  y: 0
7769
7777
  };
7770
7778
  const { duration, x, y } = { ...defaultOptions, ...options };
7779
+ if (!browser.isNativeContext && browser.isIOS) {
7780
+ return browser.execute(
7781
+ (el, duration2) => {
7782
+ const touchStart = new TouchEvent("touchstart", {
7783
+ touches: [new Touch({ identifier: 0, target: el, clientX: 0, clientY: 0 })],
7784
+ bubbles: true,
7785
+ cancelable: true
7786
+ });
7787
+ el.dispatchEvent(touchStart);
7788
+ setTimeout(() => {
7789
+ const touchEnd = new TouchEvent("touchend", {
7790
+ changedTouches: [new Touch({ identifier: 0, target: el, clientX: 0, clientY: 0 })],
7791
+ bubbles: true,
7792
+ cancelable: true
7793
+ });
7794
+ el.dispatchEvent(touchEnd);
7795
+ }, duration2);
7796
+ },
7797
+ this,
7798
+ duration
7799
+ );
7800
+ }
7771
7801
  return this.click({ duration, x, y });
7772
7802
  }
7773
7803
 
@@ -0,0 +1,6 @@
1
+ /**
2
+ * This function will be stringified and executed in the browser context.
3
+ * It searches for an <iframe> element within any nested Shadow DOM that contains the given URL fragment.
4
+ */
5
+ export default function findIframeInShadowDOM(fragment: string): HTMLIFrameElement | null;
6
+ //# sourceMappingURL=shadowDom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shadowDom.d.ts","sourceRoot":"","sources":["../../src/scripts/shadowDom.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAuBxF"}
@@ -0,0 +1,26 @@
1
+ // src/scripts/shadowDom.ts
2
+ function findIframeInShadowDOM(fragment) {
3
+ function findIframe(root) {
4
+ const allElements = Array.from(root.querySelectorAll("iframe"));
5
+ for (const el of allElements) {
6
+ if (el instanceof HTMLIFrameElement && el.src.includes(fragment)) {
7
+ return el;
8
+ }
9
+ }
10
+ const shadowHosts = Array.from(root.querySelectorAll("*"));
11
+ for (const host of shadowHosts) {
12
+ const maybeShadowRoot = host.shadowRoot;
13
+ if (maybeShadowRoot) {
14
+ const result = findIframe(maybeShadowRoot);
15
+ if (result) {
16
+ return result;
17
+ }
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+ return findIframe(document);
23
+ }
24
+ export {
25
+ findIframeInShadowDOM as default
26
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"mobile.d.ts","sourceRoot":"","sources":["../../src/utils/mobile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAKtD,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,EAC3D;IAAE,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAC1D,OAAO,CAsBT;AAED,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,EAC7E;IAAE,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,GACrF,MAAM,GAAG,SAAS,CAMpB;AAED,wBAAgB,iCAAiC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,EAC9E;IAAE,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC9D,MAAM,CAUR;AAED,wBAAgB,2BAA2B,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EACzE;IAAE,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAA;CAAE,GAC/F;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CA4BrC"}
1
+ {"version":3,"file":"mobile.d.ts","sourceRoot":"","sources":["../../src/utils/mobile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEtD,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,EAC3D;IAAE,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAC1D,OAAO,CAeT;AAED,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,EAC7E;IAAE,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,GACrF,MAAM,GAAG,SAAS,CAMpB;AAED,wBAAgB,iCAAiC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,EAC9E;IAAE,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC9D,MAAM,CAUR;AAED,wBAAgB,2BAA2B,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EACzE;IAAE,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAA;CAAE,GAC/F;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CA4BrC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "webdriverio",
3
3
  "description": "Next-gen browser and mobile automation test framework for Node.js",
4
- "version": "9.18.4",
4
+ "version": "9.19.0",
5
5
  "homepage": "https://webdriver.io",
6
6
  "author": "Christian Bromann <mail@bromann.dev>",
7
7
  "license": "MIT",
@@ -77,12 +77,12 @@
77
77
  "dependencies": {
78
78
  "@types/node": "^20.11.30",
79
79
  "@types/sinonjs__fake-timers": "^8.1.5",
80
- "@wdio/config": "9.18.0",
80
+ "@wdio/config": "9.19.0",
81
81
  "@wdio/logger": "9.18.0",
82
82
  "@wdio/protocols": "9.16.2",
83
83
  "@wdio/repl": "9.16.2",
84
- "@wdio/types": "9.16.2",
85
- "@wdio/utils": "9.18.0",
84
+ "@wdio/types": "9.19.0",
85
+ "@wdio/utils": "9.19.0",
86
86
  "archiver": "^7.0.1",
87
87
  "aria-query": "^5.3.0",
88
88
  "cheerio": "^1.0.0-rc.12",
@@ -99,7 +99,7 @@
99
99
  "rgb2hex": "0.2.5",
100
100
  "serialize-error": "^12.0.0",
101
101
  "urlpattern-polyfill": "^10.0.0",
102
- "webdriver": "9.18.0"
102
+ "webdriver": "9.19.0"
103
103
  },
104
104
  "peerDependencies": {
105
105
  "puppeteer-core": ">=22.x || <=24.x"
@@ -109,5 +109,5 @@
109
109
  "optional": true
110
110
  }
111
111
  },
112
- "gitHead": "a319103a2aa58659d427c7e475a97ffadab5df60"
112
+ "gitHead": "be9a42358a6646d48c3ce5a341761f55aa605b24"
113
113
  }