capybara 2.5.0 → 2.18.0

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 (205) hide show
  1. checksums.yaml +5 -5
  2. data/.yard/templates_custom/default/class/html/selectors.erb +38 -0
  3. data/.yard/templates_custom/default/class/html/setup.rb +17 -0
  4. data/.yard/yard_extensions.rb +78 -0
  5. data/.yardopts +1 -0
  6. data/History.md +413 -10
  7. data/License.txt +1 -1
  8. data/README.md +237 -130
  9. data/lib/capybara/config.rb +132 -0
  10. data/lib/capybara/cucumber.rb +3 -1
  11. data/lib/capybara/driver/base.rb +27 -6
  12. data/lib/capybara/driver/node.rb +14 -5
  13. data/lib/capybara/dsl.rb +2 -3
  14. data/lib/capybara/helpers.rb +13 -65
  15. data/lib/capybara/minitest/spec.rb +177 -0
  16. data/lib/capybara/minitest.rb +278 -0
  17. data/lib/capybara/node/actions.rb +180 -24
  18. data/lib/capybara/node/base.rb +17 -5
  19. data/lib/capybara/node/document.rb +5 -0
  20. data/lib/capybara/node/document_matchers.rb +15 -14
  21. data/lib/capybara/node/element.rb +55 -7
  22. data/lib/capybara/node/finders.rb +179 -67
  23. data/lib/capybara/node/matchers.rb +301 -105
  24. data/lib/capybara/node/simple.rb +15 -4
  25. data/lib/capybara/queries/ancestor_query.rb +25 -0
  26. data/lib/capybara/queries/base_query.rb +69 -3
  27. data/lib/capybara/queries/current_path_query.rb +17 -8
  28. data/lib/capybara/queries/match_query.rb +19 -0
  29. data/lib/capybara/queries/selector_query.rb +251 -0
  30. data/lib/capybara/queries/sibling_query.rb +25 -0
  31. data/lib/capybara/queries/text_query.rb +67 -16
  32. data/lib/capybara/queries/title_query.rb +4 -2
  33. data/lib/capybara/query.rb +3 -131
  34. data/lib/capybara/rack_test/browser.rb +14 -5
  35. data/lib/capybara/rack_test/css_handlers.rb +1 -0
  36. data/lib/capybara/rack_test/driver.rb +15 -8
  37. data/lib/capybara/rack_test/form.rb +34 -12
  38. data/lib/capybara/rack_test/node.rb +29 -12
  39. data/lib/capybara/rails.rb +3 -3
  40. data/lib/capybara/result.rb +104 -9
  41. data/lib/capybara/rspec/compound.rb +95 -0
  42. data/lib/capybara/rspec/features.rb +17 -6
  43. data/lib/capybara/rspec/matcher_proxies.rb +45 -0
  44. data/lib/capybara/rspec/matchers.rb +199 -80
  45. data/lib/capybara/rspec.rb +4 -2
  46. data/lib/capybara/selector/css.rb +30 -0
  47. data/lib/capybara/selector/filter.rb +20 -0
  48. data/lib/capybara/selector/filter_set.rb +74 -0
  49. data/lib/capybara/selector/filters/base.rb +33 -0
  50. data/lib/capybara/selector/filters/expression_filter.rb +40 -0
  51. data/lib/capybara/selector/filters/node_filter.rb +27 -0
  52. data/lib/capybara/selector/selector.rb +276 -0
  53. data/lib/capybara/selector.rb +452 -157
  54. data/lib/capybara/selenium/driver.rb +282 -81
  55. data/lib/capybara/selenium/node.rb +144 -46
  56. data/lib/capybara/server.rb +59 -16
  57. data/lib/capybara/session/config.rb +114 -0
  58. data/lib/capybara/session/matchers.rb +29 -19
  59. data/lib/capybara/session.rb +378 -143
  60. data/lib/capybara/spec/fixtures/no_extension +1 -0
  61. data/lib/capybara/spec/public/jquery-ui.js +13 -791
  62. data/lib/capybara/spec/public/jquery.js +4 -9045
  63. data/lib/capybara/spec/public/test.js +45 -11
  64. data/lib/capybara/spec/session/accept_alert_spec.rb +30 -7
  65. data/lib/capybara/spec/session/accept_confirm_spec.rb +14 -2
  66. data/lib/capybara/spec/session/accept_prompt_spec.rb +35 -6
  67. data/lib/capybara/spec/session/all_spec.rb +45 -32
  68. data/lib/capybara/spec/session/ancestor_spec.rb +85 -0
  69. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +110 -0
  70. data/lib/capybara/spec/session/assert_current_path.rb +15 -2
  71. data/lib/capybara/spec/session/assert_selector.rb +29 -28
  72. data/lib/capybara/spec/session/assert_text.rb +59 -20
  73. data/lib/capybara/spec/session/assert_title.rb +25 -11
  74. data/lib/capybara/spec/session/attach_file_spec.rb +42 -4
  75. data/lib/capybara/spec/session/body_spec.rb +1 -0
  76. data/lib/capybara/spec/session/check_spec.rb +90 -14
  77. data/lib/capybara/spec/session/choose_spec.rb +31 -5
  78. data/lib/capybara/spec/session/click_button_spec.rb +20 -9
  79. data/lib/capybara/spec/session/click_link_or_button_spec.rb +15 -9
  80. data/lib/capybara/spec/session/click_link_spec.rb +39 -15
  81. data/lib/capybara/spec/session/current_scope_spec.rb +2 -1
  82. data/lib/capybara/spec/session/current_url_spec.rb +12 -3
  83. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +6 -5
  84. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +4 -3
  85. data/lib/capybara/spec/session/element/assert_match_selector.rb +36 -0
  86. data/lib/capybara/spec/session/element/match_css_spec.rb +23 -0
  87. data/lib/capybara/spec/session/element/match_xpath_spec.rb +23 -0
  88. data/lib/capybara/spec/session/element/matches_selector_spec.rb +106 -0
  89. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +22 -0
  90. data/lib/capybara/spec/session/evaluate_script_spec.rb +23 -1
  91. data/lib/capybara/spec/session/execute_script_spec.rb +22 -3
  92. data/lib/capybara/spec/session/fill_in_spec.rb +50 -32
  93. data/lib/capybara/spec/session/find_button_spec.rb +43 -2
  94. data/lib/capybara/spec/session/find_by_id_spec.rb +3 -2
  95. data/lib/capybara/spec/session/find_field_spec.rb +42 -6
  96. data/lib/capybara/spec/session/find_link_spec.rb +22 -3
  97. data/lib/capybara/spec/session/find_spec.rb +103 -57
  98. data/lib/capybara/spec/session/first_spec.rb +34 -18
  99. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +103 -0
  100. data/lib/capybara/spec/session/{within_frame_spec.rb → frame/within_frame_spec.rb} +44 -2
  101. data/lib/capybara/spec/session/go_back_spec.rb +2 -1
  102. data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
  103. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  104. data/lib/capybara/spec/session/has_button_spec.rb +17 -8
  105. data/lib/capybara/spec/session/has_css_spec.rb +85 -73
  106. data/lib/capybara/spec/session/has_current_path_spec.rb +91 -7
  107. data/lib/capybara/spec/session/has_field_spec.rb +93 -58
  108. data/lib/capybara/spec/session/has_link_spec.rb +9 -8
  109. data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
  110. data/lib/capybara/spec/session/has_select_spec.rb +159 -59
  111. data/lib/capybara/spec/session/has_selector_spec.rb +64 -28
  112. data/lib/capybara/spec/session/has_table_spec.rb +1 -0
  113. data/lib/capybara/spec/session/has_text_spec.rb +27 -12
  114. data/lib/capybara/spec/session/has_title_spec.rb +22 -4
  115. data/lib/capybara/spec/session/has_xpath_spec.rb +32 -29
  116. data/lib/capybara/spec/session/headers.rb +2 -1
  117. data/lib/capybara/spec/session/html_spec.rb +4 -3
  118. data/lib/capybara/spec/session/node_spec.rb +198 -38
  119. data/lib/capybara/spec/session/refresh_spec.rb +28 -0
  120. data/lib/capybara/spec/session/reset_session_spec.rb +46 -5
  121. data/lib/capybara/spec/session/response_code.rb +2 -1
  122. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  123. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -5
  124. data/lib/capybara/spec/session/save_page_spec.rb +34 -2
  125. data/lib/capybara/spec/session/save_screenshot_spec.rb +31 -1
  126. data/lib/capybara/spec/session/screenshot_spec.rb +4 -2
  127. data/lib/capybara/spec/session/select_spec.rb +34 -32
  128. data/lib/capybara/spec/session/selectors_spec.rb +65 -0
  129. data/lib/capybara/spec/session/sibling_spec.rb +52 -0
  130. data/lib/capybara/spec/session/text_spec.rb +4 -4
  131. data/lib/capybara/spec/session/title_spec.rb +2 -1
  132. data/lib/capybara/spec/session/uncheck_spec.rb +42 -2
  133. data/lib/capybara/spec/session/unselect_spec.rb +17 -16
  134. data/lib/capybara/spec/session/visit_spec.rb +77 -2
  135. data/lib/capybara/spec/session/window/become_closed_spec.rb +12 -11
  136. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  137. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  138. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +16 -11
  139. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +7 -4
  140. data/lib/capybara/spec/session/window/window_spec.rb +36 -29
  141. data/lib/capybara/spec/session/window/windows_spec.rb +1 -0
  142. data/lib/capybara/spec/session/window/within_window_spec.rb +31 -7
  143. data/lib/capybara/spec/session/within_spec.rb +14 -6
  144. data/lib/capybara/spec/spec_helper.rb +37 -4
  145. data/lib/capybara/spec/test_app.rb +15 -3
  146. data/lib/capybara/spec/views/buttons.erb +1 -0
  147. data/lib/capybara/spec/views/fieldsets.erb +2 -1
  148. data/lib/capybara/spec/views/form.erb +169 -9
  149. data/lib/capybara/spec/views/frame_child.erb +10 -2
  150. data/lib/capybara/spec/views/frame_one.erb +2 -1
  151. data/lib/capybara/spec/views/frame_parent.erb +3 -2
  152. data/lib/capybara/spec/views/frame_two.erb +2 -1
  153. data/lib/capybara/spec/views/header_links.erb +1 -0
  154. data/lib/capybara/spec/views/host_links.erb +1 -0
  155. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  156. data/lib/capybara/spec/views/path.erb +1 -0
  157. data/lib/capybara/spec/views/popup_one.erb +1 -0
  158. data/lib/capybara/spec/views/popup_two.erb +1 -0
  159. data/lib/capybara/spec/views/postback.erb +2 -1
  160. data/lib/capybara/spec/views/tables.erb +1 -0
  161. data/lib/capybara/spec/views/with_base_tag.erb +1 -0
  162. data/lib/capybara/spec/views/with_count.erb +2 -1
  163. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  164. data/lib/capybara/spec/views/with_hover.erb +7 -1
  165. data/lib/capybara/spec/views/with_html.erb +40 -2
  166. data/lib/capybara/spec/views/with_html_entities.erb +1 -0
  167. data/lib/capybara/spec/views/with_js.erb +32 -1
  168. data/lib/capybara/spec/views/with_scope.erb +1 -0
  169. data/lib/capybara/spec/views/with_simple_html.erb +2 -1
  170. data/lib/capybara/spec/views/with_slow_unload.erb +17 -0
  171. data/lib/capybara/spec/views/with_title.erb +2 -1
  172. data/lib/capybara/spec/views/with_unload_alert.erb +14 -0
  173. data/lib/capybara/spec/views/with_windows.erb +7 -0
  174. data/lib/capybara/spec/views/within_frames.erb +3 -2
  175. data/lib/capybara/version.rb +2 -1
  176. data/lib/capybara/window.rb +20 -3
  177. data/lib/capybara.rb +189 -93
  178. data/spec/basic_node_spec.rb +7 -6
  179. data/spec/capybara_spec.rb +90 -4
  180. data/spec/dsl_spec.rb +3 -1
  181. data/spec/filter_set_spec.rb +28 -0
  182. data/spec/fixtures/capybara.csv +1 -0
  183. data/spec/fixtures/selenium_driver_rspec_failure.rb +5 -1
  184. data/spec/fixtures/selenium_driver_rspec_success.rb +5 -1
  185. data/spec/minitest_spec.rb +130 -0
  186. data/spec/minitest_spec_spec.rb +135 -0
  187. data/spec/per_session_config_spec.rb +67 -0
  188. data/spec/rack_test_spec.rb +50 -7
  189. data/spec/result_spec.rb +76 -0
  190. data/spec/rspec/features_spec.rb +21 -8
  191. data/spec/rspec/scenarios_spec.rb +21 -0
  192. data/spec/rspec/{matchers_spec.rb → shared_spec_matchers.rb} +160 -54
  193. data/spec/rspec/views_spec.rb +5 -0
  194. data/spec/rspec_matchers_spec.rb +46 -0
  195. data/spec/rspec_spec.rb +79 -1
  196. data/spec/selector_spec.rb +199 -0
  197. data/spec/selenium_spec_chrome.rb +54 -9
  198. data/spec/selenium_spec_firefox.rb +68 -0
  199. data/spec/selenium_spec_marionette.rb +127 -0
  200. data/spec/server_spec.rb +102 -14
  201. data/spec/session_spec.rb +54 -0
  202. data/spec/shared_selenium_session.rb +215 -0
  203. data/spec/spec_helper.rb +7 -0
  204. metadata +140 -15
  205. data/spec/selenium_spec.rb +0 -128
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  Capybara::SpecHelper.spec '#has_xpath?' do
2
3
  before do
3
4
  @session.visit('/with_html')
@@ -27,37 +28,39 @@ Capybara::SpecHelper.spec '#has_xpath?' do
27
28
  end
28
29
  end
29
30
 
30
- it "should wait for content to appear", :requires => [:js] do
31
- @session.visit('/with_js')
32
- @session.click_link('Click me')
33
- expect(@session).to have_xpath("//input[@type='submit' and @value='New Here']")
31
+ it "should wait for content to appear", requires: [:js] do
32
+ Capybara.using_wait_time(3) do
33
+ @session.visit('/with_js')
34
+ @session.click_link('Click me') # updates page after 500ms
35
+ expect(@session).to have_xpath("//input[@type='submit' and @value='New Here']")
36
+ end
34
37
  end
35
38
 
36
39
  context "with count" do
37
40
  it "should be true if the content occurs the given number of times" do
38
- expect(@session).to have_xpath("//p", :count => 3)
39
- expect(@session).to have_xpath("//p//a[@id='foo']", :count => 1)
40
- expect(@session).to have_xpath("//p[contains(.,'est')]", :count => 1)
41
- expect(@session).to have_xpath("//p//a[@id='doesnotexist']", :count => 0)
41
+ expect(@session).to have_xpath("//p", count: 3)
42
+ expect(@session).to have_xpath("//p//a[@id='foo']", count: 1)
43
+ expect(@session).to have_xpath("//p[contains(.,'est')]", count: 1)
44
+ expect(@session).to have_xpath("//p//a[@id='doesnotexist']", count: 0)
42
45
  end
43
46
 
44
47
  it "should be false if the content occurs a different number of times than the given" do
45
- expect(@session).not_to have_xpath("//p", :count => 6)
46
- expect(@session).not_to have_xpath("//p//a[@id='foo']", :count => 2)
47
- expect(@session).not_to have_xpath("//p[contains(.,'est')]", :count => 5)
48
- expect(@session).not_to have_xpath("//p//a[@id='doesnotexist']", :count => 1)
48
+ expect(@session).not_to have_xpath("//p", count: 6)
49
+ expect(@session).not_to have_xpath("//p//a[@id='foo']", count: 2)
50
+ expect(@session).not_to have_xpath("//p[contains(.,'est')]", count: 5)
51
+ expect(@session).not_to have_xpath("//p//a[@id='doesnotexist']", count: 1)
49
52
  end
50
53
  end
51
54
 
52
55
  context "with text" do
53
56
  it "should discard all matches where the given string is not contained" do
54
- expect(@session).to have_xpath("//p//a", :text => "Redirect", :count => 1)
55
- expect(@session).not_to have_xpath("//p", :text => "Doesnotexist")
57
+ expect(@session).to have_xpath("//p//a", text: "Redirect", count: 1)
58
+ expect(@session).not_to have_xpath("//p", text: "Doesnotexist")
56
59
  end
57
60
 
58
61
  it "should discard all matches where the given regexp is not matched" do
59
- expect(@session).to have_xpath("//p//a", :text => /re[dab]i/i, :count => 1)
60
- expect(@session).not_to have_xpath("//p//a", :text => /Red$/)
62
+ expect(@session).to have_xpath("//p//a", text: /re[dab]i/i, count: 1)
63
+ expect(@session).not_to have_xpath("//p//a", text: /Red$/)
61
64
  end
62
65
  end
63
66
  end
@@ -91,7 +94,7 @@ Capybara::SpecHelper.spec '#has_no_xpath?' do
91
94
  end
92
95
  end
93
96
 
94
- it "should wait for content to disappear", :requires => [:js] do
97
+ it "should wait for content to disappear", requires: [:js] do
95
98
  @session.visit('/with_js')
96
99
  @session.click_link('Click me')
97
100
  expect(@session).to have_no_xpath("//p[@id='change']")
@@ -99,29 +102,29 @@ Capybara::SpecHelper.spec '#has_no_xpath?' do
99
102
 
100
103
  context "with count" do
101
104
  it "should be false if the content occurs the given number of times" do
102
- expect(@session).not_to have_no_xpath("//p", :count => 3)
103
- expect(@session).not_to have_no_xpath("//p//a[@id='foo']", :count => 1)
104
- expect(@session).not_to have_no_xpath("//p[contains(.,'est')]", :count => 1)
105
- expect(@session).not_to have_no_xpath("//p//a[@id='doesnotexist']", :count => 0)
105
+ expect(@session).not_to have_no_xpath("//p", count: 3)
106
+ expect(@session).not_to have_no_xpath("//p//a[@id='foo']", count: 1)
107
+ expect(@session).not_to have_no_xpath("//p[contains(.,'est')]", count: 1)
108
+ expect(@session).not_to have_no_xpath("//p//a[@id='doesnotexist']", count: 0)
106
109
  end
107
110
 
108
111
  it "should be true if the content occurs a different number of times than the given" do
109
- expect(@session).to have_no_xpath("//p", :count => 6)
110
- expect(@session).to have_no_xpath("//p//a[@id='foo']", :count => 2)
111
- expect(@session).to have_no_xpath("//p[contains(.,'est')]", :count => 5)
112
- expect(@session).to have_no_xpath("//p//a[@id='doesnotexist']", :count => 1)
112
+ expect(@session).to have_no_xpath("//p", count: 6)
113
+ expect(@session).to have_no_xpath("//p//a[@id='foo']", count: 2)
114
+ expect(@session).to have_no_xpath("//p[contains(.,'est')]", count: 5)
115
+ expect(@session).to have_no_xpath("//p//a[@id='doesnotexist']", count: 1)
113
116
  end
114
117
  end
115
118
 
116
119
  context "with text" do
117
120
  it "should discard all matches where the given string is contained" do
118
- expect(@session).not_to have_no_xpath("//p//a", :text => "Redirect", :count => 1)
119
- expect(@session).to have_no_xpath("//p", :text => "Doesnotexist")
121
+ expect(@session).not_to have_no_xpath("//p//a", text: "Redirect", count: 1)
122
+ expect(@session).to have_no_xpath("//p", text: "Doesnotexist")
120
123
  end
121
124
 
122
125
  it "should discard all matches where the given regexp is matched" do
123
- expect(@session).not_to have_no_xpath("//p//a", :text => /re[dab]i/i, :count => 1)
124
- expect(@session).to have_no_xpath("//p//a", :text => /Red$/)
126
+ expect(@session).not_to have_no_xpath("//p//a", text: /re[dab]i/i, count: 1)
127
+ expect(@session).to have_no_xpath("//p//a", text: /Red$/)
125
128
  end
126
129
  end
127
130
  end
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  Capybara::SpecHelper.spec '#response_headers' do
2
- it "should return response headers", :requires => [:response_headers] do
3
+ it "should return response headers", requires: [:response_headers] do
3
4
  @session.visit('/with_simple_html')
4
5
  expect(@session.response_headers['Content-Type']).to match %r(text/html)
5
6
  end
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  Capybara::SpecHelper.spec '#html' do
2
3
  it "should return the unmodified page body" do
3
4
  @session.visit('/')
4
5
  expect(@session.html).to include('Hello world!')
5
6
  end
6
7
 
7
- it "should return the current state of the page", :requires => [:js] do
8
+ it "should return the current state of the page", requires: [:js] do
8
9
  @session.visit('/with_js')
9
10
  expect(@session.html).to include('I changed it')
10
11
  expect(@session.html).not_to include('This is text')
@@ -17,7 +18,7 @@ Capybara::SpecHelper.spec '#source' do
17
18
  expect(@session.source).to include('Hello world!')
18
19
  end
19
20
 
20
- it "should return the current state of the page", :requires => [:js] do
21
+ it "should return the current state of the page", requires: [:js] do
21
22
  @session.visit('/with_js')
22
23
  expect(@session.source).to include('I changed it')
23
24
  expect(@session.source).not_to include('This is text')
@@ -30,7 +31,7 @@ Capybara::SpecHelper.spec '#body' do
30
31
  expect(@session.body).to include('Hello world!')
31
32
  end
32
33
 
33
- it "should return the current state of the page", :requires => [:js] do
34
+ it "should return the current state of the page", requires: [:js] do
34
35
  @session.visit('/with_js')
35
36
  expect(@session.body).to include('I changed it')
36
37
  expect(@session.body).not_to include('This is text')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Capybara::SpecHelper.spec "node" do
2
4
  before do
3
5
  @session.visit('/with_html')
@@ -8,7 +10,7 @@ Capybara::SpecHelper.spec "node" do
8
10
  @form = @session.find(:css, '#get-form')
9
11
  expect(@form).to have_field('Middle Name')
10
12
  expect(@form).to have_no_field('Languages')
11
- @form.fill_in('Middle Name', :with => 'Monkey')
13
+ @form.fill_in('Middle Name', with: 'Monkey')
12
14
  @form.click_button('med')
13
15
  expect(extract_results(@session)['middle_name']).to eq('Monkey')
14
16
  end
@@ -17,11 +19,19 @@ Capybara::SpecHelper.spec "node" do
17
19
  expect(@session.find(:css, '#second')).to have_no_css('h1')
18
20
  end
19
21
 
22
+ describe "#query_scope" do
23
+ it "should have a reference to the element the query was evaluated on if there is one" do
24
+ @node = @session.find(:css, '#first')
25
+ expect(@node.query_scope).to eq(@node.session.document)
26
+ expect(@node.find(:css, '#foo').query_scope).to eq(@node)
27
+ end
28
+ end
29
+
20
30
  describe "#parent" do
21
- it "should have a reference to its parent if there is one" do
31
+ it "should be deprecated" do
22
32
  @node = @session.find(:css, '#first')
23
- expect(@node.parent).to eq(@node.session.document)
24
- expect(@node.find(:css, '#foo').parent).to eq(@node)
33
+ expect(@node).to receive(:warn).with(/^DEPRECATED:/)
34
+ expect(@node.parent).to eq(@node.query_scope)
25
35
  end
26
36
  end
27
37
 
@@ -86,7 +96,7 @@ Capybara::SpecHelper.spec "node" do
86
96
  expect(@session.first('//input').value).to eq('gorilla')
87
97
  end
88
98
 
89
- it "should fill the field even if the caret was not at the end", :requires => [:js] do
99
+ it "should fill the field even if the caret was not at the end", requires: [:js] do
90
100
  @session.execute_script("var el = document.getElementById('test_field'); el.focus(); el.setSelectionRange(0, 0);")
91
101
  @session.first('//input').set('')
92
102
  expect(@session.first('//input').value).to eq('')
@@ -112,23 +122,25 @@ Capybara::SpecHelper.spec "node" do
112
122
  expect(@session.first('//textarea[@readonly]').set('changed')).to raise_error(Capybara::ReadOnlyElementError)
113
123
  end if Capybara::VERSION.to_f > 3.0
114
124
 
115
- it 'should allow me to change the contents of a contenteditable element', :requires => [:js] do
116
- @session.visit('/with_js')
117
- @session.find(:css,'#existing_content_editable').set('WYSIWYG')
118
- expect(@session.find(:css,'#existing_content_editable').text).to eq('WYSIWYG')
119
- end
125
+ context "with a contenteditable element", requires: [:js] do
126
+ it 'should allow me to change the contents' do
127
+ @session.visit('/with_js')
128
+ @session.find(:css,'#existing_content_editable').set('WYSIWYG')
129
+ expect(@session.find(:css,'#existing_content_editable').text).to eq('WYSIWYG')
130
+ end
120
131
 
121
- it 'should allow me to set the contents of a contenteditable element', :requires => [:js] do
122
- @session.visit('/with_js')
123
- @session.find(:css,'#blank_content_editable').set('WYSIWYG')
124
- expect(@session.find(:css,'#blank_content_editable').text).to eq('WYSIWYG')
125
- end
132
+ it 'should allow me to set the contents' do
133
+ @session.visit('/with_js')
134
+ @session.find(:css,'#blank_content_editable').set('WYSIWYG')
135
+ expect(@session.find(:css,'#blank_content_editable').text).to eq('WYSIWYG')
136
+ end
126
137
 
127
- it 'should allow me to change the contents of a contenteditable elements child', :requires => [:js] do
128
- pending "Selenium doesn't like editing nested contents"
129
- @session.visit('/with_js')
130
- @session.find(:css,'#existing_content_editable_child').set('WYSIWYG')
131
- expect(@session.find(:css,'#existing_content_editable_child').text).to eq('WYSIWYG')
138
+ it 'should allow me to change the contents of a child element' do
139
+ @session.visit('/with_js')
140
+ @session.find(:css,'#existing_content_editable_child').set('WYSIWYG')
141
+ expect(@session.find(:css,'#existing_content_editable_child').text).to eq('WYSIWYG')
142
+ expect(@session.find(:css,'#existing_content_editable_child_parent').text).to eq('Some content WYSIWYG')
143
+ end
132
144
  end
133
145
  end
134
146
 
@@ -156,8 +168,41 @@ Capybara::SpecHelper.spec "node" do
156
168
  it "should see enabled options in disabled select as disabled" do
157
169
  @session.visit('/form')
158
170
  expect(@session.find('//select[@id="form_disabled_select"]/option')).to be_disabled
171
+ expect(@session.find('//select[@id="form_disabled_select"]/optgroup/option')).to be_disabled
159
172
  expect(@session.find('//select[@id="form_title"]/option[1]')).not_to be_disabled
160
173
  end
174
+
175
+ it "should see enabled options in disabled optgroup as disabled" do
176
+ @session.visit('/form')
177
+ expect(@session.find('//option', text: "A.B.1")).to be_disabled
178
+ expect(@session.find('//option', text: "A.2")).not_to be_disabled
179
+ end
180
+
181
+ context "in a disabled fieldset" do
182
+ # https://html.spec.whatwg.org/#the-fieldset-element
183
+ it "should see elements not in first legend as disabled" do
184
+ @session.visit('/form')
185
+ expect(@session.find('//input[@id="form_disabled_fieldset_child"]')).to be_disabled
186
+ expect(@session.find('//input[@id="form_disabled_fieldset_second_legend_child"]')).to be_disabled
187
+ expect(@session.find('//input[@id="form_enabled_fieldset_child"]')).not_to be_disabled
188
+ end
189
+
190
+ it "should see elements in first legend as enabled" do
191
+ @session.visit('/form')
192
+ expect(@session.find('//input[@id="form_disabled_fieldset_legend_child"]')).not_to be_disabled
193
+ end
194
+
195
+ it "should sees options not in first legend as disabled" do
196
+ @session.visit('/form')
197
+ expect(@session.find('//option', text: 'Disabled Child Option')).to be_disabled
198
+ end
199
+ end
200
+ it "should be boolean" do
201
+ @session.visit('/form')
202
+ expect(@session.find('//select[@id="form_disabled_select"]/option').disabled?).to be true
203
+ expect(@session.find('//select[@id="form_disabled_select2"]/option').disabled?).to be true
204
+ expect(@session.find('//select[@id="form_title"]/option[1]').disabled?).to be false
205
+ end
161
206
  end
162
207
 
163
208
  describe "#visible?" do
@@ -169,6 +214,13 @@ Capybara::SpecHelper.spec "node" do
169
214
  expect(@session.find('//div[@id="hidden_via_ancestor"]')).not_to be_visible
170
215
  expect(@session.find('//div[@id="hidden_attr"]')).not_to be_visible
171
216
  expect(@session.find('//a[@id="hidden_attr_via_ancestor"]')).not_to be_visible
217
+ expect(@session.find('//input[@id="hidden_input"]')).not_to be_visible
218
+ end
219
+
220
+ it "should be boolean" do
221
+ Capybara.ignore_hidden_elements = false
222
+ expect(@session.first('//a').visible?).to be true
223
+ expect(@session.find('//div[@id="hidden"]').visible?).to be false
172
224
  end
173
225
  end
174
226
 
@@ -179,6 +231,13 @@ Capybara::SpecHelper.spec "node" do
179
231
  expect(@session.find('//input[@id="gender_male"]')).not_to be_checked
180
232
  expect(@session.first('//h1')).not_to be_checked
181
233
  end
234
+
235
+ it "should be boolean" do
236
+ @session.visit('/form')
237
+ expect(@session.find('//input[@id="gender_female"]').checked?).to be true
238
+ expect(@session.find('//input[@id="gender_male"]').checked?).to be false
239
+ expect(@session.find('//input[@id="no_attr_value_checked"]').checked?).to be true
240
+ end
182
241
  end
183
242
 
184
243
  describe "#selected?" do
@@ -188,6 +247,13 @@ Capybara::SpecHelper.spec "node" do
188
247
  expect(@session.find('//option[@value="sv"]')).not_to be_selected
189
248
  expect(@session.first('//h1')).not_to be_selected
190
249
  end
250
+
251
+ it "should be boolean" do
252
+ @session.visit('/form')
253
+ expect(@session.find('//option[@value="en"]').selected?).to be true
254
+ expect(@session.find('//option[@value="sv"]').selected?).to be false
255
+ expect(@session.first('//h1').selected?).to be false
256
+ end
191
257
  end
192
258
 
193
259
  describe "#==" do
@@ -215,7 +281,7 @@ Capybara::SpecHelper.spec "node" do
215
281
  end
216
282
  end
217
283
 
218
- describe "#trigger", :requires => [:js, :trigger] do
284
+ describe "#trigger", requires: [:js, :trigger] do
219
285
  it "should allow triggering of custom JS events" do
220
286
  @session.visit('/with_js')
221
287
  @session.find(:css, '#with_focus_event').trigger(:focus)
@@ -223,7 +289,7 @@ Capybara::SpecHelper.spec "node" do
223
289
  end
224
290
  end
225
291
 
226
- describe '#drag_to', :requires => [:js, :drag] do
292
+ describe '#drag_to', requires: [:js, :drag] do
227
293
  it "should drag and drop an object" do
228
294
  @session.visit('/with_js')
229
295
  element = @session.find('//div[@id="drag"]')
@@ -231,14 +297,29 @@ Capybara::SpecHelper.spec "node" do
231
297
  element.drag_to(target)
232
298
  expect(@session.find('//div[contains(., "Dropped!")]')).not_to be_nil
233
299
  end
300
+
301
+ it "should drag and drop if scrolling is needed" do
302
+ @session.visit('/with_js')
303
+ element = @session.find('//div[@id="drag_scroll"]')
304
+ target = @session.find('//div[@id="drop_scroll"]')
305
+ element.drag_to(target)
306
+ expect(@session.find('//div[contains(., "Dropped!")]')).not_to be_nil
307
+ end
234
308
  end
235
309
 
236
- describe '#hover', :requires => [:hover] do
310
+ describe '#hover', requires: [:hover] do
237
311
  it "should allow hovering on an element" do
238
312
  @session.visit('/with_hover')
239
- expect(@session.find(:css,'.hidden_until_hover', :visible => false)).not_to be_visible
240
- @session.find(:css,'.wrapper').hover
241
- expect(@session.find(:css, '.hidden_until_hover', :visible => false)).to be_visible
313
+ expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).not_to be_visible
314
+ @session.find(:css,'.wrapper:not(.scroll_needed)').hover
315
+ expect(@session.find(:css, '.wrapper:not(.scroll_needed) .hidden_until_hover', visible: false)).to be_visible
316
+ end
317
+
318
+ it "should allow hovering on an element that needs to be scrolled into view" do
319
+ @session.visit('/with_hover')
320
+ expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).not_to be_visible
321
+ @session.find(:css,'.wrapper.scroll_needed').hover
322
+ expect(@session.find(:css, '.wrapper.scroll_needed .hidden_until_hover', visible: false)).to be_visible
242
323
  end
243
324
  end
244
325
 
@@ -247,17 +328,48 @@ Capybara::SpecHelper.spec "node" do
247
328
  @session.find(:css, '#link_placeholder').click
248
329
  expect(@session.current_url).to match(%r{/with_html$})
249
330
  end
331
+
332
+ it "should go to the same page if href is blank" do
333
+ @session.find(:css, '#link_blank_href').click
334
+ sleep 1
335
+ expect(@session).to have_current_path('/with_html')
336
+ end
337
+
338
+ it "should be able to check a checkbox" do
339
+ @session.visit('form')
340
+ cbox = @session.find(:checkbox, 'form_terms_of_use')
341
+ expect(cbox).not_to be_checked
342
+ cbox.click
343
+ expect(cbox).to be_checked
344
+ end
345
+
346
+ it "should be able to uncheck a checkbox" do
347
+ @session.visit('/form')
348
+ cbox = @session.find(:checkbox, 'form_pets_dog')
349
+ expect(cbox).to be_checked
350
+ cbox.click
351
+ expect(cbox).not_to be_checked
352
+ end
353
+
354
+ it "should be able to select a radio button" do
355
+ @session.visit('/form')
356
+ radio = @session.find(:radio_button, 'gender_male')
357
+ expect(radio).not_to be_checked
358
+ radio.click
359
+ expect(radio).to be_checked
360
+ end
250
361
  end
251
362
 
252
- describe '#double_click', :requires => [:js] do
363
+ describe '#double_click', requires: [:js] do
253
364
  it "should double click an element" do
365
+ pending "selenium-webdriver/geckodriver doesn't generate double click event" if marionette?(@session)
254
366
  @session.visit('/with_js')
255
367
  @session.find(:css, '#click-test').double_click
256
368
  expect(@session.find(:css, '#has-been-double-clicked')).to be
257
369
  end
258
370
  end
259
371
 
260
- describe '#right_click', :requires => [:js] do
372
+ describe '#right_click', requires: [:js] do
261
373
  it "should right click an element" do
262
374
  @session.visit('/with_js')
263
375
  @session.find(:css, '#click-test').right_click
@@ -273,25 +385,28 @@ Capybara::SpecHelper.spec "node" do
273
385
  end
274
386
 
275
387
  it "should send special characters" do
388
+ pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if marionette?(@session)
276
389
  @session.visit('/form')
277
390
  @session.find(:css, '#address1_city').send_keys('Ocean', :space, 'sie', :left, 'd')
278
391
  expect(@session.find(:css, '#address1_city').value).to eq 'Ocean side'
279
392
  end
280
393
 
281
394
  it "should allow for multiple simultaneous keys" do
395
+ pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if marionette?(@session)
282
396
  @session.visit('/form')
283
397
  @session.find(:css, '#address1_city').send_keys([:shift, 'o'], 'ceanside')
284
398
  expect(@session.find(:css, '#address1_city').value).to eq 'Oceanside'
285
399
  end
286
400
 
287
401
  it "should generate key events", requires: [:send_keys, :js] do
402
+ pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if marionette?(@session)
288
403
  @session.visit('/with_js')
289
404
  @session.find(:css, '#with-key-events').send_keys([:shift,'t'], [:shift,'w'])
290
405
  expect(@session.find(:css, '#key-events-output')).to have_text('keydown:16 keydown:84 keydown:16 keydown:87')
291
406
  end
292
407
  end
293
408
 
294
- describe '#reload', :requires => [:js] do
409
+ describe '#reload', requires: [:js] do
295
410
  context "without automatic reload" do
296
411
  before { Capybara.automatic_reload = false }
297
412
  it "should reload the current context of the node" do
@@ -317,17 +432,25 @@ Capybara::SpecHelper.spec "node" do
317
432
  node = @session.find(:css, '#reload-me')
318
433
  @session.click_link('Reload!')
319
434
  sleep(0.3)
320
- expect { node.text.to == 'has been reloaded' }.to raise_error
435
+ expect do
436
+ expect(node).to have_text('has been reloaded')
437
+ end.to raise_error do |error|
438
+ expect(error).to be_an_invalid_element_error(@session)
439
+ end
321
440
  end
322
441
  after { Capybara.automatic_reload = true }
323
442
  end
324
443
 
325
444
  context "with automatic reload" do
445
+ before do
446
+ Capybara.default_max_wait_time = 4
447
+ end
448
+
326
449
  it "should reload the current context of the node automatically" do
327
450
  @session.visit('/with_js')
328
451
  node = @session.find(:css, '#reload-me')
329
452
  @session.click_link('Reload!')
330
- sleep(0.3)
453
+ sleep(1)
331
454
  expect(node.text).to eq('has been reloaded')
332
455
  end
333
456
 
@@ -335,7 +458,7 @@ Capybara::SpecHelper.spec "node" do
335
458
  @session.visit('/with_js')
336
459
  node = @session.find(:css, '#reload-me').find(:css, 'em')
337
460
  @session.click_link('Reload!')
338
- sleep(0.3)
461
+ sleep(1)
339
462
  expect(node.text).to eq('has been reloaded')
340
463
  end
341
464
 
@@ -343,26 +466,63 @@ Capybara::SpecHelper.spec "node" do
343
466
  @session.visit('/with_js')
344
467
  node = @session.find(:css, '#reload-me')
345
468
  @session.click_link('Reload!')
346
- sleep(0.3)
469
+ sleep(1)
347
470
  expect(node.find(:css, 'a').text).to eq('has been reloaded')
348
471
  end
349
472
 
350
- it "should not reload nodes which haven't been found" do
473
+ it "should not reload nodes which haven't been found with reevaluateable queries" do
351
474
  @session.visit('/with_js')
352
475
  node = @session.all(:css, '#the-list li')[1]
353
476
  @session.click_link('Fetch new list!')
354
- sleep(0.3)
355
- expect { node.text.to == 'Foo' }.to raise_error
356
- expect { node.text.to == 'Bar' }.to raise_error
477
+ sleep(1)
478
+
479
+ expect do
480
+ expect(node).to have_text('Foo')
481
+ end.to raise_error { |error|
482
+ expect(error).to be_an_invalid_element_error(@session)
483
+ }
484
+ expect do
485
+ expect(node).to have_text('Bar')
486
+ end.to raise_error { |error|
487
+ expect(error).to be_an_invalid_element_error(@session)
488
+ }
357
489
  end
358
490
 
359
491
  it "should reload nodes with options" do
360
492
  @session.visit('/with_js')
361
- node = @session.find(:css, 'em', :text => "reloaded")
493
+ node = @session.find(:css, 'em', text: "reloaded")
362
494
  @session.click_link('Reload!')
363
495
  sleep(1)
364
496
  expect(node.text).to eq('has been reloaded')
365
497
  end
366
498
  end
367
499
  end
500
+
501
+ context "when #synchronize raises server errors" do
502
+ it "sets an explanatory exception as the cause of server exceptions", requires: [:server, :js] do
503
+ skip "This version of ruby doesn't support exception causes" unless Exception.instance_methods.include? :cause
504
+ quietly { @session.visit("/error") }
505
+ expect do
506
+ @session.find(:css, 'span')
507
+ end.to raise_error(TestApp::TestAppError) do |e|
508
+ expect(e.cause).to be_a Capybara::CapybaraError
509
+ expect(e.cause.message).to match(/Your application server raised an error/)
510
+ end
511
+ end
512
+
513
+ it "sets an explanatory exception as the cause of server exceptions with errors with initializers", requires: [:server, :js] do
514
+ skip "This version of ruby doesn't support exception causes" unless Exception.instance_methods.include? :cause
515
+ quietly { @session.visit("/other_error") }
516
+ expect do
517
+ @session.find(:css, 'span')
518
+ end.to raise_error(TestApp::TestAppOtherError) do |e|
519
+ expect(e.cause).to be_a Capybara::CapybaraError
520
+ expect(e.cause.message).to match(/Your application server raised an error/)
521
+ end
522
+ end
523
+ end
524
+
525
+ def be_an_invalid_element_error(session)
526
+ satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }
527
+ end
368
528
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ Capybara::SpecHelper.spec '#refresh' do
3
+ it "reload the page" do
4
+ @session.visit('/form')
5
+ expect(@session).to have_select('form_locale', selected: 'English')
6
+ @session.select('Swedish', from: 'form_locale')
7
+ expect(@session).to have_select('form_locale', selected: 'Swedish')
8
+ @session.refresh
9
+ expect(@session).to have_select('form_locale', selected: 'English')
10
+ end
11
+
12
+ it "raises any errors caught inside the server", requires: [:server] do
13
+ quietly { @session.visit("/error") }
14
+ expect do
15
+ @session.refresh
16
+ end.to raise_error(TestApp::TestAppError)
17
+ end
18
+
19
+ it "it reposts" do
20
+ @session.visit('/form')
21
+ @session.select('Sweden', from: 'form_region')
22
+ @session.click_button('awesome')
23
+ expect {
24
+ @session.refresh
25
+ sleep 2
26
+ }.to change{ extract_results(@session)['post_count'] }.by(1)
27
+ end
28
+ end