capybara 3.29.0 → 3.36.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (200) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +203 -15
  3. data/README.md +13 -4
  4. data/lib/capybara/config.rb +24 -10
  5. data/lib/capybara/cucumber.rb +1 -1
  6. data/lib/capybara/driver/base.rb +8 -0
  7. data/lib/capybara/driver/node.rb +1 -1
  8. data/lib/capybara/dsl.rb +10 -2
  9. data/lib/capybara/helpers.rb +19 -2
  10. data/lib/capybara/minitest/spec.rb +156 -97
  11. data/lib/capybara/minitest.rb +232 -144
  12. data/lib/capybara/node/actions.rb +41 -37
  13. data/lib/capybara/node/base.rb +6 -6
  14. data/lib/capybara/node/document.rb +2 -2
  15. data/lib/capybara/node/document_matchers.rb +3 -3
  16. data/lib/capybara/node/element.rb +24 -21
  17. data/lib/capybara/node/finders.rb +25 -18
  18. data/lib/capybara/node/matchers.rb +72 -57
  19. data/lib/capybara/node/simple.rb +13 -3
  20. data/lib/capybara/queries/active_element_query.rb +18 -0
  21. data/lib/capybara/queries/ancestor_query.rb +4 -3
  22. data/lib/capybara/queries/base_query.rb +2 -1
  23. data/lib/capybara/queries/current_path_query.rb +14 -4
  24. data/lib/capybara/queries/selector_query.rb +71 -23
  25. data/lib/capybara/queries/sibling_query.rb +4 -3
  26. data/lib/capybara/queries/style_query.rb +1 -1
  27. data/lib/capybara/queries/text_query.rb +7 -1
  28. data/lib/capybara/rack_test/browser.rb +13 -4
  29. data/lib/capybara/rack_test/driver.rb +2 -1
  30. data/lib/capybara/rack_test/form.rb +2 -2
  31. data/lib/capybara/rack_test/node.rb +43 -15
  32. data/lib/capybara/registration_container.rb +44 -0
  33. data/lib/capybara/registrations/drivers.rb +18 -12
  34. data/lib/capybara/registrations/patches/puma_ssl.rb +3 -1
  35. data/lib/capybara/registrations/servers.rb +3 -2
  36. data/lib/capybara/result.rb +35 -15
  37. data/lib/capybara/rspec/matcher_proxies.rb +8 -8
  38. data/lib/capybara/rspec/matchers/base.rb +12 -6
  39. data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
  40. data/lib/capybara/rspec/matchers/have_ancestor.rb +4 -3
  41. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  42. data/lib/capybara/rspec/matchers/have_selector.rb +16 -8
  43. data/lib/capybara/rspec/matchers/have_sibling.rb +3 -3
  44. data/lib/capybara/rspec/matchers/have_text.rb +3 -3
  45. data/lib/capybara/rspec/matchers/have_title.rb +2 -2
  46. data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
  47. data/lib/capybara/rspec/matchers/match_style.rb +7 -2
  48. data/lib/capybara/rspec/matchers/spatial_sugar.rb +2 -1
  49. data/lib/capybara/rspec/matchers.rb +33 -32
  50. data/lib/capybara/rspec.rb +2 -0
  51. data/lib/capybara/selector/builders/css_builder.rb +2 -2
  52. data/lib/capybara/selector/builders/xpath_builder.rb +4 -2
  53. data/lib/capybara/selector/css.rb +2 -2
  54. data/lib/capybara/selector/definition/button.rb +35 -13
  55. data/lib/capybara/selector/definition/checkbox.rb +3 -3
  56. data/lib/capybara/selector/definition/css.rb +3 -1
  57. data/lib/capybara/selector/definition/datalist_input.rb +2 -2
  58. data/lib/capybara/selector/definition/datalist_option.rb +1 -1
  59. data/lib/capybara/selector/definition/element.rb +3 -2
  60. data/lib/capybara/selector/definition/field.rb +1 -1
  61. data/lib/capybara/selector/definition/file_field.rb +2 -2
  62. data/lib/capybara/selector/definition/fillable_field.rb +3 -3
  63. data/lib/capybara/selector/definition/label.rb +5 -3
  64. data/lib/capybara/selector/definition/link.rb +8 -0
  65. data/lib/capybara/selector/definition/radio_button.rb +3 -3
  66. data/lib/capybara/selector/definition/select.rb +33 -14
  67. data/lib/capybara/selector/definition/table.rb +6 -3
  68. data/lib/capybara/selector/definition/table_row.rb +2 -2
  69. data/lib/capybara/selector/definition.rb +14 -11
  70. data/lib/capybara/selector/filter_set.rb +17 -17
  71. data/lib/capybara/selector/filters/base.rb +6 -1
  72. data/lib/capybara/selector/filters/locator_filter.rb +1 -1
  73. data/lib/capybara/selector/selector.rb +13 -3
  74. data/lib/capybara/selector.rb +37 -19
  75. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -1
  76. data/lib/capybara/selenium/atoms/src/getAttribute.js +1 -1
  77. data/lib/capybara/selenium/atoms/src/isDisplayed.js +1 -1
  78. data/lib/capybara/selenium/driver.rb +79 -16
  79. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +11 -13
  80. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +10 -12
  81. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +4 -4
  82. data/lib/capybara/selenium/extensions/find.rb +4 -4
  83. data/lib/capybara/selenium/extensions/html5_drag.rb +30 -13
  84. data/lib/capybara/selenium/extensions/scroll.rb +8 -10
  85. data/lib/capybara/selenium/logger_suppressor.rb +8 -2
  86. data/lib/capybara/selenium/node.rb +110 -26
  87. data/lib/capybara/selenium/nodes/chrome_node.rb +34 -19
  88. data/lib/capybara/selenium/nodes/edge_node.rb +5 -3
  89. data/lib/capybara/selenium/nodes/firefox_node.rb +11 -6
  90. data/lib/capybara/selenium/nodes/safari_node.rb +3 -3
  91. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  92. data/lib/capybara/selenium/patches/atoms.rb +4 -4
  93. data/lib/capybara/selenium/patches/logs.rb +7 -9
  94. data/lib/capybara/server/animation_disabler.rb +17 -6
  95. data/lib/capybara/server/checker.rb +1 -1
  96. data/lib/capybara/server/middleware.rb +22 -10
  97. data/lib/capybara/server.rb +15 -3
  98. data/lib/capybara/session/config.rb +9 -3
  99. data/lib/capybara/session/matchers.rb +11 -11
  100. data/lib/capybara/session.rb +73 -37
  101. data/lib/capybara/spec/public/test.js +75 -7
  102. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
  103. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  104. data/lib/capybara/spec/session/all_spec.rb +62 -9
  105. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  106. data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
  107. data/lib/capybara/spec/session/check_spec.rb +15 -0
  108. data/lib/capybara/spec/session/choose_spec.rb +6 -0
  109. data/lib/capybara/spec/session/click_button_spec.rb +16 -0
  110. data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
  111. data/lib/capybara/spec/session/current_url_spec.rb +11 -1
  112. data/lib/capybara/spec/session/fill_in_spec.rb +29 -0
  113. data/lib/capybara/spec/session/find_spec.rb +31 -8
  114. data/lib/capybara/spec/session/has_any_selectors_spec.rb +4 -0
  115. data/lib/capybara/spec/session/has_button_spec.rb +75 -0
  116. data/lib/capybara/spec/session/has_css_spec.rb +14 -10
  117. data/lib/capybara/spec/session/has_current_path_spec.rb +15 -2
  118. data/lib/capybara/spec/session/has_field_spec.rb +40 -0
  119. data/lib/capybara/spec/session/has_link_spec.rb +24 -0
  120. data/lib/capybara/spec/session/has_select_spec.rb +32 -4
  121. data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
  122. data/lib/capybara/spec/session/has_table_spec.rb +51 -5
  123. data/lib/capybara/spec/session/has_text_spec.rb +25 -1
  124. data/lib/capybara/spec/session/html_spec.rb +1 -1
  125. data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
  126. data/lib/capybara/spec/session/node_spec.rb +184 -33
  127. data/lib/capybara/spec/session/refresh_spec.rb +2 -1
  128. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  129. data/lib/capybara/spec/session/save_page_spec.rb +4 -4
  130. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
  131. data/lib/capybara/spec/session/scroll_spec.rb +4 -4
  132. data/lib/capybara/spec/session/selectors_spec.rb +15 -2
  133. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
  134. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
  135. data/lib/capybara/spec/session/window/window_spec.rb +8 -8
  136. data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
  137. data/lib/capybara/spec/spec_helper.rb +17 -17
  138. data/lib/capybara/spec/test_app.rb +40 -29
  139. data/lib/capybara/spec/views/animated.erb +1 -1
  140. data/lib/capybara/spec/views/form.erb +52 -6
  141. data/lib/capybara/spec/views/frame_child.erb +1 -1
  142. data/lib/capybara/spec/views/frame_one.erb +1 -1
  143. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  144. data/lib/capybara/spec/views/frame_two.erb +1 -1
  145. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  146. data/lib/capybara/spec/views/layout.erb +10 -0
  147. data/lib/capybara/spec/views/obscured.erb +1 -1
  148. data/lib/capybara/spec/views/offset.erb +2 -1
  149. data/lib/capybara/spec/views/path.erb +2 -2
  150. data/lib/capybara/spec/views/popup_one.erb +1 -1
  151. data/lib/capybara/spec/views/popup_two.erb +1 -1
  152. data/lib/capybara/spec/views/react.erb +2 -2
  153. data/lib/capybara/spec/views/scroll.erb +2 -1
  154. data/lib/capybara/spec/views/spatial.erb +1 -1
  155. data/lib/capybara/spec/views/with_animation.erb +10 -3
  156. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  157. data/lib/capybara/spec/views/with_dragula.erb +5 -3
  158. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  159. data/lib/capybara/spec/views/with_hover.erb +2 -2
  160. data/lib/capybara/spec/views/with_html.erb +3 -3
  161. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  162. data/lib/capybara/spec/views/with_js.erb +5 -3
  163. data/lib/capybara/spec/views/with_jstree.erb +1 -1
  164. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  165. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  166. data/lib/capybara/spec/views/with_sortable_js.erb +3 -3
  167. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  168. data/lib/capybara/spec/views/with_windows.erb +1 -1
  169. data/lib/capybara/spec/views/within_frames.erb +1 -1
  170. data/lib/capybara/version.rb +1 -1
  171. data/lib/capybara/window.rb +3 -7
  172. data/lib/capybara.rb +35 -29
  173. data/spec/basic_node_spec.rb +25 -11
  174. data/spec/capybara_spec.rb +1 -1
  175. data/spec/dsl_spec.rb +16 -3
  176. data/spec/fixtures/selenium_driver_rspec_success.rb +2 -2
  177. data/spec/minitest_spec.rb +3 -2
  178. data/spec/minitest_spec_spec.rb +46 -46
  179. data/spec/rack_test_spec.rb +37 -11
  180. data/spec/regexp_dissassembler_spec.rb +40 -36
  181. data/spec/result_spec.rb +42 -32
  182. data/spec/rspec/features_spec.rb +5 -2
  183. data/spec/rspec/scenarios_spec.rb +4 -0
  184. data/spec/rspec/shared_spec_matchers.rb +68 -56
  185. data/spec/rspec_spec.rb +8 -4
  186. data/spec/selector_spec.rb +17 -2
  187. data/spec/selenium_spec_chrome.rb +48 -25
  188. data/spec/selenium_spec_chrome_remote.rb +13 -6
  189. data/spec/selenium_spec_firefox.rb +25 -17
  190. data/spec/selenium_spec_firefox_remote.rb +2 -2
  191. data/spec/selenium_spec_ie.rb +3 -6
  192. data/spec/selenium_spec_safari.rb +27 -19
  193. data/spec/server_spec.rb +84 -31
  194. data/spec/session_spec.rb +1 -1
  195. data/spec/shared_selenium_node.rb +21 -7
  196. data/spec/shared_selenium_session.rb +114 -19
  197. data/spec/spec_helper.rb +1 -1
  198. metadata +78 -21
  199. data/lib/capybara/spec/session/source_spec.rb +0 -0
  200. data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -89,29 +89,29 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
89
89
 
90
90
  context 'on a page or node' do
91
91
  before do
92
- visit('/with_html')
92
+ session.visit('/with_html')
93
93
  end
94
94
 
95
95
  context 'with should' do
96
96
  it 'passes if has_css? returns true' do
97
- expect(page).to have_css('h1')
97
+ expect(session).to have_css('h1')
98
98
  end
99
99
 
100
100
  it 'fails if has_css? returns false' do
101
101
  expect do
102
- expect(page).to have_css('h1#doesnotexist')
102
+ expect(session).to have_css('h1#doesnotexist')
103
103
  end.to raise_error(/expected to find css "h1#doesnotexist" but there were no matches/)
104
104
  end
105
105
  end
106
106
 
107
107
  context 'with should_not' do
108
108
  it 'passes if has_no_css? returns true' do
109
- expect(page).not_to have_css('h1#doesnotexist')
109
+ expect(session).not_to have_css('h1#doesnotexist')
110
110
  end
111
111
 
112
112
  it 'fails if has_no_css? returns false' do
113
113
  expect do
114
- expect(page).not_to have_css('h1')
114
+ expect(session).not_to have_css('h1')
115
115
  end.to raise_error(/expected not to find visible css "h1"/)
116
116
  end
117
117
  end
@@ -158,29 +158,29 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
158
158
 
159
159
  context 'on a page or node' do
160
160
  before do
161
- visit('/with_html')
161
+ session.visit('/with_html')
162
162
  end
163
163
 
164
164
  context 'with should' do
165
165
  it 'passes if has_xpath? returns true' do
166
- expect(page).to have_xpath('//h1')
166
+ expect(session).to have_xpath('//h1')
167
167
  end
168
168
 
169
169
  it 'fails if has_xpath? returns false' do
170
170
  expect do
171
- expect(page).to have_xpath("//h1[@id='doesnotexist']")
171
+ expect(session).to have_xpath("//h1[@id='doesnotexist']")
172
172
  end.to raise_error(%r{expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches})
173
173
  end
174
174
  end
175
175
 
176
176
  context 'with should_not' do
177
177
  it 'passes if has_no_xpath? returns true' do
178
- expect(page).not_to have_xpath('//h1[@id="doesnotexist"]')
178
+ expect(session).not_to have_xpath('//h1[@id="doesnotexist"]')
179
179
  end
180
180
 
181
181
  it 'fails if has_no_xpath? returns false' do
182
182
  expect do
183
- expect(page).not_to have_xpath('//h1')
183
+ expect(session).not_to have_xpath('//h1')
184
184
  end.to raise_error(%r{expected not to find visible xpath "//h1"})
185
185
  end
186
186
  end
@@ -222,35 +222,35 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
222
222
 
223
223
  context 'on a page or node' do
224
224
  before do
225
- visit('/with_html')
225
+ session.visit('/with_html')
226
226
  end
227
227
 
228
228
  context 'with should' do
229
229
  it 'passes if has_selector? returns true' do
230
- expect(page).to have_selector('//h1', text: 'test')
230
+ expect(session).to have_selector('//h1', text: 'test')
231
231
  end
232
232
 
233
233
  it 'fails if has_selector? returns false' do
234
234
  expect do
235
- expect(page).to have_selector("//h1[@id='doesnotexist']")
235
+ expect(session).to have_selector("//h1[@id='doesnotexist']")
236
236
  end.to raise_error(%r{expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches})
237
237
  end
238
238
 
239
239
  it 'includes text in error message' do
240
240
  expect do
241
- expect(page).to have_selector('//h1', text: 'wrong text')
241
+ expect(session).to have_selector('//h1', text: 'wrong text')
242
242
  end.to raise_error(%r{expected to find visible xpath "//h1" with text "wrong text" but there were no matches})
243
243
  end
244
244
  end
245
245
 
246
246
  context 'with should_not' do
247
247
  it 'passes if has_no_css? returns true' do
248
- expect(page).not_to have_selector(:css, 'h1#doesnotexist')
248
+ expect(session).not_to have_selector(:css, 'h1#doesnotexist')
249
249
  end
250
250
 
251
251
  it 'fails if has_no_selector? returns false' do
252
252
  expect do
253
- expect(page).not_to have_selector(:css, 'h1', text: 'test')
253
+ expect(session).not_to have_selector(:css, 'h1', text: 'test')
254
254
  end.to raise_error(/expected not to find visible css "h1" with text "test"/)
255
255
  end
256
256
  end
@@ -265,7 +265,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
265
265
 
266
266
  describe 'have_content matcher' do
267
267
  it 'gives proper description' do
268
- expect(have_content('Text').description).to eq('text "Text"')
268
+ expect(have_content('Text').description).to eq('have text "Text"')
269
269
  end
270
270
 
271
271
  context 'on a string' do
@@ -304,21 +304,21 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
304
304
 
305
305
  context 'on a page or node' do
306
306
  before do
307
- visit('/with_html')
307
+ session.visit('/with_html')
308
308
  end
309
309
 
310
310
  context 'with should' do
311
311
  it 'passes if has_content? returns true' do
312
- expect(page).to have_content('This is a test')
312
+ expect(session).to have_content('This is a test')
313
313
  end
314
314
 
315
315
  it 'passes if has_content? returns true using regexp' do
316
- expect(page).to have_content(/test/)
316
+ expect(session).to have_content(/test/)
317
317
  end
318
318
 
319
319
  it 'fails if has_content? returns false' do
320
320
  expect do
321
- expect(page).to have_content('No such Text')
321
+ expect(session).to have_content('No such Text')
322
322
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
323
323
  end
324
324
 
@@ -329,7 +329,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
329
329
 
330
330
  it 'fails if has_content? returns false' do
331
331
  expect do
332
- expect(page).to have_content('No such Text')
332
+ expect(session).to have_content('No such Text')
333
333
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
334
334
  end
335
335
  end
@@ -337,14 +337,26 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
337
337
 
338
338
  context 'with should_not' do
339
339
  it 'passes if has_no_content? returns true' do
340
- expect(page).not_to have_content('No such Text')
340
+ expect(session).not_to have_content('No such Text')
341
341
  end
342
342
 
343
343
  it 'fails if has_no_content? returns false' do
344
344
  expect do
345
- expect(page).not_to have_content('This is a test')
345
+ expect(session).not_to have_content('This is a test')
346
346
  end.to raise_error(/expected not to find text "This is a test"/)
347
347
  end
348
+
349
+ it 'not_to have_content behaves the same as to have_no_content' do
350
+ Capybara.using_wait_time(5) do
351
+ expect(session).to have_content('This is a test')
352
+ start = Time.now
353
+ expect(session).to have_no_content('No such Text')
354
+ to_time = Time.now
355
+ expect(session).not_to have_content('No such Text')
356
+ not_to_time = Time.now
357
+ expect(not_to_time - to_time).to be_within(0.5).of(to_time - start)
358
+ end
359
+ end
348
360
  end
349
361
  end
350
362
 
@@ -357,7 +369,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
357
369
 
358
370
  describe 'have_text matcher' do
359
371
  it 'gives proper description' do
360
- expect(have_text('Text').description).to eq('text "Text"')
372
+ expect(have_text('Text').description).to eq('have text "Text"')
361
373
  end
362
374
 
363
375
  context 'on a string' do
@@ -432,30 +444,30 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
432
444
 
433
445
  context 'on a page or node' do
434
446
  before do
435
- visit('/with_html')
447
+ session.visit('/with_html')
436
448
  end
437
449
 
438
450
  context 'with should' do
439
451
  it 'passes if has_text? returns true' do
440
- expect(page).to have_text('This is a test')
452
+ expect(session).to have_text('This is a test')
441
453
  end
442
454
 
443
455
  it 'passes if has_text? returns true using regexp' do
444
- expect(page).to have_text(/test/)
456
+ expect(session).to have_text(/test/)
445
457
  end
446
458
 
447
459
  it 'can check for all text' do
448
- expect(page).to have_text(:all, 'Some of this text is hidden!')
460
+ expect(session).to have_text(:all, 'Some of this text is hidden!')
449
461
  end
450
462
 
451
463
  it 'can check for visible text' do
452
- expect(page).to have_text(:visible, 'Some of this text is')
453
- expect(page).not_to have_text(:visible, 'Some of this text is hidden!')
464
+ expect(session).to have_text(:visible, 'Some of this text is')
465
+ expect(session).not_to have_text(:visible, 'Some of this text is hidden!')
454
466
  end
455
467
 
456
468
  it 'fails if has_text? returns false' do
457
469
  expect do
458
- expect(page).to have_text('No such Text')
470
+ expect(session).to have_text('No such Text')
459
471
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
460
472
  end
461
473
 
@@ -466,7 +478,7 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
466
478
 
467
479
  it 'fails if has_text? returns false' do
468
480
  expect do
469
- expect(page).to have_text('No such Text')
481
+ expect(session).to have_text('No such Text')
470
482
  end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
471
483
  end
472
484
  end
@@ -474,12 +486,12 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
474
486
 
475
487
  context 'with should_not' do
476
488
  it 'passes if has_no_text? returns true' do
477
- expect(page).not_to have_text('No such Text')
489
+ expect(session).not_to have_text('No such Text')
478
490
  end
479
491
 
480
492
  it 'fails if has_no_text? returns false' do
481
493
  expect do
482
- expect(page).not_to have_text('This is a test')
494
+ expect(session).not_to have_text('This is a test')
483
495
  end.to raise_error(/expected not to find text "This is a test"/)
484
496
  end
485
497
  end
@@ -542,15 +554,15 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
542
554
 
543
555
  context 'on a page or node' do
544
556
  it 'passes if there is such a title' do
545
- visit('/with_js')
546
- expect(page).to have_title('with_js')
557
+ session.visit('/with_js')
558
+ expect(session).to have_title('with_js')
547
559
  end
548
560
 
549
561
  it 'fails if there is no such title' do
550
- visit('/with_js')
562
+ session.visit('/with_js')
551
563
  expect do
552
- expect(page).to have_title('No such title')
553
- end.to raise_error('expected "with_js" to include "No such title"')
564
+ expect(session).to have_title('No such title')
565
+ end.to raise_error(/ to include "No such title"/)
554
566
  end
555
567
 
556
568
  context 'with wait' do
@@ -560,14 +572,14 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
560
572
 
561
573
  it 'waits if wait time is more than timeout' do
562
574
  session.click_link('Change title')
563
- using_wait_time 0 do
575
+ session.using_wait_time 0 do
564
576
  expect(session).to have_title('changed title', wait: 2)
565
577
  end
566
578
  end
567
579
 
568
580
  it "doesn't wait if wait time is less than timeout" do
569
581
  session.click_link('Change title')
570
- using_wait_time 3 do
582
+ session.using_wait_time 3 do
571
583
  expect(session).not_to have_title('changed title', wait: 0)
572
584
  end
573
585
  end
@@ -586,15 +598,15 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
586
598
 
587
599
  context 'on a page or node' do
588
600
  it 'passes if there is such a current path' do
589
- visit('/with_js')
590
- expect(page).to have_current_path('/with_js')
601
+ session.visit('/with_js')
602
+ expect(session).to have_current_path('/with_js')
591
603
  end
592
604
 
593
605
  it 'fails if there is no such current_path' do
594
606
  visit('/with_js')
595
607
  expect do
596
- expect(page).to have_current_path('/not_with_js')
597
- end.to raise_error('expected "/with_js" to equal "/not_with_js"')
608
+ expect(session).to have_current_path('/not_with_js')
609
+ end.to raise_error(%r{to equal "/not_with_js"})
598
610
  end
599
611
 
600
612
  context 'with wait' do
@@ -604,14 +616,14 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
604
616
 
605
617
  it 'waits if wait time is more than timeout' do
606
618
  session.click_link('Change page')
607
- using_wait_time 0 do
619
+ session.using_wait_time 0 do
608
620
  expect(session).to have_current_path('/with_html', wait: 2)
609
621
  end
610
622
  end
611
623
 
612
624
  it "doesn't wait if wait time is less than timeout" do
613
625
  session.click_link('Change page')
614
- using_wait_time 0 do
626
+ session.using_wait_time 0 do
615
627
  expect(session).not_to have_current_path('/with_html')
616
628
  end
617
629
  end
@@ -619,8 +631,8 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
619
631
  end
620
632
 
621
633
  it 'supports compounding' do
622
- visit('/with_html')
623
- expect(page).to have_current_path('/not_with_html').or have_current_path('/with_html')
634
+ session.visit('/with_html')
635
+ expect(session).to have_current_path('/not_with_html').or have_current_path('/with_html')
624
636
  end
625
637
  end
626
638
 
@@ -828,10 +840,10 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
828
840
  end
829
841
 
830
842
  it 'gives proper description when :visible option passed' do
831
- 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
832
844
  expect(have_table('Lovely table', visible: :hidden).description).to eq('have non-visible table "Lovely table"')
833
845
  expect(have_table('Lovely table', visible: :all).description).to eq('have table "Lovely table"')
834
- 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
835
847
  end
836
848
 
837
849
  it 'passes if there is such a table' do
@@ -857,9 +869,9 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
857
869
  session.visit('/with_js')
858
870
  end
859
871
 
860
- context '#and' do
872
+ describe '#and' do
861
873
  it "should run 'concurrently'" do
862
- Capybara.using_wait_time(2) do
874
+ session.using_wait_time(2) do
863
875
  matcher = have_text('this is not there').and have_text('neither is this')
864
876
  expect(Benchmark.realtime do
865
877
  expect do
@@ -899,14 +911,14 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
899
911
  end
900
912
  end
901
913
 
902
- context '#and_then' do
914
+ describe '#and_then' do
903
915
  it 'should run sequentially' do
904
916
  session.click_link('reload-link')
905
917
  expect(el).to have_text('waiting to be reloaded').and_then have_text('has been reloaded')
906
918
  end
907
919
  end
908
920
 
909
- context '#or' do
921
+ describe '#or' do
910
922
  it "should run 'concurrently'" do
911
923
  session.using_wait_time(3) do
912
924
  expect(Benchmark.realtime do
data/spec/rspec_spec.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable RSpec/MultipleDescribes
4
+
3
5
  require 'spec_helper'
4
6
 
5
7
  RSpec.describe 'capybara/rspec' do
@@ -43,7 +45,7 @@ RSpec.describe 'capybara/rspec' do
43
45
  expect(Capybara.current_driver).to eq(:culerity)
44
46
  end
45
47
 
46
- context '#all' do
48
+ describe '#all' do
47
49
  it 'allows access to the Capybara finder' do
48
50
  visit('/with_html')
49
51
  found = all(:css, 'h2') { |element| element[:class] == 'head' }
@@ -57,7 +59,7 @@ RSpec.describe 'capybara/rspec' do
57
59
  end
58
60
  end
59
61
 
60
- context '#within' do
62
+ describe '#within' do
61
63
  it 'allows access to the Capybara scoper' do
62
64
  visit('/with_html')
63
65
  expect do
@@ -82,7 +84,7 @@ RSpec.describe 'capybara/rspec' do
82
84
  end.new
83
85
  end
84
86
 
85
- context '#all' do
87
+ describe '#all' do
86
88
  it 'allows access to the Capybara finder' do
87
89
  test_class_instance.visit('/with_html')
88
90
  expect(test_class_instance.all(:css, 'h2.head').size).to eq(5)
@@ -95,7 +97,7 @@ RSpec.describe 'capybara/rspec' do
95
97
  end
96
98
  end
97
99
 
98
- context '#within' do
100
+ describe '#within' do
99
101
  it 'allows access to the Capybara scoper' do
100
102
  test_class_instance.visit('/with_html')
101
103
  expect do
@@ -143,3 +145,5 @@ feature 'Feature DSL' do
143
145
  expect(page.body).to include('Another World')
144
146
  end
145
147
  end
148
+
149
+ # rubocop:enable RSpec/MultipleDescribes
@@ -3,6 +3,7 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe Capybara do
6
+ include Capybara::RSpecMatchers
6
7
  describe 'Selectors' do
7
8
  let :string do
8
9
  described_class.string <<-STRING
@@ -326,9 +327,23 @@ RSpec.describe Capybara do
326
327
  expect(string.find(:custom_xpath_selector, './/div', class: /dOm WoR/i)[:id]).to eq 'random_words'
327
328
  end
328
329
 
329
- it 'accepts Regexp for CSS base selectors' do
330
+ it 'accepts Regexp for CSS based selectors' do
330
331
  expect(string.find(:custom_css_selector, 'div', class: /random/)[:id]).to eq 'random_words'
331
332
  end
333
+
334
+ it 'accepts Regexp for individual class names for XPath based selectors' do
335
+ expect(string.find(:custom_xpath_selector, './/div', class: [/random/, 'some'])[:id]).to eq 'random_words'
336
+ expect(string.find(:custom_xpath_selector, './/div', class: [/om/, /wor/])[:id]).to eq 'random_words'
337
+ expect { string.find(:custom_xpath_selector, './/div', class: [/not/, /wor/]) }.to raise_error(Capybara::ElementNotFound)
338
+ expect { string.find(:custom_xpath_selector, './/div', class: [/dom wor/]) }.to raise_error(Capybara::ElementNotFound)
339
+ end
340
+
341
+ it 'accepts Regexp for individual class names for CSS based selectors' do
342
+ expect(string.find(:custom_css_selector, 'div', class: [/random/])[:id]).to eq 'random_words'
343
+ expect(string.find(:custom_css_selector, 'div', class: [/om/, /wor/, 'some'])[:id]).to eq 'random_words'
344
+ expect { string.find(:custom_css_selector, 'div', class: [/not/, /wor/]) }.to raise_error(Capybara::ElementNotFound)
345
+ expect { string.find(:custom_css_selector, 'div', class: [/dom wor/]) }.to raise_error(Capybara::ElementNotFound)
346
+ end
332
347
  end
333
348
 
334
349
  context 'with :style option' do
@@ -476,7 +491,7 @@ RSpec.describe Capybara do
476
491
  end
477
492
 
478
493
  describe ':link_or_button selector' do
479
- around(:all) do |example|
494
+ around do |example|
480
495
  described_class.modify_selector(:link_or_button) do
481
496
  expression_filter(:random) { |xpath, _| xpath } # do nothing filter
482
497
  end
@@ -12,45 +12,63 @@ Selenium::WebDriver::Chrome.path = '/usr/bin/google-chrome-beta' if ENV['CI'] &&
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
- # browser_options.add_preference('download.default_directory', Capybara.save_path)
17
+ # Different versions of Chrome/selenium-webdriver require setting differently - jus set them all
18
+ browser_options.add_preference('download.default_directory', Capybara.save_path)
18
19
  browser_options.add_preference(:download, default_directory: Capybara.save_path)
19
20
 
20
21
  Capybara.register_driver :selenium_chrome do |app|
21
- Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options, timeout: 30).tap do |driver|
22
+ version = Capybara::Selenium::Driver.load_selenium
23
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
24
+ driver_options = { browser: :chrome, timeout: 30 }.tap do |opts|
25
+ opts[options_key] = browser_options
26
+ end
27
+
28
+ Capybara::Selenium::Driver.new(app, **driver_options).tap do |driver|
22
29
  # Set download dir for Chrome < 77
23
30
  driver.browser.download_path = Capybara.save_path
24
31
  end
25
32
  end
26
33
 
27
34
  Capybara.register_driver :selenium_chrome_not_clear_storage do |app|
28
- chrome_options = {
29
- browser: :chrome,
30
- options: browser_options
31
- }
32
- Capybara::Selenium::Driver.new(app, chrome_options.merge(clear_local_storage: false, clear_session_storage: false))
35
+ version = Capybara::Selenium::Driver.load_selenium
36
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
37
+ chrome_options = { browser: :chrome, clear_local_storage: false, clear_session_storage: false }.tap do |opts|
38
+ opts[options_key] = browser_options
39
+ end
40
+
41
+ Capybara::Selenium::Driver.new(app, **chrome_options)
33
42
  end
34
43
 
35
44
  Capybara.register_driver :selenium_chrome_not_clear_session_storage do |app|
36
- chrome_options = {
37
- browser: :chrome,
38
- options: browser_options
39
- }
40
- Capybara::Selenium::Driver.new(app, chrome_options.merge(clear_session_storage: false))
45
+ version = Capybara::Selenium::Driver.load_selenium
46
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
47
+ chrome_options = { browser: :chrome, clear_session_storage: false }.tap do |opts|
48
+ opts[options_key] = browser_options
49
+ end
50
+
51
+ Capybara::Selenium::Driver.new(app, **chrome_options)
41
52
  end
42
53
 
43
54
  Capybara.register_driver :selenium_chrome_not_clear_local_storage do |app|
44
- chrome_options = {
45
- browser: :chrome,
46
- options: browser_options
47
- }
48
- Capybara::Selenium::Driver.new(app, chrome_options.merge(clear_local_storage: false))
55
+ version = Capybara::Selenium::Driver.load_selenium
56
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
57
+ chrome_options = { browser: :chrome, clear_local_storage: false }.tap do |opts|
58
+ opts[options_key] = browser_options
59
+ end
60
+ Capybara::Selenium::Driver.new(app, **chrome_options)
49
61
  end
50
62
 
51
63
  Capybara.register_driver :selenium_driver_subclass_with_chrome do |app|
64
+ version = Capybara::Selenium::Driver.load_selenium
65
+ options_key = Capybara::Selenium::Driver::CAPS_VERSION.satisfied_by?(version) ? :capabilities : :options
52
66
  subclass = Class.new(Capybara::Selenium::Driver)
53
- subclass.new(app, browser: :chrome, options: browser_options, timeout: 30)
67
+ chrome_options = { browser: :chrome, timeout: 30 }.tap do |opts|
68
+ opts[options_key] = browser_options
69
+ end
70
+
71
+ subclass.new(app, **chrome_options)
54
72
  end
55
73
 
56
74
  module TestSessions
@@ -67,8 +85,6 @@ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybar
67
85
  skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
68
86
  when /Capybara::Session selenium_chrome Capybara::Window#maximize/
69
87
  pending "Chrome headless doesn't support maximize" if ENV['HEADLESS']
70
- when /details non-summary descendants should be non-visible/
71
- pending 'Chromedriver built-in is_displayed is currently broken' if ENV['W3C'] == 'false'
72
88
  end
73
89
  end
74
90
 
@@ -165,19 +181,26 @@ RSpec.describe 'Capybara::Session with chrome' do
165
181
  end
166
182
 
167
183
  describe 'log access' do
168
- 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
169
189
 
170
190
  it 'does not error getting log types' do
171
- skip if Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0]) < Gem::Version.new('75.0.3770.90')
172
191
  expect do
173
- session.driver.browser.manage.logs.available_types
192
+ logs.available_types
174
193
  end.not_to raise_error
175
194
  end
176
195
 
177
196
  it 'does not error when getting logs' do
178
197
  expect do
179
- session.driver.browser.manage.logs.get(:browser)
198
+ logs.get(:browser)
180
199
  end.not_to raise_error
181
200
  end
182
201
  end
202
+
203
+ def chromedriver_version
204
+ Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0])
205
+ end
183
206
  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
@@ -76,19 +76,26 @@ RSpec.describe 'Capybara::Session with remote Chrome' do
76
76
  end
77
77
 
78
78
  describe 'log access' do
79
- 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
80
84
 
81
85
  it 'does not error when getting log types' do
82
- skip if Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0]) < Gem::Version.new('75.0.3770.90')
83
86
  expect do
84
- session.driver.browser.manage.logs.available_types
87
+ logs.available_types
85
88
  end.not_to raise_error
86
89
  end
87
90
 
88
91
  it 'does not error when getting logs' do
89
92
  expect do
90
- session.driver.browser.manage.logs.get(:browser)
93
+ logs.get(:browser)
91
94
  end.not_to raise_error
92
95
  end
93
96
  end
97
+
98
+ def chromedriver_version
99
+ Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0])
100
+ end
94
101
  end