@@ -2687,6 +2687,9 @@ class Playwright extends Helper {
26872687 if ( ( this . context && this . context . constructor . name === 'FrameLocator' ) || this . context ) {
26882688 return this . context
26892689 }
2690+ if ( this . frame ) {
2691+ return this . frame
2692+ }
26902693 return this . page
26912694 }
26922695
@@ -2751,26 +2754,21 @@ class Playwright extends Helper {
27512754 async waitForText ( text , sec = null , context = null ) {
27522755 const waitTimeout = sec ? sec * 1000 : this . options . waitForTimeout
27532756 const errorMessage = `Text "${ text } " was not found on page after ${ waitTimeout / 1000 } sec.`
2754- let waiter
27552757
27562758 const contextObject = await this . _getContext ( )
27572759
27582760 if ( context ) {
27592761 const locator = new Locator ( context , 'css' )
2760- if ( ! locator . isXPath ( ) ) {
2761- try {
2762- await contextObject
2762+ try {
2763+ if ( ! locator . isXPath ( ) ) {
2764+ return contextObject
27632765 . locator ( `${ locator . isCustom ( ) ? `${ locator . type } =${ locator . value } ` : locator . simplify ( ) } >> text=${ text } ` )
27642766 . first ( )
27652767 . waitFor ( { timeout : waitTimeout , state : 'visible' } )
2766- } catch ( e ) {
2767- throw new Error ( `${ errorMessage } \n${ e . message } ` )
27682768 }
2769- }
27702769
2771- if ( locator . isXPath ( ) ) {
2772- try {
2773- await contextObject . waitForFunction (
2770+ if ( locator . isXPath ( ) ) {
2771+ return contextObject . waitForFunction (
27742772 ( [ locator , text , $XPath ] ) => {
27752773 eval ( $XPath ) // eslint-disable-line no-eval
27762774 const el = $XPath ( null , locator )
@@ -2780,27 +2778,32 @@ class Playwright extends Helper {
27802778 [ locator . value , text , $XPath . toString ( ) ] ,
27812779 { timeout : waitTimeout } ,
27822780 )
2783- } catch ( e ) {
2784- throw new Error ( `${ errorMessage } \n${ e . message } ` )
27852781 }
2782+ } catch ( e ) {
2783+ throw new Error ( `${ errorMessage } \n${ e . message } ` )
27862784 }
2787- } else {
2788- // we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented
2789-
2790- const _contextObject = this . frame ? this . frame : contextObject
2791- let count = 0
2792- do {
2793- waiter = await _contextObject
2794- . locator ( `:has-text(${ JSON . stringify ( text ) } )` )
2795- . first ( )
2796- . isVisible ( )
2797- if ( waiter ) break
2798- await this . wait ( 1 )
2799- count += 1000
2800- } while ( count <= waitTimeout )
2801-
2802- if ( ! waiter ) throw new Error ( `${ errorMessage } ` )
28032785 }
2786+
2787+ const timeoutGap = waitTimeout + 1000
2788+
2789+ // We add basic timeout to make sure we don't wait forever
2790+ // We apply 2 strategies here: wait for text as innert text on page (wide strategy) - older
2791+ // or we use native Playwright matcher to wait for text in element (narrow strategy) - newer
2792+ // If a user waits for text on a page they are mostly expect it to be there, so wide strategy can be helpful even PW strategy is available
2793+ return Promise . race ( [
2794+ new Promise ( ( _ , reject ) => {
2795+ setTimeout ( ( ) => reject ( errorMessage ) , waitTimeout )
2796+ } ) ,
2797+ contextObject . waitForFunction ( text => document . body && document . body . innerText . indexOf ( text ) > - 1 , text , { timeout : timeoutGap } ) ,
2798+ promiseRetry (
2799+ async ( ) =>
2800+ contextObject
2801+ . locator ( `:has-text(${ JSON . stringify ( text ) } )` )
2802+ . first ( )
2803+ . isVisible ( ) ,
2804+ { retries : timeoutGap / 500 , minTimeout : 500 , factor : 1 } ,
2805+ ) ,
2806+ ] )
28042807 }
28052808
28062809 /**
0 commit comments