capybara 3.8.1 → 3.33.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (242) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/History.md +465 -0
  4. data/License.txt +1 -1
  5. data/README.md +58 -57
  6. data/lib/capybara/config.rb +10 -4
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/base.rb +2 -2
  9. data/lib/capybara/driver/node.rb +26 -5
  10. data/lib/capybara/dsl.rb +12 -4
  11. data/lib/capybara/helpers.rb +8 -4
  12. data/lib/capybara/minitest/spec.rb +162 -85
  13. data/lib/capybara/minitest.rb +248 -148
  14. data/lib/capybara/node/actions.rb +149 -96
  15. data/lib/capybara/node/base.rb +27 -10
  16. data/lib/capybara/node/document.rb +12 -0
  17. data/lib/capybara/node/document_matchers.rb +9 -5
  18. data/lib/capybara/node/element.rb +254 -109
  19. data/lib/capybara/node/finders.rb +83 -76
  20. data/lib/capybara/node/matchers.rb +279 -141
  21. data/lib/capybara/node/simple.rb +25 -6
  22. data/lib/capybara/queries/ancestor_query.rb +5 -7
  23. data/lib/capybara/queries/base_query.rb +11 -5
  24. data/lib/capybara/queries/current_path_query.rb +3 -3
  25. data/lib/capybara/queries/match_query.rb +1 -0
  26. data/lib/capybara/queries/selector_query.rb +467 -103
  27. data/lib/capybara/queries/sibling_query.rb +5 -4
  28. data/lib/capybara/queries/style_query.rb +6 -2
  29. data/lib/capybara/queries/text_query.rb +17 -3
  30. data/lib/capybara/queries/title_query.rb +2 -2
  31. data/lib/capybara/rack_test/browser.rb +22 -15
  32. data/lib/capybara/rack_test/driver.rb +10 -1
  33. data/lib/capybara/rack_test/errors.rb +6 -0
  34. data/lib/capybara/rack_test/form.rb +33 -28
  35. data/lib/capybara/rack_test/node.rb +74 -6
  36. data/lib/capybara/registration_container.rb +44 -0
  37. data/lib/capybara/registrations/drivers.rb +36 -0
  38. data/lib/capybara/registrations/patches/puma_ssl.rb +27 -0
  39. data/lib/capybara/registrations/servers.rb +44 -0
  40. data/lib/capybara/result.rb +55 -23
  41. data/lib/capybara/rspec/features.rb +4 -4
  42. data/lib/capybara/rspec/matcher_proxies.rb +36 -15
  43. data/lib/capybara/rspec/matchers/base.rb +111 -0
  44. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  45. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  46. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  47. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  48. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  49. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  50. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  51. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  52. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  53. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  54. data/lib/capybara/rspec/matchers/match_style.rb +38 -0
  55. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  56. data/lib/capybara/rspec/matchers.rb +117 -311
  57. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  58. data/lib/capybara/selector/builders/xpath_builder.rb +69 -0
  59. data/lib/capybara/selector/css.rb +17 -15
  60. data/lib/capybara/selector/definition/button.rb +52 -0
  61. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  62. data/lib/capybara/selector/definition/css.rb +10 -0
  63. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  64. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  65. data/lib/capybara/selector/definition/element.rb +27 -0
  66. data/lib/capybara/selector/definition/field.rb +40 -0
  67. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  68. data/lib/capybara/selector/definition/file_field.rb +13 -0
  69. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  70. data/lib/capybara/selector/definition/frame.rb +17 -0
  71. data/lib/capybara/selector/definition/id.rb +6 -0
  72. data/lib/capybara/selector/definition/label.rb +62 -0
  73. data/lib/capybara/selector/definition/link.rb +54 -0
  74. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  75. data/lib/capybara/selector/definition/option.rb +27 -0
  76. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  77. data/lib/capybara/selector/definition/select.rb +81 -0
  78. data/lib/capybara/selector/definition/table.rb +109 -0
  79. data/lib/capybara/selector/definition/table_row.rb +21 -0
  80. data/lib/capybara/selector/definition/xpath.rb +5 -0
  81. data/lib/capybara/selector/definition.rb +277 -0
  82. data/lib/capybara/selector/filter.rb +1 -0
  83. data/lib/capybara/selector/filter_set.rb +26 -19
  84. data/lib/capybara/selector/filters/base.rb +24 -5
  85. data/lib/capybara/selector/filters/expression_filter.rb +3 -3
  86. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  87. data/lib/capybara/selector/filters/node_filter.rb +16 -2
  88. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  89. data/lib/capybara/selector/selector.rb +73 -367
  90. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  91. data/lib/capybara/selector.rb +221 -480
  92. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  93. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  94. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  95. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  96. data/lib/capybara/selenium/driver.rb +203 -86
  97. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +88 -14
  98. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
  99. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -0
  100. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  101. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  102. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  103. data/lib/capybara/selenium/extensions/find.rb +110 -0
  104. data/lib/capybara/selenium/extensions/html5_drag.rb +191 -22
  105. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  106. data/lib/capybara/selenium/extensions/scroll.rb +78 -0
  107. data/lib/capybara/selenium/logger_suppressor.rb +34 -0
  108. data/lib/capybara/selenium/node.rb +298 -93
  109. data/lib/capybara/selenium/nodes/chrome_node.rb +100 -8
  110. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  111. data/lib/capybara/selenium/nodes/firefox_node.rb +131 -0
  112. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  113. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  114. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  115. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  116. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  117. data/lib/capybara/selenium/patches/logs.rb +45 -0
  118. data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -3
  119. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  120. data/lib/capybara/server/animation_disabler.rb +4 -3
  121. data/lib/capybara/server/checker.rb +6 -2
  122. data/lib/capybara/server/middleware.rb +23 -13
  123. data/lib/capybara/server.rb +30 -7
  124. data/lib/capybara/session/config.rb +14 -10
  125. data/lib/capybara/session/matchers.rb +11 -7
  126. data/lib/capybara/session.rb +152 -111
  127. data/lib/capybara/spec/public/offset.js +6 -0
  128. data/lib/capybara/spec/public/test.js +101 -10
  129. data/lib/capybara/spec/session/all_spec.rb +96 -6
  130. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  131. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +29 -0
  132. data/lib/capybara/spec/session/assert_current_path_spec.rb +5 -2
  133. data/lib/capybara/spec/session/assert_selector_spec.rb +0 -10
  134. data/lib/capybara/spec/session/assert_style_spec.rb +4 -4
  135. data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
  136. data/lib/capybara/spec/session/attach_file_spec.rb +63 -36
  137. data/lib/capybara/spec/session/check_spec.rb +10 -4
  138. data/lib/capybara/spec/session/choose_spec.rb +8 -2
  139. data/lib/capybara/spec/session/click_button_spec.rb +117 -61
  140. data/lib/capybara/spec/session/click_link_or_button_spec.rb +16 -0
  141. data/lib/capybara/spec/session/click_link_spec.rb +17 -6
  142. data/lib/capybara/spec/session/element/matches_selector_spec.rb +40 -39
  143. data/lib/capybara/spec/session/evaluate_script_spec.rb +13 -0
  144. data/lib/capybara/spec/session/execute_script_spec.rb +1 -0
  145. data/lib/capybara/spec/session/fill_in_spec.rb +47 -6
  146. data/lib/capybara/spec/session/find_field_spec.rb +1 -1
  147. data/lib/capybara/spec/session/find_spec.rb +74 -4
  148. data/lib/capybara/spec/session/first_spec.rb +1 -1
  149. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +13 -1
  150. data/lib/capybara/spec/session/frame/within_frame_spec.rb +12 -1
  151. data/lib/capybara/spec/session/has_all_selectors_spec.rb +1 -1
  152. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  153. data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
  154. data/lib/capybara/spec/session/has_button_spec.rb +16 -0
  155. data/lib/capybara/spec/session/has_css_spec.rb +122 -12
  156. data/lib/capybara/spec/session/has_current_path_spec.rb +6 -4
  157. data/lib/capybara/spec/session/has_field_spec.rb +55 -0
  158. data/lib/capybara/spec/session/has_select_spec.rb +34 -6
  159. data/lib/capybara/spec/session/has_selector_spec.rb +11 -4
  160. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  161. data/lib/capybara/spec/session/has_table_spec.rb +166 -0
  162. data/lib/capybara/spec/session/has_text_spec.rb +48 -1
  163. data/lib/capybara/spec/session/has_xpath_spec.rb +17 -0
  164. data/lib/capybara/spec/session/html_spec.rb +7 -0
  165. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  166. data/lib/capybara/spec/session/node_spec.rb +643 -18
  167. data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
  168. data/lib/capybara/spec/session/refresh_spec.rb +4 -0
  169. data/lib/capybara/spec/session/reset_session_spec.rb +23 -8
  170. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  171. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
  172. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  173. data/lib/capybara/spec/session/select_spec.rb +10 -10
  174. data/lib/capybara/spec/session/selectors_spec.rb +36 -5
  175. data/lib/capybara/spec/session/uncheck_spec.rb +2 -2
  176. data/lib/capybara/spec/session/unselect_spec.rb +1 -1
  177. data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
  178. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +4 -0
  179. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +4 -0
  180. data/lib/capybara/spec/session/window/window_spec.rb +59 -58
  181. data/lib/capybara/spec/session/window/windows_spec.rb +4 -0
  182. data/lib/capybara/spec/session/within_spec.rb +23 -0
  183. data/lib/capybara/spec/spec_helper.rb +16 -6
  184. data/lib/capybara/spec/test_app.rb +28 -23
  185. data/lib/capybara/spec/views/animated.erb +49 -0
  186. data/lib/capybara/spec/views/form.erb +48 -7
  187. data/lib/capybara/spec/views/frame_child.erb +3 -2
  188. data/lib/capybara/spec/views/frame_one.erb +1 -0
  189. data/lib/capybara/spec/views/obscured.erb +47 -0
  190. data/lib/capybara/spec/views/offset.erb +32 -0
  191. data/lib/capybara/spec/views/react.erb +45 -0
  192. data/lib/capybara/spec/views/scroll.erb +20 -0
  193. data/lib/capybara/spec/views/spatial.erb +31 -0
  194. data/lib/capybara/spec/views/tables.erb +67 -0
  195. data/lib/capybara/spec/views/with_animation.erb +29 -1
  196. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  197. data/lib/capybara/spec/views/with_hover.erb +1 -0
  198. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  199. data/lib/capybara/spec/views/with_html.erb +32 -6
  200. data/lib/capybara/spec/views/with_js.erb +3 -1
  201. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  202. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  203. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  204. data/lib/capybara/version.rb +1 -1
  205. data/lib/capybara/window.rb +11 -11
  206. data/lib/capybara.rb +118 -111
  207. data/spec/basic_node_spec.rb +14 -3
  208. data/spec/capybara_spec.rb +29 -29
  209. data/spec/css_builder_spec.rb +101 -0
  210. data/spec/dsl_spec.rb +46 -21
  211. data/spec/filter_set_spec.rb +5 -5
  212. data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -1
  213. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
  214. data/spec/minitest_spec.rb +18 -4
  215. data/spec/minitest_spec_spec.rb +59 -44
  216. data/spec/rack_test_spec.rb +117 -89
  217. data/spec/regexp_dissassembler_spec.rb +250 -0
  218. data/spec/result_spec.rb +51 -49
  219. data/spec/rspec/features_spec.rb +3 -0
  220. data/spec/rspec/shared_spec_matchers.rb +112 -97
  221. data/spec/rspec_spec.rb +35 -17
  222. data/spec/sauce_spec_chrome.rb +43 -0
  223. data/spec/selector_spec.rb +244 -28
  224. data/spec/selenium_spec_chrome.rb +125 -54
  225. data/spec/selenium_spec_chrome_remote.rb +26 -12
  226. data/spec/selenium_spec_edge.rb +23 -8
  227. data/spec/selenium_spec_firefox.rb +208 -0
  228. data/spec/selenium_spec_firefox_remote.rb +15 -18
  229. data/spec/selenium_spec_ie.rb +82 -13
  230. data/spec/selenium_spec_safari.rb +148 -0
  231. data/spec/server_spec.rb +118 -77
  232. data/spec/session_spec.rb +19 -3
  233. data/spec/shared_selenium_node.rb +83 -0
  234. data/spec/shared_selenium_session.rb +110 -65
  235. data/spec/spec_helper.rb +57 -9
  236. data/spec/xpath_builder_spec.rb +93 -0
  237. metadata +257 -17
  238. data/lib/capybara/rspec/compound.rb +0 -94
  239. data/lib/capybara/selenium/driver_specializations/marionette_driver.rb +0 -49
  240. data/lib/capybara/selenium/nodes/marionette_node.rb +0 -121
  241. data/lib/capybara/spec/session/has_style_spec.rb +0 -25
  242. data/spec/selenium_spec_marionette.rb +0 -172
@@ -1,501 +1,242 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'capybara/selector/xpath_extensions'
3
4
  require 'capybara/selector/selector'
5
+ require 'capybara/selector/definition'
6
+
7
+ #
8
+ # All Selectors below support the listed selector specific filters in addition to the following system-wide filters
9
+ # * :id (String, Regexp, XPath::Expression) - Matches the id attribute
10
+ # * :class (String, Array<String>, Regexp, XPath::Expression) - Matches the class(es) provided
11
+ # * :style (String, Regexp, Hash<String, String>) - Match on elements style
12
+ # * :above (Element) - Match elements above the passed element on the page
13
+ # * :below (Element) - Match elements below the passed element on the page
14
+ # * :left_of (Element) - Match elements left of the passed element on the page
15
+ # * :right_of (Element) - Match elements right of the passed element on the page
16
+ # * :near (Element) - Match elements near (within 50px) the passed element on the page
17
+ #
18
+ # ### Built-in Selectors
19
+ #
20
+ # * **:xpath** - Select elements by XPath expression
21
+ # * Locator: An XPath expression
22
+ #
23
+ # * **:css** - Select elements by CSS selector
24
+ # * Locator: A CSS selector
25
+ #
26
+ # * **:id** - Select element by id
27
+ # * Locator: (String, Regexp, XPath::Expression) The id of the element to match
28
+ #
29
+ # * **:field** - Select field elements (input [not of type submit, image, or hidden], textarea, select)
30
+ # * Locator: Matches against the id, {Capybara.configure test_id} attribute, name, placeholder, or
31
+ # associated label text
32
+ # * Filters:
33
+ # * :name (String, Regexp) - Matches the name attribute
34
+ # * :placeholder (String, Regexp) - Matches the placeholder attribute
35
+ # * :type (String) - Matches the type attribute of the field or element type for 'textarea' and 'select'
36
+ # * :readonly (Boolean) - Match on the element being readonly
37
+ # * :with (String, Regexp) - Matches the current value of the field
38
+ # * :checked (Boolean) - Match checked fields?
39
+ # * :unchecked (Boolean) - Match unchecked fields?
40
+ # * :disabled (Boolean, :all) - Match disabled field? (Default: false)
41
+ # * :multiple (Boolean) - Match fields that accept multiple values
42
+ # * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation
43
+ # * :validation_message (String, Regexp) - Matches the elements current validationMessage
44
+ #
45
+ # * **:fieldset** - Select fieldset elements
46
+ # * Locator: Matches id, {Capybara.configure test_id}, or contents of wrapped legend
47
+ # * Filters:
48
+ # * :legend (String) - Matches contents of wrapped legend
49
+ # * :disabled (Boolean) - Match disabled fieldset?
50
+ #
51
+ # * **:link** - Find links (`<a>` elements with an href attribute)
52
+ # * Locator: Matches the id, {Capybara.configure test_id}, or title attributes, or the string content of the link,
53
+ # or the alt attribute of a contained img element. By default this selector requires a link to have an href attribute.
54
+ # * Filters:
55
+ # * :title (String) - Matches the title attribute
56
+ # * :alt (String) - Matches the alt attribute of a contained img element
57
+ # * :href (String, Regexp, nil, false) - Matches the normalized href of the link, if nil will find `<a>` elements with no href attribute, if false ignores href presence
58
+ #
59
+ # * **:button** - Find buttons ( input [of type submit, reset, image, button] or button elements )
60
+ # * Locator: Matches the id, {Capybara.configure test_id} attribute, name, value, or title attributes, string content of a button, or the alt attribute of an image type button or of a descendant image of a button
61
+ # * Filters:
62
+ # * :name (String, Regexp) - Matches the name attribute
63
+ # * :title (String) - Matches the title attribute
64
+ # * :value (String) - Matches the value of an input button
65
+ # * :type (String) - Matches the type attribute
66
+ # * :disabled (Boolean, :all) - Match disabled buttons (Default: false)
67
+ #
68
+ # * **:link_or_button** - Find links or buttons
69
+ # * Locator: See :link and :button selectors
70
+ # * Filters:
71
+ # * :disabled (Boolean, :all) - Match disabled buttons? (Default: false)
72
+ #
73
+ # * **:fillable_field** - Find text fillable fields ( textarea, input [not of type submit, image, radio, checkbox, hidden, file] )
74
+ # * Locator: Matches against the id, {Capybara.configure test_id} attribute, name, placeholder, or associated label text
75
+ # * Filters:
76
+ # * :name (String, Regexp) - Matches the name attribute
77
+ # * :placeholder (String, Regexp) - Matches the placeholder attribute
78
+ # * :with (String, Regexp) - Matches the current value of the field
79
+ # * :type (String) - Matches the type attribute of the field or element type for 'textarea'
80
+ # * :disabled (Boolean, :all) - Match disabled field? (Default: false)
81
+ # * :multiple (Boolean) - Match fields that accept multiple values
82
+ # * :valid (Boolean) - Match fields that are valid/invalid according to HTML5 form validation
83
+ # * :validation_message (String, Regexp) - Matches the elements current validationMessage
84
+ #
85
+ # * **:radio_button** - Find radio buttons
86
+ # * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text
87
+ # * Filters:
88
+ # * :name (String, Regexp) - Matches the name attribute
89
+ # * :checked (Boolean) - Match checked fields?
90
+ # * :unchecked (Boolean) - Match unchecked fields?
91
+ # * :disabled (Boolean, :all) - Match disabled field? (Default: false)
92
+ # * :option (String, Regexp) - Match the current value
93
+ # * :with - Alias of :option
94
+ #
95
+ # * **:checkbox** - Find checkboxes
96
+ # * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text
97
+ # * Filters:
98
+ # * :name (String, Regexp) - Matches the name attribute
99
+ # * :checked (Boolean) - Match checked fields?
100
+ # * :unchecked (Boolean) - Match unchecked fields?
101
+ # * :disabled (Boolean, :all) - Match disabled field? (Default: false)
102
+ # * :with (String, Regexp) - Match the current value
103
+ # * :option - Alias of :with
104
+ #
105
+ # * **:select** - Find select elements
106
+ # * Locator: Match id, {Capybara.configure test_id} attribute, name, placeholder, or associated label text
107
+ # * Filters:
108
+ # * :name (String, Regexp) - Matches the name attribute
109
+ # * :placeholder (String, Placeholder) - Matches the placeholder attribute
110
+ # * :disabled (Boolean, :all) - Match disabled field? (Default: false)
111
+ # * :multiple (Boolean) - Match fields that accept multiple values
112
+ # * :options (Array<String>) - Exact match options
113
+ # * :enabled_options (Array<String>) - Exact match enabled options
114
+ # * :disabled_options (Array<String>) - Exact match disabled options
115
+ # * :with_options (Array<String>) - Partial match options
116
+ # * :selected (String, Array<String>) - Match the selection(s)
117
+ # * :with_selected (String, Array<String>) - Partial match the selection(s)
118
+ #
119
+ # * **:option** - Find option elements
120
+ # * Locator: Match text of option
121
+ # * Filters:
122
+ # * :disabled (Boolean) - Match disabled option
123
+ # * :selected (Boolean) - Match selected option
124
+ #
125
+ # * **:datalist_input** - Find input field with datalist completion
126
+ # * Locator: Matches against the id, {Capybara.configure test_id} attribute, name,
127
+ # placeholder, or associated label text
128
+ # * Filters:
129
+ # * :name (String, Regexp) - Matches the name attribute
130
+ # * :placeholder (String, Regexp) - Matches the placeholder attribute
131
+ # * :disabled (Boolean, :all) - Match disabled field? (Default: false)
132
+ # * :options (Array<String>) - Exact match options
133
+ # * :with_options (Array<String>) - Partial match options
134
+ #
135
+ # * **:datalist_option** - Find datalist option
136
+ # * Locator: Match text or value of option
137
+ # * Filters:
138
+ # * :disabled (Boolean) - Match disabled option
139
+ #
140
+ # * **:file_field** - Find file input elements
141
+ # * Locator: Match id, {Capybara.configure test_id} attribute, name, or associated label text
142
+ # * Filters:
143
+ # * :name (String, Regexp) - Matches the name attribute
144
+ # * :disabled (Boolean, :all) - Match disabled field? (Default: false)
145
+ # * :multiple (Boolean) - Match field that accepts multiple values
146
+ #
147
+ # * **:label** - Find label elements
148
+ # * Locator: Match id, {Capybara.configure test_id}, or text contents
149
+ # * Filters:
150
+ # * :for (Element, String, Regexp) - The element or id of the element associated with the label
151
+ #
152
+ # * **:table** - Find table elements
153
+ # * Locator: id, {Capybara.configure test_id}, or caption text of table
154
+ # * Filters:
155
+ # * :caption (String) - Match text of associated caption
156
+ # * :with_rows (Array<Array<String>>, Array<Hash<String, String>>) - Partial match `<td>` data - visibility of `<td>` elements is not considered
157
+ # * :rows (Array<Array<String>>) - Match all `<td>`s - visibility of `<td>` elements is not considered
158
+ # * :with_cols (Array<Array<String>>, Array<Hash<String, String>>) - Partial match `<td>` data - visibility of `<td>` elements is not considered
159
+ # * :cols (Array<Array<String>>) - Match all `<td>`s - visibility of `<td>` elements is not considered
160
+ #
161
+ # * **:table_row** - Find table row
162
+ # * Locator: Array<String>, Hash<String, String> table row `<td>` contents - visibility of `<td>` elements is not considered
163
+ #
164
+ # * **:frame** - Find frame/iframe elements
165
+ # * Locator: Match id, {Capybara.configure test_id} attribute, or name
166
+ # * Filters:
167
+ # * :name (String) - Match name attribute
168
+ #
169
+ # * **:element**
170
+ # * Locator: Type of element ('div', 'a', etc) - if not specified defaults to '*'
171
+ # * Filters:
172
+ # * :\<any> (String, Regexp) - Match on any specified element attribute
173
+ #
174
+ class Capybara::Selector; end
175
+
4
176
  Capybara::Selector::FilterSet.add(:_field) do
5
177
  node_filter(:checked, :boolean) { |node, value| !(value ^ node.checked?) }
6
178
  node_filter(:unchecked, :boolean) { |node, value| (value ^ node.checked?) }
7
179
  node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }
8
- node_filter(:multiple, :boolean) { |node, value| !(value ^ node.multiple?) }
9
-
10
- expression_filter(:name) { |xpath, val| xpath[XPath.attr(:name) == val] }
11
- expression_filter(:placeholder) { |xpath, val| xpath[XPath.attr(:placeholder) == val] }
12
-
13
- describe(:node_filters) do |checked: nil, unchecked: nil, disabled: nil, multiple: nil, **|
14
- desc, states = +'', []
15
- states << 'checked' if checked || (unchecked == false)
16
- states << 'not checked' if unchecked || (checked == false)
17
- states << 'disabled' if disabled == true
18
- states << 'not disabled' if disabled == false
19
- desc << " that is #{states.join(' and ')}" unless states.empty?
20
- desc << ' with the multiple attribute' if multiple == true
21
- desc << ' without the multiple attribute' if multiple == false
22
- desc
23
- end
24
- end
25
-
26
- # rubocop:disable Metrics/BlockLength
27
-
28
- Capybara.add_selector(:xpath) do
29
- xpath { |xpath| xpath }
30
- end
31
-
32
- Capybara.add_selector(:css) do
33
- css { |css| css }
34
- end
35
-
36
- Capybara.add_selector(:id) do
37
- xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
38
- end
39
-
40
- Capybara.add_selector(:field) do
41
- xpath do |locator, **options|
42
- xpath = XPath.descendant(:input, :textarea, :select)[!XPath.attr(:type).one_of('submit', 'image', 'hidden')]
43
- locate_field(xpath, locator, options)
44
- end
45
-
46
- expression_filter(:type) do |expr, type|
47
- type = type.to_s
48
- if %w[textarea select].include?(type)
49
- expr.self(type.to_sym)
50
- else
51
- expr[XPath.attr(:type) == type]
52
- end
53
- end
54
-
55
- filter_set(:_field) # checked/unchecked/disabled/multiple/name/placeholder
56
-
57
- node_filter(:readonly, :boolean) { |node, value| !(value ^ node.readonly?) }
58
- node_filter(:with) do |node, with|
59
- with.is_a?(Regexp) ? node.value =~ with : node.value == with.to_s
60
- end
61
-
62
- describe_expression_filters do |type: nil, **options|
63
- desc = +''
64
- (expression_filters.keys - [:type]).each { |ef| desc << " with #{ef} #{options[ef]}" if options.key?(ef) }
65
- desc << " of type #{type.inspect}" if type
66
- desc
67
- end
68
-
69
- describe_node_filters do |**options|
70
- " with value #{options[:with].to_s.inspect}" if options.key?(:with)
71
- end
72
- end
73
-
74
- Capybara.add_selector(:fieldset) do
75
- xpath(:legend) do |locator, legend: nil, **|
76
- locator_matchers = (XPath.attr(:id) == locator.to_s) | XPath.child(:legend)[XPath.string.n.is(locator.to_s)]
77
- locator_matchers |= XPath.attr(test_id) == locator if test_id
78
- xpath = XPath.descendant(:fieldset)
79
- xpath = xpath[locator_matchers] unless locator.nil?
80
- xpath = xpath[XPath.child(:legend)[XPath.string.n.is(legend)]] if legend
81
- xpath
82
- end
83
-
84
- node_filter(:disabled, :boolean) { |node, value| !(value ^ node.disabled?) }
85
- end
86
-
87
- Capybara.add_selector(:link) do
88
- xpath(:title, :alt) do |locator, href: true, alt: nil, title: nil, **|
89
- xpath = XPath.descendant(:a)
90
- xpath = xpath[
91
- case href
92
- when nil, false
93
- !XPath.attr(:href)
94
- when true
95
- XPath.attr(:href)
96
- when Regexp
97
- nil # needs to be handled in filter
98
- else
99
- XPath.attr(:href) == href.to_s
100
- end
101
- ]
102
-
103
- unless locator.nil?
104
- locator = locator.to_s
105
- matchers = [XPath.attr(:id) == locator,
106
- XPath.string.n.is(locator),
107
- XPath.attr(:title).is(locator),
108
- XPath.descendant(:img)[XPath.attr(:alt).is(locator)]]
109
- matchers << XPath.attr(:'aria-label').is(locator) if enable_aria_label
110
- matchers << XPath.attr(test_id) == locator if test_id
111
- xpath = xpath[matchers.reduce(:|)]
180
+ node_filter(:valid, :boolean) { |node, value| node.evaluate_script('this.validity.valid') == value }
181
+ node_filter(:name) { |node, value| !value.is_a?(Regexp) || value.match?(node[:name]) }
182
+ node_filter(:placeholder) { |node, value| !value.is_a?(Regexp) || value.match?(node[:placeholder]) }
183
+ node_filter(:validation_message) do |node, msg|
184
+ vm = node[:validationMessage]
185
+ (msg.is_a?(Regexp) ? msg.match?(vm) : vm == msg.to_s).tap do |res|
186
+ add_error("Expected validation message to be #{msg.inspect} but was #{vm}") unless res
112
187
  end
113
-
114
- xpath = xpath[find_by_attr(:title, title)]
115
- xpath = xpath[XPath.descendant(:img)[XPath.attr(:alt) == alt]] if alt
116
- xpath
117
188
  end
118
189
 
119
- node_filter(:href) do |node, href|
120
- # If not a Regexp it's been handled in the main XPath
121
- href.is_a?(Regexp) ? node[:href].match(href) : true
190
+ expression_filter(:name) do |xpath, val|
191
+ builder(xpath).add_attribute_conditions(name: val)
122
192
  end
123
-
124
- expression_filter(:download, valid_values: [true, false, String]) do |expr, download|
125
- mod = case download
126
- when true then XPath.attr(:download)
127
- when false then !XPath.attr(:download)
128
- when String then XPath.attr(:download) == download
129
- end
130
- expr[mod]
193
+ expression_filter(:placeholder) do |xpath, val|
194
+ builder(xpath).add_attribute_conditions(placeholder: val)
131
195
  end
196
+ expression_filter(:disabled) { |xpath, val| val ? xpath : xpath[~XPath.attr(:disabled)] }
197
+ expression_filter(:multiple) { |xpath, val| xpath[val ? XPath.attr(:multiple) : ~XPath.attr(:multiple)] }
132
198
 
133
- describe_expression_filters do |**options|
199
+ describe(:expression_filters) do |name: nil, placeholder: nil, disabled: nil, multiple: nil, **|
134
200
  desc = +''
135
- desc << " with href #{options[:href].inspect}" if options[:href] && !options[:href].is_a?(Regexp)
136
- desc << ' with no href attribute' if options.fetch(:href, true).nil?
137
- desc
138
- end
139
-
140
- describe_node_filters do |href: nil, **|
141
- " with href matching #{href.inspect}" if href.is_a? Regexp
142
- end
143
- end
144
-
145
- Capybara.add_selector(:button) do
146
- xpath(:value, :title, :type) do |locator, **options|
147
- input_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')]
148
- btn_xpath = XPath.descendant(:button)
149
- image_btn_xpath = XPath.descendant(:input)[XPath.attr(:type) == 'image']
150
-
151
- unless locator.nil?
152
- locator = locator.to_s
153
- locator_matchers = XPath.attr(:id).equals(locator) | XPath.attr(:value).is(locator) | XPath.attr(:title).is(locator)
154
- locator_matchers |= XPath.attr(:'aria-label').is(locator) if enable_aria_label
155
- locator_matchers |= XPath.attr(test_id) == locator if test_id
156
-
157
- input_btn_xpath = input_btn_xpath[locator_matchers]
158
-
159
- btn_xpath = btn_xpath[locator_matchers | XPath.string.n.is(locator) | XPath.descendant(:img)[XPath.attr(:alt).is(locator)]]
160
-
161
- alt_matches = XPath.attr(:alt).is(locator)
162
- alt_matches |= XPath.attr(:'aria-label').is(locator) if enable_aria_label
163
- image_btn_xpath = image_btn_xpath[alt_matches]
164
- end
165
-
166
- res_xpath = input_btn_xpath.union(btn_xpath).union(image_btn_xpath)
167
-
168
- res_xpath = expression_filters.keys.inject(res_xpath) { |memo, ef| memo[find_by_attr(ef, options[ef])] }
169
-
170
- res_xpath
171
- end
172
-
173
- node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }
174
-
175
- describe_expression_filters
176
- describe_node_filters do |disabled: nil, **|
177
- ' that is disabled' if disabled == true
178
- end
179
- end
180
-
181
- Capybara.add_selector(:link_or_button) do
182
- label 'link or button'
183
- xpath do |locator, **options|
184
- self.class.all.values_at(:link, :button).map { |selector| selector.xpath.call(locator, options) }.reduce(:union)
185
- end
186
-
187
- node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| node.tag_name == 'a' || !(value ^ node.disabled?) }
188
-
189
- describe_node_filters do |disabled: nil, **|
190
- ' that is disabled' if disabled == true
191
- end
192
- end
193
-
194
- Capybara.add_selector(:fillable_field) do
195
- label 'field'
196
-
197
- xpath(:allow_self) do |locator, **options|
198
- xpath = XPath.axis(options[:allow_self] ? :"descendant-or-self" : :descendant, :input, :textarea)[
199
- !XPath.attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')
200
- ]
201
- locate_field(xpath, locator, options)
202
- end
203
-
204
- expression_filter(:type) do |expr, type|
205
- type = type.to_s
206
- if type == 'textarea'
207
- expr.self(type.to_sym)
208
- else
209
- expr[XPath.attr(:type) == type]
210
- end
211
- end
212
-
213
- filter_set(:_field, %i[disabled multiple name placeholder])
214
-
215
- node_filter(:with) do |node, with|
216
- with.is_a?(Regexp) ? node.value =~ with : node.value == with.to_s
217
- end
218
-
219
- describe_expression_filters
220
- describe_node_filters do |**options|
221
- " with value #{options[:with].to_s.inspect}" if options.key?(:with)
222
- end
223
- end
224
-
225
- Capybara.add_selector(:radio_button) do
226
- label 'radio button'
227
-
228
- xpath(:allow_self) do |locator, **options|
229
- xpath = XPath.axis(options[:allow_self] ? :"descendant-or-self" : :descendant, :input)[
230
- XPath.attr(:type) == 'radio'
231
- ]
232
- locate_field(xpath, locator, options)
233
- end
234
-
235
- filter_set(:_field, %i[checked unchecked disabled name])
236
-
237
- node_filter(:option) { |node, value| node.value == value.to_s }
238
-
239
- describe_expression_filters
240
- describe_node_filters do |option: nil, **|
241
- " with value #{option.inspect}" if option
242
- end
243
- end
244
-
245
- Capybara.add_selector(:checkbox) do
246
- xpath(:allow_self) do |locator, **options|
247
- xpath = XPath.axis(options[:allow_self] ? :"descendant-or-self" : :descendant, :input)[
248
- XPath.attr(:type) == 'checkbox'
249
- ]
250
- locate_field(xpath, locator, options)
251
- end
252
-
253
- filter_set(:_field, %i[checked unchecked disabled name])
254
-
255
- node_filter(:option) { |node, value| node.value == value.to_s }
256
-
257
- describe_expression_filters
258
- describe_node_filters do |option: nil, **|
259
- " with value #{option.inspect}" if option
260
- end
261
- end
262
-
263
- Capybara.add_selector(:select) do
264
- label 'select box'
265
-
266
- xpath do |locator, **options|
267
- xpath = XPath.descendant(:select)
268
- locate_field(xpath, locator, options)
269
- end
270
-
271
- filter_set(:_field, %i[disabled multiple name placeholder])
272
-
273
- node_filter(:options) do |node, options|
274
- actual = if node.visible?
275
- node.all(:xpath, './/option', wait: false).map(&:text)
276
- else
277
- node.all(:xpath, './/option', visible: false, wait: false).map { |option| option.text(:all) }
278
- end
279
- options.sort == actual.sort
280
- end
281
-
282
- expression_filter(:with_options) do |expr, options|
283
- options.inject(expr) do |xpath, option|
284
- xpath[Capybara::Selector.all[:option].call(option)]
285
- end
286
- end
287
-
288
- node_filter(:selected) do |node, selected|
289
- actual = node.all(:xpath, './/option', visible: false, wait: false).select(&:selected?).map { |option| option.text(:all) }
290
- Array(selected).sort == actual.sort
291
- end
292
-
293
- node_filter(:with_selected) do |node, selected|
294
- actual = node.all(:xpath, './/option', visible: false, wait: false).select(&:selected?).map { |option| option.text(:all) }
295
- (Array(selected) - actual).empty?
296
- end
297
-
298
- describe_expression_filters do |with_options: nil, **opts|
299
- desc = +''
300
- desc << " with at least options #{with_options.inspect}" if with_options
301
- desc << describe_all_expression_filters(opts)
302
- desc
303
- end
304
-
305
- describe_node_filters do |options: nil, selected: nil, with_selected: nil, **|
306
- desc = +''
307
- desc << " with options #{options.inspect}" if options
308
- desc << " with #{selected.inspect} selected" if selected
309
- desc << " with at least #{with_selected.inspect} selected" if with_selected
310
- desc
311
- end
312
- end
313
-
314
- Capybara.add_selector(:datalist_input) do
315
- label 'input box with datalist completion'
316
-
317
- xpath do |locator, **options|
318
- xpath = XPath.descendant(:input)[XPath.attr(:list)]
319
- locate_field(xpath, locator, options)
320
- end
321
-
322
- filter_set(:_field, %i[disabled name placeholder])
323
-
324
- node_filter(:options) do |node, options|
325
- actual = node.find("//datalist[@id=#{node[:list]}]", visible: :all).all(:datalist_option, wait: false).map(&:value)
326
- options.sort == actual.sort
327
- end
328
-
329
- expression_filter(:with_options) do |expr, options|
330
- options.inject(expr) do |xpath, option|
331
- xpath[XPath.attr(:list) == XPath.anywhere(:datalist)[Capybara::Selector.all[:datalist_option].call(option)].attr(:id)]
332
- end
333
- end
334
-
335
- describe_expression_filters do |with_options: nil, **opts|
336
- desc = +''
337
- desc << " with at least options #{with_options.inspect}" if with_options
338
- desc << describe_all_expression_filters(opts)
201
+ desc << ' that is not disabled' if disabled == false
202
+ desc << " with name #{name}" if name
203
+ desc << " with placeholder #{placeholder}" if placeholder
204
+ desc << ' with the multiple attribute' if multiple == true
205
+ desc << ' without the multiple attribute' if multiple == false
339
206
  desc
340
207
  end
341
208
 
342
- describe_node_filters do |options: nil, **|
343
- " with options #{options.inspect}" if options
344
- end
345
- end
346
-
347
- Capybara.add_selector(:option) do
348
- xpath do |locator|
349
- xpath = XPath.descendant(:option)
350
- xpath = xpath[XPath.string.n.is(locator.to_s)] unless locator.nil?
351
- xpath
352
- end
353
-
354
- node_filter(:disabled, :boolean) { |node, value| !(value ^ node.disabled?) }
355
- node_filter(:selected, :boolean) { |node, value| !(value ^ node.selected?) }
356
-
357
- describe_node_filters do |**options|
358
- desc = +''
359
- desc << " that is#{' not' unless options[:disabled]} disabled" if options.key?(:disabled)
360
- desc << " that is#{' not' unless options[:selected]} selected" if options.key?(:selected)
209
+ describe(:node_filters) do |checked: nil, unchecked: nil, disabled: nil, valid: nil, validation_message: nil, **|
210
+ desc, states = +'', []
211
+ states << 'checked' if checked || (unchecked == false)
212
+ states << 'not checked' if unchecked || (checked == false)
213
+ states << 'disabled' if disabled == true
214
+ desc << " that is #{states.join(' and ')}" unless states.empty?
215
+ desc << ' that is valid' if valid == true
216
+ desc << ' that is invalid' if valid == false
217
+ desc << " with validation message #{validation_message.to_s.inspect}" if validation_message
361
218
  desc
362
219
  end
363
220
  end
364
221
 
365
- Capybara.add_selector(:datalist_option) do
366
- label 'datalist option'
367
- visible(:all)
368
-
369
- xpath do |locator|
370
- xpath = XPath.descendant(:option)
371
- xpath = xpath[XPath.string.n.is(locator.to_s) | (XPath.attr(:value) == locator.to_s)] unless locator.nil?
372
- xpath
373
- end
374
-
375
- node_filter(:disabled, :boolean) { |node, value| !(value ^ node.disabled?) }
376
-
377
- describe_node_filters do |**options|
378
- " that is#{' not' unless options[:disabled]} disabled" if options.key?(:disabled)
379
- end
380
- end
381
-
382
- Capybara.add_selector(:file_field) do
383
- label 'file field'
384
- xpath(:allow_self) do |locator, **options|
385
- xpath = XPath.axis(options[:allow_self] ? :"descendant-or-self" : :descendant, :input)[
386
- XPath.attr(:type) == 'file'
387
- ]
388
- locate_field(xpath, locator, options)
389
- end
390
-
391
- filter_set(:_field, %i[disabled multiple name])
392
-
393
- describe_expression_filters
394
- end
395
-
396
- Capybara.add_selector(:label) do
397
- label 'label'
398
- xpath(:for) do |locator, options|
399
- xpath = XPath.descendant(:label)
400
- unless locator.nil?
401
- locator_matchers = XPath.string.n.is(locator.to_s) | (XPath.attr(:id) == locator.to_s)
402
- locator_matchers |= XPath.attr(test_id) == locator if test_id
403
- xpath = xpath[locator_matchers]
404
- end
405
- if options.key?(:for) && !options[:for].is_a?(Capybara::Node::Element)
406
- with_attr = XPath.attr(:for) == options[:for].to_s
407
- labelable_elements = %i[button input keygen meter output progress select textarea]
408
- wrapped = !XPath.attr(:for) &
409
- XPath.descendant(*labelable_elements)[XPath.attr(:id) == options[:for].to_s]
410
- xpath = xpath[with_attr | wrapped]
411
- end
412
- xpath
413
- end
414
-
415
- node_filter(:for) do |node, field_or_value|
416
- if field_or_value.is_a? Capybara::Node::Element
417
- if node[:for]
418
- field_or_value[:id] == node[:for]
419
- else
420
- field_or_value.find_xpath('./ancestor::label[1]').include? node.base
421
- end
422
- else
423
- true # Non element values were handled through the expression filter
424
- end
425
- end
426
-
427
- describe_expression_filters do |**options|
428
- " for element with id of \"#{options[:for]}\"" if options.key?(:for) && !options[:for].is_a?(Capybara::Node::Element)
429
- end
430
- describe_node_filters do |**options|
431
- " for element #{options[:for]}" if options[:for]&.is_a?(Capybara::Node::Element)
432
- end
433
- end
434
-
435
- Capybara.add_selector(:table) do
436
- xpath(:caption) do |locator, caption: nil, **|
437
- xpath = XPath.descendant(:table)
438
- unless locator.nil?
439
- locator_matchers = (XPath.attr(:id) == locator.to_s) | XPath.descendant(:caption).is(locator.to_s)
440
- locator_matchers |= XPath.attr(test_id) == locator if test_id
441
- xpath = xpath[locator_matchers]
442
- end
443
- xpath = xpath[XPath.descendant(:caption) == caption] if caption
444
- xpath
445
- end
446
-
447
- describe_expression_filters do |caption: nil, **|
448
- " with caption \"#{caption}\"" if caption
449
- end
450
- end
451
-
452
- Capybara.add_selector(:frame) do
453
- xpath(:name) do |locator, **options|
454
- xpath = XPath.descendant(:iframe).union(XPath.descendant(:frame))
455
- unless locator.nil?
456
- locator_matchers = (XPath.attr(:id) == locator.to_s) | (XPath.attr(:name) == locator.to_s)
457
- locator_matchers |= XPath.attr(test_id) == locator if test_id
458
- xpath = xpath[locator_matchers]
459
- end
460
- xpath = expression_filters.keys.inject(xpath) { |memo, ef| memo[find_by_attr(ef, options[ef])] }
461
- xpath
462
- end
463
-
464
- describe_expression_filters do |name: nil, **|
465
- " with name #{name}" if name
466
- end
467
- end
468
-
469
- Capybara.add_selector(:element) do
470
- xpath do |locator, **|
471
- XPath.descendant.where(locator ? XPath.local_name == locator.to_s : nil)
472
- end
473
-
474
- expression_filter(:attributes, matcher: /.+/) do |xpath, name, val|
475
- case val
476
- when Regexp
477
- xpath
478
- when true
479
- xpath[XPath.attr(name)]
480
- when false
481
- xpath[!XPath.attr(name)]
482
- when XPath::Expression
483
- xpath[XPath.attr(name)[val]]
484
- else
485
- xpath[XPath.attr(name.to_sym) == val]
486
- end
487
- end
488
-
489
- node_filter(:attributes, matcher: /.+/) do |node, name, val|
490
- val.is_a?(Regexp) ? node[name] =~ val : true
491
- end
492
-
493
- describe_expression_filters do |**options|
494
- booleans, values = options.partition { |_k, v| [true, false].include? v }.map(&:to_h)
495
- desc = describe_all_expression_filters(values)
496
- desc + booleans.map do |k, v|
497
- v ? " with #{k} attribute" : "without #{k} attribute"
498
- end.join
499
- end
500
- end
501
- # rubocop:enable Metrics/BlockLength
222
+ require 'capybara/selector/definition/xpath'
223
+ require 'capybara/selector/definition/css'
224
+ require 'capybara/selector/definition/id'
225
+ require 'capybara/selector/definition/field'
226
+ require 'capybara/selector/definition/fieldset'
227
+ require 'capybara/selector/definition/link'
228
+ require 'capybara/selector/definition/button'
229
+ require 'capybara/selector/definition/link_or_button'
230
+ require 'capybara/selector/definition/fillable_field'
231
+ require 'capybara/selector/definition/radio_button'
232
+ require 'capybara/selector/definition/checkbox'
233
+ require 'capybara/selector/definition/select'
234
+ require 'capybara/selector/definition/datalist_input'
235
+ require 'capybara/selector/definition/option'
236
+ require 'capybara/selector/definition/datalist_option'
237
+ require 'capybara/selector/definition/file_field'
238
+ require 'capybara/selector/definition/label'
239
+ require 'capybara/selector/definition/table'
240
+ require 'capybara/selector/definition/table_row'
241
+ require 'capybara/selector/definition/frame'
242
+ require 'capybara/selector/definition/element'