From a71634d065cd976626e1b612134f2ef5eef90d67 Mon Sep 17 00:00:00 2001 From: Aleksey Strizhak Date: Thu, 21 Jan 2021 13:24:45 +0500 Subject: [PATCH] feature: implement in_viewport? and scroll_into_view --- CHANGELOG.md | 2 ++ README.md | 2 ++ lib/ferrum/node.rb | 20 ++++++++++++++++++++ spec/node_spec.rb | 34 ++++++++++++++++++++++++---------- spec/support/views/scroll.erb | 2 +- 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6ac96fe..631cfa76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - `Ferrum::Network::Exchange#xhr?` determines if the exchange is XHR - `Ferrum::Network::Request#xhr?` determines if the request is XHR - `Ferrum::Network::Response#loaded?` returns true if the response is fully loaded +- `Ferrum::Node#in_viewport?` checks if the element in viewport (optional argument `scope` as `Ferrum::Node`) +- `Ferrum::Node#scroll_into_view` - scrolls to element if needed (when it's not in the viewport) ### Changed diff --git a/README.md b/README.md index 89704468..3b3c3754 100644 --- a/README.md +++ b/README.md @@ -1128,6 +1128,8 @@ frame.at_css("//a[text() = 'Log in']") # => Node #### evaluate #### selected : `Array` #### select +#### scroll_into_view +#### in_viewport?(of: `Node | nil`) : `Boolean` (chainable) Selects options by passed attribute. diff --git a/lib/ferrum/node.rb b/lib/ferrum/node.rb index 9758023b..1c94456e 100644 --- a/lib/ferrum/node.rb +++ b/lib/ferrum/node.rb @@ -88,6 +88,26 @@ def hover raise NotImplementedError end + def scroll_into_view + tap { page.command("DOM.scrollIntoViewIfNeeded", nodeId: node_id) } + end + + def in_viewport?(of: nil) + function = <<~JS + function(element, scope) { + const rect = element.getBoundingClientRect(); + const [height, width] = scope + ? [scope.offsetHeight, scope.offsetWidth] + : [window.innerHeight, window.innerWidth]; + return rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= height && + rect.right <= width; + } + JS + page.evaluate_func(function, self, of) + end + def select_file(value) page.command("DOM.setFileInputFiles", slowmoable: true, nodeId: node_id, files: Array(value)) end diff --git a/spec/node_spec.rb b/spec/node_spec.rb index 963a13a8..14143d8e 100644 --- a/spec/node_spec.rb +++ b/spec/node_spec.rb @@ -72,19 +72,33 @@ end end - context "when the element is not in the viewport of parent element", skip: true do - before do - browser.go_to("/ferrum/scroll") - end + context "when the element is not in the viewport of parent element" do + before { page.go_to("/ferrum/scroll") } + + it "scrolls into view if element outside viewport" do + link = page.at_xpath("//a[text() = 'Link outside viewport']") + link.click + expect(page.current_url).to eq(base_url("/ferrum/scroll")) - it "scrolls into view", skip: "needs fix" do - browser.at_xpath("//a[text() = 'Link outside viewport']").click - expect(browser.current_url).to eq("/") + expect(link.in_viewport?).to eq(true) + box = page.at_xpath("//div[@id='overflow-box']") + expect(link.in_viewport?(of: box)).to eq(false) + + link.scroll_into_view + expect(link.in_viewport?(of: box)).to eq(true) + link.click + expect(page.current_url).to eq(base_url("/")) end - it "scrolls into view if scrollIntoViewIfNeeded fails" do - browser.click_link "Below the fold" - expect(browser.current_path).to eq("/") + it "scrolls into view if element below the fold" do + link = page.at_xpath("//a[*//text() = 'Below the fold']") + expect(link.in_viewport?).to eq(false) + + link.scroll_into_view + + expect(link.in_viewport?).to eq(true) + link.click + expect(page.current_url).to eq(base_url("/")) end end end diff --git a/spec/support/views/scroll.erb b/spec/support/views/scroll.erb index 751bdfba..01fd8ce3 100644 --- a/spec/support/views/scroll.erb +++ b/spec/support/views/scroll.erb @@ -4,7 +4,7 @@ scroll -
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin lacus odio, dapibus id bibendum in, rhoncus sed dolor. In quis nulla at diam euismod suscipit vitae vitae sapien. Nam viverra hendrerit augue a accumsan. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Fusce fermentum tortor at neque malesuada sodales. Nunc quis augue a quam venenatis pharetra sit amet et risus. Nulla pharetra enim a leo varius scelerisque aliquam urna vestibulum. Sed felis eros, iaculis convallis fermentum ac, condimentum ac lacus. Sed turpis magna, tristique eu faucibus non, faucibus vitae elit. Morbi venenatis adipiscing aliquam.