@@ -326,34 +326,34 @@ export class InjectedScript {
326
326
return { left : parseInt ( style . borderLeftWidth || '' , 10 ) , top : parseInt ( style . borderTopWidth || '' , 10 ) } ;
327
327
}
328
328
329
- private _retarget ( node : Node ) : Element | null {
329
+ private _retarget ( node : Node , behavior : 'follow-label' | 'no-follow-label' ) : Element | null {
330
330
let element = node . nodeType === Node . ELEMENT_NODE ? node as Element : node . parentElement ;
331
331
if ( ! element )
332
332
return null ;
333
333
element = element . closest ( 'button, [role=button], [role=checkbox], [role=radio]' ) || element ;
334
- if ( ! element . matches ( 'input, textarea, button, select, [role=button], [role=checkbox], [role=radio]' ) &&
335
- ! ( element as any ) . isContentEditable ) {
336
- // Go up to the label that might be connected to the input/textarea.
337
- element = element . closest ( 'label' ) || element ;
334
+ if ( behavior === 'follow-label' ) {
335
+ if ( ! element . matches ( 'input, textarea, button, select, [role=button], [role=checkbox], [role=radio]' ) &&
336
+ ! ( element as any ) . isContentEditable ) {
337
+ // Go up to the label that might be connected to the input/textarea.
338
+ element = element . closest ( 'label' ) || element ;
339
+ }
340
+ if ( element . nodeName === 'LABEL' )
341
+ element = ( element as HTMLLabelElement ) . control || element ;
338
342
}
339
- if ( element . nodeName === 'LABEL' )
340
- element = ( element as HTMLLabelElement ) . control || element ;
341
343
return element ;
342
344
}
343
345
344
346
waitForElementStatesAndPerformAction < T > ( node : Node , states : ElementState [ ] ,
345
- callback : ( element : Element | null , progress : InjectedScriptProgress , continuePolling : symbol ) => T | symbol ) : InjectedScriptPoll < T | 'error:notconnected' | FatalDOMError > {
347
+ callback : ( node : Node , progress : InjectedScriptProgress , continuePolling : symbol ) => T | symbol ) : InjectedScriptPoll < T | 'error:notconnected' | FatalDOMError > {
346
348
let lastRect : { x : number , y : number , width : number , height : number } | undefined ;
347
349
let counter = 0 ;
348
350
let samePositionCounter = 0 ;
349
351
let lastTime = 0 ;
350
352
351
353
const predicate = ( progress : InjectedScriptProgress , continuePolling : symbol ) => {
352
- const element = this . _retarget ( node ) ;
353
-
354
354
for ( const state of states ) {
355
355
if ( state !== 'stable' ) {
356
- const result = this . _checkElementState ( element , state ) ;
356
+ const result = this . checkElementState ( node , state ) ;
357
357
if ( typeof result !== 'boolean' )
358
358
return result ;
359
359
if ( ! result ) {
@@ -363,6 +363,7 @@ export class InjectedScript {
363
363
continue ;
364
364
}
365
365
366
+ const element = this . _retarget ( node , 'no-follow-label' ) ;
366
367
if ( ! element )
367
368
return 'error:notconnected' ;
368
369
@@ -394,7 +395,7 @@ export class InjectedScript {
394
395
return continuePolling ;
395
396
}
396
397
397
- return callback ( element , progress , continuePolling ) ;
398
+ return callback ( node , progress , continuePolling ) ;
398
399
} ;
399
400
400
401
if ( this . _replaceRafWithTimeout )
@@ -403,12 +404,14 @@ export class InjectedScript {
403
404
return this . pollRaf ( predicate ) ;
404
405
}
405
406
406
- private _checkElementState ( element : Element | null , state : ElementStateWithoutStable ) : boolean | 'error:notconnected' | FatalDOMError {
407
+ checkElementState ( node : Node , state : ElementStateWithoutStable ) : boolean | 'error:notconnected' | FatalDOMError {
408
+ const element = this . _retarget ( node , [ 'stable' , 'visible' , 'hidden' ] . includes ( state ) ? 'no-follow-label' : 'follow-label' ) ;
407
409
if ( ! element || ! element . isConnected ) {
408
410
if ( state === 'hidden' )
409
411
return true ;
410
412
return 'error:notconnected' ;
411
413
}
414
+
412
415
if ( state === 'visible' )
413
416
return this . isVisible ( element ) ;
414
417
if ( state === 'hidden' )
@@ -436,13 +439,9 @@ export class InjectedScript {
436
439
throw new Error ( `Unexpected element state "${ state } "` ) ;
437
440
}
438
441
439
- checkElementState ( node : Node , state : ElementStateWithoutStable ) : boolean | 'error:notconnected' | FatalDOMError {
440
- const element = this . _retarget ( node ) ;
441
- return this . _checkElementState ( element , state ) ;
442
- }
443
-
444
442
selectOptions ( optionsToSelect : ( Node | { value ?: string , label ?: string , index ?: number } ) [ ] ,
445
- element : Element | null , progress : InjectedScriptProgress , continuePolling : symbol ) : string [ ] | 'error:notconnected' | FatalDOMError | symbol {
443
+ node : Node , progress : InjectedScriptProgress , continuePolling : symbol ) : string [ ] | 'error:notconnected' | FatalDOMError | symbol {
444
+ const element = this . _retarget ( node , 'follow-label' ) ;
446
445
if ( ! element )
447
446
return 'error:notconnected' ;
448
447
if ( element . nodeName . toLowerCase ( ) !== 'select' )
@@ -487,7 +486,8 @@ export class InjectedScript {
487
486
return selectedOptions . map ( option => option . value ) ;
488
487
}
489
488
490
- fill ( value : string , element : Element | null , progress : InjectedScriptProgress ) : FatalDOMError | 'error:notconnected' | 'needsinput' | 'done' {
489
+ fill ( value : string , node : Node , progress : InjectedScriptProgress ) : FatalDOMError | 'error:notconnected' | 'needsinput' | 'done' {
490
+ const element = this . _retarget ( node , 'follow-label' ) ;
491
491
if ( ! element )
492
492
return 'error:notconnected' ;
493
493
if ( element . nodeName . toLowerCase ( ) === 'input' ) {
@@ -523,7 +523,8 @@ export class InjectedScript {
523
523
return 'needsinput' ; // Still need to input the value.
524
524
}
525
525
526
- selectText ( element : Element | null ) : 'error:notconnected' | 'done' {
526
+ selectText ( node : Node ) : 'error:notconnected' | 'done' {
527
+ const element = this . _retarget ( node , 'follow-label' ) ;
527
528
if ( ! element )
528
529
return 'error:notconnected' ;
529
530
if ( element . nodeName . toLowerCase ( ) === 'input' ) {
0 commit comments