capybara 3.12.0 → 3.13.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +13 -0
  3. data/README.md +13 -3
  4. data/lib/capybara.rb +8 -4
  5. data/lib/capybara/config.rb +3 -1
  6. data/lib/capybara/driver/base.rb +2 -2
  7. data/lib/capybara/driver/node.rb +11 -2
  8. data/lib/capybara/minitest.rb +3 -3
  9. data/lib/capybara/minitest/spec.rb +10 -3
  10. data/lib/capybara/node/actions.rb +4 -0
  11. data/lib/capybara/node/base.rb +13 -5
  12. data/lib/capybara/node/document.rb +12 -0
  13. data/lib/capybara/node/element.rb +37 -0
  14. data/lib/capybara/node/finders.rb +1 -0
  15. data/lib/capybara/node/matchers.rb +19 -4
  16. data/lib/capybara/node/simple.rb +7 -2
  17. data/lib/capybara/queries/selector_query.rb +93 -9
  18. data/lib/capybara/rspec/matchers.rb +11 -3
  19. data/lib/capybara/rspec/matchers/become_closed.rb +1 -1
  20. data/lib/capybara/rspec/matchers/match_style.rb +38 -0
  21. data/lib/capybara/selector.rb +30 -30
  22. data/lib/capybara/selector/selector.rb +47 -3
  23. data/lib/capybara/selenium/driver.rb +12 -11
  24. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +3 -3
  25. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +2 -2
  26. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +13 -0
  27. data/lib/capybara/selenium/extensions/find.rb +81 -0
  28. data/lib/capybara/selenium/extensions/scroll.rb +78 -0
  29. data/lib/capybara/selenium/node.rb +52 -28
  30. data/lib/capybara/session.rb +13 -1
  31. data/lib/capybara/spec/public/test.js +1 -0
  32. data/lib/capybara/spec/session/assert_style_spec.rb +4 -4
  33. data/lib/capybara/spec/session/attach_file_spec.rb +6 -6
  34. data/lib/capybara/spec/session/click_button_spec.rb +1 -1
  35. data/lib/capybara/spec/session/evaluate_script_spec.rb +1 -0
  36. data/lib/capybara/spec/session/execute_script_spec.rb +1 -0
  37. data/lib/capybara/spec/session/fill_in_spec.rb +7 -1
  38. data/lib/capybara/spec/session/find_field_spec.rb +1 -1
  39. data/lib/capybara/spec/session/find_spec.rb +11 -0
  40. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +0 -1
  41. data/lib/capybara/spec/session/has_css_spec.rb +32 -0
  42. data/lib/capybara/spec/session/has_select_spec.rb +2 -2
  43. data/lib/capybara/spec/session/has_selector_spec.rb +7 -0
  44. data/lib/capybara/spec/session/has_text_spec.rb +1 -1
  45. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  46. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  47. data/lib/capybara/spec/session/select_spec.rb +5 -0
  48. data/lib/capybara/spec/spec_helper.rb +1 -0
  49. data/lib/capybara/spec/views/obscured.erb +1 -1
  50. data/lib/capybara/spec/views/scroll.erb +20 -0
  51. data/lib/capybara/spec/views/with_html.erb +1 -1
  52. data/lib/capybara/version.rb +1 -1
  53. data/lib/capybara/window.rb +1 -1
  54. data/spec/basic_node_spec.rb +11 -0
  55. data/spec/dsl_spec.rb +1 -1
  56. data/spec/minitest_spec.rb +2 -2
  57. data/spec/minitest_spec_spec.rb +1 -1
  58. data/spec/rack_test_spec.rb +1 -0
  59. data/spec/result_spec.rb +2 -2
  60. data/spec/selector_spec.rb +11 -1
  61. data/spec/selenium_spec_firefox.rb +1 -1
  62. data/spec/selenium_spec_ie.rb +70 -9
  63. data/spec/session_spec.rb +9 -0
  64. data/spec/shared_selenium_session.rb +4 -3
  65. data/spec/spec_helper.rb +2 -0
  66. metadata +38 -6
  67. data/lib/capybara/rspec/matchers/have_style.rb +0 -23
  68. data/lib/capybara/spec/session/has_style_spec.rb +0 -25
@@ -39,7 +39,7 @@ module Capybara
39
39
  include Capybara::SessionMatchers
40
40
 
41
41
  NODE_METHODS = %i[
42
- all first attach_file text check choose
42
+ all first attach_file text check choose scroll_to scroll_by
43
43
  click_link_or_button click_button click_link
44
44
  fill_in find find_all find_button find_by_id find_field find_link
45
45
  has_content? has_text? has_css? has_no_content? has_no_text?
@@ -134,6 +134,18 @@ module Capybara
134
134
  alias_method :cleanup!, :reset!
135
135
  alias_method :reset_session!, :reset!
136
136
 
137
+ ##
138
+ #
139
+ # Disconnect from the current driver. A new driver will be instantiated on the next interaction
140
+ #
141
+ #
142
+ def quit
143
+ @driver.quit if @driver.respond_to? :quit
144
+ @driver = nil
145
+ @touched = false
146
+ @server&.reset_error!
147
+ end
148
+
137
149
  ##
138
150
  #
139
151
  # Raise errors encountered in the server
@@ -3,6 +3,7 @@ $(function() {
3
3
  $('#change').text('I changed it');
4
4
  $('#drag, #drag_scroll, #drag_link').draggable();
5
5
  $('#drop, #drop_scroll').droppable({
6
+ tolerance: 'touch',
6
7
  drop: function(event, ui) {
7
8
  ui.draggable.remove();
8
9
  $(this).html('Dropped!');
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Capybara::SpecHelper.spec '#assert_style', requires: [:css] do
3
+ Capybara::SpecHelper.spec '#assert_matches_style', requires: [:css] do
4
4
  it 'should not raise if the elements style contains the given properties' do
5
5
  @session.visit('/with_html')
6
6
  expect do
7
- @session.find(:css, '#first').assert_style(display: 'block')
7
+ @session.find(:css, '#first').assert_matches_style(display: 'block')
8
8
  end.not_to raise_error
9
9
  end
10
10
 
11
11
  it "should raise error if the elements style doesn't contain the given properties" do
12
12
  @session.visit('/with_html')
13
13
  expect do
14
- @session.find(:css, '#first').assert_style(display: 'inline')
14
+ @session.find(:css, '#first').assert_matches_style(display: 'inline')
15
15
  end.to raise_error(Capybara::ExpectationNotMet, 'Expected node to have styles {"display"=>"inline"}. Actual styles were {"display"=>"block"}')
16
16
  end
17
17
 
@@ -20,7 +20,7 @@ Capybara::SpecHelper.spec '#assert_style', requires: [:css] do
20
20
  el = @session.find(:css, '#change')
21
21
  @session.click_link('Change size')
22
22
  expect do
23
- el.assert_style({ 'font-size': '50px' }, wait: 3)
23
+ el.assert_matches_style({ 'font-size': '50px' }, wait: 3)
24
24
  end.not_to raise_error
25
25
  end
26
26
  end
@@ -13,26 +13,26 @@ Capybara::SpecHelper.spec '#attach_file' do
13
13
  it 'should set a file path by id' do
14
14
  @session.attach_file 'form_image', with_os_path_separators(__FILE__)
15
15
  @session.click_button('awesome')
16
- expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
16
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
17
17
  end
18
18
 
19
19
  it 'should set a file path by label' do
20
20
  @session.attach_file 'Image', with_os_path_separators(__FILE__)
21
21
  @session.click_button('awesome')
22
- expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
22
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
23
23
  end
24
24
 
25
25
  it 'should be able to set on element if no locator passed' do
26
26
  ff = @session.find(:file_field, 'Image')
27
27
  ff.attach_file(with_os_path_separators(__FILE__))
28
28
  @session.click_button('awesome')
29
- expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
29
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
30
30
  end
31
31
 
32
32
  it 'casts to string' do
33
33
  @session.attach_file :form_image, with_os_path_separators(__FILE__)
34
34
  @session.click_button('awesome')
35
- expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
35
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
36
36
  end
37
37
  end
38
38
 
@@ -137,7 +137,7 @@ Capybara::SpecHelper.spec '#attach_file' do
137
137
  it 'should set a file path by partial label when false' do
138
138
  @session.attach_file 'Imag', with_os_path_separators(__FILE__), exact: false
139
139
  @session.click_button('awesome')
140
- expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
140
+ expect(extract_results(@session)['image']).to end_with(File.basename(__FILE__))
141
141
  end
142
142
 
143
143
  it 'should not allow partial matches when true' do
@@ -181,7 +181,7 @@ Capybara::SpecHelper.spec '#attach_file' do
181
181
  end
182
182
  end
183
183
 
184
- private
184
+ private
185
185
 
186
186
  def with_os_path_separators(path)
187
187
  Gem.win_platform? ? path.to_s.tr('/', '\\') : path.to_s
@@ -5,7 +5,7 @@ Capybara::SpecHelper.spec '#click_button' do
5
5
  @session.visit('/form')
6
6
  end
7
7
 
8
- it 'should wait for asynchronous load', :focus_, requires: [:js] do
8
+ it 'should wait for asynchronous load', requires: [:js] do
9
9
  @session.visit('/with_js')
10
10
  @session.using_wait_time(1.5) do
11
11
  @session.click_link('Click me')
@@ -15,6 +15,7 @@ Capybara::SpecHelper.spec '#evaluate_script', requires: [:js] do
15
15
 
16
16
  it 'should pass arguments to the script', requires: %i[js es_args] do
17
17
  @session.visit('/with_js')
18
+ expect(@session).to have_css('#change')
18
19
  @session.evaluate_script("document.getElementById('change').textContent = arguments[0]", 'Doodle Funk')
19
20
  expect(@session).to have_css('#change', text: 'Doodle Funk')
20
21
  end
@@ -14,6 +14,7 @@ Capybara::SpecHelper.spec '#execute_script', requires: [:js] do
14
14
 
15
15
  it 'should pass arguments to the script', requires: %i[js es_args] do
16
16
  @session.visit('/with_js')
17
+ expect(@session).to have_css('#change')
17
18
  @session.execute_script("document.getElementById('change').textContent = arguments[0]", 'Doodle Funk')
18
19
  expect(@session).to have_css('#change', text: 'Doodle Funk')
19
20
  end
@@ -126,7 +126,7 @@ Capybara::SpecHelper.spec '#fill_in' do
126
126
  end
127
127
 
128
128
  it 'should fill in a field based on current value' do
129
- @session.fill_in(currently_with: 'John', with: 'Thomas')
129
+ @session.fill_in(id: /form.*name/, currently_with: 'John', with: 'Thomas')
130
130
  @session.click_button('awesome')
131
131
  expect(extract_results(@session)['first_name']).to eq('Thomas')
132
132
  end
@@ -242,4 +242,10 @@ Capybara::SpecHelper.spec '#fill_in' do
242
242
  el = @session.find(:fillable_field, 'form_first_name')
243
243
  expect(@session.fill_in('form_first_name', with: 'Harry')).to eq el
244
244
  end
245
+
246
+ it 'should warn if passed what looks like a CSS id selector' do
247
+ expect do
248
+ @session.fill_in('#form_first_name', with: 'Harry')
249
+ end.to raise_error(/you may be passing a CSS selector or XPath expression rather than a locator/)
250
+ end
245
251
  end
@@ -102,7 +102,7 @@ Capybara::SpecHelper.spec '#find_field' do
102
102
 
103
103
  context 'with no locator' do
104
104
  it 'should use options to find the field' do
105
- expect(@session.find_field(with: 'dog')['id']).to eq 'form_pets_dog'
105
+ expect(@session.find_field(type: 'checkbox', with: 'dog')['id']).to eq 'form_pets_dog'
106
106
  end
107
107
  end
108
108
 
@@ -92,6 +92,12 @@ Capybara::SpecHelper.spec '#find' do
92
92
  expect(@session.find(:css, '#\31 escape\.me').text).to eq('needs escaping')
93
93
  expect(@session.find(:css, '.\32 escape').text).to eq('needs escaping')
94
94
  end
95
+
96
+ it 'should not warn about locator' do
97
+ expect { @session.find(:css, '#not_on_page') }.to raise_error Capybara::ElementNotFound do |e|
98
+ expect(e.message).not_to match(/you may be passing a CSS selector or XPath expression/)
99
+ end
100
+ end
95
101
  end
96
102
 
97
103
  context 'with xpath selectors' do
@@ -99,6 +105,11 @@ Capybara::SpecHelper.spec '#find' do
99
105
  expect(@session.find(:xpath, '//h1').text).to eq('This is a test')
100
106
  expect(@session.find(:xpath, "//input[@id='test_field']").value).to eq('monkey')
101
107
  end
108
+
109
+ it 'should warn if passed a non-valid locator type' do
110
+ expect_any_instance_of(Kernel).to receive(:warn).with(/must respond to to_xpath or be an instance of String/)
111
+ expect { @session.find(:xpath, 123) }.to raise_error # rubocop:disable RSpec/UnspecifiedException
112
+ end
102
113
  end
103
114
 
104
115
  context 'with custom selector' do
@@ -53,7 +53,6 @@ Capybara::SpecHelper.spec '#switch_to_frame', requires: [:frames] do
53
53
  @session.switch_to_frame frame
54
54
  frame = @session.find(:frame, 'childFrame')
55
55
  @session.switch_to_frame frame
56
-
57
56
  @session.click_link 'Close Window'
58
57
  @session.switch_to_frame :parent # Go back to parentFrame
59
58
  expect(@session).to have_selector(:css, 'body#parentBody')
@@ -38,6 +38,32 @@ Capybara::SpecHelper.spec '#has_css?' do
38
38
  expect(@session).to have_css('li', class: /.*/)
39
39
  end
40
40
 
41
+ context ':style option' do
42
+ it 'should support String' do
43
+ expect(@session).to have_css('p', style: 'line-height: 25px;')
44
+
45
+ expect do
46
+ expect(@session).to have_css('p', style: 'display: not_valid')
47
+ end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /style attribute "display: not_valid"/)
48
+ end
49
+
50
+ it 'should support Regexp' do
51
+ expect(@session).to have_css('p', style: /-height: 2/)
52
+
53
+ expect do
54
+ expect(@session).to have_css('p', style: /not_valid/)
55
+ end.to raise_error(RSpec::Expectations::ExpectationNotMetError, %r{style attribute matching /not_valid/})
56
+ end
57
+
58
+ it 'should support Hash', requires: [:css] do
59
+ expect(@session).to have_css('p', style: { 'line-height': '25px' })
60
+
61
+ expect do
62
+ expect(@session).to have_css('p', style: { 'line-height': '30px' })
63
+ end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /with styles \{:"line-height"=>"30px"\}/)
64
+ end
65
+ end
66
+
41
67
  it 'should support case insensitive :class and :id options' do
42
68
  expect(@session).to have_css('li', class: /UiTaRI/i)
43
69
  expect(@session).to have_css('h2', id: /2ON/i)
@@ -118,6 +144,12 @@ Capybara::SpecHelper.spec '#has_css?' do
118
144
  expect(@session).to have_css('li', class: /guitar|drummer/, count: 4)
119
145
  expect(@session).to have_css('li', id: /john|paul/, class: /guitar|drummer/, count: 2)
120
146
  expect(@session).to have_css('li', class: %w[beatle guitarist], count: 2)
147
+ expect(@session).to have_css('p', style: 'line-height: 25px;', count: 1)
148
+ expect(@session).to have_css('p', style: /-height: 2/, count: 1)
149
+ end
150
+
151
+ it 'should be true if the content occurs the given number of times in CSS processing drivers', requires: [:css] do
152
+ expect(@session).to have_css('p', style: { 'line-height': '25px' }, count: 1)
121
153
  end
122
154
 
123
155
  it 'should be false if the content occurs a different number of times than the given' do
@@ -276,7 +276,7 @@ Capybara::SpecHelper.spec '#has_no_select?' do
276
276
  it 'should support locator-less usage' do
277
277
  expect(@session.has_no_select?(with_options: %w[Norway Sweden Finland Latvia])).to eq true
278
278
  expect(@session).to have_no_select(with_options: ['New London'])
279
- expect(@session.has_no_select?(with_selected: ['Boxers'])).to eq true
280
- expect(@session).to have_no_select(with_selected: %w[Commando Boxers])
279
+ expect(@session.has_no_select?(id: 'form_underwear', with_selected: ['Boxers'])).to eq true
280
+ expect(@session).to have_no_select(id: 'form_underwear', with_selected: %w[Commando Boxers])
281
281
  end
282
282
  end
@@ -56,6 +56,7 @@ Capybara::SpecHelper.spec '#has_selector?' do
56
56
  context 'with text' do
57
57
  it 'should discard all matches where the given string is not contained' do
58
58
  expect(@session).to have_selector('//p//a', text: 'Redirect', count: 1)
59
+ expect(@session).to have_selector(:css, 'p a', text: 'Redirect', count: 1)
59
60
  expect(@session).not_to have_selector('//p', text: 'Doesnotexist')
60
61
  end
61
62
 
@@ -191,5 +192,11 @@ Capybara::SpecHelper.spec '#has_no_selector?' do
191
192
  expect(@session).not_to have_no_selector('//p//a', text: /re[dab]i/i, count: 1)
192
193
  expect(@session).to have_no_selector('//p//a', text: /Red$/)
193
194
  end
195
+
196
+ it 'should error when matching element exists' do
197
+ expect do
198
+ expect(@session).to have_no_selector('//h2', text: 'Header Class Test Five')
199
+ end.to raise_error RSpec::Expectations::ExpectationNotMetError
200
+ end
194
201
  end
195
202
  end
@@ -226,7 +226,7 @@ Capybara::SpecHelper.spec '#has_text?' do
226
226
  Capybara.using_wait_time(0.1) do
227
227
  @session.visit('/with_js')
228
228
  @session.click_link('Click me')
229
- expect(@session).to have_text('Has been clicked', wait: 2)
229
+ expect(@session).to have_text('Has been clicked', wait: 3)
230
230
  end
231
231
  end
232
232
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec '#matches_style?', requires: [:css] do
4
+ before do
5
+ @session.visit('/with_html')
6
+ end
7
+
8
+ it 'should be true if the element has the given style' do
9
+ expect(@session.find(:css, '#first')).to match_style(display: 'block')
10
+ expect(@session.find(:css, '#first').matches_style?(display: 'block')).to be true
11
+ expect(@session.find(:css, '#second')).to match_style('display' => 'inline')
12
+ expect(@session.find(:css, '#second').matches_style?('display' => 'inline')).to be true
13
+ end
14
+
15
+ it 'should be false if the element does not have the given style' do
16
+ expect(@session.find(:css, '#first').matches_style?('display' => 'inline')).to be false
17
+ expect(@session.find(:css, '#second').matches_style?(display: 'block')).to be false
18
+ end
19
+
20
+ it 'allows Regexp for value matching' do
21
+ expect(@session.find(:css, '#first')).to match_style(display: /^bl/)
22
+ expect(@session.find(:css, '#first').matches_style?('display' => /^bl/)).to be true
23
+ expect(@session.find(:css, '#first').matches_style?(display: /^in/)).to be false
24
+ end
25
+
26
+ it 'deprecated has_style?' do
27
+ expect_any_instance_of(Kernel).to receive(:warn).once
28
+ have_style(display: /^bl/)
29
+
30
+ el = @session.find(:css, '#first')
31
+ allow(el).to receive(:warn).and_return(nil)
32
+ el.has_style?('display' => /^bl/)
33
+ expect(el).to have_received(:warn)
34
+ end
35
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec '#scroll_to', requires: [:scroll] do
4
+ before do
5
+ @session.visit('/scroll')
6
+ end
7
+
8
+ it 'can scroll an element to the top of the viewport' do
9
+ el = @session.find(:css, '#scroll')
10
+ @session.scroll_to(el, align: :top)
11
+ expect(el.evaluate_script('this.getBoundingClientRect().top')).to be_within(1).of(0)
12
+ end
13
+
14
+ it 'can scroll an element to the bottom of the viewport' do
15
+ el = @session.find(:css, '#scroll')
16
+ @session.scroll_to(el, align: :bottom)
17
+ el_bottom = el.evaluate_script('this.getBoundingClientRect().bottom')
18
+ viewport_bottom = el.evaluate_script('document.body.clientHeight')
19
+ expect(el_bottom).to be_within(1).of(viewport_bottom)
20
+ end
21
+
22
+ it 'can scroll an element to the center of the viewport' do
23
+ el = @session.find(:css, '#scroll')
24
+ @session.scroll_to(el, align: :center)
25
+ el_center = el.evaluate_script('(function(rect){return (rect.top + rect.bottom)/2})(this.getBoundingClientRect())')
26
+ viewport_bottom = el.evaluate_script('document.body.clientHeight')
27
+ expect(el_center).to be_within(1).of(viewport_bottom / 2)
28
+ end
29
+
30
+ it 'can scroll the window to the vertical top' do
31
+ @session.scroll_to :bottom
32
+ @session.scroll_to :top
33
+ expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [0, 0]
34
+ end
35
+
36
+ it 'can scroll the window to the vertical bottom' do
37
+ @session.scroll_to :bottom
38
+ max_scroll = @session.evaluate_script('document.body.scrollHeight - document.body.clientHeight')
39
+ expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [0, max_scroll]
40
+ end
41
+
42
+ it 'can scroll the window to the vertical center' do
43
+ @session.scroll_to :center
44
+ max_scroll = @session.evaluate_script('document.documentElement.scrollHeight - document.body.clientHeight')
45
+ expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [0, max_scroll / 2]
46
+ end
47
+
48
+ it 'can scroll the window to specific location' do
49
+ @session.scroll_to 100, 100
50
+ expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [100, 100]
51
+ end
52
+
53
+ it 'can scroll an element to the top of the scrolling element' do
54
+ scrolling_element = @session.find(:css, '#scrollable')
55
+ el = scrolling_element.find(:css, '#inner')
56
+ scrolling_element.scroll_to(el, align: :top)
57
+ scrolling_element_top = scrolling_element.evaluate_script('this.getBoundingClientRect().top')
58
+ expect(el.evaluate_script('this.getBoundingClientRect().top')).to be_within(3).of(scrolling_element_top)
59
+ end
60
+
61
+ it 'can scroll an element to the bottom of the scrolling element' do
62
+ scrolling_element = @session.find(:css, '#scrollable')
63
+ el = scrolling_element.find(:css, '#inner')
64
+ scrolling_element.scroll_to(el, align: :bottom)
65
+ el_bottom = el.evaluate_script('this.getBoundingClientRect().bottom')
66
+ scroller_bottom = scrolling_element.evaluate_script('this.getBoundingClientRect().top + this.clientHeight')
67
+ expect(el_bottom).to be_within(1).of(scroller_bottom)
68
+ end
69
+
70
+ it 'can scroll an element to the center of the scrolling element' do
71
+ scrolling_element = @session.find(:css, '#scrollable')
72
+ el = scrolling_element.find(:css, '#inner')
73
+ scrolling_element.scroll_to(el, align: :center)
74
+ el_center = el.evaluate_script('(function(rect){return (rect.top + rect.bottom)/2})(this.getBoundingClientRect())')
75
+ scrollable_center = scrolling_element.evaluate_script('(this.clientHeight / 2) + this.getBoundingClientRect().top')
76
+ expect(el_center).to be_within(1).of(scrollable_center)
77
+ end
78
+
79
+ it 'can scroll the scrolling element to the top' do
80
+ scrolling_element = @session.find(:css, '#scrollable')
81
+ scrolling_element.scroll_to :bottom
82
+ scrolling_element.scroll_to :top
83
+ expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [0, 0]
84
+ end
85
+
86
+ it 'can scroll the scrolling element to the bottom' do
87
+ scrolling_element = @session.find(:css, '#scrollable')
88
+ scrolling_element.scroll_to :bottom
89
+ max_scroll = scrolling_element.evaluate_script('this.scrollHeight - this.clientHeight')
90
+ expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [0, max_scroll]
91
+ end
92
+
93
+ it 'can scroll the scrolling element to the vertical center' do
94
+ scrolling_element = @session.find(:css, '#scrollable')
95
+ scrolling_element.scroll_to :center
96
+ max_scroll = scrolling_element.evaluate_script('this.scrollHeight - this.clientHeight')
97
+ expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [0, max_scroll / 2]
98
+ end
99
+
100
+ it 'can scroll the scrolling element to specific location' do
101
+ scrolling_element = @session.find(:css, '#scrollable')
102
+ scrolling_element.scroll_to 100, 100
103
+ expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [100, 100]
104
+ end
105
+
106
+ it 'can scroll the window by a specific amount' do
107
+ @session.scroll_to(:current, offset: [50, 75])
108
+ expect(@session.evaluate_script('[window.scrollX || window.pageXOffset, window.scrollY || window.pageYOffset]')).to eq [50, 75]
109
+ end
110
+
111
+ it 'can scroll the scroll the scrolling element by a specifc amount' do
112
+ scrolling_element = @session.find(:css, '#scrollable')
113
+ scrolling_element.scroll_to 100, 100
114
+ scrolling_element.scroll_to(:current, offset: [-50, 50])
115
+ expect(scrolling_element.evaluate_script('[this.scrollLeft, this.scrollTop]')).to eq [50, 150]
116
+ end
117
+ end