diff --git a/lib/capybara/cuprite/javascripts/index.js b/lib/capybara/cuprite/javascripts/index.js index 092c022..b0733b0 100644 --- a/lib/capybara/cuprite/javascripts/index.js +++ b/lib/capybara/cuprite/javascripts/index.js @@ -77,15 +77,27 @@ class Cuprite { } } + let ancestorOpacityApplies = true; + while (node) { if (node instanceof ShadowRoot) { node = node.host; } else { style = window.getComputedStyle(node); - if (style.display === "none" || style.visibility === "hidden" || parseFloat(style.opacity) === 0) { + if (style.display === "none" || style.visibility === "hidden" || (ancestorOpacityApplies && parseFloat(style.opacity) === 0)) { return false; } + // A node matching :modal or :popover-open is a top-layer element, so + // an ancestor's opacity no longer applies to it once shown. + if (ancestorOpacityApplies) { + try { + if (node.matches(":modal") || node.matches(":popover-open")) { + ancestorOpacityApplies = false; + } + } catch (e) {} + } + let parent = node.parentElement; if (parent && parent.tagName === "DETAILS" && !parent.open) { // In a closed
only the first (and its subtree) is rendered. diff --git a/spec/features/session_spec.rb b/spec/features/session_spec.rb index 4ce3309..752d2c7 100644 --- a/spec/features/session_spec.rb +++ b/spec/features/session_spec.rb @@ -410,6 +410,34 @@ it "element with all children hidden returns empty text" do expect(@session.find(:css, "div").text).to eq("") end + + it "considers a shown popover to be visible past opacity: 0" do + popover = @session.find(:css, "#popover_in_transparent", visible: false) + expect(popover.visible?).to be false + + popover.execute_script("this.showPopover()") + + expect(popover.visible?).to be true + end + + it "considers a shown modal dialog to be visible past opacity: 0" do + dialog = @session.find(:css, "#dialog_in_transparent", visible: false) + expect(dialog.visible?).to be false + + dialog.execute_script("this.showModal()") + expect(dialog.visible?).to be true + + dialog.execute_script("this.close(); this.show()") + expect(dialog.visible?).to be false + end + + it "considers a shown popover to not be visible past display: none" do + popover = @session.find(:css, "#popover_in_display_none", visible: false) + + popover.execute_script("this.showPopover()") + + expect(popover.visible?).to be false + end end describe "Node#checked?" do diff --git a/spec/support/views/visible.erb b/spec/support/views/visible.erb index 0209ddc..8733bae 100644 --- a/spec/support/views/visible.erb +++ b/spec/support/views/visible.erb @@ -15,5 +15,12 @@ Display None Hidden +
+
Popover In Transparent
+ Dialog In Transparent +
+
+
Popover In Display None
+