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 '#within_window', requires: [:windows] do
2
3
  before(:each) do
3
4
  @window = @session.current_window
@@ -29,7 +30,7 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
29
30
  window = (@session.windows - [@window]).first
30
31
  expect(@session.driver).to receive(:switch_to_window).exactly(5).times.and_call_original
31
32
  @session.within_window window do
32
- expect(['Title of the first popup', 'Title of popup two']).to include(@session.title)
33
+ expect(@session).to have_title(/Title of the first popup|Title of popup two/)
33
34
  end
34
35
  expect(@session.title).to eq('With Windows')
35
36
  end
@@ -56,10 +57,10 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
56
57
  expect(@session.send(:scopes)).to eq([nil])
57
58
  end
58
59
 
59
- it "should leave correct scopes after execution in case of error" do
60
+ it "should leave correct scopes after execution in case of error", requires: [:windows, :frames] do
60
61
  window = (@session.windows - [@window]).first
61
62
  expect do
62
- @session.within 'html' do
63
+ @session.within_frame 'frameOne' do
63
64
  @session.within_window(window) {}
64
65
  end
65
66
  end.to raise_error(Capybara::ScopeError)
@@ -101,6 +102,31 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
101
102
  expect(@session.title).to eq('With Windows')
102
103
  end
103
104
 
105
+ it "should be able to nest within_window" do
106
+ @session.within_window(->{ @session.title == 'Title of popup two'}) do
107
+ expect(@session).to have_css('#divInPopupTwo')
108
+ @session.within_window(->{ @session.title == 'Title of the first popup'}) do
109
+ expect(@session).to have_css('#divInPopupOne')
110
+ end
111
+ expect(@session).to have_css('#divInPopupTwo')
112
+ expect(@session).not_to have_css('divInPopupOne')
113
+ end
114
+ expect(@session).not_to have_css('#divInPopupTwo')
115
+ expect(@session).not_to have_css('divInPopupOne')
116
+ expect(@session.title).to eq('With Windows')
117
+ end
118
+
119
+ it "should work inside a normal scope" do
120
+ expect(@session).to have_css('#openWindow')
121
+ @session.within(:css, '#scope') do
122
+ @session.within_window(->{ @session.title == 'Title of the first popup'}) do
123
+ expect(@session).to have_css('#divInPopupOne')
124
+ end
125
+ expect(@session).to have_content('My scoped content')
126
+ expect(@session).not_to have_css('#openWindow')
127
+ end
128
+ end
129
+
104
130
  it "should raise error if window wasn't found" do
105
131
  expect do
106
132
  @session.within_window(->{ @session.title == 'Invalid title'}) do
@@ -132,16 +158,14 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
132
158
 
133
159
  context "with string" do
134
160
  it "should warn" do
135
- expect(@session).to receive(:warn).with("DEPRECATION WARNING: Passing string argument "\
136
- "to #within_window is deprecated. Pass window object or lambda. "\
137
- "(called from #{__FILE__}:138)").and_call_original
161
+ expect(@session).to receive(:warn).with(/DEPRECATION WARNING/).and_call_original
138
162
  @session.within_window('firstPopup') {}
139
163
  end
140
164
 
141
165
  it "should find window by handle" do
142
166
  window = (@session.windows - [@window]).first
143
167
  @session.within_window window.handle do
144
- expect(['Title of the first popup', 'Title of popup two']).to include(@session.title)
168
+ expect(@session).to have_title(/Title of the first popup|Title of popup two/)
145
169
  end
146
170
  end
147
171
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  Capybara::SpecHelper.spec '#within' do
2
3
  before do
3
4
  @session.visit('/with_scope')
@@ -19,7 +20,7 @@ Capybara::SpecHelper.spec '#within' do
19
20
  end
20
21
 
21
22
  it "should accept additional options" do
22
- @session.within(:css, "#for_bar li", :text => 'With Simple HTML') do
23
+ @session.within(:css, "#for_bar li", text: 'With Simple HTML') do
23
24
  @session.click_link('Go')
24
25
  end
25
26
  expect(@session).to have_content('Bar')
@@ -113,11 +114,18 @@ Capybara::SpecHelper.spec '#within' do
113
114
  expect(extract_results(@session)['first_name']).to eq('Peter')
114
115
  @session.visit('/with_scope')
115
116
  @session.within("//li[contains(.,'Bar')]") do
116
- @session.fill_in('First Name', :with => 'Dagobert')
117
+ @session.fill_in('First Name', with: 'Dagobert')
117
118
  @session.click_button('Go')
118
119
  end
119
120
  expect(extract_results(@session)['first_name']).to eq('Dagobert')
120
121
  end
122
+
123
+ it "should have #within_element as an alias" do
124
+ expect(Capybara::Session.instance_method(:within)).to eq Capybara::Session.instance_method(:within_element)
125
+ @session.within_element(:css, "#for_foo") do
126
+ expect(@session).not_to have_content('First Name')
127
+ end
128
+ end
121
129
  end
122
130
 
123
131
  Capybara::SpecHelper.spec '#within_fieldset' do
@@ -127,7 +135,7 @@ Capybara::SpecHelper.spec '#within_fieldset' do
127
135
 
128
136
  it "should restrict scope to a fieldset given by id" do
129
137
  @session.within_fieldset("villain_fieldset") do
130
- @session.fill_in("Name", :with => 'Goldfinger')
138
+ @session.fill_in("Name", with: 'Goldfinger')
131
139
  @session.click_button("Create")
132
140
  end
133
141
  expect(extract_results(@session)['villain_name']).to eq('Goldfinger')
@@ -135,7 +143,7 @@ Capybara::SpecHelper.spec '#within_fieldset' do
135
143
 
136
144
  it "should restrict scope to a fieldset given by legend" do
137
145
  @session.within_fieldset("Villain") do
138
- @session.fill_in("Name", :with => 'Goldfinger')
146
+ @session.fill_in("Name", with: 'Goldfinger')
139
147
  @session.click_button("Create")
140
148
  end
141
149
  expect(extract_results(@session)['villain_name']).to eq('Goldfinger')
@@ -149,7 +157,7 @@ Capybara::SpecHelper.spec '#within_table' do
149
157
 
150
158
  it "should restrict scope to a fieldset given by id" do
151
159
  @session.within_table("girl_table") do
152
- @session.fill_in("Name", :with => 'Christmas')
160
+ @session.fill_in("Name", with: 'Christmas')
153
161
  @session.click_button("Create")
154
162
  end
155
163
  expect(extract_results(@session)['girl_name']).to eq('Christmas')
@@ -157,7 +165,7 @@ Capybara::SpecHelper.spec '#within_table' do
157
165
 
158
166
  it "should restrict scope to a fieldset given by legend" do
159
167
  @session.within_table("Villain") do
160
- @session.fill_in("Name", :with => 'Quantum')
168
+ @session.fill_in("Name", with: 'Quantum')
161
169
  @session.click_button("Create")
162
170
  end
163
171
  expect(extract_results(@session)['villain_name']).to eq('Quantum')
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  require "rspec"
3
+ require "rspec/expectations"
2
4
  require "capybara"
3
5
  require "capybara/rspec" # Required here instead of in rspec_spec to avoid RSpec deprecation warning
4
6
  require "capybara/spec/test_app"
@@ -17,9 +19,11 @@ module Capybara
17
19
  module SpecHelper
18
20
  class << self
19
21
  def configure(config)
20
- config.filter_run_excluding :requires => method(:filter).to_proc
22
+ config.filter_run_excluding requires: method(:filter).to_proc
21
23
  config.before { Capybara::SpecHelper.reset! }
22
24
  config.after { Capybara::SpecHelper.reset! }
25
+ # Test in 3.5+ where metadata doesn't autotrigger shared context inclusion - will be only behavior in RSpec 4
26
+ config.shared_context_metadata_behavior = :apply_to_host_groups if RSpec::Core::Version::STRING.to_f >= 3.5
23
27
  end
24
28
 
25
29
  def reset!
@@ -29,11 +33,15 @@ module Capybara
29
33
  Capybara.default_max_wait_time = 1
30
34
  Capybara.ignore_hidden_elements = true
31
35
  Capybara.exact = false
32
- Capybara.exact_options = false
36
+ # `exact_options` is deprecated - set instancce var directly so we
37
+ # don't generate message every reset
38
+ Capybara.send(:config).session_options.instance_variable_set('@exact_options', false)
33
39
  Capybara.raise_server_errors = true
34
40
  Capybara.visible_text_only = false
35
41
  Capybara.match = :smart
36
42
  Capybara.wait_on_first_by_default = false
43
+ Capybara.enable_aria_label = false
44
+ reset_threadsafe
37
45
  end
38
46
 
39
47
  def filter(requires, metadata)
@@ -46,7 +54,7 @@ module Capybara
46
54
  end
47
55
  end
48
56
 
49
- def spec(name, options={}, &block)
57
+ def spec(name, *options, &block)
50
58
  @specs ||= []
51
59
  @specs << [name, options, block]
52
60
  end
@@ -59,16 +67,33 @@ module Capybara
59
67
  before do
60
68
  @session = session
61
69
  end
70
+
62
71
  after do
63
72
  @session.reset_session!
64
73
  end
74
+
75
+ before :each, psc: true do
76
+ SpecHelper.reset_threadsafe(true, @session)
77
+ end
78
+
79
+ after psc: true do
80
+ SpecHelper.reset_threadsafe(false, @session)
81
+ end
82
+
65
83
  specs.each do |spec_name, spec_options, block|
66
- describe spec_name, spec_options do
84
+ describe spec_name, *spec_options do
67
85
  class_eval(&block)
68
86
  end
69
87
  end
70
88
  end
71
89
  end
90
+
91
+ def reset_threadsafe(bool = false, session = nil)
92
+ Capybara::Session.class_variable_set(:@@instance_created, false) # Work around limit on when threadsafe can be changed
93
+ Capybara.threadsafe = bool
94
+ session = session.current_session if session.respond_to?(:current_session)
95
+ session.instance_variable_set(:@config, nil) if session
96
+ end
72
97
  end # class << self
73
98
 
74
99
  def silence_stream(stream)
@@ -92,6 +117,14 @@ module Capybara
92
117
  expect(session).to have_xpath("//pre[@id='results']")
93
118
  YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
94
119
  end
120
+
121
+ def marionette?(session)
122
+ session.driver.respond_to?(:marionette?, true) && session.driver.send(:marionette?)
123
+ end
124
+
125
+ def rspec2?
126
+ !defined?(::RSpec::Expectations::Version) || (Gem::Version.new(RSpec::Expectations::Version::STRING) < Gem::Version.new('3.0'))
127
+ end
95
128
  end
96
129
  end
97
130
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'sinatra/base'
2
3
  require 'tilt/erb'
3
4
  require 'rack'
@@ -5,12 +6,18 @@ require 'yaml'
5
6
 
6
7
  class TestApp < Sinatra::Base
7
8
  class TestAppError < StandardError; end
8
-
9
+ class TestAppOtherError < StandardError
10
+ def initialize(string1, msg)
11
+ @something = string1
12
+ @message = msg
13
+ end
14
+ end
9
15
  set :root, File.dirname(__FILE__)
10
16
  set :static, true
11
17
  set :raise_errors, true
12
18
  set :show_exceptions, false
13
19
 
20
+ @@form_post_count = 0
14
21
  # Also check lib/capybara/spec/views/*.erb for pages not listed here
15
22
 
16
23
  get '/' do
@@ -124,6 +131,10 @@ class TestApp < Sinatra::Base
124
131
  raise TestAppError, "some error"
125
132
  end
126
133
 
134
+ get '/other_error' do
135
+ raise TestAppOtherError.new("something", "other error")
136
+ end
137
+
127
138
  get '/load_error' do
128
139
  raise LoadError
129
140
  end
@@ -137,7 +148,8 @@ class TestApp < Sinatra::Base
137
148
  end
138
149
 
139
150
  post '/form' do
140
- '<pre id="results">' + params[:form].to_yaml + '</pre>'
151
+ @@form_post_count += 1
152
+ '<pre id="results">' + params[:form].merge({"post_count" => @@form_post_count}).to_yaml + '</pre>'
141
153
  end
142
154
 
143
155
  post '/upload_empty' do
@@ -174,5 +186,5 @@ class TestApp < Sinatra::Base
174
186
  end
175
187
 
176
188
  if __FILE__ == $0
177
- Rack::Handler::WEBrick.run TestApp, :Port => 8070
189
+ Rack::Handler::WEBrick.run TestApp, Port: 8070
178
190
  end
@@ -1,3 +1,4 @@
1
+
1
2
  <h1>Buttons</h1>
2
3
  <button>Click me!</button>
3
4
  <button id="click_me_123">Click me by id!</button>
@@ -1,3 +1,4 @@
1
+
1
2
  <form action="/form" method="post">
2
3
  <fieldset id="agent_fieldset">
3
4
  <legend>Agent</legend>
@@ -26,4 +27,4 @@
26
27
  <input type="submit" value="Create"/>
27
28
  </p>
28
29
  </fieldset>
29
- </form>
30
+ </form>
@@ -1,12 +1,13 @@
1
+
1
2
  <h1>Form</h1>
2
3
 
3
4
  <form action="/form" method="post">
4
5
 
5
6
  <p>
6
7
  <label for="form_title">Title</label>
7
- <select name="form[title]" id="form_title">
8
- <option>Mrs</option>
9
- <option>Mr</option>
8
+ <select name="form[title]" id="form_title" class="title">
9
+ <option class="title">Mrs</option>
10
+ <option class="title">Mr</option>
10
11
  <option>Miss</option>
11
12
  <option disabled="disabled">Other</option>
12
13
  </select>
@@ -36,7 +37,7 @@
36
37
  <p>
37
38
  <label for="form_first_name">
38
39
  First Name
39
- <input type="text" name="form[first_name]" value="John" id="form_first_name"/>
40
+ <input type="text" name="form[first_name]" value="John" id="form_first_name" placeholder="FirstName"/>
40
41
  </label>
41
42
  </p>
42
43
 
@@ -153,6 +154,19 @@ New line after and before textarea tag
153
154
  <label for="gender_both">Both</label>
154
155
  </p>
155
156
 
157
+ <p>
158
+ <input type="radio" name="form[party]" value="democrat" id="party_democrat" style="display:none"/>
159
+ <label for="party_democrat">Democrat</label>
160
+ <input type="radio" name="form[party]" value="republican" id="party_republican" style="display:none"/>
161
+ <label for="party_republican">Republican</label>
162
+ <input type="radio" name="form[party]" value="independent" id="party_independent" checked="checked" style="display:none"/>
163
+ <label for="party_independent">Independent</label>
164
+ </p>
165
+
166
+ <p>
167
+ <input type="checkbox" id="no_attr_value_checked" value="1" checked/>
168
+ </p>
169
+
156
170
  <p>
157
171
  <input type="checkbox" value="dog" name="form[pets][]" id="form_pets_dog" checked="checked"/>
158
172
  <label for="form_pets_dog">Dog</label>
@@ -162,6 +176,26 @@ New line after and before textarea tag
162
176
  <label for="form_pets_hamster">Hamster</label>
163
177
  </p>
164
178
 
179
+ <p>
180
+ <input type="checkbox" value="jaguar" name="form[cars][]" id="form_cars_jaguar" checked="checked" style="display: none"/>
181
+ <label for="form_cars_jaguar">Jaguar</label>
182
+ <input type="checkbox" value="tesla" name="form[cars][]" id="form_cars_tesla" style="display: none"/>
183
+ <label for="form_cars_tesla">Tesla</label>
184
+ <input type="checkbox" value="ferrari" name="form[cars][]" id="form_cars_ferrari" checked="checked" style="display: none"/>
185
+ <label for="form_cars_ferrari">Ferrari</label>
186
+ <input type="checkbox" value="pagani" name="form[cars][]" id="form_cars_pagani" style="position: absolute; left: -9999px"/>
187
+ <label for="form_cars_pagani">Pagani</label>
188
+ <input type="checkbox" value="ariel" name="form[cars][]" id="form_cars_ariel" style="display: none"/>
189
+ <label>
190
+ McLaren
191
+ <input type="checkbox" value="mclaren" name="form[cars][]" id="form_cars_mclaren" style="display: none"/>
192
+ </label>
193
+ <label>
194
+ Koenigsegg
195
+ <input type="checkbox" value="koenigsegg" name="form[cars][]" id="form_cars_koenigsegg" checked="checked" style="display: none"/>
196
+ </label>
197
+ </p>
198
+
165
199
  <p>
166
200
  <input type="checkbox" name="form[valueless_checkbox]" id="valueless_checkbox" checked="checked"/>
167
201
  <label for="valueless_checkbox">Valueless Checkbox</label>
@@ -191,6 +225,48 @@ New line after and before textarea tag
191
225
  </select>
192
226
  </p>
193
227
 
228
+ <!-- invisible select and options -->
229
+ <p style="display: none">
230
+ <label for="form_icecream">Icecream</label>
231
+ <select name="form[icecream]" id="form_icecream">
232
+ <option selected="selected">Chocolate</option>
233
+ <option>Vanilla</option>
234
+ <option>Strawberry</option>
235
+ </select>
236
+ </p>
237
+
238
+ <!-- invisible multiselect and options -->
239
+ <p style="display: none">
240
+ <label for="form_dessert">Dessert</label>
241
+ <select name="form[dessert]" id="form_dessert" multiple="multiple">
242
+ <option selected="selected">Pudding</option>
243
+ <option>Lava cake</option>
244
+ <option selected="selected">Tiramisu</option>
245
+ <option>Panna cotta</option>
246
+ </select>
247
+ </p>
248
+
249
+ <!-- visible select with invisible selected option (which some browsers may treat as visible) -->
250
+ <p>
251
+ <label for="form_sorbet">Sorbet</label>
252
+ <select name="form[sorbet]" id="form_sorbet">
253
+ <option>Chocolate</option>
254
+ <option selected="selected" style="display: none">Vanilla</option>
255
+ <option>Strawberry</option>
256
+ </select>
257
+ </p>
258
+
259
+ <!-- visible multiselect with invisible selected options (which some browsers may treat as visible) -->
260
+ <p>
261
+ <label for="form_cake">Cake</label>
262
+ <select name="form[cake]" id="form_cake" multiple="multiple">
263
+ <option>Butter Cake</option>
264
+ <option selected="selected" style="display: none">Chocolate Cake</option>
265
+ <option>Strawberry Cake</option>
266
+ <option selected="selected" style="display: none">Sponge Cake</option>
267
+ </select>
268
+ </p>
269
+
194
270
  <p>
195
271
  <span>First address<span>
196
272
  <label for='address1_street'>Street</label>
@@ -201,7 +277,7 @@ New line after and before textarea tag
201
277
 
202
278
  <label for='address1_country'>Country</label>
203
279
  <select name="form[addresses][][country]" id="address1_country">
204
- <option>France</option>
280
+ <option selected>France</option>
205
281
  <option>Ukraine</option>
206
282
  </select>
207
283
  </p>
@@ -217,7 +293,7 @@ New line after and before textarea tag
217
293
  <label for='address2_country'>Country</label>
218
294
  <select name="form[addresses][][country]" id="address2_country">
219
295
  <option>France</option>
220
- <option>Ukraine</option>
296
+ <option selected>Ukraine</option>
221
297
  </select>
222
298
  </p>
223
299
 
@@ -268,10 +344,23 @@ New line after and before textarea tag
268
344
  Disabled Select
269
345
  <select name="form[disabled_select]" id="form_disabled_select" disabled="disabled">
270
346
  <option value="Should not see me" selected="selected">Should not see me</option>
347
+ <optgroup>
348
+ <option value="Disabled too">Disabled too</option>
349
+ </optgroup>
271
350
  </select>
272
351
  </label>
273
352
  </p>
274
353
 
354
+ <p>
355
+ <label for="form_disabled_select2">
356
+ Disabled Select 2
357
+ <select name="form[disabled_select2]" id="form_disabled_select2" disabled>
358
+ <option value="Should not see me" selected="selected">Should not see me</option>
359
+ </select>
360
+ </label>
361
+ </p>
362
+
363
+
275
364
  <p>
276
365
  <label for="form_disabled_file">
277
366
  Disabled File
@@ -279,6 +368,51 @@ New line after and before textarea tag
279
368
  </label>
280
369
  </p>
281
370
 
371
+ <p>
372
+ <fieldset>
373
+ <input name="form[enabled_fieldset_child]" id="form_enabled_fieldset_child"/>
374
+ </fieldset>
375
+ </p>
376
+
377
+
378
+ <p>
379
+ <fieldset disabled="disabled">
380
+ <legend>Disabled Child</legend>
381
+ <input name="form[disabled_fieldset_child]" id="form_disabled_fieldset_child"/>
382
+ <select>
383
+ <option>Disabled Child Option</option>
384
+ </select>
385
+ </fieldset>
386
+
387
+ <fieldset disabled="disabled">
388
+ <legend>
389
+ Nested Disabled
390
+ <input type="checkbox" name="form[disabled_fieldeset_legend_child]" id="form_disabled_fieldset_legend_child"/>
391
+ </legend>
392
+ <legend>
393
+ Another Legend
394
+ <input type="checkbox" name="form[disabled_fieldeset_second_legend_child]" id="form_disabled_fieldset_second_legend_child"/>
395
+ </legend>
396
+ <p>
397
+ <fieldset>
398
+ <input name="form[disabled_fieldset_descendant]" id="form_disabled_fieldset_descendant"/>
399
+ </fieldset>
400
+ </p>
401
+ </fieldset>
402
+ </p>
403
+
404
+ <p>
405
+ <select>
406
+ <optgroup label="Level One">
407
+ <option> A.1 </option>
408
+ </optgroup>
409
+ <optgroup label="Level Two" disabled="disabled">
410
+ <option> A.B.1 </option>
411
+ </optgroup>
412
+ <option> A.2 </option>
413
+ </select>
414
+ </p>
415
+
282
416
  <p>
283
417
  <input type="button" name="form[fresh]" id="fresh_btn" value="i am fresh"/>
284
418
  <input type="submit" name="form[awesome]" id="awe123" title="What an Awesome Button" value="awesome"/>
@@ -287,6 +421,7 @@ New line after and before textarea tag
287
421
  <button type="submit" id="click_me_123" title="Click Title button" value="click_me">Click me!</button>
288
422
  <button type="submit" name="form[no_value]">No Value!</button>
289
423
  <button id="no_type">No Type!</button>
424
+ <button><img alt="A horse eating hay"/></button>
290
425
  <input type="button" disabled="disabled" value="Disabled button"/>
291
426
  </p>
292
427
 
@@ -298,6 +433,11 @@ New line after and before textarea tag
298
433
 
299
434
  <input type="text" name="form[outside_input]" value="outside_input" form="form1"/>
300
435
 
436
+ <label>
437
+ Nested Label
438
+ <input type="text" name="nested_label" id="nested_label"/>
439
+ </label>
440
+
301
441
  <form id="form1" action="/form" method="post">
302
442
  <input type="text" name="form[which_form]" value="form1" id="form_which_form"/>
303
443
  <input type="text" name="form[for_form2]" value="for_form2" form="form2"/>
@@ -330,7 +470,7 @@ New line after and before textarea tag
330
470
  </p>
331
471
 
332
472
  <p>
333
- <input type="submit" name="form[mediocre]" id="mediocre" value="med"/>
473
+ <input type="submit" name="form[mediocre]" id="mediocre" value="med" aria-label="Mediocre Button"/>
334
474
  <p>
335
475
  </form>
336
476
 
@@ -403,6 +543,10 @@ New line after and before textarea tag
403
543
  <label for="html5_email">Html5 Email</label>
404
544
  <input type="email" name="form[html5_email]" value="person@email.com" id="html5_email"/>
405
545
  </p>
546
+ <p>
547
+ <label for="html5_multiple_email">Html5 Multiple Email</label>
548
+ <input type="email" multiple name="form[html5_multiple_email]" value="person@email.com" id="html5_multiple_email"/>
549
+ </p>
406
550
  <p>
407
551
  <label for="html5_url">Html5 Url</label>
408
552
  <input type="url" name="form[html5_url]" value="http://www.example.com" id="html5_url"/>
@@ -411,9 +555,10 @@ New line after and before textarea tag
411
555
  <label for="html5_search">Html5 Search</label>
412
556
  <input type="search" name="form[html5_search]" value="what are you looking for" id="html5_search"/>
413
557
  </p>
558
+ <p id="emergency">Emergency Number</p>
414
559
  <p>
415
560
  <label for="html5_tel">Html5 Tel</label>
416
- <input type="tel" name="form[html5_tel]" value="911" id="html5_tel"/>
561
+ <input type="tel" aria-labelledby="emergency" name="form[html5_tel]" value="911" id="html5_tel"/>
417
562
  </p>
418
563
  <p>
419
564
  <label for="html5_color">Html5 Color</label>
@@ -436,7 +581,7 @@ New line after and before textarea tag
436
581
 
437
582
  <form action="/other_form" method="post">
438
583
  <p>
439
- <input type="text" name="form[which_form]" value="formaction form"/>
584
+ <input type="text" name="form[which_form]" value="formaction form" aria-label="Unlabelled Input"/>
440
585
  </p>
441
586
  <input type="submit" name="form[button]" formaction="/form" value="Formaction button"/>
442
587
  <input type="submit" name="form[button]" formaction="/form/get" formmethod="get" value="Formmethod button"/>
@@ -454,4 +599,19 @@ New line after and before textarea tag
454
599
  </p>
455
600
  </form>
456
601
 
602
+ <label>Confusion
603
+ <input type="checkbox" id="confusion_checkbox" class="confusion-checkbox confusion"/>
604
+ </label>
605
+
606
+ <label>Confusion
607
+ <input type="text" id="confusion_text" class="confusion-text confusion"/>
608
+ </label>
609
+
610
+ <label>Confusion
611
+ <textarea id="confusion_textarea" class="confusion confusion-textarea"></textarea>
612
+ </label>
457
613
 
614
+ <p>
615
+ <label for="asterisk_input">With Asterisk<abbr title="required">*</abbr></label>
616
+ <input id="asterisk_input" type="number"value="2016"/>
617
+ </p>
@@ -1,9 +1,17 @@
1
+
1
2
  <html>
2
3
  <head>
3
4
  <title>This is the child frame title</title>
5
+ <script>
6
+ function closeWin() {
7
+ var iframe = window.parent.document.getElementById('childFrame')
8
+ iframe.parentNode.removeChild(iframe)
9
+ }
10
+ </script>
4
11
  </head>
5
- <body>
12
+ <body id="childBody">
13
+ <a href="javascript:void(0)" onClick="closeWin()">Close Window</a>
6
14
  <iframe src="/frame_one" id="grandchildFrame1"></iframe>
7
15
  <iframe src="/frame_two" id="grandchildFrame2"></iframe>
8
16
  </body>
9
- </html>
17
+ </html>
@@ -1,3 +1,4 @@
1
+
1
2
  <html>
2
3
  <head>
3
4
  <title>This is the title of frame one</title>
@@ -5,4 +6,4 @@
5
6
  <body>
6
7
  <div id="divInFrameOne">This is the text of divInFrameOne</div>
7
8
  </body>
8
- </html>
9
+ </html>
@@ -1,8 +1,9 @@
1
+
1
2
  <html>
2
3
  <head>
3
4
  <title>This is the parent frame title</title>
4
5
  </head>
5
- <body>
6
+ <body id="parentBody">
6
7
  <iframe src='/frame_child' id='childFrame'></iframe>
7
8
  </body>
8
- </html>
9
+ </html>
@@ -1,3 +1,4 @@
1
+
1
2
  <html>
2
3
  <head>
3
4
  <title>This is the title of frame two</title>
@@ -5,4 +6,4 @@
5
6
  <body>
6
7
  <div id="divInFrameTwo">This is the text of divInFrameTwo</div>
7
8
  </body>
8
- </html>
9
+ </html>
@@ -1,3 +1,4 @@
1
+
1
2
  <p>
2
3
  <a href="/get_header">Link</a>
3
4
  </p>
@@ -1,3 +1,4 @@
1
+
1
2
  <p>
2
3
  <a href="/host">Relative Host</a>
3
4
  <a href="<%= params[:absolute_host] %>/host">Absolute Host</a>