Skip to content

Raise ObsoleteNode when a node is detached before the click hit test - #360

Open
thomasklemm wants to merge 1 commit into
rubycdp:mainfrom
thomasklemm:fix-detached-node-click
Open

thomasklemm wants to merge 1 commit into
rubycdp:mainfrom
thomasklemm:fix-detached-node-click

Conversation

@thomasklemm

Copy link
Copy Markdown

Fixes #359.

Node#command checks this.isConnected once, then before_click runs several evaluates (scrollIntoViewport, find_position, mouseEventTest). If the page removes the node between them, which React/Inertia re-renders do, mouseEventTest calls node.getRootNode() on the detached subtree. That root is an element, not a document, so the click fails with Ferrum::JavaScriptError: TypeError: node.getRootNode(...).elementFromPoint is not a function. Capybara does not retry that error, so the test errors instead of re-finding the element.

Change

  • mouseEventTest throws an ObsoleteNode JS error when node.isConnected is false.
  • before_click maps it to Capybara::Cuprite::ObsoleteNode, the same way it already maps MouseEventFailed. ObsoleteNode is in Driver#invalid_element_errors, so Capybara's synchronize reloads the element and retries.

Spec

spec/node_spec.rb "raises ObsoleteNode for an element removed before the hit test" wraps _cuprite.mouseEventTest so that the node is removed right before the hit test, which makes the race deterministic. It uses node.native.click so that Capybara's reload does not hide the error.

  • Without the change: expected Capybara::Cuprite::ObsoleteNode, got #<Ferrum::JavaScriptError: "TypeError: node.getRootNode(...).elementFromPoint is not a function ...">.
  • With the change: passes. spec/node_spec.rb passes in full (155 examples) and RuboCop is clean.

Full suite locally on Chrome for Testing 156: 1809 examples, 1 failure. The failure is Capybara's shared #obscured? should work in frames, which also fails on unchanged main with this Chrome locally while your CI is green, so I take it to be unrelated to this change.

Node#command checks isConnected once, then before_click runs several
evaluates. If the page removes the node in between, mouseEventTest called
getRootNode() on the detached subtree, which has no elementFromPoint, and
the click failed with a JavaScriptError that Capybara does not retry.

Fixes rubycdp#359

Amp-Thread-ID: https://ampcode.com/threads/T-ea46fac7-7b01-42f9-a324-72b9afb4985c
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.

Click on a node detached mid-click raises JavaScriptError instead of ObsoleteNode

1 participant