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 '#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>