Skip to content

Commit 74c53d0

Browse files
Copilotkobenguyent
andcommitted
Fix custom locator registration timing issue
Co-authored-by: kobenguyent <[email protected]>
1 parent 8dc38cd commit 74c53d0

File tree

1 file changed

+63
-3
lines changed

1 file changed

+63
-3
lines changed

lib/helper/Playwright.js

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const { findReact, findVue, findByPlaywrightLocator } = require('./extras/Playwr
3737
let playwright
3838
let perfTiming
3939
let defaultSelectorEnginesInitialized = false
40+
let registeredCustomLocatorStrategies = new Set()
4041

4142
const popupStore = new Popup()
4243
const 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

Comments
 (0)