Repository navigation
spike(locator): stale-proof click() — re-resolve on every poll - #67
Merged
Merged
Conversation
Locator.click() resolved the element once, then waited on that reference. If the page re-rendered it the wait either timed out (stale during the clickable check) or StaleElementReferenceException escaped (stale between check and click). click() now resolves inside the wait, ignores StaleElementReferenceException, and re-resolves each poll. Spike scope: click() only. Other terminal actions unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
shossain786
marked this pull request as ready for review
September 20, 2026 05:36
shossain786
added a commit
that referenced
this pull request
Sep 20, 2026
…very poll (#68) Extends the click() stale-proofing (#67) to type, append, getText, getAttribute, hover, scrollIntoView, jsClick and element(), via one shared whenReady() helper. Behaviour change: a locator that matches nothing is now retried until timeouts.explicit instead of throwing immediately. It still ends in a LocatorException (cause: TimeoutException), so existing catches keep working. isVisible/isHidden/isEnabled/count still never wait. rows() resolves through element() and inherits the wait for the table itself. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This was referenced Oct 9, 2026
This was referenced Oct 10, 2026
crystalmountain666
added a commit
to TONGdamy/selenium-boot
that referenced
this pull request
Oct 19, 2026
BasePage already offers doubleClick/rightClick, but Locator did not, so users had to drop out of the Locator API for these gestures. Both methods perform the gesture with Selenium's Actions API and go through the existing terminal-action helpers, so they follow the same contract as click() and hover() (seleniumboot#67/seleniumboot#68): the element is re-resolved from scratch on every poll, and stale or not-yet-present elements are retried until timeouts.explicit. A StaleElementReferenceException thrown while the gesture is performed is retried as well, rather than being treated as success. - doubleClick() waits for the element to be visible and enabled, like click(). - rightClick() waits for the element to be visible, like hover(). Each method has Javadoc with a usage example. Tests follow in the next commit. Refs seleniumboot#134
crystalmountain666
added a commit
to TONGdamy/selenium-boot
that referenced
this pull request
Oct 19, 2026
…eleniumboot#134) Add LocatorActionsTest, which checks that doubleClick() and rightClick() honour the same terminal-action contract as click() (seleniumboot#67/seleniumboot#68). The tests mock the driver as Interactive so the Actions sequences can be captured, and set timeouts.explicit to 1s to keep the timeout cases fast. Each pointer action is run through a shared data provider covering: - a ready element: the gesture is performed once on one lookup, and the element is never cleared or plain-clicked - an element that appears later: the locator re-resolves first - an element that is hidden at first: the action waits for it to become visible - an element that goes stale during the readiness check: a fresh element is resolved and used - an element that goes stale during the gesture: the gesture is retried on a freshly resolved element - an element that never appears: LocatorException with a TimeoutException cause, and no gesture is performed - an element that stays stale during the gesture: the action times out instead of reporting success - an element that never becomes visible: times out without acting A separate test checks that doubleClick() waits until the element is enabled. The successful cases also decode the captured gesture to check the target element, the number of press/release pairs (2 for doubleClick, 1 for rightClick) and the mouse button (left for doubleClick, right for rightClick). The data provider is shared so that the keyboard and focus actions can be added to the same matrix. Refs seleniumboot#134
TONGdamy
pushed a commit
to TONGdamy/selenium-boot
that referenced
this pull request
Oct 19, 2026
BasePage already offers doubleClick/rightClick, but Locator did not, so users had to drop out of the Locator API for these gestures. Both methods perform the gesture with Selenium's Actions API and go through the existing terminal-action helpers, so they follow the same contract as click() and hover() (seleniumboot#67/seleniumboot#68): the element is re-resolved from scratch on every poll, and stale or not-yet-present elements are retried until timeouts.explicit. A StaleElementReferenceException thrown while the gesture is performed is retried as well, rather than being treated as success. - doubleClick() waits for the element to be visible and enabled, like click(). - rightClick() waits for the element to be visible, like hover(). Each method has Javadoc with a usage example. Tests follow in the next commit. Refs seleniumboot#134
TONGdamy
pushed a commit
to TONGdamy/selenium-boot
that referenced
this pull request
Oct 19, 2026
…eleniumboot#134) Add LocatorActionsTest, which checks that doubleClick() and rightClick() honour the same terminal-action contract as click() (seleniumboot#67/seleniumboot#68). The tests mock the driver as Interactive so the Actions sequences can be captured, and set timeouts.explicit to 1s to keep the timeout cases fast. Each pointer action is run through a shared data provider covering: - a ready element: the gesture is performed once on one lookup, and the element is never cleared or plain-clicked - an element that appears later: the locator re-resolves first - an element that is hidden at first: the action waits for it to become visible - an element that goes stale during the readiness check: a fresh element is resolved and used - an element that goes stale during the gesture: the gesture is retried on a freshly resolved element - an element that never appears: LocatorException with a TimeoutException cause, and no gesture is performed - an element that stays stale during the gesture: the action times out instead of reporting success - an element that never becomes visible: times out without acting A separate test checks that doubleClick() waits until the element is enabled. The successful cases also decode the captured gesture to check the target element, the number of press/release pairs (2 for doubleClick, 1 for rightClick) and the mouse button (left for doubleClick, right for rightClick). The data provider is shared so that the keyboard and focus actions can be added to the same matrix. Refs seleniumboot#134
crystalmountain666
added a commit
to TONGdamy/selenium-boot
that referenced
this pull request
Oct 20, 2026
BasePage already offers doubleClick/rightClick, but Locator did not, so users had to drop out of the Locator API for these gestures. Both methods perform the gesture with Selenium's Actions API and go through the existing terminal-action helpers, so they follow the same contract as click() and hover() (seleniumboot#67/seleniumboot#68): the element is re-resolved from scratch on every poll, and stale or not-yet-present elements are retried until timeouts.explicit. A StaleElementReferenceException thrown while the gesture is performed is retried as well, rather than being treated as success. - doubleClick() waits for the element to be visible and enabled, like click(). - rightClick() waits for the element to be visible, like hover(). Each method has Javadoc with a usage example. Tests follow in the next commit. Refs seleniumboot#134
crystalmountain666
added a commit
to TONGdamy/selenium-boot
that referenced
this pull request
Oct 20, 2026
…eleniumboot#134) Add LocatorActionsTest, which checks that doubleClick() and rightClick() honour the same terminal-action contract as click() (seleniumboot#67/seleniumboot#68). The tests mock the driver as Interactive so the Actions sequences can be captured, and set timeouts.explicit to 1s to keep the timeout cases fast. Each pointer action is run through a shared data provider covering: - a ready element: the gesture is performed once on one lookup, and the element is never cleared or plain-clicked - an element that appears later: the locator re-resolves first - an element that is hidden at first: the action waits for it to become visible - an element that goes stale during the readiness check: a fresh element is resolved and used - an element that goes stale during the gesture: the gesture is retried on a freshly resolved element - an element that never appears: LocatorException with a TimeoutException cause, and no gesture is performed - an element that stays stale during the gesture: the action times out instead of reporting success - an element that never becomes visible: times out without acting A separate test checks that doubleClick() waits until the element is enabled. The successful cases also decode the captured gesture to check the target element, the number of press/release pairs (2 for doubleClick, 1 for rightClick) and the mouse button (left for doubleClick, right for rightClick). The data provider is shared so that the keyboard and focus actions can be added to the same matrix. Refs seleniumboot#134
6 of 10 tasks
crystalmountain666
added a commit
to TONGdamy/selenium-boot
that referenced
this pull request
Oct 21, 2026
BasePage already offers doubleClick/rightClick, but Locator did not, so users had to drop out of the Locator API for these gestures. Both methods perform the gesture with Selenium's Actions API and go through the existing terminal-action helpers, so they follow the same contract as click() and hover() (seleniumboot#67/seleniumboot#68): the element is re-resolved from scratch on every poll, and stale or not-yet-present elements are retried until timeouts.explicit. A StaleElementReferenceException thrown while the gesture is performed is retried as well, rather than being treated as success. - doubleClick() waits for the element to be visible and enabled, like click(). - rightClick() waits for the element to be visible, like hover(). Each method has Javadoc with a usage example. Tests follow in the next commit. Refs seleniumboot#134
crystalmountain666
added a commit
to TONGdamy/selenium-boot
that referenced
this pull request
Oct 21, 2026
…eleniumboot#134) Add LocatorActionsTest, which checks that doubleClick() and rightClick() honour the same terminal-action contract as click() (seleniumboot#67/seleniumboot#68). The tests mock the driver as Interactive so the Actions sequences can be captured, and set timeouts.explicit to 1s to keep the timeout cases fast. Each pointer action is run through a shared data provider covering: - a ready element: the gesture is performed once on one lookup, and the element is never cleared or plain-clicked - an element that appears later: the locator re-resolves first - an element that is hidden at first: the action waits for it to become visible - an element that goes stale during the readiness check: a fresh element is resolved and used - an element that goes stale during the gesture: the gesture is retried on a freshly resolved element - an element that never appears: LocatorException with a TimeoutException cause, and no gesture is performed - an element that stays stale during the gesture: the action times out instead of reporting success - an element that never becomes visible: times out without acting A separate test checks that doubleClick() waits until the element is enabled. The successful cases also decode the captured gesture to check the target element, the number of press/release pairs (2 for doubleClick, 1 for rightClick) and the mouse button (left for doubleClick, right for rightClick). The data provider is shared so that the keyboard and focus actions can be added to the same matrix. Refs seleniumboot#134
7 of 10 tasks
shossain786
pushed a commit
that referenced
this pull request
Oct 21, 2026
) * feat(locator): add doubleClick() and rightClick() (#134) BasePage already offers doubleClick/rightClick, but Locator did not, so users had to drop out of the Locator API for these gestures. Both methods perform the gesture with Selenium's Actions API and go through the existing terminal-action helpers, so they follow the same contract as click() and hover() (#67/#68): the element is re-resolved from scratch on every poll, and stale or not-yet-present elements are retried until timeouts.explicit. A StaleElementReferenceException thrown while the gesture is performed is retried as well, rather than being treated as success. - doubleClick() waits for the element to be visible and enabled, like click(). - rightClick() waits for the element to be visible, like hover(). Each method has Javadoc with a usage example. Tests follow in the next commit. Refs #134 * test(locator): pointer actions follow the terminal-action contract (#134) Add LocatorActionsTest, which checks that doubleClick() and rightClick() honour the same terminal-action contract as click() (#67/#68). The tests mock the driver as Interactive so the Actions sequences can be captured, and set timeouts.explicit to 1s to keep the timeout cases fast. Each pointer action is run through a shared data provider covering: - a ready element: the gesture is performed once on one lookup, and the element is never cleared or plain-clicked - an element that appears later: the locator re-resolves first - an element that is hidden at first: the action waits for it to become visible - an element that goes stale during the readiness check: a fresh element is resolved and used - an element that goes stale during the gesture: the gesture is retried on a freshly resolved element - an element that never appears: LocatorException with a TimeoutException cause, and no gesture is performed - an element that stays stale during the gesture: the action times out instead of reporting success - an element that never becomes visible: times out without acting A separate test checks that doubleClick() waits until the element is enabled. The successful cases also decode the captured gesture to check the target element, the number of press/release pairs (2 for doubleClick, 1 for rightClick) and the mouse button (left for doubleClick, right for rightClick). The data provider is shared so that the keyboard and focus actions can be added to the same matrix. Refs #134 * feat(locator): add press(Keys...) and focus() (#134) * test(locator): cover press and focus (#134) * docs(locator): document locator actions (#134) --------- Co-authored-by: Xi Hu <u8183004@anu.edu.au>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Spike from the 09-17 feature brainstorm ("stale-proof element resolution"), scoped to
Locator.click()only.click()used to resolve the element once and wait on that reference, so:TimeoutExceptionStaleElementReferenceExceptionescapesNow
click()resolves inside the wait, ignoresStaleElementReferenceException, and re-resolves each poll. The click still happens exactly once.Findings (what the spike measured)
LocatorStaleElementTest(3 tests). Before the change, 2 of 3 fail (StaleElementReferenceException;TimeoutExceptionafter 2 s); the control test (never-stale → exactly 1 lookup, 1 click) passes before and after.mvn clean verify: 511 tests, 0 failures — no existing test broke.selenium-boot-test, real browser) against a local build: 11/11 pass.LocatorException(no match) is still thrown immediately, not retried —resolve()doesn't wait for presence. Making it wait is a behavior change and needs a decision before rolling out to the other terminal actions.resolve()once → act):type,append,getText,getAttribute,hover,scrollIntoView,jsClick,element(),rows().Draft: the pattern is proven on one action; scope decision for the rest is open.
🤖 Generated with Claude Code