capybara 2.5.0 → 2.18.0

Sign up to get free protection for your applications and to get access to all the features.
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