Skip to content

spike(locator): stale-proof click() — re-resolve on every poll - #67

Merged
shossain786 merged 1 commit into
masterfrom
spike/stale-proof-click
Sep 20, 2026
Merged

shossain786 merged 1 commit into
masterfrom
spike/stale-proof-click

Conversation

@shossain786

Copy link
Copy Markdown
Contributor

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:

  • element stale during the clickable check → wait spins on the dead reference until TimeoutException
  • element stale between the check and the click → StaleElementReferenceException escapes

Now click() resolves inside the wait, ignores StaleElementReferenceException, and re-resolves each poll. The click still happens exactly once.

Findings (what the spike measured)

  • New LocatorStaleElementTest (3 tests). Before the change, 2 of 3 fail (StaleElementReferenceException; TimeoutException after 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.
  • Consumer JUnit 5 suite (selenium-boot-test, real browser) against a local build: 11/11 pass.
  • Not covered by this spike: 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.
  • Remaining terminal actions with the same pattern (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

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
shossain786 marked this pull request as ready for review September 20, 2026 05:36
@shossain786
shossain786 merged commit 592b3d1 into master Sep 20, 2026
2 checks passed
@shossain786
shossain786 deleted the spike/stale-proof-click branch 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>
shossain786 added a commit that referenced this pull request Sep 21, 2026
Covers #66 (zero-config first run), #67/#68 (terminal Locator actions
wait and re-resolve on every poll) and #64 (junit-jupiter-api 6.1.3).
No version bump: the release decision is the maintainer's.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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
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
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant