capybara 3.23.0 → 3.35.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +264 -11
  3. data/README.md +10 -6
  4. data/lib/capybara.rb +20 -8
  5. data/lib/capybara/config.rb +10 -8
  6. data/lib/capybara/cucumber.rb +1 -1
  7. data/lib/capybara/driver/base.rb +4 -0
  8. data/lib/capybara/driver/node.rb +4 -0
  9. data/lib/capybara/dsl.rb +10 -2
  10. data/lib/capybara/helpers.rb +28 -2
  11. data/lib/capybara/minitest.rb +232 -144
  12. data/lib/capybara/minitest/spec.rb +156 -97
  13. data/lib/capybara/node/actions.rb +36 -36
  14. data/lib/capybara/node/base.rb +6 -6
  15. data/lib/capybara/node/document.rb +2 -2
  16. data/lib/capybara/node/document_matchers.rb +3 -3
  17. data/lib/capybara/node/element.rb +77 -33
  18. data/lib/capybara/node/finders.rb +24 -17
  19. data/lib/capybara/node/matchers.rb +79 -64
  20. data/lib/capybara/node/simple.rb +11 -4
  21. data/lib/capybara/queries/ancestor_query.rb +6 -10
  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 +259 -23
  25. data/lib/capybara/queries/sibling_query.rb +5 -11
  26. data/lib/capybara/queries/style_query.rb +1 -1
  27. data/lib/capybara/queries/text_query.rb +13 -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 +42 -6
  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 +29 -0
  35. data/lib/capybara/registrations/servers.rb +9 -2
  36. data/lib/capybara/result.rb +39 -19
  37. data/lib/capybara/rspec.rb +2 -0
  38. data/lib/capybara/rspec/matcher_proxies.rb +5 -5
  39. data/lib/capybara/rspec/matchers.rb +97 -74
  40. data/lib/capybara/rspec/matchers/base.rb +19 -6
  41. data/lib/capybara/rspec/matchers/count_sugar.rb +2 -1
  42. data/lib/capybara/rspec/matchers/have_ancestor.rb +5 -7
  43. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  44. data/lib/capybara/rspec/matchers/have_selector.rb +15 -10
  45. data/lib/capybara/rspec/matchers/have_sibling.rb +4 -7
  46. data/lib/capybara/rspec/matchers/have_text.rb +4 -7
  47. data/lib/capybara/rspec/matchers/have_title.rb +2 -2
  48. data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
  49. data/lib/capybara/rspec/matchers/match_style.rb +7 -2
  50. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  51. data/lib/capybara/selector.rb +46 -19
  52. data/lib/capybara/selector/builders/css_builder.rb +10 -6
  53. data/lib/capybara/selector/builders/xpath_builder.rb +4 -2
  54. data/lib/capybara/selector/css.rb +1 -1
  55. data/lib/capybara/selector/definition.rb +13 -11
  56. data/lib/capybara/selector/definition/button.rb +32 -15
  57. data/lib/capybara/selector/definition/checkbox.rb +2 -2
  58. data/lib/capybara/selector/definition/css.rb +3 -1
  59. data/lib/capybara/selector/definition/datalist_input.rb +2 -2
  60. data/lib/capybara/selector/definition/datalist_option.rb +1 -1
  61. data/lib/capybara/selector/definition/element.rb +3 -2
  62. data/lib/capybara/selector/definition/field.rb +1 -1
  63. data/lib/capybara/selector/definition/file_field.rb +1 -1
  64. data/lib/capybara/selector/definition/fillable_field.rb +2 -2
  65. data/lib/capybara/selector/definition/label.rb +5 -3
  66. data/lib/capybara/selector/definition/link.rb +8 -0
  67. data/lib/capybara/selector/definition/option.rb +1 -1
  68. data/lib/capybara/selector/definition/radio_button.rb +2 -2
  69. data/lib/capybara/selector/definition/select.rb +33 -14
  70. data/lib/capybara/selector/definition/table.rb +6 -3
  71. data/lib/capybara/selector/definition/table_row.rb +2 -2
  72. data/lib/capybara/selector/filter_set.rb +13 -11
  73. data/lib/capybara/selector/filters/base.rb +6 -1
  74. data/lib/capybara/selector/filters/locator_filter.rb +1 -1
  75. data/lib/capybara/selector/regexp_disassembler.rb +7 -0
  76. data/lib/capybara/selector/selector.rb +13 -3
  77. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -1
  78. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -1
  79. data/lib/capybara/selenium/atoms/src/getAttribute.js +1 -1
  80. data/lib/capybara/selenium/atoms/src/isDisplayed.js +10 -10
  81. data/lib/capybara/selenium/driver.rb +86 -24
  82. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +24 -21
  83. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +21 -19
  84. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +17 -1
  85. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +0 -4
  86. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  87. data/lib/capybara/selenium/extensions/find.rb +37 -26
  88. data/lib/capybara/selenium/extensions/html5_drag.rb +55 -11
  89. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  90. data/lib/capybara/selenium/extensions/scroll.rb +8 -10
  91. data/lib/capybara/selenium/logger_suppressor.rb +8 -2
  92. data/lib/capybara/selenium/node.rb +160 -40
  93. data/lib/capybara/selenium/nodes/chrome_node.rb +72 -12
  94. data/lib/capybara/selenium/nodes/edge_node.rb +32 -14
  95. data/lib/capybara/selenium/nodes/firefox_node.rb +28 -32
  96. data/lib/capybara/selenium/nodes/safari_node.rb +5 -29
  97. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  98. data/lib/capybara/selenium/patches/atoms.rb +4 -4
  99. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  100. data/lib/capybara/selenium/patches/logs.rb +32 -7
  101. data/lib/capybara/server.rb +19 -3
  102. data/lib/capybara/server/animation_disabler.rb +8 -3
  103. data/lib/capybara/server/checker.rb +1 -1
  104. data/lib/capybara/server/middleware.rb +22 -10
  105. data/lib/capybara/session.rb +66 -40
  106. data/lib/capybara/session/config.rb +11 -3
  107. data/lib/capybara/session/matchers.rb +11 -11
  108. data/lib/capybara/spec/public/offset.js +6 -0
  109. data/lib/capybara/spec/public/test.js +75 -7
  110. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
  111. data/lib/capybara/spec/session/all_spec.rb +60 -5
  112. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  113. data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
  114. data/lib/capybara/spec/session/check_spec.rb +6 -0
  115. data/lib/capybara/spec/session/click_button_spec.rb +16 -0
  116. data/lib/capybara/spec/session/click_link_or_button_spec.rb +9 -0
  117. data/lib/capybara/spec/session/current_url_spec.rb +11 -1
  118. data/lib/capybara/spec/session/fill_in_spec.rb +29 -0
  119. data/lib/capybara/spec/session/find_spec.rb +55 -0
  120. data/lib/capybara/spec/session/has_ancestor_spec.rb +2 -0
  121. data/lib/capybara/spec/session/has_button_spec.rb +51 -0
  122. data/lib/capybara/spec/session/has_css_spec.rb +26 -4
  123. data/lib/capybara/spec/session/has_current_path_spec.rb +15 -2
  124. data/lib/capybara/spec/session/has_field_spec.rb +34 -0
  125. data/lib/capybara/spec/session/has_select_spec.rb +32 -4
  126. data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
  127. data/lib/capybara/spec/session/has_table_spec.rb +51 -5
  128. data/lib/capybara/spec/session/has_text_spec.rb +30 -0
  129. data/lib/capybara/spec/session/html_spec.rb +1 -1
  130. data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
  131. data/lib/capybara/spec/session/node_spec.rb +394 -9
  132. data/lib/capybara/spec/session/refresh_spec.rb +2 -1
  133. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  134. data/lib/capybara/spec/session/save_page_spec.rb +4 -4
  135. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -15
  136. data/lib/capybara/spec/session/selectors_spec.rb +16 -3
  137. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +1 -1
  138. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +1 -1
  139. data/lib/capybara/spec/session/window/window_spec.rb +8 -8
  140. data/lib/capybara/spec/session/window/windows_spec.rb +1 -1
  141. data/lib/capybara/spec/spec_helper.rb +14 -14
  142. data/lib/capybara/spec/test_app.rb +27 -21
  143. data/lib/capybara/spec/views/form.erb +47 -4
  144. data/lib/capybara/spec/views/offset.erb +32 -0
  145. data/lib/capybara/spec/views/spatial.erb +31 -0
  146. data/lib/capybara/spec/views/with_animation.erb +37 -1
  147. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  148. data/lib/capybara/spec/views/with_html.erb +24 -2
  149. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  150. data/lib/capybara/spec/views/with_js.erb +4 -1
  151. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  152. data/lib/capybara/spec/views/with_sortable_js.erb +1 -1
  153. data/lib/capybara/version.rb +1 -1
  154. data/lib/capybara/window.rb +3 -7
  155. data/spec/basic_node_spec.rb +15 -14
  156. data/spec/capybara_spec.rb +28 -28
  157. data/spec/dsl_spec.rb +16 -3
  158. data/spec/filter_set_spec.rb +5 -5
  159. data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -1
  160. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
  161. data/spec/minitest_spec.rb +3 -2
  162. data/spec/minitest_spec_spec.rb +46 -46
  163. data/spec/rack_test_spec.rb +38 -15
  164. data/spec/regexp_dissassembler_spec.rb +52 -38
  165. data/spec/result_spec.rb +43 -32
  166. data/spec/rspec/features_spec.rb +4 -1
  167. data/spec/rspec/scenarios_spec.rb +4 -0
  168. data/spec/rspec/shared_spec_matchers.rb +68 -56
  169. data/spec/rspec_spec.rb +9 -5
  170. data/spec/selector_spec.rb +32 -17
  171. data/spec/selenium_spec_chrome.rb +78 -11
  172. data/spec/selenium_spec_chrome_remote.rb +23 -6
  173. data/spec/selenium_spec_edge.rb +15 -12
  174. data/spec/selenium_spec_firefox.rb +24 -19
  175. data/spec/selenium_spec_firefox_remote.rb +0 -8
  176. data/spec/selenium_spec_ie.rb +1 -6
  177. data/spec/server_spec.rb +106 -44
  178. data/spec/session_spec.rb +5 -5
  179. data/spec/shared_selenium_node.rb +56 -2
  180. data/spec/shared_selenium_session.rb +122 -15
  181. data/spec/spec_helper.rb +2 -2
  182. metadata +63 -17
  183. data/lib/capybara/spec/session/source_spec.rb +0 -0
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Note: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
3
+ # NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
4
4
  # because of the methods being tested. In tests using Capybara this type of behavior should be implemented
5
5
  # using Capybara provided assertions with builtin waiting behavior.
6
6
 
@@ -25,6 +25,7 @@ Capybara::SpecHelper.spec '#refresh' do
25
25
  @session.visit('/form')
26
26
  @session.select('Sweden', from: 'form_region')
27
27
  @session.click_button('awesome')
28
+ sleep 2
28
29
  expect do
29
30
  @session.refresh
30
31
  sleep 2
@@ -15,7 +15,7 @@ Capybara::SpecHelper.spec '#save_and_open_screenshot' do
15
15
  @session.save_and_open_screenshot
16
16
 
17
17
  expect(@session.driver).to have_received(:save_screenshot)
18
- .with(expected_file_regex, {})
18
+ .with(expected_file_regex, any_args)
19
19
  expect(Launchy).to have_received(:open).with(expected_file_regex)
20
20
  end
21
21
 
@@ -27,7 +27,7 @@ Capybara::SpecHelper.spec '#save_and_open_screenshot' do
27
27
  @session.save_and_open_screenshot(custom_path)
28
28
 
29
29
  expect(@session.driver).to have_received(:save_screenshot)
30
- .with(/#{custom_path}$/, {})
30
+ .with(/#{custom_path}$/, any_args)
31
31
  expect(Launchy).to have_received(:open).with(/#{custom_path}$/)
32
32
  end
33
33
 
@@ -31,7 +31,7 @@ Capybara::SpecHelper.spec '#save_page' do
31
31
  it 'can store files in a specified directory' do
32
32
  Capybara.save_path = alternative_path
33
33
  @session.save_page
34
- path = Dir.glob(alternative_path + '/capybara-*.html').first
34
+ path = Dir.glob("#{alternative_path}/capybara-*.html").first
35
35
  expect(File.read(path)).to include('Another World')
36
36
  end
37
37
 
@@ -43,14 +43,14 @@ Capybara::SpecHelper.spec '#save_page' do
43
43
  it 'can store files in a specified directory with a given filename' do
44
44
  Capybara.save_path = alternative_path
45
45
  @session.save_page('capybara-001133.html')
46
- path = alternative_path + '/capybara-001133.html'
46
+ path = "#{alternative_path}/capybara-001133.html"
47
47
  expect(File.read(path)).to include('Another World')
48
48
  end
49
49
 
50
50
  it 'can store files in a specified directory with a given relative filename' do
51
51
  Capybara.save_path = alternative_path
52
52
  @session.save_page('tmp/capybara-001144.html')
53
- path = alternative_path + '/tmp/capybara-001144.html'
53
+ path = "#{alternative_path}/tmp/capybara-001144.html"
54
54
  expect(File.read(path)).to include('Another World')
55
55
  end
56
56
 
@@ -63,7 +63,7 @@ Capybara::SpecHelper.spec '#save_page' do
63
63
  it 'returns an absolute path in given directory' do
64
64
  Capybara.save_path = alternative_path
65
65
  result = @session.save_page
66
- path = File.expand_path(Dir.glob(alternative_path + '/capybara-*.html').first, alternative_path)
66
+ path = File.expand_path(Dir.glob("#{alternative_path}/capybara-*.html").first, alternative_path)
67
67
  expect(result).to eq(path)
68
68
  end
69
69
 
@@ -13,24 +13,13 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
13
13
  FileUtils.rm_rf alternative_path
14
14
  end
15
15
 
16
- around do |example|
17
- # Workaround RSpec Issue - https://github.com/rspec/rspec-support/issues/374
18
- if respond_to?(:without_partial_double_verification)
19
- without_partial_double_verification do
20
- example.run
21
- end
22
- else
23
- example.run
24
- end
25
- end
26
-
27
16
  it 'generates sensible filename' do
28
17
  allow(@session.driver).to receive(:save_screenshot)
29
18
 
30
19
  @session.save_screenshot
31
20
 
32
21
  regexp = Regexp.new(File.join(Dir.pwd, 'capybara-\d+\.png'))
33
- expect(@session.driver).to have_received(:save_screenshot).with(regexp, {})
22
+ expect(@session.driver).to have_received(:save_screenshot).with(regexp, any_args)
34
23
  end
35
24
 
36
25
  it 'allows to specify another path' do
@@ -39,7 +28,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
39
28
  custom_path = 'screenshots/1.png'
40
29
  @session.save_screenshot(custom_path)
41
30
 
42
- expect(@session.driver).to have_received(:save_screenshot).with(/#{custom_path}$/, {})
31
+ expect(@session.driver).to have_received(:save_screenshot).with(/#{custom_path}$/, any_args)
43
32
  end
44
33
 
45
34
  context 'with Capybara.save_path' do
@@ -50,7 +39,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
50
39
  @session.save_screenshot
51
40
 
52
41
  regexp = Regexp.new(File.join(alternative_path, 'capybara-\d+\.png'))
53
- expect(@session.driver).to have_received(:save_screenshot).with(regexp, {})
42
+ expect(@session.driver).to have_received(:save_screenshot).with(regexp, any_args)
54
43
  end
55
44
 
56
45
  it 'relative paths are relative to save_path' do
@@ -60,7 +49,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
60
49
  custom_path = 'screenshots/2.png'
61
50
  @session.save_screenshot(custom_path)
62
51
 
63
- expect(@session.driver).to have_received(:save_screenshot).with(File.expand_path(custom_path, alternative_path), {})
52
+ expect(@session.driver).to have_received(:save_screenshot).with(File.expand_path(custom_path, alternative_path), any_args)
64
53
  end
65
54
  end
66
55
  end
@@ -31,6 +31,11 @@ Capybara::SpecHelper.spec Capybara::Selector do
31
31
  expect(@session.find(:label, for: input).text).to eq 'Nested Label'
32
32
  end
33
33
 
34
+ it 'finds a label from nested input using :for filter with element when no id on label' do
35
+ input = @session.find(:css, '#wrapper_label').find(:css, 'input')
36
+ expect(@session.find(:label, for: input).text).to eq 'Wrapper Label'
37
+ end
38
+
34
39
  it 'finds the label for an non-nested element when using :for filter' do
35
40
  select = @session.find(:id, 'form_other_title')
36
41
  expect(@session.find(:label, for: select)['for']).to eq 'form_other_title'
@@ -62,14 +67,22 @@ Capybara::SpecHelper.spec Capybara::Selector do
62
67
  end
63
68
  end
64
69
 
65
- it 'can find specifically by name' do
70
+ it 'can find specifically by name string' do
66
71
  expect(@session.find(:field, name: 'form[other_title]')['id']).to eq 'form_other_title'
67
72
  end
68
73
 
69
- it 'can find specifically by placeholder' do
74
+ it 'can find specifically by name regex' do
75
+ expect(@session.find(:field, name: /form\[other_.*\]/)['id']).to eq 'form_other_title'
76
+ end
77
+
78
+ it 'can find specifically by placeholder string' do
70
79
  expect(@session.find(:field, placeholder: 'FirstName')['id']).to eq 'form_first_name'
71
80
  end
72
81
 
82
+ it 'can find specifically by placeholder regex' do
83
+ expect(@session.find(:field, placeholder: /FirstN.*/)['id']).to eq 'form_first_name'
84
+ end
85
+
73
86
  it 'can find by type' do
74
87
  expect(@session.find(:field, 'Confusion', type: 'checkbox')['id']).to eq 'confusion_checkbox'
75
88
  expect(@session.find(:field, 'Confusion', type: 'text')['id']).to eq 'confusion_text'
@@ -79,7 +92,7 @@ Capybara::SpecHelper.spec Capybara::Selector do
79
92
  it 'can find by class' do
80
93
  expect(@session.find(:field, class: 'confusion-checkbox')['id']).to eq 'confusion_checkbox'
81
94
  expect(@session).to have_selector(:field, class: 'confusion', count: 3)
82
- expect(@session.find(:field, class: ['confusion', 'confusion-textarea'])['id']).to eq 'confusion_textarea'
95
+ expect(@session.find(:field, class: %w[confusion confusion-textarea])['id']).to eq 'confusion_textarea'
83
96
  end
84
97
  end
85
98
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Note: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
3
+ # NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
4
4
  # because of the methods being tested. In tests using Capybara this type of behavior should be implemented
5
5
  # using Capybara provided assertions with builtin waiting behavior.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Note: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
3
+ # NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
4
4
  # because of the methods being tested. In tests using Capybara this type of behavior should be implemented
5
5
  # using Capybara provided assertions with builtin waiting behavior.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Note: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
3
+ # NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
4
4
  # because of the methods being tested. In tests using Capybara this type of behavior should be implemented
5
5
  # using Capybara provided assertions with builtin waiting behavior.
6
6
 
@@ -141,12 +141,12 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
141
141
  end
142
142
 
143
143
  describe '#maximize' do
144
- before do
145
- @initial_size = @session.current_window.size
144
+ let! :initial_size do
145
+ @session.current_window.size
146
146
  end
147
147
 
148
148
  after do
149
- @session.current_window.resize_to(*@initial_size)
149
+ @session.current_window.resize_to(*initial_size)
150
150
  sleep 0.5
151
151
  end
152
152
 
@@ -176,7 +176,7 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
176
176
 
177
177
  expect(@session.current_window).to eq(orig_window)
178
178
  # Maximizing the browser affects all tabs so this may not be valid in real browsers
179
- # expect(@session.current_window.size).to eq(@initial_size)
179
+ # expect(@session.current_window.size).to eq(initial_size)
180
180
 
181
181
  ow_width, ow_height = other_window.size
182
182
  expect(ow_width).to be > 400
@@ -185,12 +185,12 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
185
185
  end
186
186
 
187
187
  describe '#fullscreen' do
188
- before do
189
- @initial_size = @session.current_window.size
188
+ let! :initial_size do
189
+ @session.current_window.size
190
190
  end
191
191
 
192
192
  after do
193
- @session.current_window.resize_to(*@initial_size)
193
+ @session.current_window.resize_to(*initial_size)
194
194
  sleep 1
195
195
  end
196
196
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Note: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
3
+ # NOTE: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
4
4
  # because of the methods being tested. In tests using Capybara this type of behavior should be implemented
5
5
  # using Capybara provided assertions with builtin waiting behavior.
6
6
 
@@ -30,12 +30,14 @@ module Capybara
30
30
  Capybara.visible_text_only = false
31
31
  Capybara.match = :smart
32
32
  Capybara.enable_aria_label = false
33
+ Capybara.enable_aria_role = false
33
34
  Capybara.default_set_options = {}
34
35
  Capybara.disable_animation = false
35
36
  Capybara.test_id = nil
36
37
  Capybara.predicates_wait = true
37
38
  Capybara.default_normalize_ws = false
38
39
  Capybara.allow_gumbo = true
40
+ Capybara.w3c_click_offset = false
39
41
  reset_threadsafe
40
42
  end
41
43
 
@@ -56,10 +58,10 @@ module Capybara
56
58
 
57
59
  def run_specs(session, name, **options, &filter_block)
58
60
  specs = @specs
59
- RSpec.describe Capybara::Session, name, options do # rubocop:disable RSpec/EmptyExampleGroup
61
+ RSpec.describe Capybara::Session, name, options do
60
62
  include Capybara::SpecHelper
61
63
  include Capybara::RSpecMatchers
62
- # rubocop:disable RSpec/ScatteredSetup
64
+
63
65
  before do |example|
64
66
  @session = session
65
67
  instance_exec(example, &filter_block) if filter_block
@@ -70,28 +72,28 @@ module Capybara
70
72
  end
71
73
 
72
74
  before :each, psc: true do
73
- SpecHelper.reset_threadsafe(true, session)
75
+ SpecHelper.reset_threadsafe(bool: true, session: session)
74
76
  end
75
77
 
76
78
  after psc: true do
77
- SpecHelper.reset_threadsafe(false, session)
79
+ SpecHelper.reset_threadsafe(session: session)
78
80
  end
79
81
 
80
82
  before :each, :exact_false do
81
83
  Capybara.exact = false
82
84
  end
83
- # rubocop:enable RSpec/ScatteredSetup
84
85
 
85
86
  specs.each do |spec_name, spec_options, block|
86
- describe spec_name, *spec_options do # rubocop:disable RSpec/EmptyExampleGroup
87
+ describe spec_name, *spec_options do
87
88
  class_eval(&block)
88
89
  end
89
90
  end
90
91
  end
91
92
  end
92
93
 
93
- def reset_threadsafe(bool = false, session = nil)
94
- Capybara::Session.class_variable_set(:@@instance_created, false) # Work around limit on when threadsafe can be changed
94
+ def reset_threadsafe(bool: false, session: nil)
95
+ # Work around limit on when threadsafe can be changed
96
+ Capybara::Session.class_variable_set(:@@instance_created, false) # rubocop:disable Style/ClassVars
95
97
  Capybara.threadsafe = bool
96
98
  session = session.current_session if session.respond_to?(:current_session)
97
99
  session&.instance_variable_set(:@config, nil)
@@ -107,11 +109,9 @@ module Capybara
107
109
  stream.reopen(old_stream)
108
110
  end
109
111
 
110
- def quietly
111
- silence_stream(STDOUT) do
112
- silence_stream(STDERR) do
113
- yield
114
- end
112
+ def quietly(&block)
113
+ silence_stream($stdout) do
114
+ silence_stream($stderr, &block)
115
115
  end
116
116
  end
117
117
 
@@ -131,4 +131,4 @@ module Capybara
131
131
  end
132
132
  end
133
133
 
134
- Dir[File.dirname(__FILE__) + '/session/**/*.rb'].each { |file| require_relative file }
134
+ Dir["#{File.dirname(__FILE__)}/session/**/*.rb"].each { |file| require_relative file }
@@ -7,8 +7,10 @@ require 'yaml'
7
7
 
8
8
  class TestApp < Sinatra::Base
9
9
  class TestAppError < Exception; end # rubocop:disable Lint/InheritException
10
+
10
11
  class TestAppOtherError < Exception # rubocop:disable Lint/InheritException
11
12
  def initialize(string1, msg)
13
+ super()
12
14
  @something = string1
13
15
  @message = msg
14
16
  end
@@ -33,6 +35,10 @@ class TestApp < Sinatra::Base
33
35
  redirect '/redirect_again'
34
36
  end
35
37
 
38
+ get '/redirect_with_fragment' do
39
+ redirect '/landed#with_fragment'
40
+ end
41
+
36
42
  get '/redirect_again' do
37
43
  redirect '/landed'
38
44
  end
@@ -85,11 +91,11 @@ class TestApp < Sinatra::Base
85
91
  end
86
92
 
87
93
  get '/form/get' do
88
- '<pre id="results">' + params[:form].to_yaml + '</pre>'
94
+ %(<pre id="results">#{params[:form].to_yaml}</pre>)
89
95
  end
90
96
 
91
97
  post '/relative' do
92
- '<pre id="results">' + params[:form].to_yaml + '</pre>'
98
+ %(<pre id="results">#{params[:form].to_yaml}</pre>)
93
99
  end
94
100
 
95
101
  get '/favicon.ico' do
@@ -176,7 +182,7 @@ class TestApp < Sinatra::Base
176
182
 
177
183
  post '/form' do
178
184
  self.class.form_post_count += 1
179
- '<pre id="results">' + params[:form].merge('post_count' => self.class.form_post_count).to_yaml + '</pre>'
185
+ %(<pre id="results">#{params[:form].merge('post_count' => self.class.form_post_count).to_yaml}</pre>)
180
186
  end
181
187
 
182
188
  post '/upload_empty' do
@@ -188,28 +194,28 @@ class TestApp < Sinatra::Base
188
194
  end
189
195
 
190
196
  post '/upload' do
191
- begin
192
- buffer = []
193
- buffer << "Content-type: #{params.dig(:form, :document, :type)}"
194
- buffer << "File content: #{params.dig(:form, :document, :tempfile).read}"
195
- buffer.join(' | ')
196
- rescue StandardError
197
- 'No file uploaded'
198
- end
197
+ buffer = []
198
+ buffer << "Content-type: #{params.dig(:form, :document, :type)}"
199
+ buffer << "File content: #{params.dig(:form, :document, :tempfile).read}"
200
+ buffer.join(' | ')
201
+ rescue StandardError
202
+ 'No file uploaded'
199
203
  end
200
204
 
201
205
  post '/upload_multiple' do
202
- begin
203
- docs = params.dig(:form, :multiple_documents)
204
- buffer = [docs.size.to_s]
205
- docs.each do |doc|
206
- buffer << "Content-type: #{doc[:type]}"
207
- buffer << "File content: #{doc[:tempfile].read}"
208
- end
209
- buffer.join(' | ')
210
- rescue StandardError
211
- 'No files uploaded'
206
+ docs = params.dig(:form, :multiple_documents)
207
+ buffer = [docs.size.to_s]
208
+ docs.each do |doc|
209
+ buffer << "Content-type: #{doc[:type]}"
210
+ buffer << "File content: #{doc[:tempfile].read}"
212
211
  end
212
+ buffer.join(' | ')
213
+ rescue StandardError
214
+ 'No files uploaded'
215
+ end
216
+
217
+ get '/apple-touch-icon-precomposed.png' do
218
+ halt(404)
213
219
  end
214
220
 
215
221
  class << self
@@ -1,7 +1,7 @@
1
1
 
2
2
  <h1>Form</h1>
3
3
 
4
- <form action="/form" method="post">
4
+ <form action="/form" method="post" novalidate>
5
5
 
6
6
  <p>
7
7
  <label for="form_title">Title</label>
@@ -11,7 +11,7 @@
11
11
  <option>Miss</option>
12
12
  <option disabled="disabled">Other</option>
13
13
  </select>
14
- </p>
14
+ </p>
15
15
 
16
16
  <p>
17
17
  <label for="customer_name">Customer Name
@@ -62,6 +62,11 @@
62
62
  <input type="text" name="form[name]" value="John Smith" id="form_name"/>
63
63
  </p>
64
64
 
65
+ <p>
66
+ <label for="form_age">Age</label>
67
+ <input type="range" name="form[age]" value="18" min="13" max="100" step="0.5" id="form_age"/>
68
+ </p>
69
+
65
70
  <p>
66
71
  <label for="form_schmooo">Schmooo</label>
67
72
  <input type="schmooo" name="form[schmooo]" value="This is Schmooo!" id="form_schmooo"/>
@@ -135,7 +140,11 @@
135
140
 
136
141
  <p>
137
142
  <label for="form_zipcode">Zipcode</label>
138
- <input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" />
143
+ <input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" pattern="[0-9]{5,9}" />
144
+ </p>
145
+
146
+ <p>
147
+ <input maxlength="35" id="long_length" />
139
148
  </p>
140
149
 
141
150
  <p>
@@ -440,14 +449,25 @@ New line after and before textarea tag
440
449
 
441
450
  <p>
442
451
  <input type="button" aria-label="Aria button" name="form[fresh]" id="fresh_btn" value="i am fresh"/>
443
- <input type="submit" name="form[awesome]" id="awe123" title="What an Awesome Button" value="awesome"/>
452
+ <input type="submit" name="form[awesome]" id="awe123" data-test-id="test_id_button" title="What an Awesome Button" value="awesome"/>
444
453
  <input type="submit" name="form[crappy]" id="crap321" value="crappy"/>
445
454
  <input type="image" name="form[okay]" id="okay556" title="Okay 556 Image" value="okay" alt="oh hai thar"/>
446
455
  <button type="submit" id="click_me_123" title="Click Title button" value="click_me">Click me!</button>
447
456
  <button type="submit" name="form[no_value]">No Value!</button>
448
457
  <button id="no_type">No Type!</button>
449
458
  <button><img alt="A horse eating hay"/></button>
459
+ <button id="button_with_label"></button>
460
+ <label for="button_with_label">button with label element</label>
461
+ <label>
462
+ button within label element
463
+ <button></button>
464
+ </label>
465
+ <label>
466
+ role=button within label element
467
+ <span role="button">with other text</span>
468
+ </label>
450
469
  <input type="button" disabled="disabled" value="Disabled button"/>
470
+ <span role="button">ARIA button</span>
451
471
  </p>
452
472
 
453
473
  <p>
@@ -460,6 +480,11 @@ New line after and before textarea tag
460
480
  <input id="readonly" name="form[readonly_test]" readonly/>
461
481
  <input id="not_readonly" name="form[readonly_test]" />
462
482
  </p>
483
+
484
+ <p>
485
+ <input id="required" name="form[required]" required />
486
+ <input id="length" name="form[length]" minlength="4" maxlength="4" />
487
+ </p>
463
488
  </form>
464
489
 
465
490
  <input type="text" name="form[outside_input]" value="outside_input" form="form1"/>
@@ -469,6 +494,11 @@ New line after and before textarea tag
469
494
  <input type="text" name="nested_label" id="nested_label"/>
470
495
  </label>
471
496
 
497
+ <label id="wrapper_label">
498
+ Wrapper Label
499
+ <input type="checkbox"/>
500
+ </label>
501
+
472
502
  <form id="form1" action="/form" method="post">
473
503
  <input type="text" name="form[which_form]" value="form1" id="form_which_form"/>
474
504
  <input type="text" name="form[for_form2]" value="for_form2" form="form2"/>
@@ -502,6 +532,7 @@ New line after and before textarea tag
502
532
 
503
533
  <p>
504
534
  <input type="submit" name="form[mediocre]" id="mediocre" value="med" aria-label="Mediocre Button"/>
535
+ <input type="submit" formaction="/form/get?bar=foo" id="mediocre2" value="med2"/>
505
536
  <p>
506
537
  </form>
507
538
 
@@ -663,3 +694,15 @@ New line after and before textarea tag
663
694
  <p>
664
695
  <input id="special" {custom}="abcdef" value="custom attribute"/>
665
696
  </p>
697
+
698
+
699
+ <label for="multi_label_checkbox">
700
+ Label to click
701
+ </label>
702
+ <div>Something random that justifies the usage of a separate label</div>
703
+ <label>
704
+ <div>
705
+ <input type="checkbox" id="multi_label_checkbox" style="display: none"/>
706
+ <div>Visual representation of the checkbox</div>
707
+ </div>
708
+ </label>