@@ -2779,61 +2779,62 @@ class Playwright extends Helper {
2779
2779
. locator ( `${ locator . isCustom ( ) ? `${ locator . type } =${ locator . value } ` : locator . simplify ( ) } >> text=${ text } ` )
2780
2780
. first ( )
2781
2781
. waitFor ( { timeout : waitTimeout , state : 'visible' } )
2782
+ . catch ( e => {
2783
+ throw new Error ( errorMessage )
2784
+ } )
2782
2785
}
2783
2786
2784
2787
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
+ } )
2795
2802
}
2796
2803
} catch ( e ) {
2797
2804
throw new Error ( `${ errorMessage } \n${ e . message } ` )
2798
2805
}
2799
2806
}
2800
2807
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
2801
2810
const timeoutGap = waitTimeout + 1000
2802
2811
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
2822
2821
}
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
2828
2827
} ,
2829
- { retries : 10 , minTimeout : 100 , maxTimeout : 500 , factor : 1.5 } ,
2828
+ text ,
2829
+ { timeout : timeoutGap } ,
2830
2830
) ,
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 )
2837
2838
} )
2838
2839
}
2839
2840
0 commit comments