capybara 3.8.1 → 3.33.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (242) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/History.md +465 -0
  4. data/License.txt +1 -1
  5. data/README.md +58 -57
  6. data/lib/capybara/config.rb +10 -4
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/base.rb +2 -2
  9. data/lib/capybara/driver/node.rb +26 -5
  10. data/lib/capybara/dsl.rb +12 -4
  11. data/lib/capybara/helpers.rb +8 -4
  12. data/lib/capybara/minitest/spec.rb +162 -85
  13. data/lib/capybara/minitest.rb +248 -148
  14. data/lib/capybara/node/actions.rb +149 -96
  15. data/lib/capybara/node/base.rb +27 -10
  16. data/lib/capybara/node/document.rb +12 -0
  17. data/lib/capybara/node/document_matchers.rb +9 -5
  18. data/lib/capybara/node/element.rb +254 -109
  19. data/lib/capybara/node/finders.rb +83 -76
  20. data/lib/capybara/node/matchers.rb +279 -141
  21. data/lib/capybara/node/simple.rb +25 -6
  22. data/lib/capybara/queries/ancestor_query.rb +5 -7
  23. data/lib/capybara/queries/base_query.rb +11 -5
  24. data/lib/capybara/queries/current_path_query.rb +3 -3
  25. data/lib/capybara/queries/match_query.rb +1 -0
  26. data/lib/capybara/queries/selector_query.rb +467 -103
  27. data/lib/capybara/queries/sibling_query.rb +5 -4
  28. data/lib/capybara/queries/style_query.rb +6 -2
  29. data/lib/capybara/queries/text_query.rb +17 -3
  30. data/lib/capybara/queries/title_query.rb +2 -2
  31. data/lib/capybara/rack_test/browser.rb +22 -15
  32. data/lib/capybara/rack_test/driver.rb +10 -1
  33. data/lib/capybara/rack_test/errors.rb +6 -0
  34. data/lib/capybara/rack_test/form.rb +33 -28
  35. data/lib/capybara/rack_test/node.rb +74 -6
  36. data/lib/capybara/registration_container.rb +44 -0
  37. data/lib/capybara/registrations/drivers.rb +36 -0
  38. data/lib/capybara/registrations/patches/puma_ssl.rb +27 -0
  39. data/lib/capybara/registrations/servers.rb +44 -0
  40. data/lib/capybara/result.rb +55 -23
  41. data/lib/capybara/rspec/features.rb +4 -4
  42. data/lib/capybara/rspec/matcher_proxies.rb +36 -15
  43. data/lib/capybara/rspec/matchers/base.rb +111 -0
  44. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  45. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  46. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  47. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  48. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  49. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  50. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  51. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  52. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  53. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  54. data/lib/capybara/rspec/matchers/match_style.rb +38 -0
  55. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  56. data/lib/capybara/rspec/matchers.rb +117 -311
  57. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  58. data/lib/capybara/selector/builders/xpath_builder.rb +69 -0
  59. data/lib/capybara/selector/css.rb +17 -15
  60. data/lib/capybara/selector/definition/button.rb +52 -0
  61. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  62. data/lib/capybara/selector/definition/css.rb +10 -0
  63. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  64. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  65. data/lib/capybara/selector/definition/element.rb +27 -0
  66. data/lib/capybara/selector/definition/field.rb +40 -0
  67. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  68. data/lib/capybara/selector/definition/file_field.rb +13 -0
  69. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  70. data/lib/capybara/selector/definition/frame.rb +17 -0
  71. data/lib/capybara/selector/definition/id.rb +6 -0
  72. data/lib/capybara/selector/definition/label.rb +62 -0
  73. data/lib/capybara/selector/definition/link.rb +54 -0
  74. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  75. data/lib/capybara/selector/definition/option.rb +27 -0
  76. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  77. data/lib/capybara/selector/definition/select.rb +81 -0
  78. data/lib/capybara/selector/definition/table.rb +109 -0
  79. data/lib/capybara/selector/definition/table_row.rb +21 -0
  80. data/lib/capybara/selector/definition/xpath.rb +5 -0
  81. data/lib/capybara/selector/definition.rb +277 -0
  82. data/lib/capybara/selector/filter.rb +1 -0
  83. data/lib/capybara/selector/filter_set.rb +26 -19
  84. data/lib/capybara/selector/filters/base.rb +24 -5
  85. data/lib/capybara/selector/filters/expression_filter.rb +3 -3
  86. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  87. data/lib/capybara/selector/filters/node_filter.rb +16 -2
  88. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  89. data/lib/capybara/selector/selector.rb +73 -367
  90. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  91. data/lib/capybara/selector.rb +221 -480
  92. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  93. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  94. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  95. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  96. data/lib/capybara/selenium/driver.rb +203 -86
  97. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +88 -14
  98. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
  99. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -0
  100. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  101. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  102. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  103. data/lib/capybara/selenium/extensions/find.rb +110 -0
  104. data/lib/capybara/selenium/extensions/html5_drag.rb +191 -22
  105. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  106. data/lib/capybara/selenium/extensions/scroll.rb +78 -0
  107. data/lib/capybara/selenium/logger_suppressor.rb +34 -0
  108. data/lib/capybara/selenium/node.rb +298 -93
  109. data/lib/capybara/selenium/nodes/chrome_node.rb +100 -8
  110. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  111. data/lib/capybara/selenium/nodes/firefox_node.rb +131 -0
  112. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  113. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  114. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  115. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  116. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  117. data/lib/capybara/selenium/patches/logs.rb +45 -0
  118. data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -3
  119. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  120. data/lib/capybara/server/animation_disabler.rb +4 -3
  121. data/lib/capybara/server/checker.rb +6 -2
  122. data/lib/capybara/server/middleware.rb +23 -13
  123. data/lib/capybara/server.rb +30 -7
  124. data/lib/capybara/session/config.rb +14 -10
  125. data/lib/capybara/session/matchers.rb +11 -7
  126. data/lib/capybara/session.rb +152 -111
  127. data/lib/capybara/spec/public/offset.js +6 -0
  128. data/lib/capybara/spec/public/test.js +101 -10
  129. data/lib/capybara/spec/session/all_spec.rb +96 -6
  130. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  131. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +29 -0
  132. data/lib/capybara/spec/session/assert_current_path_spec.rb +5 -2
  133. data/lib/capybara/spec/session/assert_selector_spec.rb +0 -10
  134. data/lib/capybara/spec/session/assert_style_spec.rb +4 -4
  135. data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
  136. data/lib/capybara/spec/session/attach_file_spec.rb +63 -36
  137. data/lib/capybara/spec/session/check_spec.rb +10 -4
  138. data/lib/capybara/spec/session/choose_spec.rb +8 -2
  139. data/lib/capybara/spec/session/click_button_spec.rb +117 -61
  140. data/lib/capybara/spec/session/click_link_or_button_spec.rb +16 -0
  141. data/lib/capybara/spec/session/click_link_spec.rb +17 -6
  142. data/lib/capybara/spec/session/element/matches_selector_spec.rb +40 -39
  143. data/lib/capybara/spec/session/evaluate_script_spec.rb +13 -0
  144. data/lib/capybara/spec/session/execute_script_spec.rb +1 -0
  145. data/lib/capybara/spec/session/fill_in_spec.rb +47 -6
  146. data/lib/capybara/spec/session/find_field_spec.rb +1 -1
  147. data/lib/capybara/spec/session/find_spec.rb +74 -4
  148. data/lib/capybara/spec/session/first_spec.rb +1 -1
  149. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +13 -1
  150. data/lib/capybara/spec/session/frame/within_frame_spec.rb +12 -1
  151. data/lib/capybara/spec/session/has_all_selectors_spec.rb +1 -1
  152. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  153. data/lib/capybara/spec/session/has_any_selectors_spec.rb +25 -0
  154. data/lib/capybara/spec/session/has_button_spec.rb +16 -0
  155. data/lib/capybara/spec/session/has_css_spec.rb +122 -12
  156. data/lib/capybara/spec/session/has_current_path_spec.rb +6 -4
  157. data/lib/capybara/spec/session/has_field_spec.rb +55 -0
  158. data/lib/capybara/spec/session/has_select_spec.rb +34 -6
  159. data/lib/capybara/spec/session/has_selector_spec.rb +11 -4
  160. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  161. data/lib/capybara/spec/session/has_table_spec.rb +166 -0
  162. data/lib/capybara/spec/session/has_text_spec.rb +48 -1
  163. data/lib/capybara/spec/session/has_xpath_spec.rb +17 -0
  164. data/lib/capybara/spec/session/html_spec.rb +7 -0
  165. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  166. data/lib/capybara/spec/session/node_spec.rb +643 -18
  167. data/lib/capybara/spec/session/node_wrapper_spec.rb +1 -1
  168. data/lib/capybara/spec/session/refresh_spec.rb +4 -0
  169. data/lib/capybara/spec/session/reset_session_spec.rb +23 -8
  170. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  171. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
  172. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  173. data/lib/capybara/spec/session/select_spec.rb +10 -10
  174. data/lib/capybara/spec/session/selectors_spec.rb +36 -5
  175. data/lib/capybara/spec/session/uncheck_spec.rb +2 -2
  176. data/lib/capybara/spec/session/unselect_spec.rb +1 -1
  177. data/lib/capybara/spec/session/window/become_closed_spec.rb +20 -17
  178. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +4 -0
  179. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +4 -0
  180. data/lib/capybara/spec/session/window/window_spec.rb +59 -58
  181. data/lib/capybara/spec/session/window/windows_spec.rb +4 -0
  182. data/lib/capybara/spec/session/within_spec.rb +23 -0
  183. data/lib/capybara/spec/spec_helper.rb +16 -6
  184. data/lib/capybara/spec/test_app.rb +28 -23
  185. data/lib/capybara/spec/views/animated.erb +49 -0
  186. data/lib/capybara/spec/views/form.erb +48 -7
  187. data/lib/capybara/spec/views/frame_child.erb +3 -2
  188. data/lib/capybara/spec/views/frame_one.erb +1 -0
  189. data/lib/capybara/spec/views/obscured.erb +47 -0
  190. data/lib/capybara/spec/views/offset.erb +32 -0
  191. data/lib/capybara/spec/views/react.erb +45 -0
  192. data/lib/capybara/spec/views/scroll.erb +20 -0
  193. data/lib/capybara/spec/views/spatial.erb +31 -0
  194. data/lib/capybara/spec/views/tables.erb +67 -0
  195. data/lib/capybara/spec/views/with_animation.erb +29 -1
  196. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  197. data/lib/capybara/spec/views/with_hover.erb +1 -0
  198. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  199. data/lib/capybara/spec/views/with_html.erb +32 -6
  200. data/lib/capybara/spec/views/with_js.erb +3 -1
  201. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  202. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  203. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  204. data/lib/capybara/version.rb +1 -1
  205. data/lib/capybara/window.rb +11 -11
  206. data/lib/capybara.rb +118 -111
  207. data/spec/basic_node_spec.rb +14 -3
  208. data/spec/capybara_spec.rb +29 -29
  209. data/spec/css_builder_spec.rb +101 -0
  210. data/spec/dsl_spec.rb +46 -21
  211. data/spec/filter_set_spec.rb +5 -5
  212. data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -1
  213. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
  214. data/spec/minitest_spec.rb +18 -4
  215. data/spec/minitest_spec_spec.rb +59 -44
  216. data/spec/rack_test_spec.rb +117 -89
  217. data/spec/regexp_dissassembler_spec.rb +250 -0
  218. data/spec/result_spec.rb +51 -49
  219. data/spec/rspec/features_spec.rb +3 -0
  220. data/spec/rspec/shared_spec_matchers.rb +112 -97
  221. data/spec/rspec_spec.rb +35 -17
  222. data/spec/sauce_spec_chrome.rb +43 -0
  223. data/spec/selector_spec.rb +244 -28
  224. data/spec/selenium_spec_chrome.rb +125 -54
  225. data/spec/selenium_spec_chrome_remote.rb +26 -12
  226. data/spec/selenium_spec_edge.rb +23 -8
  227. data/spec/selenium_spec_firefox.rb +208 -0
  228. data/spec/selenium_spec_firefox_remote.rb +15 -18
  229. data/spec/selenium_spec_ie.rb +82 -13
  230. data/spec/selenium_spec_safari.rb +148 -0
  231. data/spec/server_spec.rb +118 -77
  232. data/spec/session_spec.rb +19 -3
  233. data/spec/shared_selenium_node.rb +83 -0
  234. data/spec/shared_selenium_session.rb +110 -65
  235. data/spec/spec_helper.rb +57 -9
  236. data/spec/xpath_builder_spec.rb +93 -0
  237. metadata +257 -17
  238. data/lib/capybara/rspec/compound.rb +0 -94
  239. data/lib/capybara/selenium/driver_specializations/marionette_driver.rb +0 -49
  240. data/lib/capybara/selenium/nodes/marionette_node.rb +0 -121
  241. data/lib/capybara/spec/session/has_style_spec.rb +0 -25
  242. data/spec/selenium_spec_marionette.rb +0 -172
@@ -1,89 +1,91 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Note: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
4
+ # because of the methods being tested. In tests using Capybara this type of behavior should be implemented
5
+ # using Capybara provided assertions with builtin waiting behavior.
6
+
3
7
  Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
8
+ let!(:orig_window) { @session.current_window }
4
9
  before do
5
- @window = @session.current_window
6
10
  @session.visit('/with_windows')
7
11
  end
8
12
 
9
13
  after do
10
- (@session.windows - [@window]).each do |w|
14
+ (@session.windows - [orig_window]).each do |w|
11
15
  @session.switch_to_window w
12
16
  w.close
13
17
  end
14
- @session.switch_to_window(@window)
18
+ @session.switch_to_window(orig_window)
15
19
  end
16
20
 
17
21
  describe '#exists?' do
18
- before do
19
- @other_window = @session.window_opened_by do
22
+ it 'should become false after window was closed' do
23
+ other_window = @session.window_opened_by do
20
24
  @session.find(:css, '#openWindow').click
21
25
  end
22
- end
23
26
 
24
- it 'should become false after window was closed' do
25
27
  expect do
26
- @session.switch_to_window @other_window
27
- @other_window.close
28
- end.to change { @other_window.exists? }.from(true).to(false)
28
+ @session.switch_to_window other_window
29
+ other_window.close
30
+ end.to change(other_window, :exists?).from(true).to(false)
29
31
  end
30
32
  end
31
33
 
32
34
  describe '#closed?' do
33
35
  it 'should become true after window was closed' do
34
- @other_window = @session.window_opened_by do
36
+ other_window = @session.window_opened_by do
35
37
  @session.find(:css, '#openWindow').click
36
38
  end
37
39
  expect do
38
- @session.switch_to_window @other_window
39
- @other_window.close
40
- end.to change { @other_window.closed? }.from(false).to(true)
40
+ @session.switch_to_window other_window
41
+ other_window.close
42
+ end.to change { other_window.closed? }.from(false).to(true)
41
43
  end
42
44
  end
43
45
 
44
46
  describe '#current?' do
45
- before do
46
- @other_window = @session.window_opened_by do
47
+ let(:other_window) do
48
+ @session.window_opened_by do
47
49
  @session.find(:css, '#openWindow').click
48
50
  end
49
51
  end
50
52
 
51
53
  it 'should become true after switching to window' do
52
54
  expect do
53
- @session.switch_to_window(@other_window)
54
- end.to change { @other_window.current? }.from(false).to(true)
55
+ @session.switch_to_window(other_window)
56
+ end.to change(other_window, :current?).from(false).to(true)
55
57
  end
56
58
 
57
59
  it 'should return false if window is closed' do
58
- @session.switch_to_window(@other_window)
59
- @other_window.close
60
- expect(@other_window.current?).to eq(false)
60
+ @session.switch_to_window(other_window)
61
+ other_window.close
62
+ expect(other_window.current?).to eq(false)
61
63
  end
62
64
  end
63
65
 
64
66
  describe '#close' do
65
- before do
66
- @other_window = @session.window_opened_by do
67
+ let!(:other_window) do
68
+ @session.window_opened_by do
67
69
  @session.find(:css, '#openWindow').click
68
70
  end
69
71
  end
70
72
 
71
73
  it 'should switch to original window if invoked not for current window' do
72
74
  expect(@session.windows.size).to eq(2)
73
- expect(@session.current_window).to eq(@window)
74
- @other_window.close
75
+ expect(@session.current_window).to eq(orig_window)
76
+ other_window.close
75
77
  expect(@session.windows.size).to eq(1)
76
- expect(@session.current_window).to eq(@window)
78
+ expect(@session.current_window).to eq(orig_window)
77
79
  end
78
80
 
79
81
  it 'should make subsequent invocations of other methods raise no_such_window_error if invoked for current window' do
80
- @session.switch_to_window(@other_window)
81
- expect(@session.current_window).to eq(@other_window)
82
- @other_window.close
82
+ @session.switch_to_window(other_window)
83
+ expect(@session.current_window).to eq(other_window)
84
+ other_window.close
83
85
  expect do
84
86
  @session.find(:css, '#some_id')
85
87
  end.to raise_error(@session.driver.no_such_window_error)
86
- @session.switch_to_window(@window)
88
+ @session.switch_to_window(orig_window)
87
89
  end
88
90
  end
89
91
 
@@ -97,55 +99,54 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
97
99
  end
98
100
 
99
101
  it 'should switch to original window if invoked not for current window' do
100
- @other_window = @session.window_opened_by do
102
+ other_window = @session.window_opened_by do
101
103
  @session.find(:css, '#openWindow').click
102
104
  end
103
105
  sleep 1
104
- size = @session.within_window(@other_window) do
106
+ size = @session.within_window(other_window) do
105
107
  win_size
106
108
  end
107
- expect(@other_window.size).to eq(size)
108
- expect(@session.current_window).to eq(@window)
109
+ expect(other_window.size).to eq(size)
110
+ expect(@session.current_window).to eq(orig_window)
109
111
  end
110
112
  end
111
113
 
112
114
  describe '#resize_to' do
113
- before do
114
- @initial_size = @session.current_window.size
115
- end
115
+ let!(:initial_size) { @session.current_window.size }
116
116
 
117
117
  after do
118
- @session.current_window.resize_to(*@initial_size)
119
- sleep 0.5
118
+ @session.current_window.resize_to(*initial_size)
119
+ sleep 1
120
120
  end
121
121
 
122
122
  it 'should be able to resize window', requires: %i[windows js] do
123
- width, height = @initial_size
123
+ width, height = initial_size
124
124
  @session.current_window.resize_to(width - 100, height - 100)
125
125
  sleep 1
126
126
  expect(@session.current_window.size).to eq([width - 100, height - 100])
127
127
  end
128
128
 
129
129
  it 'should stay on current window if invoked not for current window', requires: %i[windows js] do
130
- @other_window = @session.window_opened_by do
130
+ other_window = @session.window_opened_by do
131
131
  @session.find(:css, '#openWindow').click
132
132
  end
133
- @other_window.resize_to(600, 300)
134
- expect(@session.current_window).to eq(@window)
135
133
 
136
- @session.within_window(@other_window) do
137
- expect(@session.current_window.size).to eq([600, 300])
134
+ other_window.resize_to(600, 400)
135
+ expect(@session.current_window).to eq(orig_window)
136
+
137
+ @session.within_window(other_window) do
138
+ expect(@session.current_window.size).to eq([600, 400])
138
139
  end
139
140
  end
140
141
  end
141
142
 
142
143
  describe '#maximize' do
143
- before do
144
- @initial_size = @session.current_window.size
144
+ let! :initial_size do
145
+ @session.current_window.size
145
146
  end
146
147
 
147
148
  after do
148
- @session.current_window.resize_to(*@initial_size)
149
+ @session.current_window.resize_to(*initial_size)
149
150
  sleep 0.5
150
151
  end
151
152
 
@@ -165,32 +166,32 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
165
166
  end
166
167
 
167
168
  it 'should stay on current window if invoked not for current window', requires: %i[windows js] do
168
- @other_window = @session.window_opened_by do
169
+ other_window = @session.window_opened_by do
169
170
  @session.find(:css, '#openWindow').click
170
171
  end
171
- @other_window.resize_to(400, 300)
172
+ other_window.resize_to(400, 300)
172
173
  sleep 0.5
173
- @other_window.maximize
174
+ other_window.maximize
174
175
  sleep 0.5 # The timing on maximize is finicky on Travis -- wait a bit for maximize to occur
175
176
 
176
- expect(@session.current_window).to eq(@window)
177
+ expect(@session.current_window).to eq(orig_window)
177
178
  # Maximizing the browser affects all tabs so this may not be valid in real browsers
178
- # expect(@session.current_window.size).to eq(@initial_size)
179
+ # expect(@session.current_window.size).to eq(initial_size)
179
180
 
180
- ow_width, ow_height = @other_window.size
181
+ ow_width, ow_height = other_window.size
181
182
  expect(ow_width).to be > 400
182
183
  expect(ow_height).to be > 300
183
184
  end
184
185
  end
185
186
 
186
187
  describe '#fullscreen' do
187
- before do
188
- @initial_size = @session.current_window.size
188
+ let! :initial_size do
189
+ @session.current_window.size
189
190
  end
190
191
 
191
192
  after do
192
- @session.current_window.resize_to(*@initial_size)
193
- sleep 0.5
193
+ @session.current_window.resize_to(*initial_size)
194
+ sleep 1
194
195
  end
195
196
 
196
197
  it 'should be able to fullscreen the window' do
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Note: This file uses `sleep` to sync up parts of the tests. This is only implemented like this
4
+ # because of the methods being tested. In tests using Capybara this type of behavior should be implemented
5
+ # using Capybara provided assertions with builtin waiting behavior.
6
+
3
7
  Capybara::SpecHelper.spec '#windows', requires: [:windows] do
4
8
  before do
5
9
  @window = @session.current_window
@@ -26,6 +26,29 @@ Capybara::SpecHelper.spec '#within' do
26
26
  end
27
27
  expect(@session).to have_content('Bar')
28
28
  end
29
+
30
+ it 'should reload the node if the page is changed' do
31
+ @session.within(:css, '#for_foo') do
32
+ @session.visit('/with_scope_other')
33
+ expect(@session).to have_content('Different text')
34
+ end
35
+ end
36
+
37
+ it 'should reload multiple nodes if the page is changed' do
38
+ @session.within(:css, '#for_bar') do
39
+ @session.within(:css, 'form[action="/redirect"]') do
40
+ @session.refresh
41
+ expect(@session).to have_content('First Name')
42
+ end
43
+ end
44
+ end
45
+
46
+ it 'should error if the page is changed and a matching node no longer exists' do
47
+ @session.within(:css, '#for_foo') do
48
+ @session.visit('/')
49
+ expect { @session.text }.to raise_error(StandardError)
50
+ end
51
+ end
29
52
  end
30
53
 
31
54
  context 'with XPath selector' do
@@ -16,8 +16,7 @@ module Capybara
16
16
  config.filter_run_excluding requires: method(:filter).to_proc
17
17
  config.before { Capybara::SpecHelper.reset! }
18
18
  config.after { Capybara::SpecHelper.reset! }
19
- # Test in 3.5+ where metadata doesn't autotrigger shared context inclusion - will be only behavior in RSpec 4
20
- config.shared_context_metadata_behavior = :apply_to_host_groups if config.respond_to?(:shared_context_metadata_behavior=)
19
+ config.shared_context_metadata_behavior = :apply_to_host_groups
21
20
  end
22
21
 
23
22
  def reset!
@@ -31,11 +30,14 @@ module Capybara
31
30
  Capybara.visible_text_only = false
32
31
  Capybara.match = :smart
33
32
  Capybara.enable_aria_label = false
33
+ Capybara.enable_aria_role = false
34
34
  Capybara.default_set_options = {}
35
35
  Capybara.disable_animation = false
36
36
  Capybara.test_id = nil
37
37
  Capybara.predicates_wait = true
38
38
  Capybara.default_normalize_ws = false
39
+ Capybara.allow_gumbo = true
40
+ Capybara.w3c_click_offset = false
39
41
  reset_threadsafe
40
42
  end
41
43
 
@@ -59,7 +61,7 @@ module Capybara
59
61
  RSpec.describe Capybara::Session, name, options do # rubocop:disable RSpec/EmptyExampleGroup
60
62
  include Capybara::SpecHelper
61
63
  include Capybara::RSpecMatchers
62
- # rubocop:disable RSpec/ScatteredSetup
64
+
63
65
  before do |example|
64
66
  @session = session
65
67
  instance_exec(example, &filter_block) if filter_block
@@ -80,7 +82,6 @@ module Capybara
80
82
  before :each, :exact_false do
81
83
  Capybara.exact = false
82
84
  end
83
- # rubocop:enable RSpec/ScatteredSetup
84
85
 
85
86
  specs.each do |spec_name, spec_options, block|
86
87
  describe spec_name, *spec_options do # rubocop:disable RSpec/EmptyExampleGroup
@@ -100,7 +101,7 @@ module Capybara
100
101
 
101
102
  def silence_stream(stream)
102
103
  old_stream = stream.dup
103
- stream.reopen(RbConfig::CONFIG['host_os'] =~ /rmswin|mingw/ ? 'NUL:' : '/dev/null')
104
+ stream.reopen(RbConfig::CONFIG['host_os'].match?(/rmswin|mingw/) ? 'NUL:' : '/dev/null')
104
105
  stream.sync = true
105
106
  yield
106
107
  ensure
@@ -117,7 +118,16 @@ module Capybara
117
118
 
118
119
  def extract_results(session)
119
120
  expect(session).to have_xpath("//pre[@id='results']")
120
- YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
121
+ # YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
122
+ YAML.load Capybara::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
123
+ end
124
+
125
+ def be_an_invalid_element_error(session)
126
+ satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }
127
+ end
128
+
129
+ def with_os_path_separators(path)
130
+ Gem.win_platform? ? path.to_s.tr('/', '\\') : path.to_s
121
131
  end
122
132
  end
123
133
  end
@@ -6,8 +6,8 @@ require 'rack'
6
6
  require 'yaml'
7
7
 
8
8
  class TestApp < Sinatra::Base
9
- class TestAppError < StandardError; end
10
- class TestAppOtherError < StandardError
9
+ class TestAppError < Exception; end # rubocop:disable Lint/InheritException
10
+ class TestAppOtherError < Exception # rubocop:disable Lint/InheritException
11
11
  def initialize(string1, msg)
12
12
  @something = string1
13
13
  @message = msg
@@ -18,7 +18,6 @@ class TestApp < Sinatra::Base
18
18
  set :raise_errors, true
19
19
  set :show_exceptions, false
20
20
 
21
- @@form_post_count = 0
22
21
  # Also check lib/capybara/spec/views/*.erb for pages not listed here
23
22
 
24
23
  get '/' do
@@ -176,8 +175,8 @@ class TestApp < Sinatra::Base
176
175
  end
177
176
 
178
177
  post '/form' do
179
- @@form_post_count += 1
180
- '<pre id="results">' + params[:form].merge('post_count' => @@form_post_count).to_yaml + '</pre>'
178
+ self.class.form_post_count += 1
179
+ '<pre id="results">' + params[:form].merge('post_count' => self.class.form_post_count).to_yaml + '</pre>'
181
180
  end
182
181
 
183
182
  post '/upload_empty' do
@@ -189,29 +188,35 @@ class TestApp < Sinatra::Base
189
188
  end
190
189
 
191
190
  post '/upload' do
192
- begin
193
- buffer = []
194
- buffer << "Content-type: #{params.dig(:form, :document, :type)}"
195
- buffer << "File content: #{params.dig(:form, :document, :tempfile).read}"
196
- buffer.join(' | ')
197
- rescue StandardError
198
- 'No file uploaded'
199
- end
191
+ buffer = []
192
+ buffer << "Content-type: #{params.dig(:form, :document, :type)}"
193
+ buffer << "File content: #{params.dig(:form, :document, :tempfile).read}"
194
+ buffer.join(' | ')
195
+ rescue StandardError
196
+ 'No file uploaded'
200
197
  end
201
198
 
202
199
  post '/upload_multiple' do
203
- begin
204
- docs = params.dig(:form, :multiple_documents)
205
- buffer = [docs.size.to_s]
206
- docs.each do |doc|
207
- buffer << "Content-type: #{doc[:type]}"
208
- buffer << "File content: #{doc[:tempfile].read}"
209
- end
210
- buffer.join(' | ')
211
- rescue StandardError
212
- 'No files uploaded'
200
+ docs = params.dig(:form, :multiple_documents)
201
+ buffer = [docs.size.to_s]
202
+ docs.each do |doc|
203
+ buffer << "Content-type: #{doc[:type]}"
204
+ buffer << "File content: #{doc[:tempfile].read}"
213
205
  end
206
+ buffer.join(' | ')
207
+ rescue StandardError
208
+ 'No files uploaded'
209
+ end
210
+
211
+ get '/apple-touch-icon-precomposed.png' do
212
+ halt(404)
214
213
  end
214
+
215
+ class << self
216
+ attr_accessor :form_post_count
217
+ end
218
+
219
+ @form_post_count = 0
215
220
  end
216
221
 
217
222
  Rack::Handler::Puma.run TestApp, Port: 8070 if $PROGRAM_NAME == __FILE__
@@ -0,0 +1,49 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
4
+ <title>with_animation</title>
5
+ <script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
6
+ <script>
7
+ $(document).on('contextmenu', function(e){ e.preventDefault(); });
8
+ </script>
9
+ <style>
10
+ div {
11
+ width: 400px;
12
+ height: 400px;
13
+ position: absolute;
14
+ }
15
+ #obscured {
16
+ z-index: 1;
17
+ background-color: red;
18
+ }
19
+ #cover {
20
+ z-index: 2;
21
+ background-color: blue;
22
+ }
23
+ #offscreen {
24
+ top: 2000px;
25
+ left: 2000px;
26
+ background-color: green;
27
+ }
28
+ #offscreen_wrapper {
29
+ top: 2000px;
30
+ left: 2000px;
31
+ overflow-x: scroll;
32
+ background-color: yellow;
33
+ }
34
+ </style>
35
+ </head>
36
+
37
+ <body id="with_animation">
38
+ <div id="obscured">
39
+ <input id="obscured_input"/>
40
+ </div>
41
+ <div id="cover"></div>
42
+ <div id="offscreen_wrapper">
43
+ <div id="offscreen"></div>
44
+ </div>
45
+ </body>
46
+
47
+ <iframe id="frameOne" src="/frame_one"></iframe>
48
+ </html>
49
+
@@ -1,7 +1,7 @@
1
1
 
2
2
  <h1>Form</h1>
3
3
 
4
- <form action="/form" method="post">
4
+ <form action="/form" method="post" novalidate>
5
5
 
6
6
  <p>
7
7
  <label for="form_title">Title</label>
@@ -11,7 +11,7 @@
11
11
  <option>Miss</option>
12
12
  <option disabled="disabled">Other</option>
13
13
  </select>
14
- </p>
14
+ </p>
15
15
 
16
16
  <p>
17
17
  <label for="customer_name">Customer Name
@@ -25,6 +25,12 @@
25
25
  </label>
26
26
  </p>
27
27
 
28
+ <p>
29
+ <label for="customer_other_email">Customer Other Email
30
+ <input type="text" name="form[customer_other_email]" value="notben@notben.com" id="customer_other_email"/>
31
+ </label>
32
+ </p>
33
+
28
34
  <p>
29
35
  <label for="form_other_title">Other title</label>
30
36
  <select name="form[other_title]" id="form_other_title">
@@ -56,6 +62,11 @@
56
62
  <input type="text" name="form[name]" value="John Smith" id="form_name"/>
57
63
  </p>
58
64
 
65
+ <p>
66
+ <label for="form_age">Age</label>
67
+ <input type="range" name="form[age]" value="18" min="13" max="100" step="0.5" id="form_age"/>
68
+ </p>
69
+
59
70
  <p>
60
71
  <label for="form_schmooo">Schmooo</label>
61
72
  <input type="schmooo" name="form[schmooo]" value="This is Schmooo!" id="form_schmooo"/>
@@ -88,6 +99,11 @@
88
99
  <input type="file" name="form[image]" id="form_image"/>
89
100
  </p>
90
101
 
102
+ <p>
103
+ <label for="form_hidden_image">Hidden Image</label>
104
+ <input type="file" name="form[hidden_image]" id="form_hidden_image" style="display: none"/>
105
+ </p>
106
+
91
107
  <p>
92
108
  <input type="hidden" name="form[token]" value="12345" id="form_token"/>
93
109
  </p>
@@ -97,7 +113,7 @@
97
113
  <select name="form[locale]" id="form_locale">
98
114
  <option value="sv">Swedish</option>
99
115
  <option selected="selected" value="en">English</option>
100
- <option value="fi">Finish</option>
116
+ <option value="fi">Finnish</option>
101
117
  <option value="no">Norwegian</option>
102
118
  <option value="jo">John's made-up language</option>
103
119
  <option value="jbo"> Lojban </option>
@@ -124,7 +140,11 @@
124
140
 
125
141
  <p>
126
142
  <label for="form_zipcode">Zipcode</label>
127
- <input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" />
143
+ <input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" pattern="[0-9]{5,9}" />
144
+ </p>
145
+
146
+ <p>
147
+ <input maxlength="35" id="long_length" />
128
148
  </p>
129
149
 
130
150
  <p>
@@ -428,7 +448,7 @@ New line after and before textarea tag
428
448
  </p>
429
449
 
430
450
  <p>
431
- <input type="button" name="form[fresh]" id="fresh_btn" value="i am fresh"/>
451
+ <input type="button" aria-label="Aria button" name="form[fresh]" id="fresh_btn" value="i am fresh"/>
432
452
  <input type="submit" name="form[awesome]" id="awe123" title="What an Awesome Button" value="awesome"/>
433
453
  <input type="submit" name="form[crappy]" id="crap321" value="crappy"/>
434
454
  <input type="image" name="form[okay]" id="okay556" title="Okay 556 Image" value="okay" alt="oh hai thar"/>
@@ -437,6 +457,7 @@ New line after and before textarea tag
437
457
  <button id="no_type">No Type!</button>
438
458
  <button><img alt="A horse eating hay"/></button>
439
459
  <input type="button" disabled="disabled" value="Disabled button"/>
460
+ <span role="button">ARIA button</span>
440
461
  </p>
441
462
 
442
463
  <p>
@@ -449,6 +470,11 @@ New line after and before textarea tag
449
470
  <input id="readonly" name="form[readonly_test]" readonly/>
450
471
  <input id="not_readonly" name="form[readonly_test]" />
451
472
  </p>
473
+
474
+ <p>
475
+ <input id="required" name="form[required]" required />
476
+ <input id="length" name="form[length]" minlength="4" maxlength="4" />
477
+ </p>
452
478
  </form>
453
479
 
454
480
  <input type="text" name="form[outside_input]" value="outside_input" form="form1"/>
@@ -458,12 +484,19 @@ New line after and before textarea tag
458
484
  <input type="text" name="nested_label" id="nested_label"/>
459
485
  </label>
460
486
 
487
+ <label id="wrapper_label">
488
+ Wrapper Label
489
+ <input type="checkbox"/>
490
+ </label>
491
+
461
492
  <form id="form1" action="/form" method="post">
462
493
  <input type="text" name="form[which_form]" value="form1" id="form_which_form"/>
463
494
  <input type="text" name="form[for_form2]" value="for_form2" form="form2"/>
464
495
  <input type="submit" name="form[submit_form1]" value="submit_form1" id="submit_form1"/>
465
496
  </form>
466
497
 
498
+ <button type="submit" name="form[outside_button]" value="outside_button" form="form2">Outside!</button>
499
+
467
500
  <form id="form2" action="/form" method="post">
468
501
  <input type="text" name="form[which_form]" value="form2" id="form_which_form2"/>
469
502
  <input type="submit" name="form[unused]" value="unused"/>
@@ -480,8 +513,6 @@ New line after and before textarea tag
480
513
  </select>
481
514
 
482
515
  <input type="submit" name="form[outside_submit]" value="outside_submit" form="form1"/>
483
- <button type="submit" name="form[outside_button]" value="outside_button" form="form2">Outside!</button>
484
-
485
516
 
486
517
  <form id="get-form" action="/form/get?foo=bar" method="get">
487
518
  <p>
@@ -491,6 +522,7 @@ New line after and before textarea tag
491
522
 
492
523
  <p>
493
524
  <input type="submit" name="form[mediocre]" id="mediocre" value="med" aria-label="Mediocre Button"/>
525
+ <input type="submit" formaction="/form/get?bar=foo" id="mediocre2" value="med2"/>
494
526
  <p>
495
527
  </form>
496
528
 
@@ -547,6 +579,11 @@ New line after and before textarea tag
547
579
  <input type="file" name="form[multiple_documents][]" id="form_multiple_documents" multiple="multiple" />
548
580
  </p>
549
581
 
582
+ <p>
583
+ <label for="form_directory_upload">Directory Upload</label>
584
+ <input type="file" name="form[multiple_documents][]" id="form_directory_upload" multiple="multiple" webkitdirectory="webkitdirectory" mozdirectory="mozdirectory" />
585
+ </p>
586
+
550
587
  <p>
551
588
  <input type="submit" value="Upload Multiple"/>
552
589
  <p>
@@ -643,3 +680,7 @@ New line after and before textarea tag
643
680
  <label for="asterisk_input">With Asterisk<abbr title="required">*</abbr></label>
644
681
  <input id="asterisk_input" type="number"value="2016"/>
645
682
  </p>
683
+
684
+ <p>
685
+ <input id="special" {custom}="abcdef" value="custom attribute"/>
686
+ </p>
@@ -4,13 +4,14 @@
4
4
  <title>This is the child frame title</title>
5
5
  <script>
6
6
  function closeWin() {
7
- var iframe = window.parent.document.getElementById('childFrame')
7
+ var iframe = window.parent.document.getElementById('childFrame');
8
8
  iframe.parentNode.removeChild(iframe)
9
9
  }
10
10
  </script>
11
11
  </head>
12
12
  <body id="childBody">
13
- <a href="javascript:void(0)" onClick="closeWin()">Close Window</a>
13
+ <a href="javascript:void(0)" onClick="closeWin()">Close Window Now</a>
14
+ <a href="javascript:void(0)" onClick="setTimeout(function(){closeWin()}, 10)">Close Window Soon</a>
14
15
  <iframe src="/frame_one" id="grandchildFrame1"></iframe>
15
16
  <iframe src="/frame_two" id="grandchildFrame2"></iframe>
16
17
  </body>
@@ -5,5 +5,6 @@
5
5
  </head>
6
6
  <body>
7
7
  <div id="divInFrameOne">This is the text of divInFrameOne</div>
8
+ <div id="otherDivInFrameOne">Some other text</div>
8
9
  </body>
9
10
  </html>