@@ -37,6 +37,7 @@ const { findReact, findVue, findByPlaywrightLocator } = require('./extras/Playwr
3737let playwright
3838let perfTiming
3939let defaultSelectorEnginesInitialized = false
40+ let registeredCustomLocatorStrategies = new Set ( )
4041
4142const popupStore = new Popup ( )
4243const consoleLogStore = new Console ( )
@@ -345,6 +346,7 @@ class Playwright extends Helper {
345346 this . recordedWebSocketMessagesAtLeastOnce = false
346347 this . cdpSession = null
347348 this . customLocatorStrategies = typeof config . customLocatorStrategies === 'object' && config . customLocatorStrategies !== null ? config . customLocatorStrategies : null
349+ this . _customLocatorsRegistered = false
348350
349351 // override defaults with config
350352 this . _setConfig ( config )
@@ -470,9 +472,6 @@ class Playwright extends Helper {
470472 await playwright . selectors . register ( '__value' , createValueEngine )
471473 await playwright . selectors . register ( '__disabled' , createDisabledEngine )
472474 if ( process . env . testIdAttribute ) await playwright . selectors . setTestIdAttribute ( process . env . testIdAttribute )
473-
474- // Register custom locator strategies
475- await this . _registerCustomLocatorStrategies ( )
476475 } catch ( e ) {
477476 console . warn ( e )
478477 }
@@ -862,6 +861,10 @@ class Playwright extends Helper {
862861 this . debugSection ( 'Url' , target . url ( ) )
863862 } )
864863
864+ // Register custom locator strategies for this helper instance
865+ await this . _registerCustomLocatorStrategies ( )
866+ this . _customLocatorsRegistered = true
867+
865868 this . isRunning = true
866869 return this . browser
867870 }
@@ -893,6 +896,11 @@ class Playwright extends Helper {
893896 async _registerCustomLocatorStrategies ( ) {
894897 if ( this . _isCustomLocatorStrategyDefined ( ) ) {
895898 for ( const [ strategyName , strategyFunction ] of Object . entries ( this . customLocatorStrategies ) ) {
899+ // Skip if already registered
900+ if ( registeredCustomLocatorStrategies . has ( strategyName ) ) {
901+ continue
902+ }
903+
896904 try {
897905 this . debugSection ( 'Playwright' , `registering custom locator strategy: ${ strategyName } ` )
898906
@@ -928,6 +936,7 @@ class Playwright extends Helper {
928936 `
929937
930938 await playwright . selectors . register ( strategyName , { content : selectorEngine } )
939+ registeredCustomLocatorStrategies . add ( strategyName )
931940 } catch ( error ) {
932941 console . warn ( `Failed to register custom locator strategy '${ strategyName } ':` , error )
933942 }
@@ -1167,6 +1176,9 @@ class Playwright extends Helper {
11671176 const src = new Locator ( srcElement )
11681177 const dst = new Locator ( destElement )
11691178
1179+ // Ensure custom locators are registered
1180+ await this . _ensureCustomLocatorsRegistered ( )
1181+
11701182 if ( options ) {
11711183 return this . page . dragAndDrop ( buildLocatorString ( src ) , buildLocatorString ( dst ) , options )
11721184 }
@@ -1336,7 +1348,31 @@ class Playwright extends Helper {
13361348 * const elements = await this.helpers['Playwright']._locate({name: 'password'});
13371349 * ```
13381350 */
1351+ async _ensureCustomLocatorsRegistered ( ) {
1352+ // Only register once, and only if we have strategies defined
1353+ if ( this . _customLocatorsRegistered || ! this . _isCustomLocatorStrategyDefined ( ) ) {
1354+ return
1355+ }
1356+
1357+ try {
1358+ // If browser isn't running yet, start it to register selectors
1359+ if ( ! this . isRunning && ! this . options . manualStart ) {
1360+ await this . _startBrowser ( )
1361+ } else {
1362+ // If browser is running but custom locators not registered, register them now
1363+ await this . _registerCustomLocatorStrategies ( )
1364+ }
1365+ this . _customLocatorsRegistered = true
1366+ } catch ( error ) {
1367+ console . warn ( 'Failed to register custom locators:' , error . message )
1368+ // Continue execution - the error will surface when the locator is actually used
1369+ }
1370+ }
1371+
13391372 async _locate ( locator ) {
1373+ // Ensure custom locators are registered before any locator operations
1374+ await this . _ensureCustomLocatorsRegistered ( )
1375+
13401376 const context = await this . _getContext ( )
13411377
13421378 if ( this . frame ) return findElements ( this . frame , locator )
@@ -1368,6 +1404,9 @@ class Playwright extends Helper {
13681404 * ```
13691405 */
13701406 async _locateElement ( locator ) {
1407+ // Ensure custom locators are registered before any locator operations
1408+ await this . _ensureCustomLocatorsRegistered ( )
1409+
13711410 const context = await this . _getContext ( )
13721411 return findElement ( context , locator )
13731412 }
@@ -2649,6 +2688,9 @@ class Playwright extends Helper {
26492688 const waitTimeout = sec ? sec * 1000 : this . options . waitForTimeout
26502689 locator = new Locator ( locator , 'css' )
26512690
2691+ // Ensure custom locators are registered
2692+ await this . _ensureCustomLocatorsRegistered ( )
2693+
26522694 const context = await this . _getContext ( )
26532695 try {
26542696 await context . locator ( buildLocatorString ( locator ) ) . first ( ) . waitFor ( { timeout : waitTimeout , state : 'attached' } )
@@ -2665,6 +2707,10 @@ class Playwright extends Helper {
26652707 async waitForVisible ( locator , sec ) {
26662708 const waitTimeout = sec ? sec * 1000 : this . options . waitForTimeout
26672709 locator = new Locator ( locator , 'css' )
2710+
2711+ // Ensure custom locators are registered
2712+ await this . _ensureCustomLocatorsRegistered ( )
2713+
26682714 const context = await this . _getContext ( )
26692715 let count = 0
26702716
@@ -2694,6 +2740,10 @@ class Playwright extends Helper {
26942740 async waitForInvisible ( locator , sec ) {
26952741 const waitTimeout = sec ? sec * 1000 : this . options . waitForTimeout
26962742 locator = new Locator ( locator , 'css' )
2743+
2744+ // Ensure custom locators are registered
2745+ await this . _ensureCustomLocatorsRegistered ( )
2746+
26972747 const context = await this . _getContext ( )
26982748 let waiter
26992749 let count = 0
@@ -2724,6 +2774,10 @@ class Playwright extends Helper {
27242774 async waitToHide ( locator , sec ) {
27252775 const waitTimeout = sec ? sec * 1000 : this . options . waitForTimeout
27262776 locator = new Locator ( locator , 'css' )
2777+
2778+ // Ensure custom locators are registered
2779+ await this . _ensureCustomLocatorsRegistered ( )
2780+
27272781 const context = await this . _getContext ( )
27282782 let waiter
27292783 let count = 0
@@ -2840,6 +2894,9 @@ class Playwright extends Helper {
28402894 const waitTimeout = sec ? sec * 1000 : this . options . waitForTimeout
28412895 const errorMessage = `Text "${ text } " was not found on page after ${ waitTimeout / 1000 } sec.`
28422896
2897+ // Ensure custom locators are registered
2898+ await this . _ensureCustomLocatorsRegistered ( )
2899+
28432900 const contextObject = await this . _getContext ( )
28442901
28452902 if ( context ) {
@@ -3061,6 +3118,9 @@ class Playwright extends Helper {
30613118 const waitTimeout = sec ? sec * 1000 : this . options . waitForTimeout
30623119 locator = new Locator ( locator , 'css' )
30633120
3121+ // Ensure custom locators are registered
3122+ await this . _ensureCustomLocatorsRegistered ( )
3123+
30643124 let waiter
30653125 const context = await this . _getContext ( )
30663126 if ( ! locator . isXPath ( ) ) {
0 commit comments