capybara 3.35.3 → 3.39.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +110 -4
  3. data/README.md +28 -12
  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 +8 -13
  9. data/lib/capybara/minitest/spec.rb +2 -2
  10. data/lib/capybara/node/actions.rb +14 -9
  11. data/lib/capybara/node/base.rb +2 -1
  12. data/lib/capybara/node/document.rb +2 -2
  13. data/lib/capybara/node/element.rb +13 -2
  14. data/lib/capybara/node/finders.rb +11 -2
  15. data/lib/capybara/node/simple.rb +5 -1
  16. data/lib/capybara/node/whitespace_normalizer.rb +81 -0
  17. data/lib/capybara/queries/active_element_query.rb +18 -0
  18. data/lib/capybara/queries/ancestor_query.rb +2 -1
  19. data/lib/capybara/queries/base_query.rb +2 -2
  20. data/lib/capybara/queries/current_path_query.rb +1 -1
  21. data/lib/capybara/queries/selector_query.rb +38 -10
  22. data/lib/capybara/queries/sibling_query.rb +2 -1
  23. data/lib/capybara/queries/text_query.rb +1 -1
  24. data/lib/capybara/rack_test/browser.rb +63 -8
  25. data/lib/capybara/rack_test/driver.rb +4 -4
  26. data/lib/capybara/rack_test/form.rb +29 -7
  27. data/lib/capybara/rack_test/node.rb +28 -22
  28. data/lib/capybara/registration_container.rb +0 -3
  29. data/lib/capybara/registrations/drivers.rb +6 -6
  30. data/lib/capybara/registrations/servers.rb +30 -10
  31. data/lib/capybara/rspec/matcher_proxies.rb +6 -6
  32. data/lib/capybara/rspec/matchers/base.rb +8 -6
  33. data/lib/capybara/rspec/matchers/compound.rb +1 -1
  34. data/lib/capybara/rspec/matchers/have_selector.rb +5 -5
  35. data/lib/capybara/rspec/matchers.rb +14 -14
  36. data/lib/capybara/selector/builders/css_builder.rb +1 -1
  37. data/lib/capybara/selector/builders/xpath_builder.rb +1 -1
  38. data/lib/capybara/selector/css.rb +1 -1
  39. data/lib/capybara/selector/definition/button.rb +9 -4
  40. data/lib/capybara/selector/definition/checkbox.rb +1 -1
  41. data/lib/capybara/selector/definition/file_field.rb +1 -1
  42. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  43. data/lib/capybara/selector/definition/link.rb +2 -1
  44. data/lib/capybara/selector/definition/radio_button.rb +1 -1
  45. data/lib/capybara/selector/definition.rb +4 -2
  46. data/lib/capybara/selector/filter_set.rb +4 -7
  47. data/lib/capybara/selector/regexp_disassembler.rb +2 -5
  48. data/lib/capybara/selector/selector.rb +5 -1
  49. data/lib/capybara/selector.rb +1 -0
  50. data/lib/capybara/selenium/driver.rb +30 -13
  51. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
  52. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +9 -5
  53. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
  54. data/lib/capybara/selenium/extensions/html5_drag.rb +5 -4
  55. data/lib/capybara/selenium/logger_suppressor.rb +4 -0
  56. data/lib/capybara/selenium/node.rb +81 -32
  57. data/lib/capybara/selenium/nodes/chrome_node.rb +6 -2
  58. data/lib/capybara/selenium/nodes/edge_node.rb +25 -3
  59. data/lib/capybara/selenium/nodes/firefox_node.rb +3 -3
  60. data/lib/capybara/selenium/nodes/safari_node.rb +4 -4
  61. data/lib/capybara/selenium/patches/action_pauser.rb +3 -3
  62. data/lib/capybara/selenium/patches/atoms.rb +1 -1
  63. data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -1
  64. data/lib/capybara/server/animation_disabler.rb +40 -23
  65. data/lib/capybara/server/middleware.rb +1 -1
  66. data/lib/capybara/session/config.rb +4 -2
  67. data/lib/capybara/session.rb +31 -32
  68. data/lib/capybara/spec/public/test.js +4 -0
  69. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  70. data/lib/capybara/spec/session/all_spec.rb +10 -14
  71. data/lib/capybara/spec/session/assert_text_spec.rb +17 -17
  72. data/lib/capybara/spec/session/attach_file_spec.rb +6 -0
  73. data/lib/capybara/spec/session/check_spec.rb +10 -0
  74. data/lib/capybara/spec/session/choose_spec.rb +6 -0
  75. data/lib/capybara/spec/session/click_link_spec.rb +11 -0
  76. data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
  77. data/lib/capybara/spec/session/fill_in_spec.rb +6 -0
  78. data/lib/capybara/spec/session/find_link_spec.rb +10 -0
  79. data/lib/capybara/spec/session/find_spec.rb +7 -1
  80. data/lib/capybara/spec/session/first_spec.rb +1 -1
  81. data/lib/capybara/spec/session/frame/within_frame_spec.rb +2 -0
  82. data/lib/capybara/spec/session/has_all_selectors_spec.rb +5 -5
  83. data/lib/capybara/spec/session/has_ancestor_spec.rb +2 -2
  84. data/lib/capybara/spec/session/has_any_selectors_spec.rb +6 -2
  85. data/lib/capybara/spec/session/has_button_spec.rb +30 -0
  86. data/lib/capybara/spec/session/has_current_path_spec.rb +3 -3
  87. data/lib/capybara/spec/session/has_field_spec.rb +25 -1
  88. data/lib/capybara/spec/session/has_link_spec.rb +40 -0
  89. data/lib/capybara/spec/session/has_none_selectors_spec.rb +7 -7
  90. data/lib/capybara/spec/session/has_select_spec.rb +10 -4
  91. data/lib/capybara/spec/session/has_selector_spec.rb +15 -0
  92. data/lib/capybara/spec/session/has_text_spec.rb +6 -14
  93. data/lib/capybara/spec/session/matches_style_spec.rb +2 -0
  94. data/lib/capybara/spec/session/node_spec.rb +82 -1
  95. data/lib/capybara/spec/session/reset_session_spec.rb +13 -0
  96. data/lib/capybara/spec/session/scroll_spec.rb +7 -5
  97. data/lib/capybara/spec/session/visit_spec.rb +20 -0
  98. data/lib/capybara/spec/session/window/window_spec.rb +1 -1
  99. data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
  100. data/lib/capybara/spec/session/within_spec.rb +13 -0
  101. data/lib/capybara/spec/spec_helper.rb +12 -5
  102. data/lib/capybara/spec/test_app.rb +91 -14
  103. data/lib/capybara/spec/views/animated.erb +1 -1
  104. data/lib/capybara/spec/views/form.erb +28 -3
  105. data/lib/capybara/spec/views/frame_child.erb +1 -1
  106. data/lib/capybara/spec/views/frame_one.erb +1 -1
  107. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  108. data/lib/capybara/spec/views/frame_two.erb +1 -1
  109. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  110. data/lib/capybara/spec/views/layout.erb +10 -0
  111. data/lib/capybara/spec/views/obscured.erb +1 -1
  112. data/lib/capybara/spec/views/offset.erb +2 -1
  113. data/lib/capybara/spec/views/path.erb +2 -2
  114. data/lib/capybara/spec/views/popup_one.erb +1 -1
  115. data/lib/capybara/spec/views/popup_two.erb +1 -1
  116. data/lib/capybara/spec/views/react.erb +2 -2
  117. data/lib/capybara/spec/views/scroll.erb +2 -1
  118. data/lib/capybara/spec/views/spatial.erb +1 -1
  119. data/lib/capybara/spec/views/with_animation.erb +2 -3
  120. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  121. data/lib/capybara/spec/views/with_dragula.erb +2 -2
  122. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  123. data/lib/capybara/spec/views/with_hover.erb +2 -2
  124. data/lib/capybara/spec/views/with_html.erb +3 -3
  125. data/lib/capybara/spec/views/with_jquery_animation.erb +1 -1
  126. data/lib/capybara/spec/views/with_js.erb +2 -3
  127. data/lib/capybara/spec/views/with_jstree.erb +1 -1
  128. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  129. data/lib/capybara/spec/views/with_scope.erb +2 -2
  130. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  131. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  132. data/lib/capybara/spec/views/with_sortable_js.erb +2 -2
  133. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  134. data/lib/capybara/spec/views/with_windows.erb +1 -1
  135. data/lib/capybara/spec/views/within_frames.erb +1 -1
  136. data/lib/capybara/version.rb +1 -1
  137. data/lib/capybara/window.rb +1 -1
  138. data/lib/capybara.rb +23 -24
  139. data/spec/basic_node_spec.rb +16 -3
  140. data/spec/capybara_spec.rb +12 -0
  141. data/spec/counter_spec.rb +35 -0
  142. data/spec/css_builder_spec.rb +1 -1
  143. data/spec/css_splitter_spec.rb +1 -1
  144. data/spec/dsl_spec.rb +5 -3
  145. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -2
  146. data/spec/fixtures/selenium_driver_rspec_success.rb +2 -2
  147. data/spec/minitest_spec.rb +4 -0
  148. data/spec/minitest_spec_spec.rb +4 -0
  149. data/spec/per_session_config_spec.rb +1 -1
  150. data/spec/rack_test_spec.rb +30 -12
  151. data/spec/result_spec.rb +32 -35
  152. data/spec/rspec/features_spec.rb +3 -3
  153. data/spec/rspec/scenarios_spec.rb +2 -2
  154. data/spec/rspec/shared_spec_matchers.rb +3 -3
  155. data/spec/rspec_matchers_spec.rb +25 -0
  156. data/spec/rspec_spec.rb +2 -2
  157. data/spec/sauce_spec_chrome.rb +4 -4
  158. data/spec/selector_spec.rb +4 -4
  159. data/spec/selenium_spec_chrome.rb +16 -16
  160. data/spec/selenium_spec_chrome_remote.rb +15 -14
  161. data/spec/selenium_spec_edge.rb +12 -6
  162. data/spec/selenium_spec_firefox.rb +24 -7
  163. data/spec/selenium_spec_firefox_remote.rb +19 -4
  164. data/spec/selenium_spec_ie.rb +7 -8
  165. data/spec/selenium_spec_safari.rb +34 -20
  166. data/spec/server_spec.rb +7 -7
  167. data/spec/shared_selenium_node.rb +0 -4
  168. data/spec/shared_selenium_session.rb +24 -14
  169. data/spec/spec_helper.rb +34 -1
  170. data/spec/whitespace_normalizer_spec.rb +54 -0
  171. data/spec/xpath_builder_spec.rb +1 -1
  172. metadata +40 -14
  173. data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -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]
@@ -35,6 +30,8 @@ Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip
35
30
  skip "Nokogiri doesn't support case insensitive CSS attribute matchers"
36
31
  when /#click_button should follow permanent redirects that maintain method/
37
32
  skip "Rack < 2 doesn't support 308" if Gem.loaded_specs['rack'].version < Gem::Version.new('2.0.0')
33
+ when /#attach_file with multipart form should send prior hidden field if no file submitted/
34
+ skip 'Rack-test < 2 needs an empty file to detect multipart form' if Gem.loaded_specs['rack-test'].version < Gem::Version.new('2.0.0')
38
35
  end
39
36
  end
40
37
 
@@ -98,6 +95,12 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
98
95
  session.click_button('Upload Empty')
99
96
  expect(session.html).to include('Successfully ignored empty file field.')
100
97
  end
98
+
99
+ it 'should submit multipart even if no file is submitted' do
100
+ session.visit('/form')
101
+ session.click_button('Upload Empty')
102
+ expect(session.html).to include('Content type was multipart/form-data;')
103
+ end
101
104
  end
102
105
 
103
106
  it 'should not submit an obsolete mime type' do
@@ -153,6 +156,14 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
153
156
  end
154
157
  end
155
158
 
159
+ describe '#active_element' do
160
+ it 'raises an UnsupportedMethodError' do
161
+ session.visit('/form')
162
+
163
+ expect { session.active_element }.to raise_error(Capybara::NotSupportedByDriverError)
164
+ end
165
+ end
166
+
156
167
  describe '#text' do
157
168
  it 'should return original text content for textareas' do
158
169
  session.visit('/with_html')
@@ -209,15 +220,21 @@ RSpec.describe Capybara::RackTest::Driver do
209
220
  driver = described_class.new(TestApp)
210
221
 
211
222
  driver.visit('/redirect')
212
- expect(driver.response.header['Location']).to be_nil
223
+ expect(driver.response.headers['Location']).to be_nil
213
224
  expect(driver.current_url).to match %r{/landed$}
214
225
  end
215
226
 
227
+ it 'should not include fragments in the referer header' do
228
+ driver.visit('/header_links#an-anchor')
229
+ driver.find_xpath('.//input').first.click
230
+ expect(driver.request.get_header('HTTP_REFERER')).to eq('http://www.example.com/header_links')
231
+ end
232
+
216
233
  it 'is possible to not follow redirects' do
217
234
  driver = described_class.new(TestApp, follow_redirects: false)
218
235
 
219
236
  driver.visit('/redirect')
220
- expect(driver.response.header['Location']).to match %r{/redirect_again$}
237
+ expect(driver.response.headers['Location']).to match %r{/redirect_again$}
221
238
  expect(driver.current_url).to match %r{/redirect$}
222
239
  end
223
240
  end
@@ -256,11 +273,12 @@ RSpec.describe Capybara::RackTest::Driver do
256
273
  end
257
274
 
258
275
  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
276
+ it 'should use HTML5 parsing' do
277
+ skip 'Only valid if Nokogiri >= 1.12.0 or gumbo is included' unless defined? Nokogiri::HTML5
278
+ Capybara.use_html5_parsing = true
279
+ allow(Nokogiri::HTML5).to receive(:parse).and_call_original
262
280
  Capybara.string('<div id=test_div></div>')
263
- expect(Nokogiri).to have_received(:HTML5)
281
+ expect(Nokogiri::HTML5).to have_received(:parse)
264
282
  end
265
283
  end
266
284
 
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,12 +11,12 @@ 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
 
18
18
  feature 'if xscenario aliases to pending then' do
19
- xscenario "this test should be 'temporarily disabled with xscenario'" do
19
+ xscenario "this test should be 'temporarily disabled with xscenario'" do # rubocop:disable RSpec/PendingWithoutReason
20
20
  end
21
21
  end
22
22
 
@@ -120,7 +120,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
120
120
 
121
121
  describe 'have_xpath matcher' do
122
122
  it 'gives proper description' do
123
- expect(have_xpath('//h1').description).to eq("have visible xpath \"\/\/h1\"")
123
+ expect(have_xpath('//h1').description).to eq('have visible xpath "//h1"')
124
124
  end
125
125
 
126
126
  context 'on a string' do
@@ -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
@@ -56,6 +56,31 @@ RSpec.describe 'Capybara RSpec Matchers', type: :feature do
56
56
  end
57
57
  end
58
58
 
59
+ context 'with a filter block' do
60
+ it 'applies the filter' do
61
+ visit('/with_html')
62
+ expect(page).to have_selector(:css, 'input#test_field')
63
+
64
+ expect(page).to have_selector(:css, 'input', count: 1) { |input| input.value == 'monkey' }
65
+ expect(page).to have_selector(:css, 'input', count: 1) do |input|
66
+ input.value == 'monkey'
67
+ end
68
+ expect(page).to have_no_selector(:css, 'input#test_field') { |input| input.value == 'not a monkey' }
69
+ expect(page).to have_no_selector(:css, 'input#test_field') do |input|
70
+ input.value == 'not a monkey'
71
+ end
72
+
73
+ expect(page).not_to have_selector(:css, 'input#test_field') { |input| input.value == 'not a monkey' }
74
+ expect(page).not_to have_selector(:css, 'input#test_field') do |input|
75
+ input.value == 'not a monkey'
76
+ end
77
+ expect(page).not_to have_no_selector(:css, 'input', count: 1) { |input| input.value == 'monkey' }
78
+ expect(page).not_to have_no_selector(:css, 'input#test_field', count: 1) do |input|
79
+ input.value == 'monkey'
80
+ end
81
+ end
82
+ end
83
+
59
84
  def error_msg_for(&block)
60
85
  expect(&block).to(raise_error { |e| return e.message })
61
86
  end
data/spec/rspec_spec.rb CHANGED
@@ -15,7 +15,7 @@ RSpec.describe 'capybara/rspec' do
15
15
  expect(self.class.ancestors).to include Capybara::RSpecMatcherProxies
16
16
  end
17
17
 
18
- context 'resetting session' do
18
+ context 'resetting session', order: :defined do
19
19
  it 'sets a cookie in one example...' do
20
20
  visit('/set_cookie')
21
21
  expect(page.body).to include('Cookie set to test_cookie')
@@ -27,7 +27,7 @@ RSpec.describe 'capybara/rspec' do
27
27
  end
28
28
  end
29
29
 
30
- context 'setting the current driver' do
30
+ context 'setting the current driver', order: :defined do
31
31
  it 'sets the current driver in one example...' do
32
32
  Capybara.current_driver = :selenium
33
33
  end
@@ -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)
@@ -27,7 +27,7 @@ Capybara.register_driver :sauce_chrome do |app|
27
27
 
28
28
  Capybara::Selenium::Driver.new(app,
29
29
  browser: :remote, url: url,
30
- desired_capabilities: capabilities,
30
+ capabilities: capabilities,
31
31
  options: Selenium::WebDriver::Chrome::Options.new(args: ['']))
32
32
  end
33
33
 
@@ -111,13 +111,13 @@ RSpec.describe Capybara do
111
111
  end
112
112
 
113
113
  describe 'adding a selector' do
114
- it 'can set default visiblity' do
114
+ it 'can set default visibility' do
115
115
  described_class.add_selector :hidden_field do
116
116
  visible :hidden
117
117
  css { |_sel| 'input[type="hidden"]' }
118
118
  end
119
119
 
120
- expect(string).to have_no_css('input[type="hidden"]')
120
+ expect(string).to have_no_css('input[type="hidden"]') # rubocop:disable RSpec/Capybara/SpecificMatcher
121
121
  expect(string).to have_selector(:hidden_field)
122
122
  end
123
123
  end
@@ -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
 
@@ -471,7 +471,7 @@ RSpec.describe Capybara do
471
471
  end
472
472
 
473
473
  it 'includes wildcarded keys in description' do
474
- expect { string.find(:element, 'input', not_there: 'bad', presence: true, absence: false, count: 1) }
474
+ expect { string.all(:element, 'input', not_there: 'bad', presence: true, absence: false, count: 1) }
475
475
  .to(raise_error do |e|
476
476
  expect(e).to be_a(Capybara::ElementNotFound)
477
477
  expect(e.message).to include 'not_there => bad'
@@ -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
+
13
+ browser_options = Selenium::WebDriver::Chrome::Options.new
14
+ browser_options.add_argument('--headless') if ENV['HEADLESS']
12
15
 
13
- browser_options = ::Selenium::WebDriver::Chrome::Options.new
14
- browser_options.headless! if ENV['HEADLESS']
15
- browser_options.add_option(:w3c, ENV['W3C'] != 'false')
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,11 @@ 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'
88
+ when /Capybara::Session selenium_chrome node #shadow_root should get visible text/
89
+ pending "Selenium doesn't currently support getting visible text for shadow root elements"
90
+ when /Capybara::Session selenium_chrome node #shadow_root/
91
+ skip 'Not supported with this Selenium version' if selenium_lt?('4.1', @session)
92
+ skip 'Not supported with this chromedriver version' if chromedriver_lt?('96.0', @session)
92
93
  end
93
94
  end
94
95
 
@@ -185,23 +186,22 @@ RSpec.describe 'Capybara::Session with chrome' do
185
186
  end
186
187
 
187
188
  describe 'log access' do
188
- before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
189
+ let(:logs) do
190
+ session.driver.browser.then do |chrome_driver|
191
+ chrome_driver.respond_to?(:logs) ? chrome_driver : chrome_driver.manage
192
+ end.logs
193
+ end
189
194
 
190
195
  it 'does not error getting log types' do
191
- skip if Gem::Requirement.new('< 75.0.3770.90').satisfied_by? chromedriver_version
192
196
  expect do
193
- session.driver.browser.manage.logs.available_types
197
+ logs.available_types
194
198
  end.not_to raise_error
195
199
  end
196
200
 
197
201
  it 'does not error when getting logs' do
198
202
  expect do
199
- session.driver.browser.manage.logs.get(:browser)
203
+ logs.get(:browser)
200
204
  end.not_to raise_error
201
205
  end
202
206
  end
203
-
204
- def chromedriver_version
205
- Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0])
206
- end
207
207
  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
@@ -39,11 +39,10 @@ Capybara.register_driver :selenium_chrome_remote do |app|
39
39
  ensure_selenium_running!
40
40
 
41
41
  url = "http://#{selenium_host}:#{selenium_port}/wd/hub"
42
- browser_options = ::Selenium::WebDriver::Chrome::Options.new
42
+ browser_options = Selenium::WebDriver::Chrome::Options.new
43
43
 
44
44
  Capybara::Selenium::Driver.new app,
45
45
  browser: :remote,
46
- desired_capabilities: :chrome,
47
46
  options: browser_options,
48
47
  url: url
49
48
  end
@@ -62,8 +61,11 @@ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s,
62
61
  'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once for each set of files uploaded',
63
62
  'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once when uploading multiple files from empty'
64
63
  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'
64
+ when /Capybara::Session selenium_chrome_remote node #shadow_root should get visible text/
65
+ pending "Selenium doesn't currently support getting visible text for shadow root elements"
66
+ when /Capybara::Session selenium_chrome_remote node #shadow_root/
67
+ skip 'Not supported with this Selenium version' if selenium_lt?('4.1', @session)
68
+ skip 'Not supported with this chromedriver version' if chromedriver_lt?('96.0', @session)
67
69
  end
68
70
  end
69
71
 
@@ -78,23 +80,22 @@ RSpec.describe 'Capybara::Session with remote Chrome' do
78
80
  end
79
81
 
80
82
  describe 'log access' do
81
- before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
83
+ let(:logs) do
84
+ session.driver.browser.then do |chrome_driver|
85
+ chrome_driver.respond_to?(:logs) ? chrome_driver : chrome_driver.manage
86
+ end.logs
87
+ end
82
88
 
83
89
  it 'does not error when getting log types' do
84
- skip unless Gem::Requirement.new('>= 75.0.3770.90').satisfied_by? chromedriver_version
85
90
  expect do
86
- session.driver.browser.manage.logs.available_types
91
+ logs.available_types
87
92
  end.not_to raise_error
88
93
  end
89
94
 
90
95
  it 'does not error when getting logs' do
91
96
  expect do
92
- session.driver.browser.manage.logs.get(:browser)
97
+ logs.get(:browser)
93
98
  end.not_to raise_error
94
99
  end
95
100
  end
96
-
97
- def chromedriver_version
98
- Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0])
99
- end
100
101
  end
@@ -10,15 +10,17 @@ require 'rspec/shared_spec_matchers'
10
10
  # Selenium::WebDriver::Edge::Service.driver_path = '/usr/local/bin/msedgedriver'
11
11
  # end
12
12
 
13
- if ::Selenium::WebDriver::Platform.mac?
14
- Selenium::WebDriver::EdgeChrome.path = '/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev'
13
+ if Selenium::WebDriver::Platform.mac?
14
+ Selenium::WebDriver::Edge.path = '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge'
15
15
  end
16
16
 
17
17
  Capybara.register_driver :selenium_edge do |app|
18
18
  # ::Selenium::WebDriver.logger.level = "debug"
19
19
  # If we don't create an options object the path set above won't be used
20
- browser_options = ::Selenium::WebDriver::EdgeChrome::Options.new
21
- Capybara::Selenium::Driver.new(app, browser: :edge_chrome, options: browser_options).tap do |driver|
20
+ browser_options = Selenium::WebDriver::Edge::Options.new
21
+ browser_options.add_argument('--headless') if ENV['HEADLESS']
22
+
23
+ Capybara::Selenium::Driver.new(app, browser: :edge, options: browser_options).tap do |driver|
22
24
  driver.browser
23
25
  driver.download_path = Capybara.save_path
24
26
  end
@@ -30,12 +32,16 @@ end
30
32
 
31
33
  skipped_tests = %i[response_headers status_code trigger]
32
34
 
33
- Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::EdgeChrome) if ENV['CI']
35
+ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Edge) if ENV['CI']
34
36
 
35
37
  Capybara::SpecHelper.run_specs TestSessions::SeleniumEdge, 'selenium', capybara_skip: skipped_tests do |example|
36
38
  case example.metadata[:full_description]
37
39
  when 'Capybara::Session selenium #attach_file with a block can upload by clicking the file input'
38
- pending "EdgeChrome doesn't allow clicking on file inputs"
40
+ pending "Edge doesn't allow clicking on file inputs"
41
+ when /Capybara::Session selenium node #shadow_root should get visible text/
42
+ pending "Selenium doesn't currently support getting visible text for shadow root elements"
43
+ when /Capybara::Session selenium Capybara::Window#maximize/
44
+ pending "Edge headless doesn't support maximize" if ENV['HEADLESS']
39
45
  end
40
46
  end
41
47
 
@@ -6,7 +6,7 @@ require 'shared_selenium_session'
6
6
  require 'shared_selenium_node'
7
7
  require 'rspec/shared_spec_matchers'
8
8
 
9
- browser_options = ::Selenium::WebDriver::Firefox::Options.new
9
+ browser_options = Selenium::WebDriver::Firefox::Options.new
10
10
  browser_options.headless! if ENV['HEADLESS']
11
11
  # browser_options.add_option("log", {"level": "trace"})
12
12
 
@@ -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,18 +60,34 @@ 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)
64
- skip 'Broken again intermittently in FF 71 - jus skip it'
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)
65
+ skip 'Broken again intermittently in FF 71 - jus skip it' if firefox_lt?(109, @session) # don't really know when it was fixed
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?
67
68
  when 'Capybara::Session selenium #reset_session! removes ALL cookies'
68
69
  pending "Geckodriver doesn't provide a way to remove cookies outside the current domain"
69
70
  when /drag_to.*HTML5/
70
- pending "Firefox < 62 doesn't support a DataTransfer constuctor" if firefox_lt?(62.0, @session)
71
+ pending "Firefox < 62 doesn't support a DataTransfer constructor" if firefox_lt?(62.0, @session)
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
- skip 'No clue what Firefox is doing here - works fine on MacOS locally'
74
+ skip 'No clue what Firefox is doing here - works fine on MacOS locally' if firefox_lt?(109, @session) # don't really know when it was fixed
75
+ when 'Capybara::Session selenium node #shadow_root should find elements inside the shadow dom using CSS',
76
+ 'Capybara::Session selenium node #shadow_root should find nested shadow roots',
77
+ 'Capybara::Session selenium node #shadow_root should click on elements',
78
+ 'Capybara::Session selenium node #shadow_root should use convenience methods once moved to a descendant of the shadow root',
79
+ 'Capybara::Session selenium node #shadow_root should produce error messages when failing',
80
+ 'Capybara::Session with firefox with selenium driver #evaluate_script returns a shadow root'
81
+ pending "Firefox doesn't yet have full W3C shadow root support"
82
+ when 'Capybara::Session selenium #fill_in should handle carriage returns with line feeds in a textarea correctly'
83
+ pending 'Not sure what firefox is doing here'
84
+ when /Capybara::Session selenium node #shadow_root should get visible text/
85
+ pending "Selenium doesn't currently support getting visible text for shadow root elements"
86
+ when /Capybara::Session selenium node #shadow_root/
87
+ skip 'Not supported with this Selenium version' if selenium_lt?('4.1', @session)
88
+ skip 'Not supported with this geckodriver version' if geckodriver_lt?('0.31.0', @session)
89
+ when /Capybara::Session selenium node #set should submit single text input forms if ended with \\n/
90
+ pending 'Firefox/geckodriver doesn\'t submit with values ending in \n'
74
91
  end
75
92
  end
76
93
 
@@ -102,7 +119,7 @@ RSpec.describe 'Capybara::Session with firefox' do # rubocop:disable RSpec/Multi
102
119
  end
103
120
 
104
121
  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
122
+ pending 'Need to figure out what string format this will actually accept'
106
123
  session.fill_in('form_datetime', with: datetime.iso8601)
107
124
  session.click_button('awesome')
108
125
  expect(Time.parse(extract_results(session)['datetime'])).to eq datetime