capybara-lightpanda 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a8f6c1cfdad13de4569b3d79828d9d19848b166e220b6a91329c7c0cb2fa9781
|
|
4
|
+
data.tar.gz: 2f7c90bb35b746682f5533c9d7ebfe1b64fbf7aea1f53a6c93f563428d9f3b46
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d1632dc29185af1e1d1c594abd7a9fe4b0af584585aa6c6534428d59b23316174db581d901bd7d67430b2e708c664c9c7175918cfeca4d386ba95453816b910
|
|
7
|
+
data.tar.gz: 76a79eed2e960c294a09c1ee8882014d543c5695cd519d51c3d9560ca7b153b085ae4161f18e2a11a301465b95c0cc71140a269c3c8970c86e93d291430630cb
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.16.0] - 2026-10-26
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **`trigger(:click)` waits for the page it loads.** Calling `element.trigger(:click)` on a link or submit button returned before the new page arrived, so the next step ran against the old page. It now waits the way `click` does.
|
|
8
|
+
- **Clicking a `<a download>` link no longer cancels the download on recent nightlies.** From nightly 11097 (and the upcoming 1.1 release line), Lightpanda starts the download itself when a link has a `download` attribute. The driver then also went to the same URL, which cancelled the download and replaced the page. The driver now leaves the download to the browser. Older browsers behave as before.
|
|
9
|
+
- **`obscured?` sees overlays inside a shadow root.** On browsers that can hit-test inside shadow trees (recent nightlies), an element covered by another element in the same shadow root now counts as obscured; before, it was always reported as not obscured. Older browsers give the same answer as before.
|
|
10
|
+
|
|
3
11
|
## [0.15.0] - 2026-10-23
|
|
4
12
|
|
|
5
13
|
> **Update Lightpanda before upgrading.** This release requires Lightpanda **1.0.2** or a nightly build ≥ 10965. The driver refuses anything older and names the version it found. Pin `1.0.2` for a reproducible browser.
|
|
@@ -12,10 +12,10 @@ module Capybara
|
|
|
12
12
|
# `Browser.downloadProgress`. We mirror those into a completed-files list +
|
|
13
13
|
# a blocking `wait`, the way ferrum's Downloads does.
|
|
14
14
|
#
|
|
15
|
-
#
|
|
16
|
-
# type.
|
|
17
|
-
#
|
|
18
|
-
#
|
|
15
|
+
# Navigation downloads require Content-Disposition: attachment, not just a
|
|
16
|
+
# MIME type. New browsers also honor an anchor's download attribute (build
|
|
17
|
+
# 11097 / 1.1 release line); Node#click lets that native activation finish.
|
|
18
|
+
# Capybara's MIME-only :download shared spec still stays in capybara_skip.
|
|
19
19
|
#
|
|
20
20
|
# Structure deliberately mirrors Network (same browser ref, same mutex +
|
|
21
21
|
# subscribe/unsubscribe lifecycle, same reset-after-disposeBrowserContext
|
|
@@ -54,17 +54,24 @@ function isObscured(el) {
|
|
|
54
54
|
if (cx < 0 || cy < 0 || cx > w || cy > h) return true;
|
|
55
55
|
var hit = doc.elementFromPoint(cx, cy);
|
|
56
56
|
if (!hit) return true;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
// hosts is the best "not obscured" answer available.
|
|
62
|
-
var root = el.getRootNode ? el.getRootNode() : doc;
|
|
57
|
+
// Document hit testing retargets a shadow child to its outermost host.
|
|
58
|
+
// Check each enclosing shadow tree from the outside in: an inner root must
|
|
59
|
+
// never let us see through an overlay covering its host in an outer root.
|
|
60
|
+
var roots = [], root = el.getRootNode ? el.getRootNode() : doc;
|
|
63
61
|
while (root && root !== doc && root.host) {
|
|
64
|
-
|
|
62
|
+
roots.push(root);
|
|
65
63
|
root = root.host.getRootNode();
|
|
66
64
|
}
|
|
67
|
-
|
|
65
|
+
for (var i = roots.length - 1; i >= 0; i--) {
|
|
66
|
+
root = roots[i];
|
|
67
|
+
if (hit !== root.host) break;
|
|
68
|
+
// Older supported builds have no shadow hit testing. A hit on our own
|
|
69
|
+
// host remains the best available evidence that the child is actionable.
|
|
70
|
+
if (typeof root.elementFromPoint !== 'function') return false;
|
|
71
|
+
hit = root.elementFromPoint(cx, cy);
|
|
72
|
+
if (!hit) return true;
|
|
73
|
+
}
|
|
74
|
+
return hit !== el && !el.contains(hit);
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
// Capybara's `Node#disabled?` is more permissive than CSS `:disabled`:
|
|
@@ -135,7 +135,7 @@ module Capybara
|
|
|
135
135
|
end
|
|
136
136
|
|
|
137
137
|
def click(_keys = [], **_options)
|
|
138
|
-
call(CLICK_JS)
|
|
138
|
+
call(CLICK_JS, native_anchor_downloads?)
|
|
139
139
|
driver.browser.wait_for_idle
|
|
140
140
|
end
|
|
141
141
|
|
|
@@ -178,7 +178,9 @@ module Capybara
|
|
|
178
178
|
# generic Event for everything else (so callers can fire custom events
|
|
179
179
|
# like `node.trigger('lp:custom')`).
|
|
180
180
|
def trigger(event)
|
|
181
|
-
|
|
181
|
+
name = event.to_s
|
|
182
|
+
call(TRIGGER_JS, name)
|
|
183
|
+
driver.browser.wait_for_idle if name == "click"
|
|
182
184
|
end
|
|
183
185
|
|
|
184
186
|
def set(value, **_options)
|
|
@@ -374,6 +376,18 @@ module Capybara
|
|
|
374
376
|
|
|
375
377
|
private
|
|
376
378
|
|
|
379
|
+
# Below #4124 a download attribute suppresses native activation entirely,
|
|
380
|
+
# so the manual navigation is still needed for attachment responses.
|
|
381
|
+
# The API has no feature marker: keep the floor path through 1.0.x and
|
|
382
|
+
# enable native download activation on build 11097 / the 1.1 release line.
|
|
383
|
+
def native_anchor_downloads?
|
|
384
|
+
browser = driver.browser
|
|
385
|
+
build = browser.nightly_build
|
|
386
|
+
return build >= Gem::Version.new("11097") if build
|
|
387
|
+
|
|
388
|
+
browser.release && browser.release >= Gem::Version.new("1.1.0")
|
|
389
|
+
end
|
|
390
|
+
|
|
377
391
|
def find_hinted(method, selector, hints)
|
|
378
392
|
driver.browser.find_within_hinted(@remote_object_id, method, selector, self.class.hint_spec(**hints))
|
|
379
393
|
.map { |oid, cache| self.class.new(driver, oid, cache, frame_scoped: @frame_scoped) }
|
|
@@ -593,7 +607,7 @@ module Capybara
|
|
|
593
607
|
# 6167 as duplicate `turbo:submit-start` events; the first request
|
|
594
608
|
# gets aborted by the second and Turbo never renders the response.
|
|
595
609
|
CLICK_JS = <<~JS
|
|
596
|
-
function() {
|
|
610
|
+
function(nativeAnchorDownloads) {
|
|
597
611
|
var EventCtor = (typeof MouseEvent !== 'undefined') ? MouseEvent : Event;
|
|
598
612
|
// Emulate coordinate hit-testing without a layout engine. In a real
|
|
599
613
|
// browser a pointer click on a container lands on its frontmost
|
|
@@ -658,6 +672,11 @@ module Capybara
|
|
|
658
672
|
var external = !!scheme && !/^(https?|about|blob|data|file|javascript)$/i.test(scheme[1]);
|
|
659
673
|
var notCancelled = hit.dispatchEvent(clickEvt);
|
|
660
674
|
if (external || !notCancelled || clickEvt.defaultPrevented) return;
|
|
675
|
+
// Native activation has already started the download. Navigating
|
|
676
|
+
// again cancels it and replaces the document. Keep the complete
|
|
677
|
+
// synthetic event sequence and its cancellation, but stop here on
|
|
678
|
+
// browsers that support the download attribute.
|
|
679
|
+
if (nativeAnchorDownloads && link && link.hasAttribute('download')) return;
|
|
661
680
|
var tag = hit.tagName;
|
|
662
681
|
// A `javascript:` link never navigates: the click's own activation
|
|
663
682
|
// behavior has already run its code. Assigning it to location.href
|