Skip to content

Commit a71634d

Browse files
Mifrillroute
authored andcommitted
feature: implement in_viewport? and scroll_into_view
1 parent 797558d commit a71634d

File tree

5 files changed

+49
-11
lines changed

5 files changed

+49
-11
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
- `Ferrum::Network::Exchange#xhr?` determines if the exchange is XHR
55
- `Ferrum::Network::Request#xhr?` determines if the request is XHR
66
- `Ferrum::Network::Response#loaded?` returns true if the response is fully loaded
7+
- `Ferrum::Node#in_viewport?` checks if the element in viewport (optional argument `scope` as `Ferrum::Node`)
8+
- `Ferrum::Node#scroll_into_view` - scrolls to element if needed (when it's not in the viewport)
79

810
### Changed
911

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,8 @@ frame.at_css("//a[text() = 'Log in']") # => Node
11281128
#### evaluate
11291129
#### selected : `Array<Node>`
11301130
#### select
1131+
#### scroll_into_view
1132+
#### in_viewport?(of: `Node | nil`) : `Boolean`
11311133

11321134
(chainable) Selects options by passed attribute.
11331135

lib/ferrum/node.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,26 @@ def hover
8888
raise NotImplementedError
8989
end
9090

91+
def scroll_into_view
92+
tap { page.command("DOM.scrollIntoViewIfNeeded", nodeId: node_id) }
93+
end
94+
95+
def in_viewport?(of: nil)
96+
function = <<~JS
97+
function(element, scope) {
98+
const rect = element.getBoundingClientRect();
99+
const [height, width] = scope
100+
? [scope.offsetHeight, scope.offsetWidth]
101+
: [window.innerHeight, window.innerWidth];
102+
return rect.top >= 0 &&
103+
rect.left >= 0 &&
104+
rect.bottom <= height &&
105+
rect.right <= width;
106+
}
107+
JS
108+
page.evaluate_func(function, self, of)
109+
end
110+
91111
def select_file(value)
92112
page.command("DOM.setFileInputFiles", slowmoable: true, nodeId: node_id, files: Array(value))
93113
end

spec/node_spec.rb

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,33 @@
7272
end
7373
end
7474

75-
context "when the element is not in the viewport of parent element", skip: true do
76-
before do
77-
browser.go_to("/ferrum/scroll")
78-
end
75+
context "when the element is not in the viewport of parent element" do
76+
before { page.go_to("/ferrum/scroll") }
77+
78+
it "scrolls into view if element outside viewport" do
79+
link = page.at_xpath("//a[text() = 'Link outside viewport']")
80+
link.click
81+
expect(page.current_url).to eq(base_url("/ferrum/scroll"))
7982

80-
it "scrolls into view", skip: "needs fix" do
81-
browser.at_xpath("//a[text() = 'Link outside viewport']").click
82-
expect(browser.current_url).to eq("/")
83+
expect(link.in_viewport?).to eq(true)
84+
box = page.at_xpath("//div[@id='overflow-box']")
85+
expect(link.in_viewport?(of: box)).to eq(false)
86+
87+
link.scroll_into_view
88+
expect(link.in_viewport?(of: box)).to eq(true)
89+
link.click
90+
expect(page.current_url).to eq(base_url("/"))
8391
end
8492

85-
it "scrolls into view if scrollIntoViewIfNeeded fails" do
86-
browser.click_link "Below the fold"
87-
expect(browser.current_path).to eq("/")
93+
it "scrolls into view if element below the fold" do
94+
link = page.at_xpath("//a[*//text() = 'Below the fold']")
95+
expect(link.in_viewport?).to eq(false)
96+
97+
link.scroll_into_view
98+
99+
expect(link.in_viewport?).to eq(true)
100+
link.click
101+
expect(page.current_url).to eq(base_url("/"))
88102
end
89103
end
90104
end

spec/support/views/scroll.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<title>scroll</title>
55
</head>
66
<body>
7-
<div style="height: 100px; overflow-y: auto">
7+
<div id="overflow-box" style="height: 100px; overflow-y: auto">
88
<div style="height: 300px;">
99
<p>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.</p>
1010
</div>

0 commit comments

Comments
 (0)