1
1
import logger from '@wdio/logger'
2
- import { ELEMENT_KEY , type local , type remote } from 'webdriver'
2
+ import { ELEMENT_KEY , type remote } from 'webdriver'
3
3
import type { ElementReference } from '@wdio/protocols'
4
4
5
- import { getContextManager } from '../../session/context.js'
5
+ import { getContextManager , type FlatContextTree } from '../../session/context.js'
6
6
import { LocalValue } from '../../utils/bidi/value.js'
7
7
import { parseScriptResult } from '../../utils/bidi/index.js'
8
8
import { SCRIPT_PREFIX , SCRIPT_SUFFIX } from '../constant.js'
9
9
import type { ChainablePromiseElement } from '../../types.js'
10
10
11
- type FlatContextTree = Omit < local . BrowsingContextInfo , 'children' > & { children : string [ ] }
12
11
const log = logger ( 'webdriverio:switchFrame' )
13
12
14
13
/**
@@ -94,6 +93,8 @@ export async function switchFrame (
94
93
return switchToFrame ( this , context )
95
94
}
96
95
96
+ const sessionContext = getContextManager ( this )
97
+
97
98
/**
98
99
* if context is `null` the user is switching to the top level frame
99
100
* which is always represented by the value of `getWindowHandle`
@@ -115,15 +116,15 @@ export async function switchFrame (
115
116
let newContextId : string | undefined
116
117
117
118
const urlContext = (
118
- findContext ( context , tree . contexts , byUrl ) ||
119
+ sessionContext . findContext ( context , tree . contexts , ' byUrl' ) ||
119
120
/**
120
121
* In case the user provides an url without `/` at the end, e.g. `https://example.com`,
121
122
* the `browsingContextGetTree` command may return a context with the url `https://example.com/`.
122
123
*/
123
- findContext ( `${ context } /` , tree . contexts , byUrl )
124
+ sessionContext . findContext ( `${ context } /` , tree . contexts , ' byUrl' )
124
125
)
125
- const urlContextContaining = findContext ( context , tree . contexts , byUrlContaining )
126
- const contextIdContext = findContext ( context , tree . contexts , byContextId )
126
+ const urlContextContaining = sessionContext . findContext ( context , tree . contexts , ' byUrlContaining' )
127
+ const contextIdContext = sessionContext . findContext ( context , tree . contexts , ' byContextId' )
127
128
if ( urlContext ) {
128
129
log . info ( `Found context by url "${ urlContext . url } " with context id "${ urlContext . context } "` )
129
130
newContextId = urlContext . context
@@ -139,9 +140,8 @@ export async function switchFrame (
139
140
throw new Error ( `No frame with url or id "${ context } " found!` )
140
141
}
141
142
142
- const sessionContext = getContextManager ( this )
143
143
const currentContext = await sessionContext . getCurrentContext ( )
144
- const allContexts = await getFlatContextTree ( this )
144
+ const allContexts = await sessionContext . getFlatContextTree ( )
145
145
146
146
/**
147
147
* Fetch all iframes located in any available frame
@@ -252,6 +252,7 @@ export async function switchFrame (
252
252
await switchToFrame ( this , contextToSwitch . frameElement )
253
253
}
254
254
255
+ sessionContext . setCurrentContext ( newContextId )
255
256
return newContextId
256
257
}
257
258
@@ -273,7 +274,7 @@ export async function switchFrame (
273
274
* the function for each of them.
274
275
*/
275
276
if ( typeof context === 'function' ) {
276
- const allContexts = await getFlatContextTree ( this )
277
+ const allContexts = await sessionContext . getFlatContextTree ( )
277
278
const allContextIds = Object . keys ( allContexts )
278
279
for ( const contextId of allContextIds ) {
279
280
const functionDeclaration = new Function ( `
@@ -319,7 +320,6 @@ function switchToFrameHelper (browser: WebdriverIO.Browser, context: string) {
319
320
}
320
321
321
322
async function switchToFrameUsingElement ( browser : WebdriverIO . Browser , element : WebdriverIO . Element ) {
322
- // await switchToFrame(browser, element)
323
323
const frame = await browser . execute (
324
324
( iframe : unknown ) => ( iframe as HTMLIFrameElement ) . contentWindow ,
325
325
element
@@ -332,60 +332,6 @@ async function switchToFrameUsingElement (browser: WebdriverIO.Browser, element:
332
332
return frame . context
333
333
}
334
334
335
- function byUrl ( context : local . BrowsingContextInfo , url : string ) {
336
- return context . url === url
337
- }
338
-
339
- function byUrlContaining ( context : local . BrowsingContextInfo , url : string ) {
340
- return context . url . includes ( url )
341
- }
342
-
343
- function byContextId ( context : local . BrowsingContextInfo , contextId : string ) {
344
- return context . context === contextId
345
- }
346
-
347
- function findContext (
348
- urlOrId : string ,
349
- contexts : local . BrowsingContextInfoList | null ,
350
- matcher : typeof byUrl | typeof byUrlContaining | typeof byContextId
351
- ) : local . BrowsingContextInfo | undefined {
352
- for ( const context of contexts || [ ] ) {
353
- if ( matcher ( context , urlOrId ) ) {
354
- return context
355
- }
356
-
357
- if ( Array . isArray ( context . children ) && context . children . length > 0 ) {
358
- const result = findContext ( urlOrId , context . children , matcher )
359
- if ( result ) {
360
- return result
361
- }
362
- }
363
- }
364
-
365
- return undefined
366
- }
367
-
368
- async function getFlatContextTree ( browser : WebdriverIO . Browser ) : Promise < Record < string , FlatContextTree > > {
369
- const tree = await browser . browsingContextGetTree ( { } )
370
-
371
- const mapContext = ( context : local . BrowsingContextInfo ) : string [ ] => [
372
- context . context ,
373
- ...( context . children || [ ] ) . map ( mapContext ) . flat ( Infinity ) as string [ ]
374
- ]
375
-
376
- /**
377
- * transform context tree into a flat list of context objects with references
378
- * to children
379
- */
380
- const allContexts : Record < string , FlatContextTree > = tree . contexts . map ( mapContext ) . flat ( Infinity )
381
- . reduce ( ( acc , ctx : string ) => {
382
- const context = findContext ( ctx , tree . contexts , byContextId )
383
- acc [ ctx ] = context as unknown as FlatContextTree
384
- return acc
385
- } , { } as Record < string , FlatContextTree > )
386
- return allContexts
387
- }
388
-
389
335
/**
390
336
* While we deprecated the `switchToFrame` command for users, we still
391
337
* have to use it internally to enable support for WebDriver Classic.
@@ -394,7 +340,16 @@ async function getFlatContextTree (browser: WebdriverIO.Browser): Promise<Record
394
340
*/
395
341
function switchToFrame ( browser : WebdriverIO . Browser , frame : ElementReference | number | null ) {
396
342
process . env . DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS = 'true'
397
- return browser . switchToFrame ( frame ) . finally ( ( ) => {
343
+ return browser . switchToFrame ( frame ) . finally ( async ( ) => {
344
+ const sessionContext = getContextManager ( browser )
345
+ const [ frameTree , documentUrl ] = await Promise . all ( [
346
+ sessionContext . getFlatContextTree ( ) ,
347
+ browser . execute ( ( ) => document . URL )
348
+ ] )
349
+ const frame = Object . values ( frameTree ) . find ( ( ctx ) => ctx . url === documentUrl )
350
+ if ( frame ) {
351
+ switchToFrameHelper ( browser , frame . context )
352
+ }
398
353
delete process . env . DISABLE_WEBDRIVERIO_DEPRECATION_WARNINGS
399
354
} )
400
355
}
0 commit comments