From 4ee94b47a78a2b9a5cbbaefb6d16974ca942df9b Mon Sep 17 00:00:00 2001 From: Thomas Klemm Date: Wed, 4 Nov 2026 09:06:14 +0000 Subject: [PATCH] fix(node): click the center of a transformed node's bounding rect when content quads fail When `DOM.getContentQuads` fails, `find_position` falls back to the node's bounding rect. It added half of `offsetWidth`/`offsetHeight` to the rect's left/top, but those are the untransformed layout size while the rect includes transforms, so a scaled node could be missed. Use the rect's own width and height. Fixes #695 --- CHANGELOG.md | 3 +++ lib/ferrum/node.rb | 8 +++++--- spec/node_spec.rb | 11 +++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e74bf49..1339ce6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,9 @@ node's own frame - `Node#moving?` returned `true` for a node that wasn't moving and `false` for one that was. Its default delay is now 50ms instead of 10ms, which missed a slowly moving node, set it with `FERRUM_NODE_MOVING_CHECK` +- `Node#click` and `#find_position` on a CSS-transformed node whose content quads can't be computed aimed by its + untransformed size and could miss it, now they aim at the center of its bounding rect. An SVG node raised + `JSON::GeneratorError` there [#695] ### Removed - `#evaluate_async`, `#evaluate_func` and `#evaluate_on`, use `#evaluate` and `Node#evaluate`, and diff --git a/lib/ferrum/node.rb b/lib/ferrum/node.rb index 452542c4..aebc8985 100644 --- a/lib/ferrum/node.rb +++ b/lib/ferrum/node.rb @@ -714,9 +714,11 @@ def exists? private def bounding_rect_coordinates - evaluate <<~JS - [this.getBoundingClientRect().left + (this.offsetWidth / 2), - this.getBoundingClientRect().top + (this.offsetHeight / 2)] + evaluate(<<~JS) + function() { + const { left, top, width, height } = this.getBoundingClientRect(); + return [left + (width / 2), top + (height / 2)]; + } JS end diff --git a/spec/node_spec.rb b/spec/node_spec.rb index ef1a6fa4..57f4ed7f 100644 --- a/spec/node_spec.rb +++ b/spec/node_spec.rb @@ -192,6 +192,17 @@ expect(browser.url).to eq(base_url("/")) end + + it "clicks the element by its bounding rect when it's transformed" do + browser.go_to("/simple") + link = browser.at_css("#nav") + # Rotated, the link covers the center of its bounding rect, but little else of it. + link.execute("this.style.cssText = 'display: inline-block; width: 200px; height: 20px; transform: rotate(45deg)'") + + link.click + + expect(browser.url).to eq(base_url("/")) + end end it "synchronizes page loads properly" do