capybara 2.15.0 → 3.0.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 (177) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +137 -2
  3. data/README.md +36 -25
  4. data/lib/capybara/config.rb +11 -57
  5. data/lib/capybara/cucumber.rb +2 -3
  6. data/lib/capybara/driver/base.rb +19 -16
  7. data/lib/capybara/driver/node.rb +5 -4
  8. data/lib/capybara/dsl.rb +1 -0
  9. data/lib/capybara/helpers.rb +19 -29
  10. data/lib/capybara/minitest/spec.rb +16 -13
  11. data/lib/capybara/minitest.rb +140 -137
  12. data/lib/capybara/node/actions.rb +68 -89
  13. data/lib/capybara/node/base.rb +11 -18
  14. data/lib/capybara/node/document.rb +2 -2
  15. data/lib/capybara/node/document_matchers.rb +8 -8
  16. data/lib/capybara/node/element.rb +32 -42
  17. data/lib/capybara/node/finders.rb +64 -71
  18. data/lib/capybara/node/matchers.rb +50 -71
  19. data/lib/capybara/node/simple.rb +11 -17
  20. data/lib/capybara/queries/ancestor_query.rb +12 -8
  21. data/lib/capybara/queries/base_query.rb +22 -18
  22. data/lib/capybara/queries/current_path_query.rb +12 -25
  23. data/lib/capybara/queries/match_query.rb +3 -7
  24. data/lib/capybara/queries/selector_query.rb +100 -96
  25. data/lib/capybara/queries/sibling_query.rb +5 -5
  26. data/lib/capybara/queries/text_query.rb +35 -35
  27. data/lib/capybara/queries/title_query.rb +8 -11
  28. data/lib/capybara/rack_test/browser.rb +15 -18
  29. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  30. data/lib/capybara/rack_test/driver.rb +6 -10
  31. data/lib/capybara/rack_test/form.rb +52 -39
  32. data/lib/capybara/rack_test/node.rb +93 -63
  33. data/lib/capybara/rails.rb +2 -6
  34. data/lib/capybara/result.rb +22 -22
  35. data/lib/capybara/rspec/compound.rb +5 -10
  36. data/lib/capybara/rspec/features.rb +17 -48
  37. data/lib/capybara/rspec/matcher_proxies.rb +31 -15
  38. data/lib/capybara/rspec/matchers.rb +116 -58
  39. data/lib/capybara/rspec.rb +5 -10
  40. data/lib/capybara/selector/css.rb +6 -11
  41. data/lib/capybara/selector/filter.rb +1 -17
  42. data/lib/capybara/selector/filter_set.rb +18 -15
  43. data/lib/capybara/selector/filters/base.rb +7 -6
  44. data/lib/capybara/selector/filters/expression_filter.rb +6 -23
  45. data/lib/capybara/selector/filters/node_filter.rb +2 -12
  46. data/lib/capybara/selector/selector.rb +28 -34
  47. data/lib/capybara/selector.rb +129 -117
  48. data/lib/capybara/selenium/driver.rb +172 -163
  49. data/lib/capybara/selenium/node.rb +218 -104
  50. data/lib/capybara/server.rb +3 -2
  51. data/lib/capybara/session/config.rb +47 -59
  52. data/lib/capybara/session/matchers.rb +23 -14
  53. data/lib/capybara/session.rb +175 -229
  54. data/lib/capybara/spec/fixtures/no_extension +1 -0
  55. data/lib/capybara/spec/public/test.js +38 -6
  56. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -0
  57. data/lib/capybara/spec/session/accept_confirm_spec.rb +3 -2
  58. data/lib/capybara/spec/session/accept_prompt_spec.rb +30 -1
  59. data/lib/capybara/spec/session/all_spec.rb +31 -18
  60. data/lib/capybara/spec/session/ancestor_spec.rb +6 -8
  61. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +6 -5
  62. data/lib/capybara/spec/session/assert_current_path.rb +12 -11
  63. data/lib/capybara/spec/session/assert_selector.rb +1 -0
  64. data/lib/capybara/spec/session/assert_text.rb +31 -23
  65. data/lib/capybara/spec/session/assert_title.rb +13 -3
  66. data/lib/capybara/spec/session/attach_file_spec.rb +57 -29
  67. data/lib/capybara/spec/session/body_spec.rb +1 -0
  68. data/lib/capybara/spec/session/check_spec.rb +7 -6
  69. data/lib/capybara/spec/session/choose_spec.rb +5 -4
  70. data/lib/capybara/spec/session/click_button_spec.rb +24 -32
  71. data/lib/capybara/spec/session/click_link_or_button_spec.rb +8 -7
  72. data/lib/capybara/spec/session/click_link_spec.rb +8 -7
  73. data/lib/capybara/spec/session/current_scope_spec.rb +4 -3
  74. data/lib/capybara/spec/session/current_url_spec.rb +19 -8
  75. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +1 -1
  76. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +1 -0
  77. data/lib/capybara/spec/session/element/assert_match_selector.rb +1 -1
  78. data/lib/capybara/spec/session/element/match_xpath_spec.rb +1 -1
  79. data/lib/capybara/spec/session/element/matches_selector_spec.rb +5 -5
  80. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +23 -0
  81. data/lib/capybara/spec/session/evaluate_script_spec.rb +5 -4
  82. data/lib/capybara/spec/session/execute_script_spec.rb +4 -3
  83. data/lib/capybara/spec/session/fill_in_spec.rb +30 -5
  84. data/lib/capybara/spec/session/find_button_spec.rb +4 -3
  85. data/lib/capybara/spec/session/find_by_id_spec.rb +2 -1
  86. data/lib/capybara/spec/session/find_field_spec.rb +9 -15
  87. data/lib/capybara/spec/session/find_link_spec.rb +6 -5
  88. data/lib/capybara/spec/session/find_spec.rb +37 -31
  89. data/lib/capybara/spec/session/first_spec.rb +60 -33
  90. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  91. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  92. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +2 -1
  93. data/lib/capybara/spec/session/frame/within_frame_spec.rb +9 -16
  94. data/lib/capybara/spec/session/go_back_spec.rb +1 -0
  95. data/lib/capybara/spec/session/go_forward_spec.rb +1 -0
  96. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  97. data/lib/capybara/spec/session/has_button_spec.rb +2 -1
  98. data/lib/capybara/spec/session/has_css_spec.rb +3 -2
  99. data/lib/capybara/spec/session/has_current_path_spec.rb +49 -22
  100. data/lib/capybara/spec/session/has_field_spec.rb +4 -3
  101. data/lib/capybara/spec/session/has_link_spec.rb +5 -4
  102. data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
  103. data/lib/capybara/spec/session/has_select_spec.rb +32 -31
  104. data/lib/capybara/spec/session/has_selector_spec.rb +5 -4
  105. data/lib/capybara/spec/session/has_table_spec.rb +2 -1
  106. data/lib/capybara/spec/session/has_text_spec.rb +9 -13
  107. data/lib/capybara/spec/session/has_title_spec.rb +1 -0
  108. data/lib/capybara/spec/session/has_xpath_spec.rb +1 -0
  109. data/lib/capybara/spec/session/headers.rb +2 -1
  110. data/lib/capybara/spec/session/html_spec.rb +1 -0
  111. data/lib/capybara/spec/session/node_spec.rb +107 -58
  112. data/lib/capybara/spec/session/node_wrapper_spec.rb +36 -0
  113. data/lib/capybara/spec/session/refresh_spec.rb +6 -2
  114. data/lib/capybara/spec/session/reset_session_spec.rb +19 -0
  115. data/lib/capybara/spec/session/response_code.rb +1 -0
  116. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  117. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -11
  118. data/lib/capybara/spec/session/save_page_spec.rb +1 -17
  119. data/lib/capybara/spec/session/save_screenshot_spec.rb +3 -3
  120. data/lib/capybara/spec/session/select_spec.rb +21 -20
  121. data/lib/capybara/spec/session/selectors_spec.rb +2 -2
  122. data/lib/capybara/spec/session/sibling_spec.rb +1 -1
  123. data/lib/capybara/spec/session/text_spec.rb +17 -3
  124. data/lib/capybara/spec/session/title_spec.rb +11 -1
  125. data/lib/capybara/spec/session/uncheck_spec.rb +4 -3
  126. data/lib/capybara/spec/session/unselect_spec.rb +7 -6
  127. data/lib/capybara/spec/session/visit_spec.rb +64 -3
  128. data/lib/capybara/spec/session/window/become_closed_spec.rb +2 -1
  129. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  130. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  131. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +2 -1
  132. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
  133. data/lib/capybara/spec/session/window/window_spec.rb +12 -12
  134. data/lib/capybara/spec/session/window/windows_spec.rb +2 -3
  135. data/lib/capybara/spec/session/window/within_window_spec.rb +15 -71
  136. data/lib/capybara/spec/session/within_spec.rb +1 -0
  137. data/lib/capybara/spec/spec_helper.rb +36 -18
  138. data/lib/capybara/spec/test_app.rb +17 -9
  139. data/lib/capybara/spec/views/form.erb +7 -0
  140. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  141. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  142. data/lib/capybara/spec/views/with_hover.erb +5 -0
  143. data/lib/capybara/spec/views/with_html.erb +27 -1
  144. data/lib/capybara/spec/views/with_js.erb +11 -0
  145. data/lib/capybara/spec/views/within_frames.erb +4 -1
  146. data/lib/capybara/version.rb +2 -1
  147. data/lib/capybara/window.rb +6 -10
  148. data/lib/capybara.rb +29 -26
  149. data/spec/basic_node_spec.rb +1 -0
  150. data/spec/capybara_spec.rb +16 -69
  151. data/spec/dsl_spec.rb +5 -13
  152. data/spec/filter_set_spec.rb +5 -4
  153. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -1
  154. data/spec/fixtures/selenium_driver_rspec_success.rb +3 -2
  155. data/spec/minitest_spec.rb +13 -4
  156. data/spec/minitest_spec_spec.rb +12 -3
  157. data/spec/per_session_config_spec.rb +9 -8
  158. data/spec/rack_test_spec.rb +21 -20
  159. data/spec/result_spec.rb +17 -16
  160. data/spec/rspec/features_spec.rb +17 -14
  161. data/spec/rspec/scenarios_spec.rb +5 -7
  162. data/spec/rspec/shared_spec_matchers.rb +96 -99
  163. data/spec/rspec/views_spec.rb +2 -1
  164. data/spec/rspec_matchers_spec.rb +18 -2
  165. data/spec/rspec_spec.rb +11 -15
  166. data/spec/selector_spec.rb +5 -6
  167. data/spec/selenium_spec_chrome.rb +20 -11
  168. data/spec/selenium_spec_edge.rb +27 -0
  169. data/spec/selenium_spec_ie.rb +31 -0
  170. data/spec/selenium_spec_marionette.rb +38 -12
  171. data/spec/server_spec.rb +33 -33
  172. data/spec/session_spec.rb +2 -1
  173. data/spec/shared_selenium_session.rb +82 -22
  174. data/spec/spec_helper.rb +3 -6
  175. metadata +76 -81
  176. data/lib/capybara/query.rb +0 -7
  177. data/spec/selenium_spec_firefox.rb +0 -68
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
3
4
  before(:each) do
4
5
  @window = @session.current_window
@@ -90,7 +91,7 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
90
91
  @session.evaluate_script("[window.outerWidth || window.innerWidth, window.outerHeight || window.innerHeight]")
91
92
  end
92
93
 
93
- it 'should return size of whole window', requires: [:windows, :js] do
94
+ it 'should return size of whole window', requires: %i[windows js] do
94
95
  expect(@session.current_window.size).to eq win_size
95
96
  end
96
97
 
@@ -108,15 +109,14 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
108
109
  end
109
110
 
110
111
  describe '#resize_to' do
111
- it 'should be able to resize window', requires: [:windows, :js] do
112
+ it 'should be able to resize window', requires: %i[windows js] do
112
113
  width, height = @session.current_window.size
113
- @session.current_window.resize_to(width-100, height-100)
114
+ @session.current_window.resize_to(width - 100, height - 100)
114
115
  sleep 1
115
- expect(@session.current_window.size).to eq([width-100, height-100])
116
+ expect(@session.current_window.size).to eq([width - 100, height - 100])
116
117
  end
117
118
 
118
- it 'should stay on current window if invoked not for current window', requires: [:windows, :js] do
119
-
119
+ it 'should stay on current window if invoked not for current window', requires: %i[windows js] do
120
120
  @other_window = @session.window_opened_by do
121
121
  @session.find(:css, '#openWindow').click
122
122
  end
@@ -125,35 +125,35 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
125
125
 
126
126
  # #size returns values larger than availWidth, availHeight with Chromedriver
127
127
  @session.within_window(@other_window) do
128
- expect(@session.current_window.size).to eq([400,300])
128
+ expect(@session.current_window.size).to eq([400, 300])
129
129
  # expect(@session.evaluate_script("[window.outerWidth, window.outerHeight]")).to eq([400,300])
130
130
  end
131
131
  end
132
132
  end
133
133
 
134
134
  describe '#maximize' do
135
- it 'should be able to maximize window', requires: [:windows, :js] do
135
+ it 'should be able to maximize window', requires: %i[windows js] do
136
136
  start_width, start_height = 400, 300
137
137
  @session.current_window.resize_to(start_width, start_height)
138
138
  sleep 0.5
139
139
 
140
140
  @session.current_window.maximize
141
- sleep 0.5 # The timing on maximize is finicky on Travis -- wait a bit for maximize to occur
141
+ sleep 0.5 # The timing on maximize is finicky on Travis -- wait a bit for maximize to occur
142
142
 
143
143
  max_width, max_height = @session.current_window.size
144
144
 
145
- #maximize behavior is window manage dependant, so just make sure it increases in size
145
+ # maximize behavior is window manage dependant, so just make sure it increases in size
146
146
  expect(max_width).to be > start_width
147
147
  expect(max_height).to be > start_height
148
148
  end
149
149
 
150
- it 'should stay on current window if invoked not for current window', requires: [:windows, :js] do
150
+ it 'should stay on current window if invoked not for current window', requires: %i[windows js] do
151
151
  cur_window_size = @session.current_window.size
152
152
  @other_window = @session.window_opened_by do
153
153
  @session.find(:css, '#openWindow').click
154
154
  end
155
155
 
156
- @other_window.resize_to(400,300)
156
+ @other_window.resize_to(400, 300)
157
157
  sleep 0.5
158
158
  @other_window.maximize
159
159
  sleep 0.5 # The timing on maximize is finicky on Travis -- wait a bit for maximize to occur
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#windows', requires: [:windows] do
3
4
  before(:each) do
4
5
  @window = @session.current_window
@@ -25,8 +26,6 @@ Capybara::SpecHelper.spec '#windows', requires: [:windows] do
25
26
  titles = @session.windows.map do |window|
26
27
  @session.within_window(window) { @session.title }
27
28
  end
28
- expect(titles).to match_array([
29
- 'With Windows', 'Title of the first popup', 'Title of popup two'
30
- ])
29
+ expect(titles).to match_array(['With Windows', 'Title of the first popup', 'Title of popup two'])
31
30
  end
32
31
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
3
4
  before(:each) do
4
5
  @window = @session.current_window
@@ -19,16 +20,15 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
19
20
 
20
21
  context "with an instance of Capybara::Window" do
21
22
  it "should not invoke driver#switch_to_window when given current window" do
22
- # switch_to_window is invoked in after hook
23
- expect(@session.driver).to receive(:switch_to_window).exactly(3).times.and_call_original
23
+ allow(@session.driver).to receive(:switch_to_window).and_call_original
24
24
  @session.within_window @window do
25
25
  expect(@session.title).to eq('With Windows')
26
26
  end
27
+ expect(@session.driver).not_to have_received(:switch_to_window)
27
28
  end
28
29
 
29
30
  it "should be able to switch to another window" do
30
31
  window = (@session.windows - [@window]).first
31
- expect(@session.driver).to receive(:switch_to_window).exactly(5).times.and_call_original
32
32
  @session.within_window window do
33
33
  expect(@session).to have_title(/Title of the first popup|Title of popup two/)
34
34
  end
@@ -38,8 +38,8 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
38
38
  it "returns value from the block" do
39
39
  window = (@session.windows - [@window]).first
40
40
  value = @session.within_window window do
41
- 43252003274489856000
42
- end
41
+ 43252003274489856000
42
+ end
43
43
  expect(value).to eq(43252003274489856000)
44
44
  end
45
45
 
@@ -57,7 +57,7 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
57
57
  expect(@session.send(:scopes)).to eq([nil])
58
58
  end
59
59
 
60
- it "should leave correct scopes after execution in case of error", requires: [:windows, :frames] do
60
+ it "should leave correct scopes after execution in case of error", requires: %i[windows frames] do
61
61
  window = (@session.windows - [@window]).first
62
62
  expect do
63
63
  @session.within_frame 'frameOne' do
@@ -87,25 +87,25 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
87
87
 
88
88
  context "with lambda" do
89
89
  it "should find the div in another window" do
90
- @session.within_window(->{ @session.title == 'Title of the first popup'}) do
90
+ @session.within_window(-> { @session.title == 'Title of the first popup' }) do
91
91
  expect(@session).to have_css('#divInPopupOne')
92
92
  end
93
93
  end
94
94
 
95
95
  it "should find divs in both windows" do
96
- @session.within_window(->{ @session.title == 'Title of popup two'}) do
96
+ @session.within_window(-> { @session.title == 'Title of popup two' }) do
97
97
  expect(@session).to have_css('#divInPopupTwo')
98
98
  end
99
- @session.within_window(->{ @session.title == 'Title of the first popup'}) do
99
+ @session.within_window(-> { @session.title == 'Title of the first popup' }) do
100
100
  expect(@session).to have_css('#divInPopupOne')
101
101
  end
102
102
  expect(@session.title).to eq('With Windows')
103
103
  end
104
104
 
105
105
  it "should be able to nest within_window" do
106
- @session.within_window(->{ @session.title == 'Title of popup two'}) do
106
+ @session.within_window(-> { @session.title == 'Title of popup two' }) do
107
107
  expect(@session).to have_css('#divInPopupTwo')
108
- @session.within_window(->{ @session.title == 'Title of the first popup'}) do
108
+ @session.within_window(-> { @session.title == 'Title of the first popup' }) do
109
109
  expect(@session).to have_css('#divInPopupOne')
110
110
  end
111
111
  expect(@session).to have_css('#divInPopupTwo')
@@ -119,7 +119,7 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
119
119
  it "should work inside a normal scope" do
120
120
  expect(@session).to have_css('#openWindow')
121
121
  @session.within(:css, '#scope') do
122
- @session.within_window(->{ @session.title == 'Title of the first popup'}) do
122
+ @session.within_window(-> { @session.title == 'Title of the first popup' }) do
123
123
  expect(@session).to have_css('#divInPopupOne')
124
124
  end
125
125
  expect(@session).to have_content('My scoped content')
@@ -129,7 +129,7 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
129
129
 
130
130
  it "should raise error if window wasn't found" do
131
131
  expect do
132
- @session.within_window(->{ @session.title == 'Invalid title'}) do
132
+ @session.within_window(-> { @session.title == 'Invalid title' }) do
133
133
  expect(@session).to have_css('#divInPopupOne')
134
134
  end
135
135
  end.to raise_error(Capybara::WindowError, "Could not find a window matching block/lambda")
@@ -139,15 +139,13 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
139
139
  end
140
140
 
141
141
  it "returns value from the block" do
142
- value = @session.within_window(->{ @session.title == 'Title of popup two'}) do
143
- 42
144
- end
142
+ value = @session.within_window(-> { @session.title == 'Title of popup two' }) { 42 }
145
143
  expect(value).to eq(42)
146
144
  end
147
145
 
148
146
  it "should switch back if exception was raised inside block" do
149
147
  expect do
150
- @session.within_window(->{ @session.title == 'Title of popup two'}) do
148
+ @session.within_window(-> { @session.title == 'Title of popup two' }) do
151
149
  raise 'some error'
152
150
  end
153
151
  end.to raise_error(StandardError, 'some error')
@@ -155,58 +153,4 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
155
153
  expect(@session.send(:scopes)).to eq([nil])
156
154
  end
157
155
  end
158
-
159
- context "with string" do
160
- it "should warn" do
161
- expect(@session).to receive(:warn).with(/DEPRECATION WARNING/).and_call_original
162
- @session.within_window('firstPopup') {}
163
- end
164
-
165
- it "should find window by handle" do
166
- window = (@session.windows - [@window]).first
167
- @session.within_window window.handle do
168
- expect(@session).to have_title(/Title of the first popup|Title of popup two/)
169
- end
170
- end
171
-
172
- it "should find the div in firstPopup" do
173
- @session.within_window("firstPopup") do
174
- expect(@session.find("//*[@id='divInPopupOne']").text).to eq 'This is the text of divInPopupOne'
175
- end
176
- end
177
- it "should find the div in secondPopup" do
178
- @session.within_window("secondPopup") do
179
- expect(@session.find("//*[@id='divInPopupTwo']").text).to eq 'This is the text of divInPopupTwo'
180
- end
181
- end
182
- it "should find the divs in both popups" do
183
- @session.within_window("secondPopup") do
184
- expect(@session.find("//*[@id='divInPopupTwo']").text).to eq 'This is the text of divInPopupTwo'
185
- end
186
- @session.within_window("firstPopup") do
187
- expect(@session.find("//*[@id='divInPopupOne']").text).to eq 'This is the text of divInPopupOne'
188
- end
189
- end
190
- it "should find the div in the main window after finding a div in a popup" do
191
- @session.within_window("secondPopup") do
192
- expect(@session.find("//*[@id='divInPopupTwo']").text).to eq 'This is the text of divInPopupTwo'
193
- end
194
- expect(@session.find("//*[@id='doesNotOpenWindows']").text).to eq 'Does not open windows'
195
- end
196
- it "should reset scope when switching windows" do
197
- @session.within(:css, '#doesNotOpenWindows') do
198
- @session.within_window("secondPopup") do
199
- expect(@session.find("//*[@id='divInPopupTwo']").text).to eq 'This is the text of divInPopupTwo'
200
- end
201
- end
202
- end
203
- it "should switch back if exception was raised inside block" do
204
- expect do
205
- @session.within_window('secondPopup') do
206
- raise 'some error'
207
- end
208
- end.to raise_error(StandardError, 'some error')
209
- expect(@session.current_window).to eq(@window)
210
- end
211
- end
212
156
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Capybara::SpecHelper.spec '#within' do
3
4
  before do
4
5
  @session.visit('/with_scope')
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "rspec"
3
4
  require "rspec/expectations"
4
5
  require "capybara"
@@ -6,15 +7,6 @@ require "capybara/rspec" # Required here instead of in rspec_spec to avoid RSpec
6
7
  require "capybara/spec/test_app"
7
8
  require "nokogiri"
8
9
 
9
- # Alias be_truthy/be_falsey if not already defined to be able to use in RSpec 2 and 3
10
- unless RSpec::Matchers.method_defined?(:be_truthy)
11
- RSpec::Matchers.module_eval do
12
- alias be_truthy be_true
13
- alias be_falsey be_false
14
- alias be_falsy be_false
15
- end
16
- end
17
-
18
10
  module Capybara
19
11
  module SpecHelper
20
12
  class << self
@@ -33,11 +25,9 @@ module Capybara
33
25
  Capybara.default_max_wait_time = 1
34
26
  Capybara.ignore_hidden_elements = true
35
27
  Capybara.exact = false
36
- Capybara.exact_options = false
37
28
  Capybara.raise_server_errors = true
38
29
  Capybara.visible_text_only = false
39
30
  Capybara.match = :smart
40
- Capybara.wait_on_first_by_default = false
41
31
  Capybara.enable_aria_label = false
42
32
  reset_threadsafe
43
33
  end
@@ -52,12 +42,12 @@ module Capybara
52
42
  end
53
43
  end
54
44
 
55
- def spec(name, options={}, &block)
45
+ def spec(name, *options, &block)
56
46
  @specs ||= []
57
47
  @specs << [name, options, block]
58
48
  end
59
49
 
60
- def run_specs(session, name, options={})
50
+ def run_specs(session, name, **options)
61
51
  specs = @specs
62
52
  RSpec.describe Capybara::Session, name, options do
63
53
  include Capybara::SpecHelper
@@ -78,8 +68,12 @@ module Capybara
78
68
  SpecHelper.reset_threadsafe(false, @session)
79
69
  end
80
70
 
71
+ before :each, :exact_false do
72
+ Capybara.exact = false
73
+ end
74
+
81
75
  specs.each do |spec_name, spec_options, block|
82
- describe spec_name, spec_options do
76
+ describe spec_name, *spec_options do
83
77
  class_eval(&block)
84
78
  end
85
79
  end
@@ -92,7 +86,7 @@ module Capybara
92
86
  session = session.current_session if session.respond_to?(:current_session)
93
87
  session.instance_variable_set(:@config, nil) if session
94
88
  end
95
- end # class << self
89
+ end
96
90
 
97
91
  def silence_stream(stream)
98
92
  old_stream = stream.dup
@@ -117,11 +111,35 @@ module Capybara
117
111
  end
118
112
 
119
113
  def marionette?(session)
120
- session.driver.respond_to?(:marionette?, true) && session.driver.send(:marionette?)
114
+ session.respond_to?(:driver) && session.driver.respond_to?(:marionette?, true) && session.driver.send(:marionette?)
115
+ end
116
+
117
+ def marionette_lt?(version, session)
118
+ marionette?(session) && (session.driver.browser.capabilities[:browser_version].to_f < version)
119
+ end
120
+
121
+ def marionette_gte?(version, session)
122
+ marionette?(session) && (session.driver.browser.capabilities[:browser_version].to_f >= version)
123
+ end
124
+
125
+ def chrome?(session)
126
+ session.respond_to?(:driver) && session.driver.respond_to?(:chrome?, true) && session.driver.send(:chrome?)
127
+ end
128
+
129
+ def chrome_lt?(version, session)
130
+ chrome?(session) && (session.driver.browser.capabilities[:version].to_f < version)
131
+ end
132
+
133
+ def chrome_gte?(version, session)
134
+ chrome?(session) && (session.driver.browser.capabilities[:version].to_f >= version)
135
+ end
136
+
137
+ def edge?(session)
138
+ session.respond_to?(:driver) && session.driver.respond_to?(:edge?, true) && session.driver.send(:edge?)
121
139
  end
122
140
 
123
- def rspec2?
124
- !defined?(::RSpec::Expectations::Version) || (Gem::Version.new(RSpec::Expectations::Version::STRING) < Gem::Version.new('3.0'))
141
+ def ie?(session)
142
+ session.respond_to?(:driver) && session.driver.respond_to?(:ie?, true) && session.driver.send(:ie?)
125
143
  end
126
144
  end
127
145
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'sinatra/base'
3
4
  require 'tilt/erb'
4
5
  require 'rack'
@@ -21,7 +22,7 @@ class TestApp < Sinatra::Base
21
22
  # Also check lib/capybara/spec/views/*.erb for pages not listed here
22
23
 
23
24
  get '/' do
24
- response.set_cookie('capybara', { value: 'root cookie', domain: request.host, path: request.path} )
25
+ response.set_cookie('capybara', value: 'root cookie', domain: request.host, path: request.path)
25
26
  'Hello world! <a href="with_html">Relative</a>'
26
27
  end
27
28
 
@@ -38,8 +39,8 @@ class TestApp < Sinatra::Base
38
39
  end
39
40
 
40
41
  get '/referer_base' do
41
- '<a href="/get_referer">direct link</a>' +
42
- '<a href="/redirect_to_get_referer">link via redirect</a>' +
42
+ '<a href="/get_referer">direct link</a>' \
43
+ '<a href="/redirect_to_get_referer">link via redirect</a>' \
43
44
  '<form action="/get_referer" method="get"><input type="submit"></form>'
44
45
  end
45
46
 
@@ -69,7 +70,7 @@ class TestApp < Sinatra::Base
69
70
  end
70
71
 
71
72
  get '/with-quotes' do
72
- %q{"No," he said, "you can't do that."}
73
+ %q("No," he said, "you can't do that.")
73
74
  end
74
75
 
75
76
  get '/form/get' do
@@ -143,13 +144,22 @@ class TestApp < Sinatra::Base
143
144
  erb :with_html, locals: { referrer: request.referrer }
144
145
  end
145
146
 
147
+ get '/with_title' do
148
+ <<-HTML
149
+ <title>#{params[:title] || 'Test Title'}</title>
150
+ <body>
151
+ <svg><title>abcdefg</title></svg>
152
+ </body>
153
+ HTML
154
+ end
155
+
146
156
  get '/:view' do |view|
147
157
  erb view.to_sym, locals: { referrer: request.referrer }
148
158
  end
149
159
 
150
160
  post '/form' do
151
161
  @@form_post_count += 1
152
- '<pre id="results">' + params[:form].merge({"post_count" => @@form_post_count}).to_yaml + '</pre>'
162
+ '<pre id="results">' + params[:form].merge("post_count" => @@form_post_count).to_yaml + '</pre>'
153
163
  end
154
164
 
155
165
  post '/upload_empty' do
@@ -173,7 +183,7 @@ class TestApp < Sinatra::Base
173
183
 
174
184
  post '/upload_multiple' do
175
185
  begin
176
- buffer = ["#{params[:form][:multiple_documents].size}"]
186
+ buffer = [params[:form][:multiple_documents].size.to_s]
177
187
  params[:form][:multiple_documents].each do |doc|
178
188
  buffer << "Content-type: #{doc[:type]}"
179
189
  buffer << "File content: #{doc[:tempfile].read}"
@@ -185,6 +195,4 @@ class TestApp < Sinatra::Base
185
195
  end
186
196
  end
187
197
 
188
- if __FILE__ == $0
189
- Rack::Handler::WEBrick.run TestApp, Port: 8070
190
- end
198
+ Rack::Handler::Puma.run TestApp, Port: 8070 if $PROGRAM_NAME == __FILE__
@@ -186,6 +186,7 @@ New line after and before textarea tag
186
186
  <input type="checkbox" value="pagani" name="form[cars][]" id="form_cars_pagani" style="position: absolute; left: -9999px"/>
187
187
  <label for="form_cars_pagani">Pagani</label>
188
188
  <input type="checkbox" value="ariel" name="form[cars][]" id="form_cars_ariel" style="display: none"/>
189
+ <input type="checkbox" value="porsche" name="form[cars][]" id="form_cars_porsche" checked="checked" style="display: none"/>
189
190
  <label>
190
191
  McLaren
191
192
  <input type="checkbox" value="mclaren" name="form[cars][]" id="form_cars_mclaren" style="display: none"/>
@@ -425,6 +426,12 @@ New line after and before textarea tag
425
426
  <input type="button" disabled="disabled" value="Disabled button"/>
426
427
  </p>
427
428
 
429
+ <p>
430
+ <input type="date" name="form[date]" id="form_date"/>
431
+ <input type="time" name="form[time]" id="form_time"/>
432
+ <input type="datetime-local" name="form[datetime]" id="form_datetime">
433
+ </p>
434
+
428
435
  <p>
429
436
  <input id="readonly" name="form[readonly_test]" readonly/>
430
437
  <input id="not_readonly" name="form[readonly_test]" />
@@ -0,0 +1,10 @@
1
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
2
+ <body>
3
+ <div>
4
+ Initial alert page
5
+ </div>
6
+ <script>
7
+ window.alert("Initial alert");
8
+ </script>
9
+ </body>
10
+ </html>
@@ -0,0 +1,17 @@
1
+ <html>
2
+ <head>
3
+ <style>
4
+ header { height: 45px; position: fixed; top: 0; background-color: red; width: 100%;}
5
+ footer { height: 45px; position: fixed; bottom: 0; background-color: red; width: 100%;}
6
+ #main { margin: 45px;}
7
+ #tall { display: block; height: 2000px;}
8
+ </style>
9
+ </head>
10
+ <body>
11
+ <header>My headers</header>
12
+ <div id="main">
13
+ <div id="tall">A tall block</div>
14
+ <a href="/">Go to root</a>
15
+ </div>
16
+ <footer>My footer</footer>
17
+ </body>
@@ -14,5 +14,10 @@
14
14
  Some text here so the wrapper has size
15
15
  <div class="hidden_until_hover">Here I am</div>
16
16
  </div>
17
+ <div style="display: block; height: 1000px; width: 100%"></div>
18
+ <div class="wrapper scroll_needed" >
19
+ Some text here so the wrapper has size
20
+ <div class="hidden_until_hover">Here I am</div>
21
+ </div>
17
22
  </body>
18
23
  </html>
@@ -122,6 +122,10 @@ banana</textarea>
122
122
  <a id="link_blank_href" href="">Blank href</a>
123
123
  </div>
124
124
 
125
+ <div id="uppercase" style="text-transform: uppercase;">
126
+ text here
127
+ </div>
128
+
125
129
  <div id="ancestor3">
126
130
  Ancestor
127
131
  <div id="ancestor2">
@@ -146,4 +150,26 @@ banana</textarea>
146
150
  <div data-pre=true>Pre Sibling</div>
147
151
  <div data-post=true>Post Sibling</div>
148
152
  </div>
149
- </div>
153
+ </div>
154
+
155
+ <div id='1escape.me' class="2escape">needs escaping</div>
156
+
157
+ <div id="normalized">
158
+ Some text<div>More text</div>
159
+ <div> And more text</div>
160
+ Even more &nbsp;&nbsp; text
161
+
162
+ on multiple lines
163
+ </div>
164
+
165
+ <div id="non_visible_normalized" style="display: none">
166
+ Some text<div>More text</div>
167
+ <div> And more text</div>
168
+ Even more &nbsp;&nbsp; text
169
+
170
+ on multiple lines
171
+ </div>
172
+
173
+ <div id="ws">
174
+ &#x20;&#x1680;&#x2000;&#x2001;&#x2002; &#x2003;&#x2004;&nbsp;&#x2005; &#x2006;&#x2007;&#x2008;&#x2009;&#x200A;&#x202F;&#x205F;&#x3000;
175
+ </div>
@@ -96,6 +96,10 @@
96
96
  <a href="#" id="open-prompt">Open prompt</a>
97
97
  </p>
98
98
 
99
+ <p>
100
+ <a href="#" id="open-prompt-with-default">Open defaulted prompt</a>
101
+ </p>
102
+
99
103
  <p>
100
104
  <input id="disable-on-click"/>
101
105
  </p>
@@ -117,6 +121,13 @@
117
121
  <input type="file" id="hidden_file" style="opacity:0; display: none;">
118
122
  </p>
119
123
 
124
+ <div id="drag_scroll">
125
+ <p>This is a draggable element.</p>
126
+ </div>
127
+ <div id="drop_scroll">
128
+ <p>It should be dropped here.</p>
129
+ </div>
130
+
120
131
  <script type="text/javascript">
121
132
  // a javascript comment
122
133
  var aVar = 123;
@@ -4,7 +4,10 @@
4
4
  <title>With Frames</title>
5
5
  </head>
6
6
  <body>
7
- <div id="divInMainWindow">This is the text for divInMainWindow</div>
7
+ <div id="divInMainWindow">
8
+ This is the text for divInMainWindow
9
+ <iframe src="/frame_parent" id="innerParentFrame"></iframe>
10
+ </div>
8
11
  <iframe src="/frame_one" id="frameOne" name="my frame one"></iframe>
9
12
  <iframe src="/frame_two" id="frameTwo"></iframe>
10
13
  <iframe src="/frame_parent" id="parentFrame"></iframe>
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Capybara
3
- VERSION = '2.15.0'
4
+ VERSION = '3.0.0'.freeze
4
5
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Capybara
3
4
  ##
4
5
  # The Window class represents a browser window.
@@ -101,7 +102,7 @@ module Capybara
101
102
  end
102
103
 
103
104
  def eql?(other)
104
- other.kind_of?(self.class) && @session == other.session && @handle == other.handle
105
+ other.is_a?(self.class) && @session == other.session && @handle == other.handle
105
106
  end
106
107
  alias_method :==, :eql?
107
108
 
@@ -113,9 +114,9 @@ module Capybara
113
114
  "#<Window @handle=#{@handle.inspect}>"
114
115
  end
115
116
 
116
- private
117
+ private
117
118
 
118
- def wait_for_stable_size(seconds=session.config.default_max_wait_time)
119
+ def wait_for_stable_size(seconds = session.config.default_max_wait_time)
119
120
  res = yield if block_given?
120
121
  prev_size = size
121
122
  start_time = Capybara::Helpers.monotonic_time
@@ -125,16 +126,11 @@ module Capybara
125
126
  return res if cur_size == prev_size
126
127
  prev_size = cur_size
127
128
  end while (Capybara::Helpers.monotonic_time - start_time) < seconds
128
- #TODO raise error in 3.0
129
- #raise Capybara::WindowError, "Window size not stable."
130
- warn "Window size not stable in #{seconds} seconds. This will raise an exception in a future version of Capybara"
131
- return res
129
+ raise Capybara::WindowError, "Window size not stable within #{seconds} seconds."
132
130
  end
133
131
 
134
132
  def raise_unless_current(what)
135
- unless current?
136
- raise Capybara::WindowError, "#{what} not current window is not possible."
137
- end
133
+ raise Capybara::WindowError, "#{what} not current window is not possible." unless current?
138
134
  end
139
135
  end
140
136
  end