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 '#find' do
2
3
  before do
3
4
  @session.visit('/with_html')
@@ -9,19 +10,19 @@ Capybara::SpecHelper.spec '#find' do
9
10
 
10
11
  it "should find the first element using the given locator" do
11
12
  expect(@session.find('//h1').text).to eq('This is a test')
12
- expect(@session.find("//input[@id='test_field']")[:value]).to eq('monkey')
13
+ expect(@session.find("//input[@id='test_field']").value).to eq('monkey')
13
14
  end
14
15
 
15
16
  it "should find the first element using the given locator and options" do
16
- expect(@session.find('//a', :text => 'Redirect')[:id]).to eq('red')
17
- expect(@session.find(:css, 'a', :text => 'A link came first')[:title]).to eq('twas a fine link')
17
+ expect(@session.find('//a', text: 'Redirect')[:id]).to eq('red')
18
+ expect(@session.find(:css, 'a', text: 'A link came first')[:title]).to eq('twas a fine link')
18
19
  end
19
20
 
20
21
  it "should raise an error if there are multiple matches" do
21
22
  expect { @session.find('//a') }.to raise_error(Capybara::Ambiguous)
22
23
  end
23
24
 
24
- it "should wait for asynchronous load", :requires => [:js] do
25
+ it "should wait for asynchronous load", requires: [:js] do
25
26
  @session.visit('/with_js')
26
27
  @session.click_link('Click me')
27
28
  expect(@session.find(:css, "a#has-been-clicked").text).to include('Has been clicked')
@@ -33,12 +34,12 @@ Capybara::SpecHelper.spec '#find' do
33
34
  end
34
35
  end
35
36
 
36
- context "with :wait option", :requires => [:js] do
37
+ context "with :wait option", requires: [:js] do
37
38
  it "should not wait for asynchronous load when `false` given" do
38
39
  @session.visit('/with_js')
39
40
  @session.click_link('Click me')
40
41
  expect do
41
- @session.find(:css, "a#has-been-clicked", :wait => false)
42
+ @session.find(:css, "a#has-been-clicked", wait: false)
42
43
  end.to raise_error(Capybara::ElementNotFound)
43
44
  end
44
45
 
@@ -46,18 +47,18 @@ Capybara::SpecHelper.spec '#find' do
46
47
  @session.visit('/with_js')
47
48
  @session.click_link('Slowly')
48
49
  expect do
49
- @session.find(:css, "a#slow-clicked", :wait => 0.2)
50
+ @session.find(:css, "a#slow-clicked", wait: 0.2)
50
51
  end.to raise_error(Capybara::ElementNotFound)
51
52
  end
52
53
 
53
54
  it "should find element if it appears before given wait duration" do
54
55
  @session.visit('/with_js')
55
56
  @session.click_link('Click me')
56
- expect(@session.find(:css, "a#has-been-clicked", :wait => 0.9).text).to include('Has been clicked')
57
+ expect(@session.find(:css, "a#has-been-clicked", wait: 2.0).text).to include('Has been clicked')
57
58
  end
58
59
  end
59
60
 
60
- context "with frozen time", :requires => [:js] do
61
+ context "with frozen time", requires: [:js] do
61
62
  if defined?(Process::CLOCK_MONOTONIC)
62
63
  it "will time out even if time is frozen" do
63
64
  @session.visit('/with_js')
@@ -78,7 +79,7 @@ Capybara::SpecHelper.spec '#find' do
78
79
  context "with css selectors" do
79
80
  it "should find the first element using the given locator" do
80
81
  expect(@session.find(:css, 'h1').text).to eq('This is a test')
81
- expect(@session.find(:css, "input[id='test_field']")[:value]).to eq('monkey')
82
+ expect(@session.find(:css, "input[id='test_field']").value).to eq('monkey')
82
83
  end
83
84
 
84
85
  it "should support pseudo selectors" do
@@ -89,7 +90,7 @@ Capybara::SpecHelper.spec '#find' do
89
90
  context "with xpath selectors" do
90
91
  it "should find the first element using the given locator" do
91
92
  expect(@session.find(:xpath, '//h1').text).to eq('This is a test')
92
- expect(@session.find(:xpath, "//input[@id='test_field']")[:value]).to eq('monkey')
93
+ expect(@session.find(:xpath, "//input[@id='test_field']").value).to eq('monkey')
93
94
  end
94
95
  end
95
96
 
@@ -103,11 +104,11 @@ Capybara::SpecHelper.spec '#find' do
103
104
  end
104
105
  end
105
106
 
106
- context "with custom selector with :for option" do
107
- it "should use the selector when it matches the :for option" do
107
+ context "with custom selector with custom `match` block" do
108
+ it "should use the custom selector when locator matches the block" do
108
109
  Capybara.add_selector(:beatle) do
109
110
  xpath { |num| ".//*[contains(@class, 'beatle')][#{num}]" }
110
- match { |value| value.is_a?(Fixnum) }
111
+ match { |value| value.is_a?(Integer) }
111
112
  end
112
113
  expect(@session.find(:beatle, '2').text).to eq('Paul')
113
114
  expect(@session.find(1).text).to eq('John')
@@ -125,8 +126,8 @@ Capybara::SpecHelper.spec '#find' do
125
126
  end
126
127
 
127
128
  it "should find elements that match the filter" do
128
- expect(@session.find(:beatle, 'Paul', :type => 'drummer').text).to eq('Paul')
129
- expect(@session.find(:beatle, 'Ringo', :type => 'drummer').text).to eq('Ringo')
129
+ expect(@session.find(:beatle, 'Paul', type: 'drummer').text).to eq('Paul')
130
+ expect(@session.find(:beatle, 'Ringo', type: 'drummer').text).to eq('Ringo')
130
131
  end
131
132
 
132
133
  it "ignores filter when it is not given" do
@@ -135,8 +136,8 @@ Capybara::SpecHelper.spec '#find' do
135
136
  end
136
137
 
137
138
  it "should not find elements that don't match the filter" do
138
- expect { @session.find(:beatle, 'John', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
139
- expect { @session.find(:beatle, 'George', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
139
+ expect { @session.find(:beatle, 'John', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)
140
+ expect { @session.find(:beatle, 'George', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)
140
141
  end
141
142
  end
142
143
 
@@ -144,13 +145,13 @@ Capybara::SpecHelper.spec '#find' do
144
145
  before do
145
146
  Capybara.add_selector(:beatle) do
146
147
  xpath { |name| ".//li[contains(@class, 'beatle')][contains(text(), '#{name}')]" }
147
- filter(:type, :default => "drummer") { |node, type| node[:class].split(/\s+/).include?(type) }
148
+ filter(:type, default: "drummer") { |node, type| node[:class].split(/\s+/).include?(type) }
148
149
  end
149
150
  end
150
151
 
151
152
  it "should find elements that match the filter" do
152
- expect(@session.find(:beatle, 'Paul', :type => 'drummer').text).to eq('Paul')
153
- expect(@session.find(:beatle, 'Ringo', :type => 'drummer').text).to eq('Ringo')
153
+ expect(@session.find(:beatle, 'Paul', type: 'drummer').text).to eq('Paul')
154
+ expect(@session.find(:beatle, 'Ringo', type: 'drummer').text).to eq('Ringo')
154
155
  end
155
156
 
156
157
  it "should use default value when filter is not given" do
@@ -159,8 +160,36 @@ Capybara::SpecHelper.spec '#find' do
159
160
  end
160
161
 
161
162
  it "should not find elements that don't match the filter" do
162
- expect { @session.find(:beatle, 'John', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
163
- expect { @session.find(:beatle, 'George', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
163
+ expect { @session.find(:beatle, 'John', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)
164
+ expect { @session.find(:beatle, 'George', type: 'drummer') }.to raise_error(Capybara::ElementNotFound)
165
+ end
166
+ end
167
+
168
+ context "with alternate filter set" do
169
+ before do
170
+ Capybara::Selector::FilterSet.add(:value) do
171
+ filter(:with) { |node, with| node.value == with.to_s }
172
+ end
173
+
174
+ Capybara.add_selector(:id_with_field_filters) do
175
+ xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
176
+ filter_set(:field)
177
+ end
178
+ end
179
+
180
+ it "should allow use of filters from custom filter set" do
181
+ expect(@session.find(:id, 'test_field', filter_set: :value, with: 'monkey').value).to eq('monkey')
182
+ expect{ @session.find(:id, 'test_field', filter_set: :value, with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)
183
+ end
184
+
185
+ it "should allow use of filter set from a different selector" do
186
+ expect(@session.find(:id, 'test_field', filter_set: :field, with: 'monkey').value).to eq('monkey')
187
+ expect{ @session.find(:id, 'test_field', filter_set: :field, with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)
188
+ end
189
+
190
+ it "should allow importing of filter set into selector" do
191
+ expect(@session.find(:id_with_field_filters, 'test_field', with: 'monkey').value).to eq('monkey')
192
+ expect{ @session.find(:id_with_field_filters, 'test_field', with: 'not_monkey') }.to raise_error(Capybara::ElementNotFound)
164
193
  end
165
194
  end
166
195
 
@@ -168,7 +197,7 @@ Capybara::SpecHelper.spec '#find' do
168
197
  before { Capybara.default_selector = :css }
169
198
  it "should find the first element using the given locator" do
170
199
  expect(@session.find('h1').text).to eq('This is a test')
171
- expect(@session.find("input[id='test_field']")[:value]).to eq('monkey')
200
+ expect(@session.find("input[id='test_field']").value).to eq('monkey')
172
201
  end
173
202
  after { Capybara.default_selector = :xpath }
174
203
  end
@@ -176,26 +205,27 @@ Capybara::SpecHelper.spec '#find' do
176
205
  it "should raise ElementNotFound with a useful default message if nothing was found" do
177
206
  expect do
178
207
  @session.find(:xpath, '//div[@id="nosuchthing"]').to be_nil
179
- end.to raise_error(Capybara::ElementNotFound, "Unable to find xpath \"//div[@id=\\\"nosuchthing\\\"]\"")
208
+ end.to raise_error(Capybara::ElementNotFound, "Unable to find visible xpath \"//div[@id=\\\"nosuchthing\\\"]\"")
180
209
  end
181
210
 
182
211
  it "should accept an XPath instance" do
183
212
  @session.visit('/form')
184
- @xpath = XPath::HTML.fillable_field('First Name')
213
+ @xpath = Capybara::Selector.all[:fillable_field].call('First Name')
214
+ expect(@xpath).to be_a(::XPath::Union)
185
215
  expect(@session.find(@xpath).value).to eq('John')
186
216
  end
187
217
 
188
218
  context "with :exact option" do
189
219
  it "matches exactly when true" do
190
- expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("test_field")], :exact => true).value).to eq("monkey")
220
+ expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("test_field")], exact: true).value).to eq("monkey")
191
221
  expect do
192
- @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")], :exact => true)
222
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")], exact: true)
193
223
  end.to raise_error(Capybara::ElementNotFound)
194
224
  end
195
225
 
196
226
  it "matches loosely when false" do
197
- expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("test_field")], :exact => false).value).to eq("monkey")
198
- expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")], :exact => false).value).to eq("monkey")
227
+ expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("test_field")], exact: false).value).to eq("monkey")
228
+ expect(@session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")], exact: false).value).to eq("monkey")
199
229
  end
200
230
 
201
231
  it "defaults to `Capybara.exact`" do
@@ -206,37 +236,43 @@ Capybara::SpecHelper.spec '#find' do
206
236
  Capybara.exact = false
207
237
  @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")])
208
238
  end
239
+
240
+ it "warns when the option has no effect" do
241
+ expect_any_instance_of(Kernel).to receive(:warn).
242
+ with('The :exact option only has an effect on queries using the XPath#is method. Using it with the query "#test_field" has no effect.')
243
+ @session.find(:css, '#test_field', exact: true)
244
+ end
209
245
  end
210
246
 
211
247
  context "with :match option" do
212
248
  context "when set to `one`" do
213
249
  it "raises an error when multiple matches exist" do
214
250
  expect do
215
- @session.find(:css, ".multiple", :match => :one)
251
+ @session.find(:css, ".multiple", match: :one)
216
252
  end.to raise_error(Capybara::Ambiguous)
217
253
  end
218
254
  it "raises an error even if there the match is exact and the others are inexact" do
219
255
  expect do
220
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :exact => false, :match => :one)
256
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], exact: false, match: :one)
221
257
  end.to raise_error(Capybara::Ambiguous)
222
258
  end
223
259
  it "returns the element if there is only one" do
224
- expect(@session.find(:css, ".singular", :match => :one).text).to eq("singular")
260
+ expect(@session.find(:css, ".singular", match: :one).text).to eq("singular")
225
261
  end
226
262
  it "raises an error if there is no match" do
227
263
  expect do
228
- @session.find(:css, ".does-not-exist", :match => :one)
264
+ @session.find(:css, ".does-not-exist", match: :one)
229
265
  end.to raise_error(Capybara::ElementNotFound)
230
266
  end
231
267
  end
232
268
 
233
269
  context "when set to `first`" do
234
270
  it "returns the first matched element" do
235
- expect(@session.find(:css, ".multiple", :match => :first).text).to eq("multiple one")
271
+ expect(@session.find(:css, ".multiple", match: :first).text).to eq("multiple one")
236
272
  end
237
273
  it "raises an error if there is no match" do
238
274
  expect do
239
- @session.find(:css, ".does-not-exist", :match => :first)
275
+ @session.find(:css, ".does-not-exist", match: :first)
240
276
  end.to raise_error(Capybara::ElementNotFound)
241
277
  end
242
278
  end
@@ -245,25 +281,25 @@ Capybara::SpecHelper.spec '#find' do
245
281
  context "and `exact` set to `false`" do
246
282
  it "raises an error when there are multiple exact matches" do
247
283
  expect do
248
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :smart, :exact => false)
284
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], match: :smart, exact: false)
249
285
  end.to raise_error(Capybara::Ambiguous)
250
286
  end
251
287
  it "finds a single exact match when there also are inexact matches" do
252
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :smart, :exact => false)
288
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], match: :smart, exact: false)
253
289
  expect(result.text).to eq("almost singular")
254
290
  end
255
291
  it "raises an error when there are multiple inexact matches" do
256
292
  expect do
257
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :smart, :exact => false)
293
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], match: :smart, exact: false)
258
294
  end.to raise_error(Capybara::Ambiguous)
259
295
  end
260
296
  it "finds a single inexact match" do
261
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :smart, :exact => false)
297
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], match: :smart, exact: false)
262
298
  expect(result.text).to eq("almost singular but not quite")
263
299
  end
264
300
  it "raises an error if there is no match" do
265
301
  expect do
266
- @session.find(:css, ".does-not-exist", :match => :smart, :exact => false)
302
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], match: :smart, exact: false)
267
303
  end.to raise_error(Capybara::ElementNotFound)
268
304
  end
269
305
  end
@@ -271,26 +307,26 @@ Capybara::SpecHelper.spec '#find' do
271
307
  context "with `exact` set to `true`" do
272
308
  it "raises an error when there are multiple exact matches" do
273
309
  expect do
274
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :smart, :exact => true)
310
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], match: :smart, exact: true)
275
311
  end.to raise_error(Capybara::Ambiguous)
276
312
  end
277
313
  it "finds a single exact match when there also are inexact matches" do
278
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :smart, :exact => true)
314
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], match: :smart, exact: true)
279
315
  expect(result.text).to eq("almost singular")
280
316
  end
281
317
  it "raises an error when there are multiple inexact matches" do
282
318
  expect do
283
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :smart, :exact => true)
319
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], match: :smart, exact: true)
284
320
  end.to raise_error(Capybara::ElementNotFound)
285
321
  end
286
322
  it "raises an error when there is a single inexact matches" do
287
323
  expect do
288
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :smart, :exact => true)
324
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], match: :smart, exact: true)
289
325
  end.to raise_error(Capybara::ElementNotFound)
290
326
  end
291
327
  it "raises an error if there is no match" do
292
328
  expect do
293
- @session.find(:css, ".does-not-exist", :match => :smart, :exact => true)
329
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], match: :smart, exact: true)
294
330
  end.to raise_error(Capybara::ElementNotFound)
295
331
  end
296
332
  end
@@ -299,50 +335,50 @@ Capybara::SpecHelper.spec '#find' do
299
335
  context "when set to `prefer_exact`" do
300
336
  context "and `exact` set to `false`" do
301
337
  it "picks the first one when there are multiple exact matches" do
302
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :prefer_exact, :exact => false)
338
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], match: :prefer_exact, exact: false)
303
339
  expect(result.text).to eq("multiple one")
304
340
  end
305
341
  it "finds a single exact match when there also are inexact matches" do
306
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :prefer_exact, :exact => false)
342
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], match: :prefer_exact, exact: false)
307
343
  expect(result.text).to eq("almost singular")
308
344
  end
309
345
  it "picks the first one when there are multiple inexact matches" do
310
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :prefer_exact, :exact => false)
346
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], match: :prefer_exact, exact: false)
311
347
  expect(result.text).to eq("almost singular but not quite")
312
348
  end
313
349
  it "finds a single inexact match" do
314
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :prefer_exact, :exact => false)
350
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], match: :prefer_exact, exact: false)
315
351
  expect(result.text).to eq("almost singular but not quite")
316
352
  end
317
353
  it "raises an error if there is no match" do
318
354
  expect do
319
- @session.find(:css, ".does-not-exist", :match => :prefer_exact, :exact => false)
355
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], match: :prefer_exact, exact: false)
320
356
  end.to raise_error(Capybara::ElementNotFound)
321
357
  end
322
358
  end
323
359
 
324
360
  context "with `exact` set to `true`" do
325
361
  it "picks the first one when there are multiple exact matches" do
326
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :prefer_exact, :exact => true)
362
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], match: :prefer_exact, exact: true)
327
363
  expect(result.text).to eq("multiple one")
328
364
  end
329
365
  it "finds a single exact match when there also are inexact matches" do
330
- result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :prefer_exact, :exact => true)
366
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], match: :prefer_exact, exact: true)
331
367
  expect(result.text).to eq("almost singular")
332
368
  end
333
369
  it "raises an error if there are multiple inexact matches" do
334
370
  expect do
335
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :prefer_exact, :exact => true)
371
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], match: :prefer_exact, exact: true)
336
372
  end.to raise_error(Capybara::ElementNotFound)
337
373
  end
338
374
  it "raises an error if there is a single inexact match" do
339
375
  expect do
340
- @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :prefer_exact, :exact => true)
376
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], match: :prefer_exact, exact: true)
341
377
  end.to raise_error(Capybara::ElementNotFound)
342
378
  end
343
379
  it "raises an error if there is no match" do
344
380
  expect do
345
- @session.find(:css, ".does-not-exist", :match => :prefer_exact, :exact => true)
381
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], match: :prefer_exact, exact: true)
346
382
  end.to raise_error(Capybara::ElementNotFound)
347
383
  end
348
384
  end
@@ -359,11 +395,15 @@ Capybara::SpecHelper.spec '#find' do
359
395
 
360
396
  it "raises an error when unknown option given" do
361
397
  expect do
362
- @session.find(:css, ".singular", :match => :schmoo)
398
+ @session.find(:css, ".singular", match: :schmoo)
363
399
  end.to raise_error(ArgumentError)
364
400
  end
365
401
  end
366
402
 
403
+ it "supports a custom filter block" do
404
+ expect(@session.find(:css, 'input'){|node| node.disabled? }[:name]).to eq('disabled_text')
405
+ end
406
+
367
407
  context "within a scope" do
368
408
  before do
369
409
  @session.visit('/with_scope')
@@ -381,4 +421,10 @@ Capybara::SpecHelper.spec '#find' do
381
421
  end
382
422
  end
383
423
  end
424
+
425
+ it "should raise if selector type is unknown" do
426
+ expect do
427
+ @session.find(:unknown, '//h1')
428
+ end.to raise_error(ArgumentError)
429
+ end
384
430
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  Capybara::SpecHelper.spec '#first' do
2
3
  before do
3
4
  @session.visit('/with_html')
@@ -5,7 +6,7 @@ Capybara::SpecHelper.spec '#first' do
5
6
 
6
7
  it "should find the first element using the given locator" do
7
8
  expect(@session.first('//h1').text).to eq('This is a test')
8
- expect(@session.first("//input[@id='test_field']")[:value]).to eq('monkey')
9
+ expect(@session.first("//input[@id='test_field']").value).to eq('monkey')
9
10
  end
10
11
 
11
12
  it "should return nil when nothing was found" do
@@ -14,21 +15,27 @@ Capybara::SpecHelper.spec '#first' do
14
15
 
15
16
  it "should accept an XPath instance" do
16
17
  @session.visit('/form')
17
- @xpath = XPath::HTML.fillable_field('First Name')
18
+ @xpath = Capybara::Selector.all[:fillable_field].call('First Name')
19
+ expect(@xpath).to be_a(::XPath::Union)
18
20
  expect(@session.first(@xpath).value).to eq('John')
19
21
  end
20
22
 
23
+ it "should warn when unused parameters are passed" do
24
+ expect_any_instance_of(Kernel).to receive(:warn).with(/Unused parameters passed.*unused text/)
25
+ @session.first(:css, '.header h2', 'unused text')
26
+ end
27
+
21
28
  context "with css selectors" do
22
29
  it "should find the first element using the given selector" do
23
30
  expect(@session.first(:css, 'h1').text).to eq('This is a test')
24
- expect(@session.first(:css, "input[id='test_field']")[:value]).to eq('monkey')
31
+ expect(@session.first(:css, "input[id='test_field']").value).to eq('monkey')
25
32
  end
26
33
  end
27
34
 
28
35
  context "with xpath selectors" do
29
36
  it "should find the first element using the given locator" do
30
37
  expect(@session.first(:xpath, '//h1').text).to eq('This is a test')
31
- expect(@session.first(:xpath, "//input[@id='test_field']")[:value]).to eq('monkey')
38
+ expect(@session.first(:xpath, "//input[@id='test_field']").value).to eq('monkey')
32
39
  end
33
40
  end
34
41
 
@@ -36,33 +43,38 @@ Capybara::SpecHelper.spec '#first' do
36
43
  before { Capybara.default_selector = :css }
37
44
  it "should find the first element using the given locator" do
38
45
  expect(@session.first('h1').text).to eq('This is a test')
39
- expect(@session.first("input[id='test_field']")[:value]).to eq('monkey')
46
+ expect(@session.first("input[id='test_field']").value).to eq('monkey')
40
47
  end
41
48
  end
42
49
 
43
50
  context "with visible filter" do
44
51
  it "should only find visible nodes when true" do
45
- expect(@session.first(:css, "a#invisible", :visible => true)).to be_nil
52
+ expect(@session.first(:css, "a#invisible", visible: true)).to be_nil
46
53
  end
47
54
 
48
55
  it "should find nodes regardless of whether they are invisible when false" do
49
- expect(@session.first(:css, "a#invisible", :visible => false)).not_to be_nil
50
- expect(@session.first(:css, "a#visible", :visible => false)).not_to be_nil
56
+ expect(@session.first(:css, "a#invisible", visible: false)).not_to be_nil
57
+ expect(@session.first(:css, "a#invisible", visible: false, text: 'hidden link')).not_to be_nil
58
+ expect(@session.first(:css, "a#visible", visible: false)).not_to be_nil
51
59
  end
52
60
 
53
61
  it "should find nodes regardless of whether they are invisible when :all" do
54
- expect(@session.first(:css, "a#invisible", :visible => :all)).not_to be_nil
55
- expect(@session.first(:css, "a#visible", :visible => :all)).not_to be_nil
62
+ expect(@session.first(:css, "a#invisible", visible: :all)).not_to be_nil
63
+ expect(@session.first(:css, "a#invisible", visible: :all, text: 'hidden link')).not_to be_nil
64
+ expect(@session.first(:css, "a#visible", visible: :all)).not_to be_nil
56
65
  end
57
66
 
58
67
  it "should find only hidden nodes when :hidden" do
59
- expect(@session.first(:css, "a#invisible", :visible => :hidden)).not_to be_nil
60
- expect(@session.first(:css, "a#visible", :visible => :hidden)).to be_nil
68
+ expect(@session.first(:css, "a#invisible", visible: :hidden)).not_to be_nil
69
+ expect(@session.first(:css, "a#invisible", visible: :hidden, text: 'hidden link')).not_to be_nil
70
+ expect(@session.first(:css, "a#invisible", visible: :hidden, text: 'not hidden link')).to be_nil
71
+ expect(@session.first(:css, "a#visible", visible: :hidden)).to be_nil
61
72
  end
62
73
 
63
74
  it "should find only visible nodes when :visible" do
64
- expect(@session.first(:css, "a#invisible", :visible => :visible)).to be_nil
65
- expect(@session.first(:css, "a#visible", :visible => :visible)).not_to be_nil
75
+ expect(@session.first(:css, "a#invisible", visible: :visible)).to be_nil
76
+ expect(@session.first(:css, "a#invisible", visible: :visible, text: 'hidden link')).to be_nil
77
+ expect(@session.first(:css, "a#visible", visible: :visible)).not_to be_nil
66
78
  end
67
79
 
68
80
  it "should default to Capybara.ignore_hidden_elements" do
@@ -99,14 +111,18 @@ Capybara::SpecHelper.spec '#first' do
99
111
 
100
112
  it "should wait for at least one match if true" do
101
113
  Capybara.wait_on_first_by_default = true
102
- @session.click_link('clickable')
103
- expect(@session.first(:css, 'a#has-been-clicked')).not_to be_nil
114
+ Capybara.using_wait_time(3) do
115
+ @session.click_link('clickable')
116
+ expect(@session.first(:css, 'a#has-been-clicked')).not_to be_nil
117
+ end
104
118
  end
105
119
 
106
120
  it "should return nil after waiting if no match" do
107
121
  Capybara.wait_on_first_by_default = true
108
- @session.click_link('clickable')
109
- expect(@session.first(:css, 'a#not-a-real-link')).to be_nil
122
+ Capybara.using_wait_time(3) do
123
+ @session.click_link('clickable')
124
+ expect(@session.first(:css, 'a#not-a-real-link')).to be_nil
125
+ end
110
126
  end
111
127
  end
112
128
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+ Capybara::SpecHelper.spec '#switch_to_frame', requires: [:frames] do
3
+ before(:each) do
4
+ @session.visit('/within_frames')
5
+ end
6
+
7
+ after(:each) do
8
+ # Ensure we clean up after the frame changes
9
+ @session.switch_to_frame(:top)
10
+ end
11
+
12
+ it "should find the div in frameOne" do
13
+ frame = @session.find(:frame, "frameOne")
14
+ @session.switch_to_frame(frame)
15
+ expect(@session.find("//*[@id='divInFrameOne']").text).to eql 'This is the text of divInFrameOne'
16
+ end
17
+
18
+ it "should find the div in FrameTwo" do
19
+ frame = @session.find(:frame, "frameTwo")
20
+ @session.switch_to_frame(frame)
21
+ expect(@session.find("//*[@id='divInFrameTwo']").text).to eql 'This is the text of divInFrameTwo'
22
+ end
23
+
24
+ it "should return to the parent frame when told to" do
25
+ frame = @session.find(:frame, "frameOne")
26
+ @session.switch_to_frame(frame)
27
+ @session.switch_to_frame(:parent)
28
+ expect(@session.find("//*[@id='divInMainWindow']").text).to eql 'This is the text for divInMainWindow'
29
+ end
30
+
31
+ it "should be able to switch to nested frames" do
32
+ frame = @session.find(:frame, "parentFrame")
33
+ @session.switch_to_frame frame
34
+ frame = @session.find(:frame, "childFrame")
35
+ @session.switch_to_frame frame
36
+ frame = @session.find(:frame, "grandchildFrame1")
37
+ @session.switch_to_frame frame
38
+ expect(@session).to have_selector(:css, '#divInFrameOne', text: 'This is the text of divInFrameOne')
39
+ end
40
+
41
+ it "should reset scope when changing frames" do
42
+ frame = @session.find(:frame, 'parentFrame')
43
+ @session.within(:css, '#divInMainWindow') do
44
+ @session.switch_to_frame(frame)
45
+ expect(@session.has_selector?(:css, "iframe#childFrame")).to be true
46
+ @session.switch_to_frame(:parent)
47
+ end
48
+ end
49
+
50
+ it "works if the frame is closed", requires: [:frames, :js] do
51
+ frame = @session.find(:frame, 'parentFrame')
52
+ @session.switch_to_frame frame
53
+ frame = @session.find(:frame, 'childFrame')
54
+ @session.switch_to_frame frame
55
+
56
+ @session.click_link 'Close Window'
57
+ @session.switch_to_frame :parent # Go back to parentFrame
58
+ expect(@session).to have_selector(:css, 'body#parentBody')
59
+ expect(@session).not_to have_selector(:css, '#childFrame')
60
+ @session.switch_to_frame :parent # Go back to top
61
+ end
62
+
63
+ it "can return to the top frame", requires: [:frames] do
64
+ frame = @session.find(:frame, "parentFrame")
65
+ @session.switch_to_frame frame
66
+ frame = @session.find(:frame, "childFrame")
67
+ @session.switch_to_frame frame
68
+ @session.switch_to_frame :top
69
+ expect(@session.find("//*[@id='divInMainWindow']").text).to eql 'This is the text for divInMainWindow'
70
+ end
71
+
72
+ it "should raise error if switching to parent unmatched inside `within` as it's nonsense" do
73
+ expect do
74
+ frame = @session.find(:frame, 'parentFrame')
75
+ @session.switch_to_frame(frame)
76
+ @session.within(:css, '#parentBody') do
77
+ @session.switch_to_frame(:parent)
78
+ end
79
+ end.to raise_error(Capybara::ScopeError, "`switch_to_frame(:parent)` cannot be called from inside a descendant frame's `within` block.")
80
+ end
81
+
82
+ it "should raise error if switching to top inside a `within` in a frame as it's nonsense" do
83
+ frame = @session.find(:frame, 'parentFrame')
84
+ @session.switch_to_frame(frame)
85
+ @session.within(:css, '#parentBody') do
86
+ expect do
87
+ @session.switch_to_frame(:top)
88
+ end.to raise_error(Capybara::ScopeError, "`switch_to_frame(:top)` cannot be called from inside a descendant frame's `within` block.")
89
+ end
90
+ end
91
+
92
+ it "should raise error if switching to top inside a nested `within` in a frame as it's nonsense" do
93
+ frame = @session.find(:frame, 'parentFrame')
94
+ @session.switch_to_frame(frame)
95
+ @session.within(:css, '#parentBody') do
96
+ @session.switch_to_frame(@session.find(:frame, "childFrame"))
97
+ expect do
98
+ @session.switch_to_frame(:top)
99
+ end.to raise_error(Capybara::ScopeError, "`switch_to_frame(:top)` cannot be called from inside a descendant frame's `within` block.")
100
+ @session.switch_to_frame(:parent)
101
+ end
102
+ end
103
+ end