@@ -246,10 +246,13 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
246
246
}
247
247
248
248
async _retryPointerAction ( progress : Progress , action : ( point : types . Point ) => Promise < void > , options : PointerActionOptions & types . PointerActionWaitOptions & types . NavigatingActionWaitOptions ) : Promise < void > {
249
+ let first = true ;
249
250
while ( progress . isRunning ( ) ) {
251
+ progress . log ( apiLog , `${ first ? 'attempting' : 'retrying' } ${ progress . apiName } action` ) ;
250
252
const result = await this . _performPointerAction ( progress , action , options ) ;
251
253
if ( result === 'done' )
252
254
return ;
255
+ first = false ;
253
256
}
254
257
}
255
258
@@ -258,57 +261,57 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
258
261
if ( ! force )
259
262
await this . _waitForDisplayedAtStablePositionAndEnabled ( progress ) ;
260
263
261
- progress . log ( apiLog , 'scrolling into view if needed... ' ) ;
264
+ progress . log ( apiLog , ' scrolling into view if needed' ) ;
262
265
const scrolled = await this . _scrollRectIntoViewIfNeeded ( position ? { x : position . x , y : position . y , width : 0 , height : 0 } : undefined ) ;
263
266
if ( scrolled === 'invisible' ) {
264
267
if ( force )
265
268
throw new Error ( 'Element is not visible' ) ;
266
- progress . log ( apiLog , '... element is not visible, retrying input action ' ) ;
269
+ progress . log ( apiLog , ' element is not visible' ) ;
267
270
return 'retry' ;
268
271
}
269
- progress . log ( apiLog , '... done scrolling' ) ;
272
+ progress . log ( apiLog , ' done scrolling' ) ;
270
273
271
274
const maybePoint = position ? await this . _offsetPoint ( position ) : await this . _clickablePoint ( ) ;
272
275
if ( maybePoint === 'invisible' ) {
273
276
if ( force )
274
277
throw new Error ( 'Element is not visible' ) ;
275
- progress . log ( apiLog , 'element is not visibile, retrying input action ' ) ;
278
+ progress . log ( apiLog , ' element is not visibile' ) ;
276
279
return 'retry' ;
277
280
}
278
281
if ( maybePoint === 'outsideviewport' ) {
279
282
if ( force )
280
283
throw new Error ( 'Element is outside of the viewport' ) ;
281
- progress . log ( apiLog , 'element is outside of the viewport, retrying input action ' ) ;
284
+ progress . log ( apiLog , ' element is outside of the viewport' ) ;
282
285
return 'retry' ;
283
286
}
284
287
const point = roundPoint ( maybePoint ) ;
285
288
286
289
if ( ! force ) {
287
290
if ( ( options as any ) . __testHookBeforeHitTarget )
288
291
await ( options as any ) . __testHookBeforeHitTarget ( ) ;
289
- progress . log ( apiLog , `checking that element receives pointer events at (${ point . x } ,${ point . y } )... ` ) ;
292
+ progress . log ( apiLog , ` checking that element receives pointer events at (${ point . x } ,${ point . y } )` ) ;
290
293
const matchesHitTarget = await this . _checkHitTargetAt ( point ) ;
291
294
if ( ! matchesHitTarget ) {
292
- progress . log ( apiLog , '... element does not receive pointer events, retrying input action ' ) ;
295
+ progress . log ( apiLog , ' element does not receive pointer events' ) ;
293
296
return 'retry' ;
294
297
}
295
- progress . log ( apiLog , `... element does receive pointer events, continuing input action` ) ;
298
+ progress . log ( apiLog , ` element does receive pointer events, continuing input action` ) ;
296
299
}
297
300
298
301
await this . _page . _frameManager . waitForSignalsCreatedBy ( progress , options . noWaitAfter , async ( ) => {
299
302
let restoreModifiers : input . Modifier [ ] | undefined ;
300
303
if ( options && options . modifiers )
301
304
restoreModifiers = await this . _page . keyboard . _ensureModifiers ( options . modifiers ) ;
302
- progress . log ( apiLog , `performing ${ progress . apiName } action... ` ) ;
305
+ progress . log ( apiLog , ` performing ${ progress . apiName } action` ) ;
303
306
await action ( point ) ;
304
- progress . log ( apiLog , `... ${ progress . apiName } action done` ) ;
305
- progress . log ( apiLog , 'waiting for scheduled navigations to finish... ' ) ;
307
+ progress . log ( apiLog , ` ${ progress . apiName } action done` ) ;
308
+ progress . log ( apiLog , ' waiting for scheduled navigations to finish' ) ;
306
309
if ( ( options as any ) . __testHookAfterPointerAction )
307
310
await ( options as any ) . __testHookAfterPointerAction ( ) ;
308
311
if ( restoreModifiers )
309
312
await this . _page . keyboard . _ensureModifiers ( restoreModifiers ) ;
310
313
} , 'input' ) ;
311
- progress . log ( apiLog , '... navigations have finished' ) ;
314
+ progress . log ( apiLog , ' navigations have finished' ) ;
312
315
313
316
return 'done' ;
314
317
}
@@ -342,7 +345,6 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
342
345
}
343
346
344
347
async _selectOption ( progress : Progress , values : string | ElementHandle | types . SelectOption | string [ ] | ElementHandle [ ] | types . SelectOption [ ] , options : types . NavigatingActionWaitOptions ) : Promise < string [ ] > {
345
- progress . log ( apiLog , progress . apiName ) ;
346
348
let vals : string [ ] | ElementHandle [ ] | types . SelectOption [ ] ;
347
349
if ( ! Array . isArray ( values ) )
348
350
vals = [ values ] as ( string [ ] | ElementHandle [ ] | types . SelectOption [ ] ) ;
@@ -376,8 +378,8 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
376
378
const poll = await this . _evaluateHandleInUtility ( ( [ injected , node , value ] ) => {
377
379
return injected . waitForEnabledAndFill ( node , value ) ;
378
380
} , value ) ;
379
- new InjectedScriptPollHandler ( progress , poll ) ;
380
- const injectedResult = await poll . evaluate ( poll => poll . result ) ;
381
+ const pollHandler = new InjectedScriptPollHandler ( progress , poll ) ;
382
+ const injectedResult = await pollHandler . finish ( ) ;
381
383
const needsInput = handleInjectedResult ( injectedResult ) ;
382
384
if ( needsInput ) {
383
385
if ( value )
@@ -399,7 +401,6 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
399
401
}
400
402
401
403
async _setInputFiles ( progress : Progress , files : string | types . FilePayload | string [ ] | types . FilePayload [ ] , options : types . NavigatingActionWaitOptions ) {
402
- progress . log ( apiLog , progress . apiName ) ;
403
404
const injectedResult = await this . _evaluateInUtility ( ( [ injected , node ] ) : types . InjectedScriptResult < boolean > => {
404
405
if ( node . nodeType !== Node . ELEMENT_NODE || ( node as Node as Element ) . tagName !== 'INPUT' )
405
406
return { status : 'error' , error : 'Node is not an HTMLInputElement' } ;
@@ -522,15 +523,15 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
522
523
}
523
524
524
525
async _waitForDisplayedAtStablePositionAndEnabled ( progress : Progress ) : Promise < void > {
525
- progress . log ( apiLog , 'waiting for element to be displayed, enabled and not moving... ' ) ;
526
+ progress . log ( apiLog , ' waiting for element to be displayed, enabled and not moving' ) ;
526
527
const rafCount = this . _page . _delegate . rafCountForStablePosition ( ) ;
527
528
const poll = await this . _evaluateHandleInUtility ( ( [ injected , node , rafCount ] ) => {
528
529
return injected . waitForDisplayedAtStablePositionAndEnabled ( node , rafCount ) ;
529
530
} , rafCount ) ;
530
- new InjectedScriptPollHandler ( progress , poll ) ;
531
- const injectedResult = await poll . evaluate ( poll => poll . result ) ;
531
+ const pollHandler = new InjectedScriptPollHandler < types . InjectedScriptResult > ( progress , poll ) ;
532
+ const injectedResult = await pollHandler . finish ( ) ;
532
533
handleInjectedResult ( injectedResult ) ;
533
- progress . log ( apiLog , '... element is displayed and does not move' ) ;
534
+ progress . log ( apiLog , ' element is displayed and does not move' ) ;
534
535
}
535
536
536
537
async _checkHitTargetAt ( point : types . Point ) : Promise < boolean > {
@@ -553,11 +554,11 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
553
554
// Handles an InjectedScriptPoll running in injected script:
554
555
// - streams logs into progress;
555
556
// - cancels the poll when progress cancels.
556
- export class InjectedScriptPollHandler {
557
+ export class InjectedScriptPollHandler < T > {
557
558
private _progress : Progress ;
558
- private _poll : js . JSHandle < types . InjectedScriptPoll < any > > | null ;
559
+ private _poll : js . JSHandle < types . InjectedScriptPoll < T > > | null ;
559
560
560
- constructor ( progress : Progress , poll : js . JSHandle < types . InjectedScriptPoll < any > > ) {
561
+ constructor ( progress : Progress , poll : js . JSHandle < types . InjectedScriptPoll < T > > ) {
561
562
this . _progress = progress ;
562
563
this . _poll = poll ;
563
564
this . _progress . cleanupWhenAborted ( ( ) => this . cancel ( ) ) ;
@@ -577,6 +578,35 @@ export class InjectedScriptPollHandler {
577
578
} ) ;
578
579
}
579
580
581
+ async finishHandle ( ) : Promise < types . SmartHandle < T > > {
582
+ try {
583
+ const result = await this . _poll ! . evaluateHandle ( poll => poll . result ) ;
584
+ await this . _finishInternal ( ) ;
585
+ return result ;
586
+ } finally {
587
+ this . cancel ( ) ;
588
+ }
589
+ }
590
+
591
+ async finish ( ) : Promise < T > {
592
+ try {
593
+ const result = await this . _poll ! . evaluate ( poll => poll . result ) ;
594
+ await this . _finishInternal ( ) ;
595
+ return result ;
596
+ } finally {
597
+ this . cancel ( ) ;
598
+ }
599
+ }
600
+
601
+ private async _finishInternal ( ) {
602
+ if ( ! this . _poll )
603
+ return ;
604
+ // Retrieve all the logs before continuing.
605
+ const messages = await this . _poll . evaluate ( poll => poll . takeLastLogs ( ) ) . catch ( e => [ ] as string [ ] ) ;
606
+ for ( const message of messages )
607
+ this . _progress . log ( apiLog , message ) ;
608
+ }
609
+
580
610
cancel ( ) {
581
611
if ( ! this . _poll )
582
612
return ;
0 commit comments