capybara 2.7.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 (318) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +1 -0
  3. data/History.md +1147 -11
  4. data/License.txt +1 -1
  5. data/README.md +252 -131
  6. data/lib/capybara/config.rb +92 -0
  7. data/lib/capybara/cucumber.rb +3 -3
  8. data/lib/capybara/driver/base.rb +52 -21
  9. data/lib/capybara/driver/node.rb +48 -14
  10. data/lib/capybara/dsl.rb +16 -9
  11. data/lib/capybara/helpers.rb +72 -81
  12. data/lib/capybara/minitest/spec.rb +267 -0
  13. data/lib/capybara/minitest.rb +385 -0
  14. data/lib/capybara/node/actions.rb +337 -89
  15. data/lib/capybara/node/base.rb +50 -32
  16. data/lib/capybara/node/document.rb +19 -3
  17. data/lib/capybara/node/document_matchers.rb +22 -24
  18. data/lib/capybara/node/element.rb +388 -125
  19. data/lib/capybara/node/finders.rb +231 -121
  20. data/lib/capybara/node/matchers.rb +503 -217
  21. data/lib/capybara/node/simple.rb +64 -27
  22. data/lib/capybara/queries/ancestor_query.rb +27 -0
  23. data/lib/capybara/queries/base_query.rb +87 -11
  24. data/lib/capybara/queries/current_path_query.rb +24 -24
  25. data/lib/capybara/queries/match_query.rb +15 -10
  26. data/lib/capybara/queries/selector_query.rb +675 -81
  27. data/lib/capybara/queries/sibling_query.rb +26 -0
  28. data/lib/capybara/queries/style_query.rb +45 -0
  29. data/lib/capybara/queries/text_query.rb +88 -20
  30. data/lib/capybara/queries/title_query.rb +9 -11
  31. data/lib/capybara/rack_test/browser.rb +63 -39
  32. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  33. data/lib/capybara/rack_test/driver.rb +26 -16
  34. data/lib/capybara/rack_test/errors.rb +6 -0
  35. data/lib/capybara/rack_test/form.rb +73 -58
  36. data/lib/capybara/rack_test/node.rb +187 -67
  37. data/lib/capybara/rails.rb +4 -8
  38. data/lib/capybara/registration_container.rb +44 -0
  39. data/lib/capybara/registrations/drivers.rb +42 -0
  40. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  41. data/lib/capybara/registrations/servers.rb +45 -0
  42. data/lib/capybara/result.rb +142 -14
  43. data/lib/capybara/rspec/features.rb +17 -42
  44. data/lib/capybara/rspec/matcher_proxies.rb +82 -0
  45. data/lib/capybara/rspec/matchers/base.rb +111 -0
  46. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  47. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  48. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  49. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  50. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  51. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  52. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  53. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  54. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  55. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  56. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  57. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  58. data/lib/capybara/rspec/matchers.rb +143 -244
  59. data/lib/capybara/rspec.rb +10 -12
  60. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  61. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  62. data/lib/capybara/selector/css.rb +102 -0
  63. data/lib/capybara/selector/definition/button.rb +63 -0
  64. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  65. data/lib/capybara/selector/definition/css.rb +10 -0
  66. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  67. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  68. data/lib/capybara/selector/definition/element.rb +28 -0
  69. data/lib/capybara/selector/definition/field.rb +40 -0
  70. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  71. data/lib/capybara/selector/definition/file_field.rb +13 -0
  72. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  73. data/lib/capybara/selector/definition/frame.rb +17 -0
  74. data/lib/capybara/selector/definition/id.rb +6 -0
  75. data/lib/capybara/selector/definition/label.rb +62 -0
  76. data/lib/capybara/selector/definition/link.rb +54 -0
  77. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  78. data/lib/capybara/selector/definition/option.rb +27 -0
  79. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  80. data/lib/capybara/selector/definition/select.rb +81 -0
  81. data/lib/capybara/selector/definition/table.rb +109 -0
  82. data/lib/capybara/selector/definition/table_row.rb +21 -0
  83. data/lib/capybara/selector/definition/xpath.rb +5 -0
  84. data/lib/capybara/selector/definition.rb +278 -0
  85. data/lib/capybara/selector/filter.rb +3 -46
  86. data/lib/capybara/selector/filter_set.rb +124 -0
  87. data/lib/capybara/selector/filters/base.rb +77 -0
  88. data/lib/capybara/selector/filters/expression_filter.rb +22 -0
  89. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  90. data/lib/capybara/selector/filters/node_filter.rb +31 -0
  91. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  92. data/lib/capybara/selector/selector.rb +155 -0
  93. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  94. data/lib/capybara/selector.rb +232 -369
  95. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  96. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  97. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  98. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  99. data/lib/capybara/selenium/driver.rb +380 -142
  100. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  101. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
  102. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -0
  103. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  104. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  105. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  106. data/lib/capybara/selenium/extensions/find.rb +110 -0
  107. data/lib/capybara/selenium/extensions/html5_drag.rb +228 -0
  108. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  109. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  110. data/lib/capybara/selenium/logger_suppressor.rb +40 -0
  111. data/lib/capybara/selenium/node.rb +528 -97
  112. data/lib/capybara/selenium/nodes/chrome_node.rb +137 -0
  113. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  114. data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
  115. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  116. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  117. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  118. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  119. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  120. data/lib/capybara/selenium/patches/logs.rb +45 -0
  121. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  122. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  123. data/lib/capybara/server/animation_disabler.rb +63 -0
  124. data/lib/capybara/server/checker.rb +44 -0
  125. data/lib/capybara/server/middleware.rb +71 -0
  126. data/lib/capybara/server.rb +74 -71
  127. data/lib/capybara/session/config.rb +126 -0
  128. data/lib/capybara/session/matchers.rb +44 -27
  129. data/lib/capybara/session.rb +500 -297
  130. data/lib/capybara/spec/fixtures/no_extension +1 -0
  131. data/lib/capybara/spec/public/jquery.js +5 -5
  132. data/lib/capybara/spec/public/offset.js +6 -0
  133. data/lib/capybara/spec/public/test.js +168 -14
  134. data/lib/capybara/spec/session/accept_alert_spec.rb +37 -14
  135. data/lib/capybara/spec/session/accept_confirm_spec.rb +7 -6
  136. data/lib/capybara/spec/session/accept_prompt_spec.rb +38 -10
  137. data/lib/capybara/spec/session/all_spec.rb +179 -59
  138. data/lib/capybara/spec/session/ancestor_spec.rb +88 -0
  139. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +140 -0
  140. data/lib/capybara/spec/session/assert_current_path_spec.rb +75 -0
  141. data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
  142. data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
  143. data/lib/capybara/spec/session/assert_text_spec.rb +258 -0
  144. data/lib/capybara/spec/session/assert_title_spec.rb +93 -0
  145. data/lib/capybara/spec/session/attach_file_spec.rb +154 -48
  146. data/lib/capybara/spec/session/body_spec.rb +12 -13
  147. data/lib/capybara/spec/session/check_spec.rb +168 -41
  148. data/lib/capybara/spec/session/choose_spec.rb +75 -23
  149. data/lib/capybara/spec/session/click_button_spec.rb +243 -175
  150. data/lib/capybara/spec/session/click_link_or_button_spec.rb +57 -32
  151. data/lib/capybara/spec/session/click_link_spec.rb +100 -53
  152. data/lib/capybara/spec/session/current_scope_spec.rb +11 -10
  153. data/lib/capybara/spec/session/current_url_spec.rb +61 -35
  154. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +7 -7
  155. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +5 -4
  156. data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +13 -6
  157. data/lib/capybara/spec/session/element/match_css_spec.rb +21 -7
  158. data/lib/capybara/spec/session/element/match_xpath_spec.rb +9 -7
  159. data/lib/capybara/spec/session/element/matches_selector_spec.rb +91 -34
  160. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +23 -0
  161. data/lib/capybara/spec/session/evaluate_script_spec.rb +45 -3
  162. data/lib/capybara/spec/session/execute_script_spec.rb +24 -4
  163. data/lib/capybara/spec/session/fill_in_spec.rb +166 -64
  164. data/lib/capybara/spec/session/find_button_spec.rb +37 -18
  165. data/lib/capybara/spec/session/find_by_id_spec.rb +10 -9
  166. data/lib/capybara/spec/session/find_field_spec.rb +57 -34
  167. data/lib/capybara/spec/session/find_link_spec.rb +47 -10
  168. data/lib/capybara/spec/session/find_spec.rb +290 -144
  169. data/lib/capybara/spec/session/first_spec.rb +91 -48
  170. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  171. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  172. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +116 -0
  173. data/lib/capybara/spec/session/frame/within_frame_spec.rb +112 -0
  174. data/lib/capybara/spec/session/go_back_spec.rb +3 -2
  175. data/lib/capybara/spec/session/go_forward_spec.rb +3 -2
  176. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  177. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  178. data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
  179. data/lib/capybara/spec/session/has_button_spec.rb +76 -19
  180. data/lib/capybara/spec/session/has_css_spec.rb +277 -131
  181. data/lib/capybara/spec/session/has_current_path_spec.rb +98 -26
  182. data/lib/capybara/spec/session/has_field_spec.rb +177 -107
  183. data/lib/capybara/spec/session/has_link_spec.rb +13 -12
  184. data/lib/capybara/spec/session/has_none_selectors_spec.rb +78 -0
  185. data/lib/capybara/spec/session/has_select_spec.rb +191 -95
  186. data/lib/capybara/spec/session/has_selector_spec.rb +128 -64
  187. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  188. data/lib/capybara/spec/session/has_table_spec.rb +172 -5
  189. data/lib/capybara/spec/session/has_text_spec.rb +126 -60
  190. data/lib/capybara/spec/session/has_title_spec.rb +35 -12
  191. data/lib/capybara/spec/session/has_xpath_spec.rb +74 -53
  192. data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +3 -2
  193. data/lib/capybara/spec/session/html_spec.rb +14 -6
  194. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  195. data/lib/capybara/spec/session/node_spec.rb +1028 -131
  196. data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
  197. data/lib/capybara/spec/session/refresh_spec.rb +34 -0
  198. data/lib/capybara/spec/session/reset_session_spec.rb +75 -34
  199. data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +2 -1
  200. data/lib/capybara/spec/session/save_and_open_page_spec.rb +3 -2
  201. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +11 -15
  202. data/lib/capybara/spec/session/save_page_spec.rb +42 -55
  203. data/lib/capybara/spec/session/save_screenshot_spec.rb +16 -14
  204. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  205. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  206. data/lib/capybara/spec/session/select_spec.rb +112 -85
  207. data/lib/capybara/spec/session/selectors_spec.rb +71 -8
  208. data/lib/capybara/spec/session/sibling_spec.rb +52 -0
  209. data/lib/capybara/spec/session/text_spec.rb +38 -23
  210. data/lib/capybara/spec/session/title_spec.rb +17 -5
  211. data/lib/capybara/spec/session/uncheck_spec.rb +71 -12
  212. data/lib/capybara/spec/session/unselect_spec.rb +44 -43
  213. data/lib/capybara/spec/session/visit_spec.rb +99 -32
  214. data/lib/capybara/spec/session/window/become_closed_spec.rb +33 -29
  215. data/lib/capybara/spec/session/window/current_window_spec.rb +5 -3
  216. data/lib/capybara/spec/session/window/open_new_window_spec.rb +5 -3
  217. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +39 -30
  218. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +17 -10
  219. data/lib/capybara/spec/session/window/window_spec.rb +121 -73
  220. data/lib/capybara/spec/session/window/windows_spec.rb +12 -10
  221. data/lib/capybara/spec/session/window/within_window_spec.rb +52 -82
  222. data/lib/capybara/spec/session/within_spec.rb +76 -43
  223. data/lib/capybara/spec/spec_helper.rb +67 -33
  224. data/lib/capybara/spec/test_app.rb +85 -36
  225. data/lib/capybara/spec/views/animated.erb +49 -0
  226. data/lib/capybara/spec/views/buttons.erb +1 -1
  227. data/lib/capybara/spec/views/fieldsets.erb +1 -1
  228. data/lib/capybara/spec/views/form.erb +227 -20
  229. data/lib/capybara/spec/views/frame_child.erb +10 -2
  230. data/lib/capybara/spec/views/frame_one.erb +2 -1
  231. data/lib/capybara/spec/views/frame_parent.erb +2 -2
  232. data/lib/capybara/spec/views/frame_two.erb +1 -1
  233. data/lib/capybara/spec/views/header_links.erb +1 -1
  234. data/lib/capybara/spec/views/host_links.erb +1 -1
  235. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  236. data/lib/capybara/spec/views/obscured.erb +47 -0
  237. data/lib/capybara/spec/views/offset.erb +32 -0
  238. data/lib/capybara/spec/views/path.erb +1 -1
  239. data/lib/capybara/spec/views/popup_one.erb +1 -1
  240. data/lib/capybara/spec/views/popup_two.erb +1 -1
  241. data/lib/capybara/spec/views/postback.erb +1 -1
  242. data/lib/capybara/spec/views/react.erb +45 -0
  243. data/lib/capybara/spec/views/scroll.erb +20 -0
  244. data/lib/capybara/spec/views/spatial.erb +31 -0
  245. data/lib/capybara/spec/views/tables.erb +69 -2
  246. data/lib/capybara/spec/views/with_animation.erb +82 -0
  247. data/lib/capybara/spec/views/with_base_tag.erb +1 -1
  248. data/lib/capybara/spec/views/with_count.erb +1 -1
  249. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  250. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  251. data/lib/capybara/spec/views/with_hover.erb +7 -1
  252. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  253. data/lib/capybara/spec/views/with_html.erb +100 -10
  254. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  255. data/lib/capybara/spec/views/with_html_entities.erb +1 -1
  256. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  257. data/lib/capybara/spec/views/with_js.erb +49 -3
  258. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  259. data/lib/capybara/spec/views/with_namespace.erb +20 -0
  260. data/lib/capybara/spec/views/with_scope.erb +1 -1
  261. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  262. data/lib/capybara/spec/views/with_simple_html.erb +1 -1
  263. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  264. data/lib/capybara/spec/views/with_title.erb +1 -1
  265. data/lib/capybara/spec/views/with_unload_alert.erb +3 -1
  266. data/lib/capybara/spec/views/with_windows.erb +7 -1
  267. data/lib/capybara/spec/views/within_frames.erb +6 -3
  268. data/lib/capybara/version.rb +2 -1
  269. data/lib/capybara/window.rb +39 -21
  270. data/lib/capybara.rb +208 -186
  271. data/spec/basic_node_spec.rb +52 -39
  272. data/spec/capybara_spec.rb +72 -50
  273. data/spec/css_builder_spec.rb +101 -0
  274. data/spec/css_splitter_spec.rb +38 -0
  275. data/spec/dsl_spec.rb +81 -61
  276. data/spec/filter_set_spec.rb +46 -0
  277. data/spec/fixtures/capybara.csv +1 -0
  278. data/spec/fixtures/certificate.pem +25 -0
  279. data/spec/fixtures/key.pem +27 -0
  280. data/spec/fixtures/selenium_driver_rspec_failure.rb +7 -3
  281. data/spec/fixtures/selenium_driver_rspec_success.rb +7 -3
  282. data/spec/minitest_spec.rb +164 -0
  283. data/spec/minitest_spec_spec.rb +162 -0
  284. data/spec/per_session_config_spec.rb +68 -0
  285. data/spec/rack_test_spec.rb +189 -96
  286. data/spec/regexp_dissassembler_spec.rb +250 -0
  287. data/spec/result_spec.rb +143 -13
  288. data/spec/rspec/features_spec.rb +38 -32
  289. data/spec/rspec/scenarios_spec.rb +9 -7
  290. data/spec/rspec/shared_spec_matchers.rb +959 -0
  291. data/spec/rspec/views_spec.rb +9 -3
  292. data/spec/rspec_matchers_spec.rb +62 -0
  293. data/spec/rspec_spec.rb +127 -30
  294. data/spec/sauce_spec_chrome.rb +43 -0
  295. data/spec/selector_spec.rb +458 -37
  296. data/spec/selenium_spec_chrome.rb +196 -9
  297. data/spec/selenium_spec_chrome_remote.rb +100 -0
  298. data/spec/selenium_spec_edge.rb +47 -0
  299. data/spec/selenium_spec_firefox.rb +210 -0
  300. data/spec/selenium_spec_firefox_remote.rb +80 -0
  301. data/spec/selenium_spec_ie.rb +150 -0
  302. data/spec/selenium_spec_safari.rb +148 -0
  303. data/spec/server_spec.rb +200 -101
  304. data/spec/session_spec.rb +91 -0
  305. data/spec/shared_selenium_node.rb +83 -0
  306. data/spec/shared_selenium_session.rb +558 -0
  307. data/spec/spec_helper.rb +94 -2
  308. data/spec/xpath_builder_spec.rb +93 -0
  309. metadata +420 -60
  310. data/lib/capybara/query.rb +0 -7
  311. data/lib/capybara/spec/session/assert_current_path.rb +0 -60
  312. data/lib/capybara/spec/session/assert_selector.rb +0 -148
  313. data/lib/capybara/spec/session/assert_text.rb +0 -196
  314. data/lib/capybara/spec/session/assert_title.rb +0 -70
  315. data/lib/capybara/spec/session/source_spec.rb +0 -0
  316. data/lib/capybara/spec/session/within_frame_spec.rb +0 -53
  317. data/spec/rspec/matchers_spec.rb +0 -827
  318. data/spec/selenium_spec.rb +0 -151
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module XPath
4
+ class Renderer
5
+ def join(*expressions)
6
+ expressions.join('/')
7
+ end
8
+ end
9
+ end
10
+
11
+ module XPath
12
+ module DSL
13
+ def join(*expressions)
14
+ XPath::Expression.new(:join, *[self, expressions].flatten)
15
+ end
16
+ end
17
+ end
@@ -1,379 +1,242 @@
1
1
  # frozen_string_literal: true
2
- require 'capybara/selector/filter'
3
2
 
4
- module Capybara
5
- class Selector
6
-
7
- attr_reader :name, :custom_filters, :format
8
-
9
- class << self
10
- def all
11
- @selectors ||= {}
12
- end
13
-
14
- def add(name, &block)
15
- all[name.to_sym] = Capybara::Selector.new(name.to_sym, &block)
16
- end
17
-
18
- def update(name, &block)
19
- all[name.to_sym].instance_eval(&block)
20
- end
21
-
22
- def remove(name)
23
- all.delete(name.to_sym)
24
- end
25
- end
26
-
27
- def initialize(name, &block)
28
- @name = name
29
- @custom_filters = {}
30
- @match = nil
31
- @label = nil
32
- @failure_message = nil
33
- @description = nil
34
- @format = nil
35
- @expression = nil
36
- instance_eval(&block)
37
- end
38
-
39
- def xpath(&block)
40
- @format, @expression = :xpath, block if block
41
- format == :xpath ? @expression : nil
42
- end
43
-
44
- def css(&block)
45
- @format, @expression = :css, block if block
46
- format == :css ? @expression : nil
47
- end
48
-
49
- def match(&block)
50
- @match = block if block
51
- @match
52
- end
53
-
54
- def label(label=nil)
55
- @label = label if label
56
- @label
57
- end
58
-
59
- def description(options={})
60
- (@description && @description.call(options)).to_s
61
- end
62
-
63
- def call(locator)
64
- if format
65
- @expression.call(locator)
66
- else
67
- warn "Selector has no format"
68
- end
69
- end
70
-
71
- def match?(locator)
72
- @match and @match.call(locator)
73
- end
74
-
75
- def filter(name, options={}, &block)
76
- @custom_filters[name] = Filter.new(name, block, options)
77
- end
78
-
79
- def describe &block
80
- @description = block
81
- end
82
-
83
- private
84
-
85
- def locate_field(xpath, locator)
86
- locate_field = xpath[XPath.attr(:id).equals(locator) |
87
- XPath.attr(:name).equals(locator) |
88
- XPath.attr(:placeholder).equals(locator) |
89
- XPath.attr(:id).equals(XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for))]
90
- locate_field += XPath.descendant(:label)[XPath.string.n.is(locator)].descendant(xpath)
91
- locate_field
92
- end
93
- end
94
- end
95
-
96
- Capybara.add_selector(:xpath) do
97
- xpath { |xpath| xpath }
98
- end
99
-
100
- Capybara.add_selector(:css) do
101
- css { |css| css }
102
- end
103
-
104
- Capybara.add_selector(:id) do
105
- xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
106
- end
107
-
108
- Capybara.add_selector(:field) do
109
- xpath do |locator|
110
- xpath = XPath.descendant(:input, :textarea, :select)[~XPath.attr(:type).one_of('submit', 'image', 'hidden')]
111
- xpath = locate_field(xpath, locator.to_s) unless locator.nil?
112
- xpath
113
- end
114
- filter(:checked, boolean: true) { |node, value| not(value ^ node.checked?) }
115
- filter(:unchecked, boolean: true) { |node, value| (value ^ node.checked?) }
116
- filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
117
- filter(:readonly, boolean: true) { |node, value| not(value ^ node[:readonly]) }
118
- filter(:with) { |node, with| node.value == with.to_s }
119
- filter(:type) do |node, type|
120
- if ['textarea', 'select'].include?(type)
121
- node.tag_name == type
122
- else
123
- node[:type] == type
124
- end
125
- end
126
- filter(:multiple, boolean: true) { |node, value| !(value ^ node[:multiple]) }
127
- describe do |options|
128
- desc, states = String.new, []
129
- desc << " of type #{options[:type].inspect}" if options[:type]
130
- desc << " with value #{options[:with].to_s.inspect}" if options.has_key?(:with)
131
- states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
132
- states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
133
- states << 'disabled' if options[:disabled] == true
134
- desc << " that is #{states.join(' and ')}" unless states.empty?
135
- desc << " with the multiple attribute" if options[:multiple] == true
136
- desc << " without the multiple attribute" if options[:multiple] === false
3
+ require 'capybara/selector/xpath_extensions'
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>, 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 # rubocop:disable Lint/EmptyClass
175
+
176
+ Capybara::Selector::FilterSet.add(:_field) do
177
+ node_filter(:checked, :boolean) { |node, value| !(value ^ node.checked?) }
178
+ node_filter(:unchecked, :boolean) { |node, value| (value ^ node.checked?) }
179
+ node_filter(:disabled, :boolean, default: false, skip_if: :all) { |node, value| !(value ^ node.disabled?) }
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
187
+ end
188
+ end
189
+
190
+ expression_filter(:name) do |xpath, val|
191
+ builder(xpath).add_attribute_conditions(name: val)
192
+ end
193
+ expression_filter(:placeholder) do |xpath, val|
194
+ builder(xpath).add_attribute_conditions(placeholder: val)
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)] }
198
+
199
+ describe(:expression_filters) do |name: nil, placeholder: nil, disabled: nil, multiple: nil, **|
200
+ desc = +''
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
137
206
  desc
138
207
  end
139
- end
140
-
141
- Capybara.add_selector(:fieldset) do
142
- xpath do |locator|
143
- xpath = XPath.descendant(:fieldset)
144
- xpath = xpath[XPath.attr(:id).equals(locator.to_s) | XPath.child(:legend)[XPath.string.n.is(locator.to_s)]] unless locator.nil?
145
- xpath
146
- end
147
- end
148
-
149
- Capybara.add_selector(:link) do
150
- xpath do |locator|
151
- xpath = XPath.descendant(:a)[XPath.attr(:href)]
152
- unless locator.nil?
153
- locator = locator.to_s
154
- xpath = xpath[XPath.attr(:id).equals(locator) |
155
- XPath.string.n.is(locator) |
156
- XPath.attr(:title).is(locator) |
157
- XPath.descendant(:img)[XPath.attr(:alt).is(locator)]]
158
- end
159
- xpath
160
- end
161
-
162
- filter(:href) do |node, href|
163
- if href.is_a? Regexp
164
- node[:href].match href
165
- else
166
- node.first(:xpath, XPath.axis(:self)[XPath.attr(:href).equals(href.to_s)], minimum: 0)
167
- end
168
- end
169
-
170
- describe { |options| " with href #{options[:href].inspect}" if options[:href] }
171
- end
172
-
173
- Capybara.add_selector(:button) do
174
- xpath do |locator|
175
- input_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')]
176
- btn_xpath = XPath.descendant(:button)
177
- image_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).equals('image')]
178
-
179
- unless locator.nil?
180
- locator = locator.to_s
181
- input_btn_xpath = input_btn_xpath[XPath.attr(:id).equals(locator) | XPath.attr(:value).is(locator) | XPath.attr(:title).is(locator)]
182
- btn_xpath = btn_xpath[XPath.attr(:id).equals(locator) | XPath.attr(:value).is(locator) | XPath.string.n.is(locator) | XPath.attr(:title).is(locator)]
183
- image_btn_xpath = image_btn_xpath[XPath.attr(:alt).is(locator)]
184
- end
185
-
186
- input_btn_xpath + btn_xpath + image_btn_xpath
187
- end
188
-
189
- filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
190
208
 
191
- describe { |options| " that is disabled" if options[:disabled] == true }
192
- end
193
-
194
- Capybara.add_selector(:link_or_button) do
195
- label "link or button"
196
- xpath do |locator|
197
- self.class.all.values_at(:link, :button).map {|selector| selector.xpath.call(locator)}.reduce(:+)
198
- end
199
-
200
- filter(:disabled, default: false, boolean: true) { |node, value| node.tag_name == "a" or not(value ^ node.disabled?) }
201
-
202
- describe { |options| " that is disabled" if options[:disabled] }
203
- end
204
-
205
- Capybara.add_selector(:fillable_field) do
206
- label "field"
207
- xpath do |locator|
208
- xpath = XPath.descendant(:input, :textarea)[~XPath.attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')]
209
- xpath = locate_field(xpath, locator.to_s) unless locator.nil?
210
- xpath
211
- end
212
-
213
- filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
214
- filter(:multiple, boolean: true) { |node, value| !(value ^ node[:multiple]) }
215
-
216
- describe do |options|
217
- desc = String.new
218
- desc << " that is disabled" if options[:disabled] == true
219
- desc << " with the multiple attribute" if options[:multiple] == true
220
- desc << " without the multiple attribute" if options[:multiple] === false
221
- desc
222
- end
223
- end
224
-
225
- Capybara.add_selector(:radio_button) do
226
- label "radio button"
227
- xpath do |locator|
228
- xpath = XPath.descendant(:input)[XPath.attr(:type).equals('radio')]
229
- xpath = locate_field(xpath, locator.to_s) unless locator.nil?
230
- xpath
231
- end
232
-
233
- filter(:checked, boolean: true) { |node, value| not(value ^ node.checked?) }
234
- filter(:unchecked, boolean: true) { |node, value| (value ^ node.checked?) }
235
- filter(:option) { |node, value| node.value == value.to_s }
236
- filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
237
-
238
- describe do |options|
239
- desc, states = String.new, []
240
- desc << " with value #{options[:option].inspect}" if options[:option]
241
- states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
242
- states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
243
- states << 'disabled' if options[:disabled] == true
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
244
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
245
218
  desc
246
219
  end
247
220
  end
248
221
 
249
- Capybara.add_selector(:checkbox) do
250
- xpath do |locator|
251
- xpath = XPath.descendant(:input)[XPath.attr(:type).equals('checkbox')]
252
- xpath = locate_field(xpath, locator.to_s) unless locator.nil?
253
- xpath
254
- end
255
-
256
- filter(:checked, boolean: true) { |node, value| not(value ^ node.checked?) }
257
- filter(:unchecked, boolean: true) { |node, value| (value ^ node.checked?) }
258
- filter(:option) { |node, value| node.value == value.to_s }
259
- filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
260
-
261
- describe do |options|
262
- desc, states = String.new, []
263
- desc << " with value #{options[:option].inspect}" if options[:option]
264
- states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
265
- states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
266
- states << 'disabled' if options[:disabled] == true
267
- desc << " that is #{states.join(' and ')}" unless states.empty?
268
- desc
269
- end
270
- end
271
-
272
- Capybara.add_selector(:select) do
273
- label "select box"
274
- xpath do |locator|
275
- xpath = XPath.descendant(:select)
276
- xpath = locate_field(xpath, locator.to_s) unless locator.nil?
277
- xpath
278
- end
279
-
280
- filter(:options) do |node, options|
281
- if node.visible?
282
- actual = node.all(:xpath, './/option').map { |option| option.text }
283
- else
284
- actual = node.all(:xpath, './/option', visible: false).map { |option| option.text(:all) }
285
- end
286
- options.sort == actual.sort
287
- end
288
- filter(:with_options) do |node, options|
289
- finder_settings = { minimum: 0 }
290
- if !node.visible?
291
- finder_settings[:visible] = false
292
- end
293
- options.all? { |option| node.first(:option, option, finder_settings) }
294
- end
295
- filter(:selected) do |node, selected|
296
- actual = node.all(:xpath, './/option', visible: false).select { |option| option.selected? }.map { |option| option.text(:all) }
297
- [selected].flatten.sort == actual.sort
298
- end
299
- filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
300
- filter(:multiple, boolean: true) { |node, value| !(value ^ node[:multiple]) }
301
-
302
- describe do |options|
303
- desc = String.new
304
- desc << " with options #{options[:options].inspect}" if options[:options]
305
- desc << " with at least options #{options[:with_options].inspect}" if options[:with_options]
306
- desc << " with #{options[:selected].inspect} selected" if options[:selected]
307
- desc << " that is disabled" if options[:disabled] == true
308
- desc << " that allows multiple selection" if options[:multiple] == true
309
- desc << " that only allows single selection" if options[:multiple] === false
310
- desc
311
- end
312
- end
313
-
314
- Capybara.add_selector(:option) do
315
- xpath do |locator|
316
- xpath = XPath.descendant(:option)
317
- xpath = xpath[XPath.string.n.is(locator.to_s)] unless locator.nil?
318
- xpath
319
- end
320
-
321
- filter(:disabled, boolean: true) { |node, value| not(value ^ node.disabled?) }
322
- filter(:selected, boolean: true) { |node, value| not(value ^ node.selected?) }
323
-
324
- describe do |options|
325
- desc = String.new
326
- desc << " that is#{' not' unless options[:disabled]} disabled" if options.has_key?(:disabled)
327
- desc << " that is#{' not' unless options[:selected]} selected" if options.has_key?(:selected)
328
- desc
329
- end
330
- end
331
-
332
- Capybara.add_selector(:file_field) do
333
- label "file field"
334
- xpath do |locator|
335
- xpath = XPath.descendant(:input)[XPath.attr(:type).equals('file')]
336
- xpath = locate_field(xpath, locator.to_s) unless locator.nil?
337
- xpath
338
- end
339
-
340
- filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
341
- filter(:multiple, boolean: true) { |node, value| !(value ^ node[:multiple]) }
342
-
343
- describe do |options|
344
- desc = String.new
345
- desc << " that is disabled" if options[:disabled] == true
346
- desc << " that allows multiple files" if options[:multiple] == true
347
- desc << " that only allows a single file" if options[:multiple] === false
348
- desc
349
- end
350
- end
351
-
352
- Capybara.add_selector(:label) do
353
- label "label"
354
- xpath do |locator|
355
- xpath = XPath.descendant(:label)
356
- xpath = xpath[XPath.string.n.is(locator.to_s) | XPath.attr(:id).equals(locator.to_s)] unless locator.nil?
357
- xpath
358
- end
359
-
360
- filter(:for) do |node, field_or_value|
361
- if field_or_value.is_a? Capybara::Node::Element
362
- if field_or_value[:id] && (field_or_value[:id] == node[:for])
363
- true
364
- else
365
- field_or_value.find_xpath('./ancestor::label[1]').include? node.base
366
- end
367
- else
368
- node[:for] == field_or_value.to_s
369
- end
370
- end
371
- end
372
-
373
- Capybara.add_selector(:table) do
374
- xpath do |locator|
375
- xpath = XPath.descendant(:table)
376
- xpath = xpath[XPath.attr(:id).equals(locator.to_s) | XPath.descendant(:caption).is(locator.to_s)] unless locator.nil?
377
- xpath
378
- end
379
- end
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'