@@ -2779,61 +2779,62 @@ class Playwright extends Helper {
27792779 . locator ( `${ locator . isCustom ( ) ? `${ locator . type } =${ locator . value } ` : locator . simplify ( ) } >> text=${ text } ` )
27802780 . first ( )
27812781 . waitFor ( { timeout : waitTimeout , state : 'visible' } )
2782+ . catch ( e => {
2783+ throw new Error ( errorMessage )
2784+ } )
27822785 }
27832786
27842787 if ( locator . isXPath ( ) ) {
2785- return contextObject . waitForFunction (
2786- ( [ locator , text , $XPath ] ) => {
2787- eval ( $XPath )
2788- const el = $XPath ( null , locator )
2789- if ( ! el . length ) return false
2790- return el [ 0 ] . innerText . indexOf ( text ) > - 1
2791- } ,
2792- [ locator . value , text , $XPath . toString ( ) ] ,
2793- { timeout : waitTimeout } ,
2794- )
2788+ return contextObject
2789+ . waitForFunction (
2790+ ( [ locator , text , $XPath ] ) => {
2791+ eval ( $XPath )
2792+ const el = $XPath ( null , locator )
2793+ if ( ! el . length ) return false
2794+ return el [ 0 ] . innerText . indexOf ( text ) > - 1
2795+ } ,
2796+ [ locator . value , text , $XPath . toString ( ) ] ,
2797+ { timeout : waitTimeout } ,
2798+ )
2799+ . catch ( e => {
2800+ throw new Error ( errorMessage )
2801+ } )
27952802 }
27962803 } catch ( e ) {
27972804 throw new Error ( `${ errorMessage } \n${ e . message } ` )
27982805 }
27992806 }
28002807
2808+ // Based on original implementation but fixed to check title text and remove problematic promiseRetry
2809+ // Original used timeoutGap for waitForFunction to give it slightly more time than the locator
28012810 const timeoutGap = waitTimeout + 1000
28022811
2803- // We add basic timeout to make sure we don't wait forever
2804- // We apply 2 strategies here: wait for text as innert text on page (wide strategy) - older
2805- // or we use native Playwright matcher to wait for text in element (narrow strategy) - newer
2806- // 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
2807-
2808- // Use a flag to stop retries when race resolves
2809- let shouldStop = false
2810- let timeoutId
2811-
2812- const racePromise = Promise . race ( [
2813- new Promise ( ( _ , reject ) => {
2814- timeoutId = setTimeout ( ( ) => reject ( errorMessage ) , waitTimeout )
2815- } ) ,
2816- this . page . waitForFunction ( text => document . body && document . body . innerText . indexOf ( text ) > - 1 , text , { timeout : timeoutGap } ) ,
2817- promiseRetry (
2818- async ( retry , number ) => {
2819- // Stop retrying if race has resolved
2820- if ( shouldStop ) {
2821- throw new Error ( 'Operation cancelled' )
2812+ return Promise . race ( [
2813+ // Strategy 1: waitForFunction that checks both body AND title text
2814+ // Use this.page instead of contextObject because FrameLocator doesn't have waitForFunction
2815+ // Original only checked document.body.innerText, missing title text like "TestEd"
2816+ this . page . waitForFunction (
2817+ function ( text ) {
2818+ // Check body text (original behavior)
2819+ if ( document . body && document . body . innerText && document . body . innerText . indexOf ( text ) > - 1 ) {
2820+ return true
28222821 }
2823- const textPresent = await contextObject
2824- . locator ( `:has-text( ${ JSON . stringify ( text ) } )` )
2825- . first ( )
2826- . isVisible ( )
2827- if ( ! textPresent ) retry ( errorMessage )
2822+ // Check document title (fixes the TestEd in title issue)
2823+ if ( document . title && document . title . indexOf ( text ) > - 1 ) {
2824+ return true
2825+ }
2826+ return false
28282827 } ,
2829- { retries : 10 , minTimeout : 100 , maxTimeout : 500 , factor : 1.5 } ,
2828+ text ,
2829+ { timeout : timeoutGap } ,
28302830 ) ,
2831- ] )
2832-
2833- // Clean up when race resolves/rejects
2834- return racePromise . finally ( ( ) => {
2835- if ( timeoutId ) clearTimeout ( timeoutId )
2836- shouldStop = true
2831+ // Strategy 2: Native Playwright text locator (replaces problematic promiseRetry)
2832+ contextObject
2833+ . locator ( `:has-text(${ JSON . stringify ( text ) } )` )
2834+ . first ( )
2835+ . waitFor ( { timeout : waitTimeout } ) ,
2836+ ] ) . catch ( err => {
2837+ throw new Error ( errorMessage )
28372838 } )
28382839 }
28392840
0 commit comments