Skip to content

Commit

Permalink
fixed regression in waitfortext (#4717)
Browse files Browse the repository at this point in the history
* fixed regression in waitfortext

* fixed wait test for wait for text

* fixed retries for PW waitForText test

---------

Co-authored-by: DavertMik <[email protected]>
  • Loading branch information
DavertMik and DavertMik authored Jan 7, 2025
1 parent 21b02eb commit 8fda0b9
Showing 1 changed file with 33 additions and 28 deletions.
61 changes: 33 additions & 28 deletions lib/helper/Playwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -2688,6 +2688,9 @@ class Playwright extends Helper {
if ((this.context && this.context.constructor.name === 'FrameLocator') || this.context) {
return this.context
}
if (this.frame) {
return this.frame
}
return this.page
}

Expand Down Expand Up @@ -2752,26 +2755,21 @@ class Playwright extends Helper {
async waitForText(text, sec = null, context = null) {
const waitTimeout = sec ? sec * 1000 : this.options.waitForTimeout
const errorMessage = `Text "${text}" was not found on page after ${waitTimeout / 1000} sec.`
let waiter

const contextObject = await this._getContext()

if (context) {
const locator = new Locator(context, 'css')
if (!locator.isXPath()) {
try {
await contextObject
try {
if (!locator.isXPath()) {
return contextObject
.locator(`${locator.isCustom() ? `${locator.type}=${locator.value}` : locator.simplify()} >> text=${text}`)
.first()
.waitFor({ timeout: waitTimeout, state: 'visible' })
} catch (e) {
throw new Error(`${errorMessage}\n${e.message}`)
}
}

if (locator.isXPath()) {
try {
await contextObject.waitForFunction(
if (locator.isXPath()) {
return contextObject.waitForFunction(
([locator, text, $XPath]) => {
eval($XPath) // eslint-disable-line no-eval
const el = $XPath(null, locator)
Expand All @@ -2781,27 +2779,34 @@ class Playwright extends Helper {
[locator.value, text, $XPath.toString()],
{ timeout: waitTimeout },
)
} catch (e) {
throw new Error(`${errorMessage}\n${e.message}`)
}
} catch (e) {
throw new Error(`${errorMessage}\n${e.message}`)
}
} else {
// we have this as https://github.com/microsoft/playwright/issues/26829 is not yet implemented

const _contextObject = this.frame ? this.frame : contextObject
let count = 0
do {
waiter = await _contextObject
.locator(`:has-text(${JSON.stringify(text)})`)
.first()
.isVisible()
if (waiter) break
await this.wait(1)
count += 1000
} while (count <= waitTimeout)

if (!waiter) throw new Error(`${errorMessage}`)
}

const timeoutGap = waitTimeout + 1000

// We add basic timeout to make sure we don't wait forever
// We apply 2 strategies here: wait for text as innert text on page (wide strategy) - older
// or we use native Playwright matcher to wait for text in element (narrow strategy) - newer
// 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
return Promise.race([
new Promise((_, reject) => {
setTimeout(() => reject(errorMessage), waitTimeout)
}),
this.page.waitForFunction(text => document.body && document.body.innerText.indexOf(text) > -1, text, { timeout: timeoutGap }),
promiseRetry(
async retry => {
const textPresent = await contextObject
.locator(`:has-text(${JSON.stringify(text)})`)
.first()
.isVisible()
if (!textPresent) retry(errorMessage)
},
{ retries: 1000, minTimeout: 500, maxTimeout: 500, factor: 1 },
),
])
}

/**
Expand Down

0 comments on commit 8fda0b9

Please sign in to comment.