capybara 3.35.2 → 3.37.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +59 -4
  3. data/README.md +5 -1
  4. data/lib/capybara/config.rb +16 -4
  5. data/lib/capybara/driver/base.rb +4 -0
  6. data/lib/capybara/driver/node.rb +5 -1
  7. data/lib/capybara/dsl.rb +4 -10
  8. data/lib/capybara/helpers.rb +2 -11
  9. data/lib/capybara/minitest/spec.rb +2 -2
  10. data/lib/capybara/node/actions.rb +10 -5
  11. data/lib/capybara/node/document.rb +2 -2
  12. data/lib/capybara/node/element.rb +13 -2
  13. data/lib/capybara/node/finders.rb +2 -2
  14. data/lib/capybara/node/simple.rb +5 -1
  15. data/lib/capybara/queries/active_element_query.rb +18 -0
  16. data/lib/capybara/queries/ancestor_query.rb +2 -1
  17. data/lib/capybara/queries/current_path_query.rb +1 -1
  18. data/lib/capybara/queries/selector_query.rb +34 -8
  19. data/lib/capybara/queries/sibling_query.rb +2 -1
  20. data/lib/capybara/rack_test/browser.rb +41 -6
  21. data/lib/capybara/rack_test/driver.rb +4 -4
  22. data/lib/capybara/rack_test/node.rb +10 -7
  23. data/lib/capybara/registration_container.rb +0 -3
  24. data/lib/capybara/registrations/drivers.rb +3 -3
  25. data/lib/capybara/rspec/matcher_proxies.rb +3 -3
  26. data/lib/capybara/rspec/matchers/have_selector.rb +5 -5
  27. data/lib/capybara/rspec/matchers.rb +14 -14
  28. data/lib/capybara/selector/builders/css_builder.rb +1 -1
  29. data/lib/capybara/selector/builders/xpath_builder.rb +1 -1
  30. data/lib/capybara/selector/css.rb +1 -1
  31. data/lib/capybara/selector/definition/button.rb +9 -4
  32. data/lib/capybara/selector/definition/checkbox.rb +1 -1
  33. data/lib/capybara/selector/definition/file_field.rb +1 -1
  34. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  35. data/lib/capybara/selector/definition/radio_button.rb +1 -1
  36. data/lib/capybara/selector/definition.rb +3 -1
  37. data/lib/capybara/selector/filter_set.rb +4 -6
  38. data/lib/capybara/selector.rb +1 -0
  39. data/lib/capybara/selenium/driver.rb +25 -11
  40. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
  41. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +1 -1
  42. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
  43. data/lib/capybara/selenium/node.rb +22 -8
  44. data/lib/capybara/selenium/nodes/chrome_node.rb +1 -1
  45. data/lib/capybara/selenium/nodes/edge_node.rb +1 -1
  46. data/lib/capybara/selenium/nodes/firefox_node.rb +1 -1
  47. data/lib/capybara/selenium/nodes/safari_node.rb +2 -2
  48. data/lib/capybara/server/animation_disabler.rb +35 -17
  49. data/lib/capybara/session/config.rb +1 -1
  50. data/lib/capybara/session.rb +20 -23
  51. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  52. data/lib/capybara/spec/session/all_spec.rb +9 -13
  53. data/lib/capybara/spec/session/assert_text_spec.rb +17 -17
  54. data/lib/capybara/spec/session/check_spec.rb +9 -0
  55. data/lib/capybara/spec/session/choose_spec.rb +6 -0
  56. data/lib/capybara/spec/session/has_any_selectors_spec.rb +4 -0
  57. data/lib/capybara/spec/session/has_button_spec.rb +24 -0
  58. data/lib/capybara/spec/session/has_current_path_spec.rb +2 -2
  59. data/lib/capybara/spec/session/has_field_spec.rb +25 -1
  60. data/lib/capybara/spec/session/has_link_spec.rb +24 -0
  61. data/lib/capybara/spec/session/has_select_spec.rb +4 -4
  62. data/lib/capybara/spec/session/has_selector_spec.rb +15 -0
  63. data/lib/capybara/spec/session/has_text_spec.rb +2 -6
  64. data/lib/capybara/spec/session/node_spec.rb +43 -1
  65. data/lib/capybara/spec/session/scroll_spec.rb +4 -4
  66. data/lib/capybara/spec/session/visit_spec.rb +14 -0
  67. data/lib/capybara/spec/session/window/window_spec.rb +1 -1
  68. data/lib/capybara/spec/spec_helper.rb +4 -3
  69. data/lib/capybara/spec/test_app.rb +50 -8
  70. data/lib/capybara/spec/views/animated.erb +1 -1
  71. data/lib/capybara/spec/views/form.erb +11 -3
  72. data/lib/capybara/spec/views/frame_child.erb +1 -1
  73. data/lib/capybara/spec/views/frame_one.erb +1 -1
  74. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  75. data/lib/capybara/spec/views/frame_two.erb +1 -1
  76. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  77. data/lib/capybara/spec/views/layout.erb +10 -0
  78. data/lib/capybara/spec/views/obscured.erb +1 -1
  79. data/lib/capybara/spec/views/offset.erb +2 -1
  80. data/lib/capybara/spec/views/path.erb +2 -2
  81. data/lib/capybara/spec/views/popup_one.erb +1 -1
  82. data/lib/capybara/spec/views/popup_two.erb +1 -1
  83. data/lib/capybara/spec/views/react.erb +2 -2
  84. data/lib/capybara/spec/views/scroll.erb +2 -1
  85. data/lib/capybara/spec/views/spatial.erb +1 -1
  86. data/lib/capybara/spec/views/with_animation.erb +2 -3
  87. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  88. data/lib/capybara/spec/views/with_dragula.erb +2 -2
  89. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  90. data/lib/capybara/spec/views/with_hover.erb +2 -2
  91. data/lib/capybara/spec/views/with_html.erb +1 -1
  92. data/lib/capybara/spec/views/with_jquery_animation.erb +1 -1
  93. data/lib/capybara/spec/views/with_js.erb +2 -3
  94. data/lib/capybara/spec/views/with_jstree.erb +1 -1
  95. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  96. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  97. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  98. data/lib/capybara/spec/views/with_sortable_js.erb +2 -2
  99. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  100. data/lib/capybara/spec/views/with_windows.erb +1 -1
  101. data/lib/capybara/spec/views/within_frames.erb +1 -1
  102. data/lib/capybara/version.rb +1 -1
  103. data/lib/capybara/window.rb +1 -1
  104. data/lib/capybara.rb +19 -22
  105. data/spec/basic_node_spec.rb +16 -3
  106. data/spec/dsl_spec.rb +3 -3
  107. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -2
  108. data/spec/fixtures/selenium_driver_rspec_success.rb +2 -2
  109. data/spec/rack_test_spec.rb +20 -10
  110. data/spec/result_spec.rb +32 -35
  111. data/spec/rspec/features_spec.rb +3 -3
  112. data/spec/rspec/scenarios_spec.rb +1 -1
  113. data/spec/rspec/shared_spec_matchers.rb +2 -2
  114. data/spec/sauce_spec_chrome.rb +3 -3
  115. data/spec/selector_spec.rb +1 -1
  116. data/spec/selenium_spec_chrome.rb +9 -10
  117. data/spec/selenium_spec_chrome_remote.rb +9 -8
  118. data/spec/selenium_spec_firefox.rb +8 -3
  119. data/spec/selenium_spec_firefox_remote.rb +2 -2
  120. data/spec/selenium_spec_ie.rb +3 -6
  121. data/spec/selenium_spec_safari.rb +31 -19
  122. data/spec/server_spec.rb +5 -5
  123. data/spec/shared_selenium_node.rb +0 -4
  124. data/spec/shared_selenium_session.rb +20 -10
  125. data/spec/spec_helper.rb +1 -1
  126. metadata +37 -14
  127. data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -111,14 +111,27 @@ RSpec.describe Capybara do
111
111
  expect(string.find('//form/input[@name="meh"]')).not_to be_disabled
112
112
  end
113
113
 
114
+ it 'allows finding siblings' do
115
+ h1 = string.find(:css, 'h1')
116
+ expect(h1).to have_sibling(:css, 'p', text: 'Yes it is')
117
+ expect(h1).not_to have_sibling(:css, 'p', text: 'Jonas Nicklas')
118
+ end
119
+
120
+ it 'allows finding ancestor' do
121
+ h1 = string.find(:css, 'h1')
122
+ expect(h1).to have_ancestor(:css, '#content')
123
+ expect(h1).not_to have_ancestor(:css, '#footer')
124
+ end
125
+
114
126
  it 'drops illegal fragments when using gumbo' do
115
127
  skip 'libxml is less strict than Gumbo' unless Nokogiri.respond_to?(:HTML5)
128
+ described_class.use_html5_parsing = true
116
129
  expect(described_class.string('<td>1</td>')).not_to have_css('td')
117
130
  end
118
131
 
119
- it 'can disable use of gumbo' do
120
- skip "Test doesn't make sense unlesss nokogumbo is loaded" unless Nokogiri.respond_to?(:HTML5)
121
- described_class.allow_gumbo = false
132
+ it 'can disable use of HTML5 parsing' do
133
+ skip "Test doesn't make sense unlesss HTML5 parsing is loaded (Nokogumbo or Nokogiri >= 1.12.0)" unless Nokogiri.respond_to?(:HTML5)
134
+ described_class.use_html5_parsing = false
122
135
  expect(described_class.string('<td>1</td>')).to have_css('td')
123
136
  end
124
137
 
data/spec/dsl_spec.rb CHANGED
@@ -8,7 +8,7 @@ class TestClass
8
8
  end
9
9
 
10
10
  Capybara::SpecHelper.run_specs TestClass.new, 'DSL', capybara_skip: %i[
11
- js modals screenshot frames windows send_keys server hover about_scheme psc download css driver scroll spatial html_validation shadow_dom
11
+ js modals screenshot frames windows send_keys server hover about_scheme psc download css driver scroll spatial html_validation shadow_dom active_element
12
12
  ] do |example|
13
13
  case example.metadata[:full_description]
14
14
  when /has_css\? should support case insensitive :class and :id options/
@@ -115,7 +115,7 @@ RSpec.describe Capybara::DSL do
115
115
  it 'should yield the passed block' do
116
116
  called = false
117
117
  Capybara.using_driver(:selenium) { called = true }
118
- expect(called).to eq(true)
118
+ expect(called).to be(true)
119
119
  end
120
120
  end
121
121
 
@@ -220,7 +220,7 @@ RSpec.describe Capybara::DSL do
220
220
  it 'should yield the passed block' do
221
221
  called = false
222
222
  Capybara.using_session(:administrator) { called = true }
223
- expect(called).to eq(true)
223
+ expect(called).to be(true)
224
224
  end
225
225
 
226
226
  it 'should be nestable' do
@@ -5,9 +5,9 @@ require 'selenium-webdriver'
5
5
 
6
6
  RSpec.describe Capybara::Selenium::Driver do
7
7
  it 'should exit with a non-zero exit status' do
8
- options = { browser: (ENV['SELENIUM_BROWSER'] || :firefox).to_sym }
8
+ options = { browser: ENV.fetch('SELENIUM_BROWSER', :firefox).to_sym }
9
9
  browser = described_class.new(TestApp, options).browser
10
10
  expect(browser).to be_truthy
11
- expect(true).to eq(false) # rubocop:disable RSpec/ExpectActual
11
+ expect(true).to be(false) # rubocop:disable RSpec/ExpectActual
12
12
  end
13
13
  end
@@ -5,9 +5,9 @@ require 'selenium-webdriver'
5
5
 
6
6
  RSpec.describe Capybara::Selenium::Driver do
7
7
  it 'should exit with a zero exit status' do
8
- options = { browser: (ENV['SELENIUM_BROWSER'] || :firefox).to_sym }
8
+ options = { browser: ENV.fetch('SELENIUM_BROWSER', :firefox).to_sym }
9
9
  browser = described_class.new(TestApp, **options).browser
10
10
  expect(browser).to be_truthy
11
- expect(true).to eq(true) # rubocop:disable RSpec/ExpectActual
11
+ expect(true).to be(true) # rubocop:disable RSpec/ExpectActual,RSpec/IdenticalEqualityAssertion
12
12
  end
13
13
  end
@@ -1,12 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
- nokogumbo_required = begin
5
- require 'nokogumbo'
6
- true
7
- rescue LoadError
8
- false
9
- end
10
4
 
11
5
  module TestSessions
12
6
  RackTest = Capybara::Session.new(:rack_test, TestApp)
@@ -28,6 +22,7 @@ skipped_tests = %i[
28
22
  spatial
29
23
  html_validation
30
24
  shadow_dom
25
+ active_element
31
26
  ]
32
27
  Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip: skipped_tests do |example|
33
28
  case example.metadata[:full_description]
@@ -153,6 +148,14 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
153
148
  end
154
149
  end
155
150
 
151
+ describe '#active_element' do
152
+ it 'raises an UnsupportedMethodError' do
153
+ session.visit('/form')
154
+
155
+ expect { session.active_element }.to raise_error(Capybara::NotSupportedByDriverError)
156
+ end
157
+ end
158
+
156
159
  describe '#text' do
157
160
  it 'should return original text content for textareas' do
158
161
  session.visit('/with_html')
@@ -213,6 +216,12 @@ RSpec.describe Capybara::RackTest::Driver do
213
216
  expect(driver.current_url).to match %r{/landed$}
214
217
  end
215
218
 
219
+ it 'should not include fragments in the referer header' do
220
+ driver.visit('/header_links#an-anchor')
221
+ driver.find_xpath('.//input').first.click
222
+ expect(driver.request.get_header('HTTP_REFERER')).to eq('http://www.example.com/header_links')
223
+ end
224
+
216
225
  it 'is possible to not follow redirects' do
217
226
  driver = described_class.new(TestApp, follow_redirects: false)
218
227
 
@@ -256,11 +265,12 @@ RSpec.describe Capybara::RackTest::Driver do
256
265
  end
257
266
 
258
267
  RSpec.describe 'Capybara::String' do
259
- it 'should use gumbo' do
260
- skip 'Only valid if gumbo is included' unless nokogumbo_required
261
- allow(Nokogiri).to receive(:HTML5).and_call_original
268
+ it 'should use HTML5 parsing' do
269
+ skip 'Only valid if Nokogiri >= 1.12.0 or gumbo is included' unless defined? Nokogiri::HTML5
270
+ Capybara.use_html5_parsing = true
271
+ allow(Nokogiri::HTML5).to receive(:parse).and_call_original
262
272
  Capybara.string('<div id=test_div></div>')
263
- expect(Nokogiri).to have_received(:HTML5)
273
+ expect(Nokogiri::HTML5).to have_received(:parse)
264
274
  end
265
275
  end
266
276
 
data/spec/result_spec.rb CHANGED
@@ -78,34 +78,31 @@ RSpec.describe Capybara::Result do
78
78
  expect(recalc_result[1...3].map(&:text)).to eq %w[Beta Gamma]
79
79
  expect(recalc_result[1..7].map(&:text)).to eq %w[Beta Gamma Delta]
80
80
  expect(recalc_result[2...-1].map(&:text)).to eq %w[Gamma]
81
- expect(recalc_result[2..-1].map(&:text)).to eq %w[Gamma Delta]
81
+ expect(recalc_result[2..-1].map(&:text)).to eq %w[Gamma Delta] # rubocop:disable Style/SlicingWithRange
82
+ expect(recalc_result[2..].map(&:text)).to eq %w[Gamma Delta]
82
83
  end
83
84
 
84
- eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.5
85
- it 'supports endless ranges' do
86
- expect(result[2..].map(&:text)).to eq %w[Gamma Delta]
87
- end
88
- TEST
85
+ it 'supports endless ranges' do
86
+ expect(result[2..].map(&:text)).to eq %w[Gamma Delta]
87
+ end
89
88
 
90
- eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.6
91
- it 'supports inclusive positive beginless ranges' do
92
- expect(result[..2].map(&:text)).to eq %w[Alpha Beta Gamma]
93
- end
89
+ it 'supports inclusive positive beginless ranges' do
90
+ expect(result[..2].map(&:text)).to eq %w[Alpha Beta Gamma]
91
+ end
94
92
 
95
- it 'supports inclusive negative beginless ranges' do
96
- expect(result[..-2].map(&:text)).to eq %w[Alpha Beta Gamma]
97
- expect(result[..-1].map(&:text)).to eq %w[Alpha Beta Gamma Delta]
98
- end
93
+ it 'supports inclusive negative beginless ranges' do
94
+ expect(result[..-2].map(&:text)).to eq %w[Alpha Beta Gamma]
95
+ expect(result[..-1].map(&:text)).to eq %w[Alpha Beta Gamma Delta]
96
+ end
99
97
 
100
- it 'supports exclusive positive beginless ranges' do
101
- expect(result[...2].map(&:text)).to eq %w[Alpha Beta]
102
- end
98
+ it 'supports exclusive positive beginless ranges' do
99
+ expect(result[...2].map(&:text)).to eq %w[Alpha Beta]
100
+ end
103
101
 
104
- it 'supports exclusive negative beginless ranges' do
105
- expect(result[...-2].map(&:text)).to eq %w[Alpha Beta]
106
- expect(result[...-1].map(&:text)).to eq %w[Alpha Beta Gamma]
107
- end
108
- TEST
102
+ it 'supports exclusive negative beginless ranges' do
103
+ expect(result[...-2].map(&:text)).to eq %w[Alpha Beta]
104
+ expect(result[...-1].map(&:text)).to eq %w[Alpha Beta Gamma]
105
+ end
109
106
 
110
107
  it 'works with filter blocks' do
111
108
  result = string.all('//li') { |node| node.text == 'Alpha' }
@@ -116,52 +113,52 @@ RSpec.describe Capybara::Result do
116
113
  it 'should evaluate filters lazily for idx' do
117
114
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
118
115
  # Not processed until accessed
119
- expect(result.instance_variable_get('@result_cache').size).to be 0
116
+ expect(result.instance_variable_get(:@result_cache).size).to be 0
120
117
 
121
118
  # Only one retrieved when needed
122
119
  result.first
123
- expect(result.instance_variable_get('@result_cache').size).to be 1
120
+ expect(result.instance_variable_get(:@result_cache).size).to be 1
124
121
 
125
122
  # works for indexed access
126
123
  result[0]
127
- expect(result.instance_variable_get('@result_cache').size).to be 1
124
+ expect(result.instance_variable_get(:@result_cache).size).to be 1
128
125
 
129
126
  result[2]
130
- expect(result.instance_variable_get('@result_cache').size).to be 3
127
+ expect(result.instance_variable_get(:@result_cache).size).to be 3
131
128
 
132
129
  # All cached when converted to array
133
130
  result.to_a
134
- expect(result.instance_variable_get('@result_cache').size).to eq 4
131
+ expect(result.instance_variable_get(:@result_cache).size).to eq 4
135
132
  end
136
133
 
137
134
  it 'should evaluate filters lazily for range' do
138
135
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
139
136
  result[0..1]
140
- expect(result.instance_variable_get('@result_cache').size).to be 2
137
+ expect(result.instance_variable_get(:@result_cache).size).to be 2
141
138
 
142
139
  expect(result[0..7].size).to eq 4
143
- expect(result.instance_variable_get('@result_cache').size).to be 4
140
+ expect(result.instance_variable_get(:@result_cache).size).to be 4
144
141
  end
145
142
 
146
143
  it 'should evaluate filters lazily for idx and length' do
147
144
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
148
145
  result[1, 2]
149
- expect(result.instance_variable_get('@result_cache').size).to be 3
146
+ expect(result.instance_variable_get(:@result_cache).size).to be 3
150
147
 
151
148
  expect(result[2, 5].size).to eq 2
152
- expect(result.instance_variable_get('@result_cache').size).to be 4
149
+ expect(result.instance_variable_get(:@result_cache).size).to be 4
153
150
  end
154
151
 
155
152
  it 'should only need to evaluate one result for any?' do
156
153
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
157
154
  result.any?
158
- expect(result.instance_variable_get('@result_cache').size).to be 1
155
+ expect(result.instance_variable_get(:@result_cache).size).to be 1
159
156
  end
160
157
 
161
158
  it 'should evaluate all elements when #to_a called' do
162
159
  # All cached when converted to array
163
160
  result.to_a
164
- expect(result.instance_variable_get('@result_cache').size).to eq 4
161
+ expect(result.instance_variable_get(:@result_cache).size).to eq 4
165
162
  end
166
163
 
167
164
  describe '#each' do
@@ -170,7 +167,7 @@ RSpec.describe Capybara::Result do
170
167
  results = []
171
168
  result.each do |el|
172
169
  results << el
173
- expect(result.instance_variable_get('@result_cache').size).to eq results.size
170
+ expect(result.instance_variable_get(:@result_cache).size).to eq results.size
174
171
  end
175
172
 
176
173
  expect(results.size).to eq 4
@@ -184,7 +181,7 @@ RSpec.describe Capybara::Result do
184
181
  it 'lazily evaluates' do
185
182
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
186
183
  result.each.with_index do |_el, idx|
187
- expect(result.instance_variable_get('@result_cache').size).to eq(idx + 1) # 0 indexing
184
+ expect(result.instance_variable_get(:@result_cache).size).to eq(idx + 1) # 0 indexing
188
185
  end
189
186
  end
190
187
  end
@@ -91,11 +91,11 @@ end
91
91
 
92
92
  ffeature 'if ffeature aliases focused tag then' do # rubocop:disable RSpec/Focus
93
93
  scenario 'scenario inside this feature has metatag focus tag' do |example|
94
- expect(example.metadata[:focus]).to eq true
94
+ expect(example.metadata[:focus]).to be true
95
95
  end
96
96
 
97
- scenario 'other scenarios also has metatag focus tag ' do |example|
98
- expect(example.metadata[:focus]).to eq true
97
+ scenario 'other scenarios also has metatag focus tag' do |example|
98
+ expect(example.metadata[:focus]).to be true
99
99
  end
100
100
  end
101
101
  # rubocop:enable RSpec/RepeatedExample, RSpec/MultipleDescribes
@@ -11,7 +11,7 @@ end
11
11
 
12
12
  feature 'if fscenario aliases focused tag then' do
13
13
  fscenario 'scenario should have focused meta tag' do |example| # rubocop:disable RSpec/Focus
14
- expect(example.metadata[:focus]).to eq true
14
+ expect(example.metadata[:focus]).to be true
15
15
  end
16
16
  end
17
17
 
@@ -840,10 +840,10 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
840
840
  end
841
841
 
842
842
  it 'gives proper description when :visible option passed' do
843
- expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"')
843
+ expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"') # rubocop:disable RSpec/Capybara/VisibilityMatcher
844
844
  expect(have_table('Lovely table', visible: :hidden).description).to eq('have non-visible table "Lovely table"')
845
845
  expect(have_table('Lovely table', visible: :all).description).to eq('have table "Lovely table"')
846
- expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"')
846
+ expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"') # rubocop:disable RSpec/Capybara/VisibilityMatcher
847
847
  end
848
848
 
849
849
  it 'passes if there is such a table' do
@@ -15,9 +15,9 @@ Capybara.register_driver :sauce_chrome do |app|
15
15
  browser_name: 'chrome',
16
16
  version: '65.0',
17
17
  name: 'Capybara test',
18
- build: ENV['TRAVIS_REPO_SLUG'] || "Ruby-RSpec-Selenium: Local-#{Time.now.to_i}",
19
- username: ENV['SAUCE_USERNAME'],
20
- access_key: ENV['SAUCE_ACCESS_KEY']
18
+ build: ENV.fetch('TRAVIS_REPO_SLUG', "Ruby-RSpec-Selenium: Local-#{Time.now.to_i}"),
19
+ username: ENV.fetch('SAUCE_USERNAME', nil),
20
+ access_key: ENV.fetch('SAUCE_ACCESS_KEY', nil)
21
21
  }
22
22
 
23
23
  options.delete(:browser_name)
@@ -159,7 +159,7 @@ RSpec.describe Capybara do
159
159
  end
160
160
 
161
161
  it 'returns nil if no match' do
162
- expect(Capybara::Selector.for('nothing')).to be nil
162
+ expect(Capybara::Selector.for('nothing')).to be_nil
163
163
  end
164
164
  end
165
165
 
@@ -8,11 +8,11 @@ require 'rspec/shared_spec_matchers'
8
8
 
9
9
  CHROME_DRIVER = :selenium_chrome
10
10
 
11
- Selenium::WebDriver::Chrome.path = '/usr/bin/google-chrome-beta' if ENV['CI'] && ENV['CHROME_BETA']
11
+ Selenium::WebDriver::Chrome.path = '/usr/bin/google-chrome-beta' if ENV.fetch('CI', nil) && ENV.fetch('CHROME_BETA', nil)
12
12
 
13
13
  browser_options = ::Selenium::WebDriver::Chrome::Options.new
14
14
  browser_options.headless! if ENV['HEADLESS']
15
- browser_options.add_option(:w3c, ENV['W3C'] != 'false')
15
+
16
16
  # Chromedriver 77 requires setting this for headless mode on linux
17
17
  # Different versions of Chrome/selenium-webdriver require setting differently - jus set them all
18
18
  browser_options.add_preference('download.default_directory', Capybara.save_path)
@@ -85,10 +85,6 @@ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybar
85
85
  skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
86
86
  when /Capybara::Session selenium_chrome Capybara::Window#maximize/
87
87
  pending "Chrome headless doesn't support maximize" if ENV['HEADLESS']
88
- when /Capybara::Window#fullscreen should be able to fullscreen the window/
89
- skip 'Chromedriver hangs on attempts to fullscreen in headless mode' if ENV['HEADLESS']
90
- when /node #right_click delay should delay the mouse up/
91
- skip "Legacy selenium doesn't support separate right button down/up" if ENV['W3C'] == 'false'
92
88
  end
93
89
  end
94
90
 
@@ -185,18 +181,21 @@ RSpec.describe 'Capybara::Session with chrome' do
185
181
  end
186
182
 
187
183
  describe 'log access' do
188
- before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
184
+ let(:logs) do
185
+ session.driver.browser.then do |chrome_driver|
186
+ chrome_driver.respond_to?(:logs) ? chrome_driver : chrome_driver.manage
187
+ end.logs
188
+ end
189
189
 
190
190
  it 'does not error getting log types' do
191
- skip if Gem::Requirement.new('< 75.0.3770.90').satisfied_by? chromedriver_version
192
191
  expect do
193
- session.driver.browser.manage.logs.available_types
192
+ logs.available_types
194
193
  end.not_to raise_error
195
194
  end
196
195
 
197
196
  it 'does not error when getting logs' do
198
197
  expect do
199
- session.driver.browser.manage.logs.get(:browser)
198
+ logs.get(:browser)
200
199
  end.not_to raise_error
201
200
  end
202
201
  end
@@ -21,8 +21,8 @@ def ensure_selenium_running!
21
21
  rescue StandardError
22
22
  if timer.expired?
23
23
  raise 'Selenium is not running. ' \
24
- "You can run a selenium server easily with: \n" \
25
- ' $ docker-compose up -d selenium_chrome'
24
+ "You can run a selenium server easily with: \n" \
25
+ ' $ docker-compose up -d selenium_chrome'
26
26
  else
27
27
  puts 'Waiting for Selenium docker instance...'
28
28
  sleep 1
@@ -62,8 +62,6 @@ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s,
62
62
  'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once for each set of files uploaded',
63
63
  'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once when uploading multiple files from empty'
64
64
  pending "Selenium with Remote Chrome doesn't support multiple file upload" unless selenium_gte?(3.14)
65
- when /node #right_click delay should delay the mouse up/
66
- skip "Legacy selenium doesn't support separate right button down/up" if ENV['W3C'] == 'false'
67
65
  end
68
66
  end
69
67
 
@@ -78,18 +76,21 @@ RSpec.describe 'Capybara::Session with remote Chrome' do
78
76
  end
79
77
 
80
78
  describe 'log access' do
81
- before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
79
+ let(:logs) do
80
+ session.driver.browser.then do |chrome_driver|
81
+ chrome_driver.respond_to?(:logs) ? chrome_driver : chrome_driver.manage
82
+ end.logs
83
+ end
82
84
 
83
85
  it 'does not error when getting log types' do
84
- skip unless Gem::Requirement.new('>= 75.0.3770.90').satisfied_by? chromedriver_version
85
86
  expect do
86
- session.driver.browser.manage.logs.available_types
87
+ logs.available_types
87
88
  end.not_to raise_error
88
89
  end
89
90
 
90
91
  it 'does not error when getting logs' do
91
92
  expect do
92
- session.driver.browser.manage.logs.get(:browser)
93
+ logs.get(:browser)
93
94
  end.not_to raise_error
94
95
  end
95
96
  end
@@ -15,6 +15,7 @@ browser_options.profile = Selenium::WebDriver::Firefox::Profile.new.tap do |prof
15
15
  profile['browser.download.folderList'] = 2
16
16
  profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/csv'
17
17
  profile['browser.startup.homepage'] = 'about:blank' # workaround bug in Selenium 4 alpha4-7
18
+ profile['accessibility.tabfocus'] = 7 # make tab move over links too
18
19
  end
19
20
 
20
21
  Capybara.register_driver :selenium_firefox do |app|
@@ -59,8 +60,8 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumFirefox, 'selenium', capyba
59
60
  when 'Capybara::Session selenium #attach_file with multipart form should fire change once when uploading multiple files from empty'
60
61
  pending "FF < 62 doesn't support setting all files at once" if firefox_lt?(62, @session)
61
62
  when 'Capybara::Session selenium #accept_confirm should work with nested modals'
62
- skip 'Broken in 63 <= FF < 69 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if firefox_gte?(63, @session) && firefox_lt?(69, @session)
63
- skip 'Hangs in 69 <= FF < 71 - Dont know what issue for this - previous issue was closed as fixed but it is not' if firefox_gte?(69, @session) && firefox_lt?(71, @session)
63
+ skip 'Broken in 63 <= FF < 69 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if firefox_gte?(63, @session) && firefox_lt?(69, @session)
64
+ skip 'Hangs in 69 <= FF < 71 - Dont know what issue for this - previous issue was closed as fixed but it is not' if firefox_gte?(69, @session) && firefox_lt?(71, @session)
64
65
  skip 'Broken again intermittently in FF 71 - jus skip it'
65
66
  when 'Capybara::Session selenium #click_link can download a file'
66
67
  skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
@@ -71,6 +72,10 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumFirefox, 'selenium', capyba
71
72
  when 'Capybara::Session selenium #accept_alert should handle the alert if the page changes',
72
73
  'Capybara::Session selenium #accept_alert with an asynchronous alert should accept the alert'
73
74
  skip 'No clue what Firefox is doing here - works fine on MacOS locally'
75
+ when 'Capybara::Session selenium node #shadow_root should get the shadow root',
76
+ 'Capybara::Session selenium node #shadow_root should find elements inside the shadow dom using CSS',
77
+ 'Capybara::Session selenium node #shadow_root should find nested shadow roots'
78
+ pending "Firefox doesn't yet have W3C shadow root support"
74
79
  end
75
80
  end
76
81
 
@@ -102,7 +107,7 @@ RSpec.describe 'Capybara::Session with firefox' do # rubocop:disable RSpec/Multi
102
107
  end
103
108
 
104
109
  it 'should fill in a datetime input with a String' do
105
- # FF doesn't currently support datetime-local so this is really just a text input
110
+ pending 'Need to figure out what string format this will actually accept'
106
111
  session.fill_in('form_datetime', with: datetime.iso8601)
107
112
  session.click_button('awesome')
108
113
  expect(Time.parse(extract_results(session)['datetime'])).to eq datetime
@@ -21,8 +21,8 @@ def ensure_selenium_running!
21
21
  rescue StandardError
22
22
  if timer.expired?
23
23
  raise 'Selenium is not running. ' \
24
- "You can run a selenium server easily with: \n" \
25
- ' $ docker-compose up -d selenium_firefox'
24
+ "You can run a selenium server easily with: \n" \
25
+ ' $ docker-compose up -d selenium_firefox'
26
26
  else
27
27
  puts 'Waiting for Selenium docker instance...'
28
28
  sleep 1
@@ -71,13 +71,10 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumIE, 'selenium', capybara_sk
71
71
  pending "IE 11 doesn't support date input types"
72
72
  when /#click_link_or_button with :disabled option happily clicks on links which incorrectly have the disabled attribute$/
73
73
  skip 'IE 11 obeys non-standard disabled attribute on anchor tag'
74
- when /#right_click should allow modifiers$/
75
- skip "Windows can't :meta click because :meta triggers start menu"
76
- when /#click should allow modifiers$/
74
+ when /#click should allow modifiers$/, /#double_click should allow modifiers$/
77
75
  pending "Doesn't work with IE for some unknown reason$"
78
- when /#double_click should allow modifiers$/
79
76
  pending "Doesn't work with IE for some unknown reason$"
80
- when /#click should allow multiple modifiers$/
77
+ when /#click should allow multiple modifiers$/, /#right_click should allow modifiers$/
81
78
  skip "Windows can't :meta click because :meta triggers start menu"
82
79
  when /#double_click should allow multiple modifiers$/
83
80
  skip "Windows can't :alt double click due to being properties shortcut"
@@ -91,7 +88,7 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumIE, 'selenium', capybara_sk
91
88
  pending "Window 7 and 8.1 don't support 308 http status code"
92
89
  when /#scroll_to can scroll an element to the center of the viewport$/,
93
90
  /#scroll_to can scroll an element to the center of the scrolling element$/
94
- pending " IE doesn't support ScrollToOptions"
91
+ pending "IE doesn't support ScrollToOptions"
95
92
  when /#attach_file with multipart form should fire change once for each set of files uploaded$/,
96
93
  /#attach_file with multipart form should fire change once when uploading multiple files from empty$/,
97
94
  /#attach_file with multipart form should not break when using HTML5 multiple file input uploading multiple files$/
@@ -8,28 +8,40 @@ require 'rspec/shared_spec_matchers'
8
8
 
9
9
  SAFARI_DRIVER = :selenium_safari
10
10
 
11
- if ::Selenium::WebDriver::Service.respond_to? :driver_path=
12
- ::Selenium::WebDriver::Safari::Service
13
- else
14
- ::Selenium::WebDriver::Safari
15
- end.driver_path = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
11
+ # if ::Selenium::WebDriver::Service.respond_to? :driver_path=
12
+ # ::Selenium::WebDriver::Safari::Service
13
+ # else
14
+ # ::Selenium::WebDriver::Safari
15
+ # end.driver_path = '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
16
16
 
17
17
  browser_options = ::Selenium::WebDriver::Safari::Options.new
18
18
  # browser_options.headless! if ENV['HEADLESS']
19
- # browser_options.add_option(:w3c, !!ENV['W3C'])
20
19
 
21
20
  Capybara.register_driver :selenium_safari do |app|
22
- Capybara::Selenium::Driver.new(app, browser: :safari, options: browser_options, timeout: 30).tap do |driver|
21
+ version = Capybara::Selenium::Driver.load_selenium
22
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
23
+ driver_options = { browser: :safari, timeout: 30 }.tap do |opts|
24
+ opts[options_key] = browser_options
25
+ end
26
+
27
+ Capybara::Selenium::Driver.new(app, **driver_options).tap do |driver|
23
28
  # driver.browser.download_path = Capybara.save_path
24
29
  end
25
30
  end
26
31
 
27
32
  Capybara.register_driver :selenium_safari_not_clear_storage do |app|
28
- safari_options = {
33
+ version = Capybara::Selenium::Driver.load_selenium
34
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
35
+ driver_options = {
29
36
  browser: :safari,
30
- options: browser_options
31
- }
32
- Capybara::Selenium::Driver.new(app, safari_options.merge(clear_local_storage: false, clear_session_storage: false))
37
+ clear_local_storage: false,
38
+ clear_session_storage: false,
39
+ timeout: 30
40
+ }.tap do |opts|
41
+ opts[options_key] = browser_options
42
+ end
43
+
44
+ Capybara::Selenium::Driver.new(app, **driver_options)
33
45
  end
34
46
 
35
47
  module TestSessions
@@ -65,16 +77,17 @@ Capybara::SpecHelper.run_specs TestSessions::Safari, SAFARI_DRIVER.to_s, capybar
65
77
  when 'Capybara::Session selenium_safari node #double_click should allow to adjust the offset',
66
78
  'Capybara::Session selenium_safari node #double_click should double click an element'
67
79
  pending "safardriver doesn't generate a double click event"
68
- when 'Capybara::Session selenium_safari node #click should allow multiple modifiers',
69
- /Capybara::Session selenium_safari node #(click|right_click|double_click) should allow modifiers/
70
- pending "safaridriver doesn't take key state into account when clicking"
71
- when 'Capybara::Session selenium_safari #fill_in on a pre-populated textfield with a reformatting onchange should trigger change when clearing field'
72
- pending "safardriver clear doesn't generate change event"
80
+ when 'Capybara::Session selenium_safari node #double_click should allow modifiers'
81
+ pending "safaridriver doesn't generate double click with key modifiers"
82
+ when /when w3c_click_offset is true should offset/
83
+ pending 'w3c_click_offset is not currently supported with safaridriver'
73
84
  when 'Capybara::Session selenium_safari #go_back should fetch a response from the driver from the previous page',
74
85
  'Capybara::Session selenium_safari #go_forward should fetch a response from the driver from the previous page'
75
86
  skip 'safaridriver loses the ability to find elements in the document after `go_back`'
76
- when /drag_to.*HTML5/
77
- pending "Safari doesn't support"
87
+ when 'Capybara::Session selenium node #shadow_root should get the shadow root',
88
+ 'Capybara::Session selenium node #shadow_root should find elements inside the shadow dom using CSS',
89
+ 'Capybara::Session selenium node #shadow_root should find nested shadow roots'
90
+ pending "Safari doesn't yet have W3C shadow root support"
78
91
  end
79
92
  end
80
93
 
@@ -124,7 +137,6 @@ RSpec.describe 'Capybara::Session with safari' do
124
137
  end
125
138
 
126
139
  it 'should fill in a date input with a String' do
127
- pending "Safari doesn't support date inputs"
128
140
  session.fill_in('form_date', with: '06/19/1983')
129
141
  session.click_button('awesome')
130
142
  expect(Date.parse(extract_results(session)['date'])).to eq datetime.to_date