webdriverio 9.1.4 → 9.2.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.
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type local } from 'webdriver';
|
|
2
|
+
import type { ChainablePromiseElement } from '../../types.js';
|
|
3
|
+
type FlatContextTree = Omit<local.BrowsingContextInfo, 'children'> & {
|
|
4
|
+
children: string[];
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Switches the active context to a frame, e.g. an iframe on the page. There are multiple ways you can query a frame
|
|
8
|
+
* on the page:
|
|
9
|
+
*
|
|
10
|
+
* - If given a string it switches to the frame with a matching context id, url or url that contains that string
|
|
11
|
+
* ```ts
|
|
12
|
+
* // switch to a frame that has the url "https://the-internet.herokuapp.com/iframe"
|
|
13
|
+
* await browser.switchFrame('https://the-internet.herokuapp.com/iframe')
|
|
14
|
+
* // switch to a frame that has a certain context id
|
|
15
|
+
* await browser.switchFrame('A5734774C41F8C91D483BDD4022B2EF3')
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* - If given a WebdriverIO element that references an `iframe` element it will switch to that frame
|
|
19
|
+
* ```ts
|
|
20
|
+
* // switch to a frame element queried from current context
|
|
21
|
+
* await browser.switchFrame($('iframe'))
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* - If given a function it will loop through all iframes on the page and call the function with the context
|
|
25
|
+
* object. The function should return a boolean indicating if the frame should be selected. Within the function
|
|
26
|
+
* you can use WebdriverIO commands to e.g. check if a certain frame element exists.
|
|
27
|
+
* ```ts
|
|
28
|
+
* // switch to first frame that contains an element with id "#frameContent"
|
|
29
|
+
* await browser.switchFrame(() => $('#frameContent').isExisting())
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* - If given `null` it will switch to the top level frame
|
|
33
|
+
* ```ts
|
|
34
|
+
* // first switch into a frame
|
|
35
|
+
* await browser.switchFrame($('iframe'))
|
|
36
|
+
* // do more automation within that frame, then ...
|
|
37
|
+
*
|
|
38
|
+
* // switch to the top level frame
|
|
39
|
+
* await browser.switchFrame(null)
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @alias browser.switchFrame
|
|
43
|
+
* @param {string|object|function} context
|
|
44
|
+
* @returns {Promise<string>} the current active context id
|
|
45
|
+
*/
|
|
46
|
+
export declare function switchFrame(this: WebdriverIO.Browser, context: WebdriverIO.Element | ChainablePromiseElement | string | null | ((tree: FlatContextTree) => boolean | Promise<boolean>)): Promise<string | ((tree: FlatContextTree) => boolean | Promise<boolean>)>;
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=switchFrame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switchFrame.d.ts","sourceRoot":"","sources":["../../../src/commands/browser/switchFrame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,WAAW,CAAA;AAGtC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAE7D,KAAK,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE,UAAU,CAAC,GAAG;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAE3F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;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,4BAA/C,eAAe,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAgFlI"}
|
|
@@ -34,6 +34,7 @@ export * from './browser/setTimeout.js';
|
|
|
34
34
|
export * from './browser/setViewport.js';
|
|
35
35
|
export * from './browser/setWindowSize.js';
|
|
36
36
|
export * from './browser/switchWindow.js';
|
|
37
|
+
export * from './browser/switchFrame.js';
|
|
37
38
|
export * from './browser/throttle.js';
|
|
38
39
|
export * from './browser/throttleCPU.js';
|
|
39
40
|
export * from './browser/throttleNetwork.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/commands/browser.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,qBAAqB,CAAA;AACnC,cAAc,sBAAsB,CAAA;AACpC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,2BAA2B,CAAA;AACzC,cAAc,yBAAyB,CAAA;AACvC,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,2BAA2B,CAAA;AACzC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,kCAAkC,CAAA;AAChD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA;AACnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kBAAkB,CAAA;AAChC,cAAc,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/commands/browser.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,qBAAqB,CAAA;AACnC,cAAc,sBAAsB,CAAA;AACpC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AACpC,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,2BAA2B,CAAA;AACzC,cAAc,yBAAyB,CAAA;AACvC,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,2BAA2B,CAAA;AACzC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,sBAAsB,CAAA;AACpC,cAAc,qBAAqB,CAAA;AACnC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,kCAAkC,CAAA;AAChD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA;AACnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kBAAkB,CAAA;AAChC,cAAc,wBAAwB,CAAA"}
|
package/build/index.js
CHANGED
|
@@ -122,6 +122,7 @@ __export(browser_exports, {
|
|
|
122
122
|
setTimeout: () => setTimeout2,
|
|
123
123
|
setViewport: () => setViewport,
|
|
124
124
|
setWindowSize: () => setWindowSize,
|
|
125
|
+
switchFrame: () => switchFrame,
|
|
125
126
|
switchWindow: () => switchWindow,
|
|
126
127
|
throttle: () => throttle,
|
|
127
128
|
throttleCPU: () => throttleCPU,
|
|
@@ -885,7 +886,7 @@ async function addInitScript(script, ...args) {
|
|
|
885
886
|
throw new Error("This command is only supported when automating browser using WebDriver Bidi protocol");
|
|
886
887
|
}
|
|
887
888
|
const serializedParameters = (args || []).map((arg) => JSON.stringify(arg));
|
|
888
|
-
const
|
|
889
|
+
const context2 = await this.getWindowHandle();
|
|
889
890
|
const fn = `(emit) => {
|
|
890
891
|
const closure = new Function(\`return ${script.toString()}\`)
|
|
891
892
|
return closure()(${serializedParameters.length ? `${serializedParameters.join(", ")}, emit` : "emit"})
|
|
@@ -897,7 +898,7 @@ async function addInitScript(script, ...args) {
|
|
|
897
898
|
type: "channel",
|
|
898
899
|
value: { channel }
|
|
899
900
|
}],
|
|
900
|
-
contexts: [
|
|
901
|
+
contexts: [context2]
|
|
901
902
|
});
|
|
902
903
|
await this.sessionSubscribe({
|
|
903
904
|
events: ["script.message"]
|
|
@@ -971,13 +972,13 @@ function debug(commandTimeout = 5e3) {
|
|
|
971
972
|
const { introMessage } = WDIORepl;
|
|
972
973
|
if (!process.env.WDIO_WORKER_ID || typeof process.send !== "function") {
|
|
973
974
|
console.log(WDIORepl.introMessage);
|
|
974
|
-
const
|
|
975
|
+
const context2 = {
|
|
975
976
|
browser: this,
|
|
976
977
|
driver: this,
|
|
977
978
|
$: this.$.bind(this),
|
|
978
979
|
$$: this.$$.bind(this)
|
|
979
980
|
};
|
|
980
|
-
return repl.start(
|
|
981
|
+
return repl.start(context2);
|
|
981
982
|
}
|
|
982
983
|
process._debugProcess(process.pid);
|
|
983
984
|
process.send({
|
|
@@ -3012,15 +3013,15 @@ var ContextManager = class {
|
|
|
3012
3013
|
*
|
|
3013
3014
|
* @param {local.BrowsingContextNavigationInfo} context browsing context used to navigate
|
|
3014
3015
|
*/
|
|
3015
|
-
async #handleNavigationStarted(
|
|
3016
|
+
async #handleNavigationStarted(context2) {
|
|
3016
3017
|
const windowHandle = await this.#browser.getWindowHandle();
|
|
3017
|
-
if (
|
|
3018
|
-
log4.info(`Update current context: ${
|
|
3019
|
-
this.#currentContext =
|
|
3018
|
+
if (context2.context === windowHandle && context2.url !== "UNKNOWN") {
|
|
3019
|
+
log4.info(`Update current context: ${context2.context}`);
|
|
3020
|
+
this.#currentContext = context2.context;
|
|
3020
3021
|
}
|
|
3021
3022
|
}
|
|
3022
|
-
setCurrentContext(
|
|
3023
|
-
this.#currentContext =
|
|
3023
|
+
setCurrentContext(context2) {
|
|
3024
|
+
this.#currentContext = context2;
|
|
3024
3025
|
}
|
|
3025
3026
|
async getCurrentContext() {
|
|
3026
3027
|
if (!this.#currentContext) {
|
|
@@ -3076,7 +3077,7 @@ async function execute(script, ...args) {
|
|
|
3076
3077
|
if (this.isBidi && !this.isMultiremote) {
|
|
3077
3078
|
const browser = getBrowserObject2(this);
|
|
3078
3079
|
const contextManager2 = getContextManager(browser);
|
|
3079
|
-
const
|
|
3080
|
+
const context2 = await contextManager2.getCurrentContext();
|
|
3080
3081
|
const userScript = typeof script === "string" ? new Function(script) : script;
|
|
3081
3082
|
const functionDeclaration = new Function(`
|
|
3082
3083
|
return (${SCRIPT_PREFIX}${userScript.toString()}${SCRIPT_SUFFIX}).apply(this, arguments);
|
|
@@ -3086,7 +3087,7 @@ async function execute(script, ...args) {
|
|
|
3086
3087
|
awaitPromise: true,
|
|
3087
3088
|
arguments: args.map((arg) => LocalValue.getArgument(arg)),
|
|
3088
3089
|
target: {
|
|
3089
|
-
context
|
|
3090
|
+
context: context2
|
|
3090
3091
|
}
|
|
3091
3092
|
};
|
|
3092
3093
|
const result = await browser.scriptCallFunction(params);
|
|
@@ -3110,7 +3111,7 @@ async function executeAsync(script, ...args) {
|
|
|
3110
3111
|
if (this.isBidi && !this.isMultiremote) {
|
|
3111
3112
|
const browser = getBrowserObject3(this);
|
|
3112
3113
|
const contextManager2 = getContextManager(browser);
|
|
3113
|
-
const
|
|
3114
|
+
const context2 = await contextManager2.getCurrentContext();
|
|
3114
3115
|
const userScript = typeof script === "string" ? new Function(script) : script;
|
|
3115
3116
|
const functionDeclaration = new Function(`
|
|
3116
3117
|
const args = Array.from(arguments)
|
|
@@ -3128,7 +3129,7 @@ async function executeAsync(script, ...args) {
|
|
|
3128
3129
|
awaitPromise: true,
|
|
3129
3130
|
arguments: args.map((arg) => LocalValue.getArgument(arg)),
|
|
3130
3131
|
target: {
|
|
3131
|
-
context
|
|
3132
|
+
context: context2
|
|
3132
3133
|
}
|
|
3133
3134
|
};
|
|
3134
3135
|
const result = await browser.scriptCallFunction(params);
|
|
@@ -3801,12 +3802,12 @@ async function mock(url6, filterOptions) {
|
|
|
3801
3802
|
}
|
|
3802
3803
|
const browser = getBrowserObject5(this);
|
|
3803
3804
|
const contextManager2 = getContextManager(browser);
|
|
3804
|
-
const
|
|
3805
|
-
if (!SESSION_MOCKS[
|
|
3806
|
-
SESSION_MOCKS[
|
|
3805
|
+
const context2 = await contextManager2.getCurrentContext();
|
|
3806
|
+
if (!SESSION_MOCKS[context2]) {
|
|
3807
|
+
SESSION_MOCKS[context2] = /* @__PURE__ */ new Set();
|
|
3807
3808
|
}
|
|
3808
3809
|
const networkInterception = await WebDriverInterception.initiate(url6, filterOptions || {}, this);
|
|
3809
|
-
SESSION_MOCKS[
|
|
3810
|
+
SESSION_MOCKS[context2].add(networkInterception);
|
|
3810
3811
|
return networkInterception;
|
|
3811
3812
|
}
|
|
3812
3813
|
|
|
@@ -3848,9 +3849,9 @@ async function newWindow(url6, { windowName = "", windowFeatures = "" } = {}) {
|
|
|
3848
3849
|
const tabsBefore = await this.getWindowHandles();
|
|
3849
3850
|
if (this.isBidi) {
|
|
3850
3851
|
const contextManager2 = getContextManager(this);
|
|
3851
|
-
const { context } = await this.browsingContextCreate({ type: "window" });
|
|
3852
|
-
contextManager2.setCurrentContext(
|
|
3853
|
-
await this.browsingContextNavigate({ context, url: url6 });
|
|
3852
|
+
const { context: context2 } = await this.browsingContextCreate({ type: "window" });
|
|
3853
|
+
contextManager2.setCurrentContext(context2);
|
|
3854
|
+
await this.browsingContextNavigate({ context: context2, url: url6 });
|
|
3854
3855
|
} else {
|
|
3855
3856
|
await this.execute(newWindowHelper, url6, windowName, windowFeatures);
|
|
3856
3857
|
}
|
|
@@ -4016,8 +4017,8 @@ async function saveScreenshot(filepath) {
|
|
|
4016
4017
|
if (this.isBidi) {
|
|
4017
4018
|
const browser = getBrowserObject6(this);
|
|
4018
4019
|
const contextManager2 = getContextManager(browser);
|
|
4019
|
-
const
|
|
4020
|
-
const { data } = await this.browsingContextCaptureScreenshot({ context });
|
|
4020
|
+
const context2 = await contextManager2.getCurrentContext();
|
|
4021
|
+
const { data } = await this.browsingContextCaptureScreenshot({ context: context2 });
|
|
4021
4022
|
screenBuffer = data;
|
|
4022
4023
|
} else {
|
|
4023
4024
|
screenBuffer = await this.takeScreenshot();
|
|
@@ -4103,9 +4104,9 @@ async function setViewport(options) {
|
|
|
4103
4104
|
throw new Error("setViewport expects devicePixelRatio to be a number in the 0 to 2^31 \u2212 1 range");
|
|
4104
4105
|
}
|
|
4105
4106
|
const contextManager2 = getContextManager(this);
|
|
4106
|
-
const
|
|
4107
|
+
const context2 = await contextManager2.getCurrentContext();
|
|
4107
4108
|
await this.browsingContextSetViewport({
|
|
4108
|
-
context,
|
|
4109
|
+
context: context2,
|
|
4109
4110
|
devicePixelRatio: options.devicePixelRatio || 1,
|
|
4110
4111
|
viewport: {
|
|
4111
4112
|
width: options.width,
|
|
@@ -4164,6 +4165,107 @@ async function switchWindow(matcher) {
|
|
|
4164
4165
|
throw new Error(`No window found with title, url or name matching "${matcher}"`);
|
|
4165
4166
|
}
|
|
4166
4167
|
|
|
4168
|
+
// src/commands/browser/switchFrame.ts
|
|
4169
|
+
async function switchFrame(context2) {
|
|
4170
|
+
if (context2 === null) {
|
|
4171
|
+
const handle = await this.getWindowHandle();
|
|
4172
|
+
await switchToFrameHelper(this, handle);
|
|
4173
|
+
return handle;
|
|
4174
|
+
}
|
|
4175
|
+
if (typeof context2 === "string") {
|
|
4176
|
+
const tree = await this.browsingContextGetTree({});
|
|
4177
|
+
const urlContext = findContext(context2, tree.contexts, byUrl)?.context;
|
|
4178
|
+
if (urlContext) {
|
|
4179
|
+
await switchToFrameHelper(this, urlContext);
|
|
4180
|
+
return urlContext;
|
|
4181
|
+
}
|
|
4182
|
+
const urlContextContaining = findContext(context2, tree.contexts, byUrlContaining)?.context;
|
|
4183
|
+
if (urlContextContaining) {
|
|
4184
|
+
await switchToFrameHelper(this, urlContextContaining);
|
|
4185
|
+
return urlContextContaining;
|
|
4186
|
+
}
|
|
4187
|
+
const contextIdContext = findContext(context2, tree.contexts, byContextId)?.context;
|
|
4188
|
+
if (contextIdContext) {
|
|
4189
|
+
await switchToFrameHelper(this, contextIdContext);
|
|
4190
|
+
return contextIdContext;
|
|
4191
|
+
}
|
|
4192
|
+
throw new Error(`Frame with url or context id "${context2}" not found`);
|
|
4193
|
+
}
|
|
4194
|
+
if (typeof context2 === "object" && typeof context2.getElement === "function") {
|
|
4195
|
+
const element = await context2.getElement();
|
|
4196
|
+
return switchToFrameUsingElement(this, element);
|
|
4197
|
+
}
|
|
4198
|
+
if (typeof context2 === "function") {
|
|
4199
|
+
const tree = await this.browsingContextGetTree({});
|
|
4200
|
+
const mapContext = (context3) => [
|
|
4201
|
+
context3.context,
|
|
4202
|
+
...(context3.children || []).map(mapContext)
|
|
4203
|
+
];
|
|
4204
|
+
const sessionContext = getContextManager(this);
|
|
4205
|
+
const currentContext = await sessionContext.getCurrentContext();
|
|
4206
|
+
const allContexts = tree.contexts.map(mapContext).flat(Infinity).filter((ctx) => ctx !== currentContext).reduce((acc, ctx) => {
|
|
4207
|
+
const context3 = findContext(ctx, tree.contexts, byContextId);
|
|
4208
|
+
acc[ctx] = context3;
|
|
4209
|
+
return acc;
|
|
4210
|
+
}, {});
|
|
4211
|
+
for (const [contextId, ctx] of Object.entries(allContexts)) {
|
|
4212
|
+
sessionContext.setCurrentContext(contextId);
|
|
4213
|
+
const isDesiredFrame = await context2(ctx);
|
|
4214
|
+
if (isDesiredFrame) {
|
|
4215
|
+
return context2;
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
sessionContext.setCurrentContext(currentContext);
|
|
4219
|
+
throw new Error("Could not find the desired frame");
|
|
4220
|
+
}
|
|
4221
|
+
throw new Error(
|
|
4222
|
+
`Invalid type for context parameter: ${typeof context2}, expected one of number, string or null. Check out our docs: https://webdriver.io/docs/api/browser/switchToFrame.html`
|
|
4223
|
+
);
|
|
4224
|
+
}
|
|
4225
|
+
function switchToFrameHelper(browser, context2) {
|
|
4226
|
+
const sessionContext = getContextManager(browser);
|
|
4227
|
+
sessionContext.setCurrentContext(context2);
|
|
4228
|
+
}
|
|
4229
|
+
async function switchToFrameUsingElement(browser, element) {
|
|
4230
|
+
let frameSrc = await element.getAttribute("src");
|
|
4231
|
+
if (!frameSrc) {
|
|
4232
|
+
throw new Error(`Frame with index ${context} has no src attribute`);
|
|
4233
|
+
}
|
|
4234
|
+
if (!frameSrc.startsWith("http")) {
|
|
4235
|
+
frameSrc = await browser.execute((urlPath) => URL.parse(urlPath, window.location.href)?.href, frameSrc) || frameSrc;
|
|
4236
|
+
}
|
|
4237
|
+
const tree = await browser.browsingContextGetTree({});
|
|
4238
|
+
const urlContext = findContext(frameSrc, tree.contexts, byUrl)?.context;
|
|
4239
|
+
if (!urlContext) {
|
|
4240
|
+
throw new Error(`Frame with url "${frameSrc}" not found`);
|
|
4241
|
+
}
|
|
4242
|
+
await switchToFrameHelper(browser, urlContext);
|
|
4243
|
+
return urlContext;
|
|
4244
|
+
}
|
|
4245
|
+
function byUrl(context2, url6) {
|
|
4246
|
+
return context2.url === url6;
|
|
4247
|
+
}
|
|
4248
|
+
function byUrlContaining(context2, url6) {
|
|
4249
|
+
return context2.url.includes(url6);
|
|
4250
|
+
}
|
|
4251
|
+
function byContextId(context2, contextId) {
|
|
4252
|
+
return context2.context === contextId;
|
|
4253
|
+
}
|
|
4254
|
+
function findContext(url6, contexts, matcher) {
|
|
4255
|
+
for (const context2 of contexts || []) {
|
|
4256
|
+
if (matcher(context2, url6)) {
|
|
4257
|
+
return context2;
|
|
4258
|
+
}
|
|
4259
|
+
if (Array.isArray(context2.children) && context2.children.length > 0) {
|
|
4260
|
+
const result = findContext(url6, context2.children, matcher);
|
|
4261
|
+
if (result) {
|
|
4262
|
+
return result;
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
return void 0;
|
|
4267
|
+
}
|
|
4268
|
+
|
|
4167
4269
|
// src/commands/browser/throttle.ts
|
|
4168
4270
|
import logger13 from "@wdio/logger";
|
|
4169
4271
|
import { getBrowserObject as getBrowserObject8 } from "@wdio/utils";
|
|
@@ -4455,18 +4557,18 @@ var NetworkManager = class {
|
|
|
4455
4557
|
};
|
|
4456
4558
|
response.children?.push(request);
|
|
4457
4559
|
}
|
|
4458
|
-
getRequestResponseData(
|
|
4459
|
-
return this.#requests.get(
|
|
4560
|
+
getRequestResponseData(context2) {
|
|
4561
|
+
return this.#requests.get(context2);
|
|
4460
4562
|
}
|
|
4461
4563
|
/**
|
|
4462
4564
|
* Returns the number of requests that are currently pending.
|
|
4463
4565
|
* @param context browsing context id
|
|
4464
4566
|
* @returns the number of requests that are currently pending
|
|
4465
4567
|
*/
|
|
4466
|
-
getPendingRequests(
|
|
4467
|
-
const request = this.#requests.get(
|
|
4568
|
+
getPendingRequests(context2) {
|
|
4569
|
+
const request = this.#requests.get(context2);
|
|
4468
4570
|
if (!request) {
|
|
4469
|
-
throw new Error(`Couldn't find request for context ${
|
|
4571
|
+
throw new Error(`Couldn't find request for context ${context2}`);
|
|
4470
4572
|
}
|
|
4471
4573
|
const subRequests = request.children || [];
|
|
4472
4574
|
return subRequests.filter((child) => (
|
|
@@ -4500,7 +4602,7 @@ async function url3(path4, options = {}) {
|
|
|
4500
4602
|
if (this.isBidi) {
|
|
4501
4603
|
let resetPreloadScript;
|
|
4502
4604
|
const contextManager2 = getContextManager(this);
|
|
4503
|
-
const
|
|
4605
|
+
const context2 = await contextManager2.getCurrentContext();
|
|
4504
4606
|
if (options.onBeforeLoad) {
|
|
4505
4607
|
if (typeof options.onBeforeLoad !== "function") {
|
|
4506
4608
|
throw new Error(`Option "onBeforeLoad" must be a function, but received: ${typeof options.onBeforeLoad}`);
|
|
@@ -4521,22 +4623,22 @@ async function url3(path4, options = {}) {
|
|
|
4521
4623
|
const classicPageLoadStrategy = this.capabilities.pageLoadStrategy === "none" ? "none" : this.capabilities.pageLoadStrategy === "normal" ? "complete" : this.capabilities.pageLoadStrategy === "eager" ? "interactive" : void 0;
|
|
4522
4624
|
const wait = options.wait === "networkIdle" ? "complete" : options.wait || classicPageLoadStrategy || DEFAULT_WAIT_STATE;
|
|
4523
4625
|
await this.browsingContextNavigate({
|
|
4524
|
-
context,
|
|
4626
|
+
context: context2,
|
|
4525
4627
|
url: path4,
|
|
4526
4628
|
wait
|
|
4527
4629
|
});
|
|
4528
4630
|
const network = networkManager.get(this);
|
|
4529
|
-
const request = network?.getRequestResponseData(
|
|
4631
|
+
const request = network?.getRequestResponseData(context2);
|
|
4530
4632
|
if (mock2) {
|
|
4531
4633
|
await mock2.restore();
|
|
4532
4634
|
}
|
|
4533
4635
|
if (network && options.wait === "networkIdle") {
|
|
4534
4636
|
const timeout = options.timeout || DEFAULT_NETWORK_IDLE_TIMEOUT;
|
|
4535
4637
|
await this.waitUntil(async () => {
|
|
4536
|
-
return network.getPendingRequests(
|
|
4638
|
+
return network.getPendingRequests(context2).length === 0;
|
|
4537
4639
|
}, {
|
|
4538
4640
|
timeout,
|
|
4539
|
-
timeoutMsg: `Navigation to '${path4}' timed out after ${timeout}ms with ${network.getPendingRequests(
|
|
4641
|
+
timeoutMsg: `Navigation to '${path4}' timed out after ${timeout}ms with ${network.getPendingRequests(context2).length} (${network.getPendingRequests(context2).map((r) => r.url).join(", ")}) pending requests`
|
|
4540
4642
|
});
|
|
4541
4643
|
}
|
|
4542
4644
|
if (resetPreloadScript) {
|
|
@@ -4955,7 +5057,7 @@ var ShadowRootManager = class {
|
|
|
4955
5057
|
}).then(() => true, () => false);
|
|
4956
5058
|
this.#browser.on("log.entryAdded", this.handleLogEntry.bind(this));
|
|
4957
5059
|
this.#browser.on("result", this.#commandResultHandler.bind(this));
|
|
4958
|
-
this.#browser.on("
|
|
5060
|
+
this.#browser.on("bidiCommand", this.#handleBidiCommand.bind(this));
|
|
4959
5061
|
browser.scriptAddPreloadScript({
|
|
4960
5062
|
functionDeclaration: customElementWrapper.toString()
|
|
4961
5063
|
});
|
|
@@ -4966,8 +5068,12 @@ var ShadowRootManager = class {
|
|
|
4966
5068
|
/**
|
|
4967
5069
|
* keep track of navigation events and remove shadow roots when they are no longer needed
|
|
4968
5070
|
*/
|
|
4969
|
-
#
|
|
4970
|
-
|
|
5071
|
+
#handleBidiCommand(command) {
|
|
5072
|
+
if (command.method !== "browsingContext.navigate") {
|
|
5073
|
+
return;
|
|
5074
|
+
}
|
|
5075
|
+
const params = command.params;
|
|
5076
|
+
this.#shadowRoots.delete(params.context);
|
|
4971
5077
|
}
|
|
4972
5078
|
/**
|
|
4973
5079
|
* keep track of frame depth
|
|
@@ -5213,8 +5319,8 @@ async function getHTML(options = {}) {
|
|
|
5213
5319
|
const { load } = await import("cheerio");
|
|
5214
5320
|
const shadowRootManager2 = getShadowRootManager(browser);
|
|
5215
5321
|
const contextManager2 = getContextManager(browser);
|
|
5216
|
-
const
|
|
5217
|
-
const shadowRootElementPairs = shadowRootManager2.getShadowElementPairsByContextId(
|
|
5322
|
+
const context2 = await contextManager2.getCurrentContext();
|
|
5323
|
+
const shadowRootElementPairs = shadowRootManager2.getShadowElementPairsByContextId(context2, this.elementId);
|
|
5218
5324
|
const elementsWithShadowRootAndIdVerified = (await Promise.all(
|
|
5219
5325
|
shadowRootElementPairs.map(([elemId, elem]) => browser.execute((elem2) => elem2.tagName, { [ELEMENT_KEY11]: elemId }).then(
|
|
5220
5326
|
() => [elemId, elem],
|
|
@@ -5235,7 +5341,7 @@ async function getHTML(options = {}) {
|
|
|
5235
5341
|
populateHTML($3, shadowElementHTML.map(({ id, ...props }) => ({
|
|
5236
5342
|
...props,
|
|
5237
5343
|
id,
|
|
5238
|
-
mode: shadowRootManager2.getShadowRootModeById(
|
|
5344
|
+
mode: shadowRootManager2.getShadowRootModeById(context2, id) || "open"
|
|
5239
5345
|
})));
|
|
5240
5346
|
return sanitizeHTML($3, { removeCommentNodes, prettify, excludeElements });
|
|
5241
5347
|
}
|
|
@@ -5386,8 +5492,8 @@ var getWebElement = (el) => ({
|
|
|
5386
5492
|
async function isEqual(el) {
|
|
5387
5493
|
const browser = getBrowserObject21(this);
|
|
5388
5494
|
if (browser.isMobile) {
|
|
5389
|
-
const
|
|
5390
|
-
const contextId = typeof
|
|
5495
|
+
const context2 = await browser.getContext().catch(() => void 0);
|
|
5496
|
+
const contextId = typeof context2 === "string" ? context2 : context2?.id;
|
|
5391
5497
|
if (contextId && contextId.toLowerCase().includes("native")) {
|
|
5392
5498
|
return this.elementId === el.elementId;
|
|
5393
5499
|
}
|
|
@@ -6489,15 +6595,15 @@ async function findDeepElement(selector) {
|
|
|
6489
6595
|
const browser = getBrowserObject30(this);
|
|
6490
6596
|
const shadowRootManager2 = getShadowRootManager(browser);
|
|
6491
6597
|
const contextManager2 = getContextManager(browser);
|
|
6492
|
-
const
|
|
6598
|
+
const context2 = await contextManager2.getCurrentContext();
|
|
6493
6599
|
const shadowRoots = shadowRootManager2.getShadowElementsByContextId(
|
|
6494
|
-
|
|
6600
|
+
context2,
|
|
6495
6601
|
this.elementId
|
|
6496
6602
|
);
|
|
6497
6603
|
const { using, value } = findStrategy(selector, this.isW3C, this.isMobile);
|
|
6498
6604
|
const locator = transformClassicToBidiSelector(using, value);
|
|
6499
6605
|
const startNodes = shadowRoots.length > 0 ? shadowRoots.map((shadowRootNodeId) => ({ sharedId: shadowRootNodeId })) : this.elementId ? [{ sharedId: this.elementId }] : void 0;
|
|
6500
|
-
const deepElementResult = await browser.browsingContextLocateNodes({ locator, context, startNodes }).then(async (result) => {
|
|
6606
|
+
const deepElementResult = await browser.browsingContextLocateNodes({ locator, context: context2, startNodes }).then(async (result) => {
|
|
6501
6607
|
const nodes = result.nodes.filter((node) => Boolean(node.sharedId)).map((node) => ({
|
|
6502
6608
|
[ELEMENT_KEY17]: node.sharedId,
|
|
6503
6609
|
locator
|
|
@@ -6527,15 +6633,15 @@ async function findDeepElements(selector) {
|
|
|
6527
6633
|
const browser = getBrowserObject30(this);
|
|
6528
6634
|
const shadowRootManager2 = getShadowRootManager(browser);
|
|
6529
6635
|
const contextManager2 = getContextManager(browser);
|
|
6530
|
-
const
|
|
6636
|
+
const context2 = await contextManager2.getCurrentContext();
|
|
6531
6637
|
const shadowRoots = shadowRootManager2.getShadowElementsByContextId(
|
|
6532
|
-
|
|
6638
|
+
context2,
|
|
6533
6639
|
this.elementId
|
|
6534
6640
|
);
|
|
6535
6641
|
const { using, value } = findStrategy(selector, this.isW3C, this.isMobile);
|
|
6536
6642
|
const locator = transformClassicToBidiSelector(using, value);
|
|
6537
6643
|
const startNodes = shadowRoots.length > 0 ? shadowRoots.map((shadowRootNodeId) => ({ sharedId: shadowRootNodeId })) : this.elementId ? [{ sharedId: this.elementId }] : void 0;
|
|
6538
|
-
const deepElementResult = await browser.browsingContextLocateNodes({ locator, context, startNodes }).then(async (result) => {
|
|
6644
|
+
const deepElementResult = await browser.browsingContextLocateNodes({ locator, context: context2, startNodes }).then(async (result) => {
|
|
6539
6645
|
const nodes = result.nodes.filter((node) => Boolean(node.sharedId)).map((node) => ({
|
|
6540
6646
|
[ELEMENT_KEY17]: node.sharedId,
|
|
6541
6647
|
locator
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shadowRoot.d.ts","sourceRoot":"","sources":["../src/shadowRoot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"shadowRoot.d.ts","sourceRoot":"","sources":["../src/shadowRoot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,WAAW,CAAA;AAStC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,qBAShE;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;;gBAMd,OAAO,EAAE,WAAW,CAAC,OAAO;IAyBlC,UAAU;IA2BhB;;;OAGG;IACH,aAAa;IAIb;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ;IA2FvC,4BAA4B,CAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAwB1E,gCAAgC,CAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE;IAgBpG,qBAAqB,CAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IActF,gBAAgB,CAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAOvD;AAED,qBAAa,cAAc;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,QAAQ,sBAA4B;gBAEvB,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc;IAMxE;;OAEG;IACH,gBAAgB,CAAE,IAAI,EAAE,cAAc,GAAG,IAAI;IAC7C;;;;;OAKG;IACH,gBAAgB,CAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI;IA6B5D,IAAI,CAAE,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAelD,cAAc,CAAE,UAAU,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAe/D,kBAAkB,IAAK,MAAM,EAAE;IAO/B,IAAI,IAAK,cAAc,EAAE;IAIzB,MAAM,CAAE,OAAO,EAAE,MAAM,GAAG,OAAO;CAcpC"}
|
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.
|
|
4
|
+
"version": "9.2.0",
|
|
5
5
|
"homepage": "https://webdriver.io",
|
|
6
6
|
"author": "Christian Bromann <mail@bromann.dev>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"@types/sinonjs__fake-timers": "^8.1.5",
|
|
79
79
|
"@wdio/config": "9.1.3",
|
|
80
80
|
"@wdio/logger": "9.1.3",
|
|
81
|
-
"@wdio/protocols": "9.0
|
|
81
|
+
"@wdio/protocols": "9.2.0",
|
|
82
82
|
"@wdio/repl": "9.0.8",
|
|
83
83
|
"@wdio/types": "9.1.3",
|
|
84
84
|
"@wdio/utils": "9.1.3",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"rgb2hex": "0.2.5",
|
|
101
101
|
"serialize-error": "^11.0.3",
|
|
102
102
|
"urlpattern-polyfill": "^10.0.0",
|
|
103
|
-
"webdriver": "9.
|
|
103
|
+
"webdriver": "9.2.0"
|
|
104
104
|
},
|
|
105
105
|
"peerDependencies": {
|
|
106
106
|
"puppeteer-core": "^22.3.0"
|
|
@@ -110,5 +110,5 @@
|
|
|
110
110
|
"optional": true
|
|
111
111
|
}
|
|
112
112
|
},
|
|
113
|
-
"gitHead": "
|
|
113
|
+
"gitHead": "d19039c7166c6df2e47a02de289a66865372107e"
|
|
114
114
|
}
|