capybara 3.16.1 → 3.33.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (197) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/History.md +321 -0
  4. data/README.md +51 -60
  5. data/lib/capybara.rb +71 -114
  6. data/lib/capybara/config.rb +8 -5
  7. data/lib/capybara/cucumber.rb +1 -1
  8. data/lib/capybara/driver/node.rb +15 -3
  9. data/lib/capybara/dsl.rb +10 -2
  10. data/lib/capybara/helpers.rb +5 -3
  11. data/lib/capybara/minitest.rb +242 -141
  12. data/lib/capybara/minitest/spec.rb +159 -90
  13. data/lib/capybara/node/actions.rb +85 -74
  14. data/lib/capybara/node/base.rb +4 -4
  15. data/lib/capybara/node/document.rb +2 -2
  16. data/lib/capybara/node/document_matchers.rb +3 -3
  17. data/lib/capybara/node/element.rb +216 -117
  18. data/lib/capybara/node/finders.rb +65 -65
  19. data/lib/capybara/node/matchers.rb +228 -126
  20. data/lib/capybara/node/simple.rb +9 -4
  21. data/lib/capybara/queries/ancestor_query.rb +5 -7
  22. data/lib/capybara/queries/base_query.rb +2 -1
  23. data/lib/capybara/queries/current_path_query.rb +1 -1
  24. data/lib/capybara/queries/selector_query.rb +296 -30
  25. data/lib/capybara/queries/sibling_query.rb +5 -4
  26. data/lib/capybara/queries/style_query.rb +2 -2
  27. data/lib/capybara/queries/text_query.rb +13 -1
  28. data/lib/capybara/queries/title_query.rb +1 -1
  29. data/lib/capybara/rack_test/browser.rb +7 -2
  30. data/lib/capybara/rack_test/driver.rb +1 -1
  31. data/lib/capybara/rack_test/form.rb +1 -1
  32. data/lib/capybara/rack_test/node.rb +43 -7
  33. data/lib/capybara/registration_container.rb +44 -0
  34. data/lib/capybara/registrations/drivers.rb +36 -0
  35. data/lib/capybara/registrations/patches/puma_ssl.rb +27 -0
  36. data/lib/capybara/registrations/servers.rb +44 -0
  37. data/lib/capybara/result.rb +36 -8
  38. data/lib/capybara/rspec/matcher_proxies.rb +6 -4
  39. data/lib/capybara/rspec/matchers.rb +100 -63
  40. data/lib/capybara/rspec/matchers/base.rb +23 -10
  41. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  42. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  43. data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
  44. data/lib/capybara/rspec/matchers/have_selector.rb +16 -8
  45. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  46. data/lib/capybara/rspec/matchers/have_text.rb +4 -4
  47. data/lib/capybara/rspec/matchers/have_title.rb +2 -2
  48. data/lib/capybara/rspec/matchers/match_selector.rb +3 -3
  49. data/lib/capybara/rspec/matchers/match_style.rb +2 -2
  50. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  51. data/lib/capybara/selector.rb +219 -588
  52. data/lib/capybara/selector/builders/css_builder.rb +10 -6
  53. data/lib/capybara/selector/builders/xpath_builder.rb +1 -1
  54. data/lib/capybara/selector/css.rb +4 -2
  55. data/lib/capybara/selector/definition.rb +277 -0
  56. data/lib/capybara/selector/definition/button.rb +52 -0
  57. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  58. data/lib/capybara/selector/definition/css.rb +10 -0
  59. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  60. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  61. data/lib/capybara/selector/definition/element.rb +27 -0
  62. data/lib/capybara/selector/definition/field.rb +40 -0
  63. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  64. data/lib/capybara/selector/definition/file_field.rb +13 -0
  65. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  66. data/lib/capybara/selector/definition/frame.rb +17 -0
  67. data/lib/capybara/selector/definition/id.rb +6 -0
  68. data/lib/capybara/selector/definition/label.rb +62 -0
  69. data/lib/capybara/selector/definition/link.rb +54 -0
  70. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  71. data/lib/capybara/selector/definition/option.rb +27 -0
  72. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  73. data/lib/capybara/selector/definition/select.rb +81 -0
  74. data/lib/capybara/selector/definition/table.rb +109 -0
  75. data/lib/capybara/selector/definition/table_row.rb +21 -0
  76. data/lib/capybara/selector/definition/xpath.rb +5 -0
  77. data/lib/capybara/selector/filter_set.rb +13 -9
  78. data/lib/capybara/selector/filters/base.rb +11 -2
  79. data/lib/capybara/selector/filters/locator_filter.rb +13 -3
  80. data/lib/capybara/selector/regexp_disassembler.rb +9 -2
  81. data/lib/capybara/selector/selector.rb +43 -448
  82. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  83. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  84. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  85. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  86. data/lib/capybara/selenium/driver.rb +125 -56
  87. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +73 -17
  88. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
  89. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +41 -2
  90. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +14 -1
  91. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +14 -5
  92. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  93. data/lib/capybara/selenium/extensions/find.rb +67 -45
  94. data/lib/capybara/selenium/extensions/html5_drag.rb +152 -36
  95. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  96. data/lib/capybara/selenium/logger_suppressor.rb +34 -0
  97. data/lib/capybara/selenium/node.rb +227 -56
  98. data/lib/capybara/selenium/nodes/chrome_node.rb +93 -8
  99. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  100. data/lib/capybara/selenium/nodes/firefox_node.rb +37 -59
  101. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  102. data/lib/capybara/selenium/nodes/safari_node.rb +27 -54
  103. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  104. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  105. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  106. data/lib/capybara/selenium/patches/logs.rb +45 -0
  107. data/lib/capybara/server.rb +19 -3
  108. data/lib/capybara/server/animation_disabler.rb +2 -2
  109. data/lib/capybara/server/checker.rb +6 -2
  110. data/lib/capybara/server/middleware.rb +23 -13
  111. data/lib/capybara/session.rb +124 -106
  112. data/lib/capybara/session/config.rb +12 -10
  113. data/lib/capybara/session/matchers.rb +6 -6
  114. data/lib/capybara/spec/public/offset.js +6 -0
  115. data/lib/capybara/spec/public/test.js +94 -5
  116. data/lib/capybara/spec/session/all_spec.rb +84 -6
  117. data/lib/capybara/spec/session/ancestor_spec.rb +5 -0
  118. data/lib/capybara/spec/session/assert_current_path_spec.rb +5 -2
  119. data/lib/capybara/spec/session/assert_text_spec.rb +9 -5
  120. data/lib/capybara/spec/session/attach_file_spec.rb +14 -6
  121. data/lib/capybara/spec/session/check_spec.rb +10 -4
  122. data/lib/capybara/spec/session/choose_spec.rb +8 -2
  123. data/lib/capybara/spec/session/click_button_spec.rb +44 -1
  124. data/lib/capybara/spec/session/click_link_spec.rb +11 -0
  125. data/lib/capybara/spec/session/evaluate_script_spec.rb +12 -0
  126. data/lib/capybara/spec/session/fill_in_spec.rb +37 -2
  127. data/lib/capybara/spec/session/find_spec.rb +60 -6
  128. data/lib/capybara/spec/session/first_spec.rb +1 -1
  129. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +14 -1
  130. data/lib/capybara/spec/session/frame/within_frame_spec.rb +12 -1
  131. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  132. data/lib/capybara/spec/session/has_button_spec.rb +16 -0
  133. data/lib/capybara/spec/session/has_css_spec.rb +35 -6
  134. data/lib/capybara/spec/session/has_current_path_spec.rb +6 -4
  135. data/lib/capybara/spec/session/has_field_spec.rb +34 -0
  136. data/lib/capybara/spec/session/has_select_spec.rb +32 -4
  137. data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
  138. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  139. data/lib/capybara/spec/session/has_table_spec.rb +51 -5
  140. data/lib/capybara/spec/session/has_text_spec.rb +47 -0
  141. data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
  142. data/lib/capybara/spec/session/node_spec.rb +574 -16
  143. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +2 -2
  144. data/lib/capybara/spec/session/save_screenshot_spec.rb +4 -4
  145. data/lib/capybara/spec/session/scroll_spec.rb +1 -1
  146. data/lib/capybara/spec/session/select_spec.rb +5 -10
  147. data/lib/capybara/spec/session/selectors_spec.rb +24 -3
  148. data/lib/capybara/spec/session/uncheck_spec.rb +2 -2
  149. data/lib/capybara/spec/session/unselect_spec.rb +1 -1
  150. data/lib/capybara/spec/session/window/window_spec.rb +10 -9
  151. data/lib/capybara/spec/spec_helper.rb +7 -2
  152. data/lib/capybara/spec/test_app.rb +26 -21
  153. data/lib/capybara/spec/views/animated.erb +49 -0
  154. data/lib/capybara/spec/views/form.erb +25 -4
  155. data/lib/capybara/spec/views/frame_child.erb +2 -1
  156. data/lib/capybara/spec/views/frame_one.erb +1 -0
  157. data/lib/capybara/spec/views/obscured.erb +9 -9
  158. data/lib/capybara/spec/views/offset.erb +32 -0
  159. data/lib/capybara/spec/views/react.erb +45 -0
  160. data/lib/capybara/spec/views/spatial.erb +31 -0
  161. data/lib/capybara/spec/views/with_animation.erb +29 -1
  162. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  163. data/lib/capybara/spec/views/with_html.erb +28 -2
  164. data/lib/capybara/spec/views/with_js.erb +2 -1
  165. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  166. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  167. data/lib/capybara/version.rb +1 -1
  168. data/lib/capybara/window.rb +10 -10
  169. data/spec/basic_node_spec.rb +6 -6
  170. data/spec/capybara_spec.rb +28 -28
  171. data/spec/dsl_spec.rb +16 -3
  172. data/spec/filter_set_spec.rb +5 -5
  173. data/spec/fixtures/selenium_driver_rspec_failure.rb +1 -1
  174. data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
  175. data/spec/minitest_spec.rb +12 -2
  176. data/spec/minitest_spec_spec.rb +56 -45
  177. data/spec/rack_test_spec.rb +25 -12
  178. data/spec/regexp_dissassembler_spec.rb +53 -39
  179. data/spec/result_spec.rb +50 -54
  180. data/spec/rspec/features_spec.rb +1 -0
  181. data/spec/rspec/shared_spec_matchers.rb +78 -62
  182. data/spec/rspec_spec.rb +5 -5
  183. data/spec/sauce_spec_chrome.rb +1 -0
  184. data/spec/selector_spec.rb +26 -16
  185. data/spec/selenium_spec_chrome.rb +84 -5
  186. data/spec/selenium_spec_chrome_remote.rb +23 -8
  187. data/spec/selenium_spec_edge.rb +23 -8
  188. data/spec/selenium_spec_firefox.rb +16 -21
  189. data/spec/selenium_spec_firefox_remote.rb +4 -13
  190. data/spec/selenium_spec_ie.rb +23 -15
  191. data/spec/selenium_spec_safari.rb +17 -17
  192. data/spec/server_spec.rb +87 -42
  193. data/spec/session_spec.rb +11 -4
  194. data/spec/shared_selenium_node.rb +83 -0
  195. data/spec/shared_selenium_session.rb +62 -72
  196. data/spec/spec_helper.rb +43 -5
  197. metadata +114 -16
@@ -43,7 +43,7 @@ RSpec.describe 'capybara/rspec' do
43
43
  expect(Capybara.current_driver).to eq(:culerity)
44
44
  end
45
45
 
46
- context '#all' do
46
+ describe '#all' do
47
47
  it 'allows access to the Capybara finder' do
48
48
  visit('/with_html')
49
49
  found = all(:css, 'h2') { |element| element[:class] == 'head' }
@@ -57,7 +57,7 @@ RSpec.describe 'capybara/rspec' do
57
57
  end
58
58
  end
59
59
 
60
- context '#within' do
60
+ describe '#within' do
61
61
  it 'allows access to the Capybara scoper' do
62
62
  visit('/with_html')
63
63
  expect do
@@ -76,13 +76,13 @@ RSpec.describe 'capybara/rspec' do
76
76
  context 'Type: Other', type: :other do
77
77
  context 'when RSpec::Matchers is included after Capybara::DSL' do
78
78
  let(:test_class_instance) do
79
- class DSLMatchersTest
79
+ Class.new do
80
80
  include Capybara::DSL
81
81
  include RSpec::Matchers
82
82
  end.new
83
83
  end
84
84
 
85
- context '#all' do
85
+ describe '#all' do
86
86
  it 'allows access to the Capybara finder' do
87
87
  test_class_instance.visit('/with_html')
88
88
  expect(test_class_instance.all(:css, 'h2.head').size).to eq(5)
@@ -95,7 +95,7 @@ RSpec.describe 'capybara/rspec' do
95
95
  end
96
96
  end
97
97
 
98
- context '#within' do
98
+ describe '#within' do
99
99
  it 'allows access to the Capybara scoper' do
100
100
  test_class_instance.visit('/with_html')
101
101
  expect do
@@ -5,6 +5,7 @@ require 'selenium-webdriver'
5
5
 
6
6
  require 'sauce_whisk'
7
7
  # require 'shared_selenium_session'
8
+ # require 'shared_selenium_node'
8
9
  # require 'rspec/shared_spec_matchers'
9
10
 
10
11
  Capybara.register_driver :sauce_chrome do |app|
@@ -5,7 +5,7 @@ require 'spec_helper'
5
5
  RSpec.describe Capybara do
6
6
  describe 'Selectors' do
7
7
  let :string do
8
- Capybara.string <<-STRING
8
+ described_class.string <<-STRING
9
9
  <html>
10
10
  <head>
11
11
  <title>selectors</title>
@@ -69,12 +69,12 @@ RSpec.describe Capybara do
69
69
  end
70
70
 
71
71
  before do
72
- Capybara.add_selector :custom_selector do
72
+ described_class.add_selector :custom_selector do
73
73
  css { |css_class| "div.#{css_class}" }
74
74
  node_filter(:not_empty, boolean: true, default: true, skip_if: :all) { |node, value| value ^ (node.text == '') }
75
75
  end
76
76
 
77
- Capybara.add_selector :custom_css_selector do
77
+ described_class.add_selector :custom_css_selector do
78
78
  css(:name, :other_name) do |selector, name: nil, **|
79
79
  selector ||= ''
80
80
  selector += "[name='#{name}']" if name
@@ -94,7 +94,7 @@ RSpec.describe Capybara do
94
94
  end
95
95
  end
96
96
 
97
- Capybara.add_selector :custom_xpath_selector do
97
+ described_class.add_selector :custom_xpath_selector do
98
98
  xpath(:valid1, :valid2) { |selector| selector }
99
99
  match { |value| value == 'match_me' }
100
100
  end
@@ -102,7 +102,7 @@ RSpec.describe Capybara do
102
102
 
103
103
  it 'supports `filter` as an alias for `node_filter`' do
104
104
  expect do
105
- Capybara.add_selector :filter_alias_selector do
105
+ described_class.add_selector :filter_alias_selector do
106
106
  css { |_unused| 'div' }
107
107
  filter(:something) { |_node, _value| true }
108
108
  end
@@ -111,7 +111,7 @@ RSpec.describe Capybara do
111
111
 
112
112
  describe 'adding a selector' do
113
113
  it 'can set default visiblity' do
114
- Capybara.add_selector :hidden_field do
114
+ described_class.add_selector :hidden_field do
115
115
  visible :hidden
116
116
  css { |_sel| 'input[type="hidden"]' }
117
117
  end
@@ -125,7 +125,7 @@ RSpec.describe Capybara do
125
125
  it 'allows modifying a selector' do
126
126
  el = string.find(:custom_selector, 'aa')
127
127
  expect(el.tag_name).to eq 'div'
128
- Capybara.modify_selector :custom_selector do
128
+ described_class.modify_selector :custom_selector do
129
129
  css { |css_class| "h1.#{css_class}" }
130
130
  end
131
131
  el = string.find(:custom_selector, 'aa')
@@ -133,7 +133,7 @@ RSpec.describe Capybara do
133
133
  end
134
134
 
135
135
  it "doesn't change existing filters" do
136
- Capybara.modify_selector :custom_selector do
136
+ described_class.modify_selector :custom_selector do
137
137
  css { |css_class| "p.#{css_class}" }
138
138
  end
139
139
  expect(string).to have_selector(:custom_selector, 'bb', count: 1)
@@ -164,25 +164,28 @@ RSpec.describe Capybara do
164
164
 
165
165
  describe 'xpath' do
166
166
  it 'uses filter names passed in' do
167
- selector = Capybara::Selector.new :test do
167
+ described_class.add_selector :test do
168
168
  xpath(:something, :other) { |_locator| XPath.descendant }
169
169
  end
170
+ selector = Capybara::Selector.new :test, config: nil, format: nil
170
171
 
171
172
  expect(selector.expression_filters.keys).to include(:something, :other)
172
173
  end
173
174
 
174
175
  it 'gets filter names from block if none passed to xpath method' do
175
- selector = Capybara::Selector.new :test do
176
+ described_class.add_selector :test do
176
177
  xpath { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
177
178
  end
179
+ selector = Capybara::Selector.new :test, config: nil, format: nil
178
180
 
179
181
  expect(selector.expression_filters.keys).to include(:valid3, :valid4)
180
182
  end
181
183
 
182
184
  it 'ignores block parameters if names passed in' do
183
- selector = Capybara::Selector.new :test do
185
+ described_class.add_selector :test do
184
186
  xpath(:valid1) { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
185
187
  end
188
+ selector = Capybara::Selector.new :test, config: nil, format: nil
186
189
 
187
190
  expect(selector.expression_filters.keys).to include(:valid1)
188
191
  expect(selector.expression_filters.keys).not_to include(:valid3, :valid4)
@@ -202,25 +205,28 @@ RSpec.describe Capybara do
202
205
  end
203
206
 
204
207
  it 'uses filter names passed in' do
205
- selector = Capybara::Selector.new :text do
208
+ described_class.add_selector :test do
206
209
  css(:name, :other_name) { |_locator| '' }
207
210
  end
211
+ selector = Capybara::Selector.new :test, config: nil, format: nil
208
212
 
209
213
  expect(selector.expression_filters.keys).to include(:name, :other_name)
210
214
  end
211
215
 
212
216
  it 'gets filter names from block if none passed to css method' do
213
- selector = Capybara::Selector.new :test do
217
+ described_class.add_selector :test do
214
218
  css { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
215
219
  end
220
+ selector = Capybara::Selector.new :test, config: nil, format: nil
216
221
 
217
222
  expect(selector.expression_filters.keys).to include(:valid3, :valid4)
218
223
  end
219
224
 
220
225
  it 'ignores block parameters if names passed in' do
221
- selector = Capybara::Selector.new :test do
226
+ described_class.add_selector :test do
222
227
  css(:valid1) { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
223
228
  end
229
+ selector = Capybara::Selector.new :test, config: nil, format: nil
224
230
 
225
231
  expect(selector.expression_filters.keys).to include(:valid1)
226
232
  expect(selector.expression_filters.keys).not_to include(:valid3, :valid4)
@@ -470,14 +476,18 @@ RSpec.describe Capybara do
470
476
  end
471
477
 
472
478
  describe ':link_or_button selector' do
473
- around(:all) do |example|
474
- Capybara.modify_selector(:link_or_button) do
479
+ around do |example|
480
+ described_class.modify_selector(:link_or_button) do
475
481
  expression_filter(:random) { |xpath, _| xpath } # do nothing filter
476
482
  end
477
483
  example.run
478
484
  Capybara::Selector[:link_or_button].expression_filters.delete(:random)
479
485
  end
480
486
 
487
+ it 'should not find links when disabled == true' do
488
+ expect(string.all(:link_or_button, disabled: true).size).to eq 0
489
+ end
490
+
481
491
  context 'when modified' do
482
492
  it 'should still work' do
483
493
  filter = Capybara::Selector[:link_or_button].expression_filters[:random]
@@ -3,16 +3,24 @@
3
3
  require 'spec_helper'
4
4
  require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
6
7
  require 'rspec/shared_spec_matchers'
7
8
 
8
9
  CHROME_DRIVER = :selenium_chrome
9
10
 
11
+ Selenium::WebDriver::Chrome.path = '/usr/bin/google-chrome-beta' if ENV['CI'] && ENV['CHROME_BETA']
12
+
10
13
  browser_options = ::Selenium::WebDriver::Chrome::Options.new
11
14
  browser_options.headless! if ENV['HEADLESS']
12
- browser_options.add_option(:w3c, !!ENV['W3C'])
15
+ browser_options.add_option(:w3c, ENV['W3C'] != 'false')
16
+ # Chromedriver 77 requires setting this for headless mode on linux
17
+ # Different versions of Chrome/selenium-webdriver require setting differently - jus set them all
18
+ browser_options.add_preference('download.default_directory', Capybara.save_path)
19
+ browser_options.add_preference(:download, default_directory: Capybara.save_path)
13
20
 
14
21
  Capybara.register_driver :selenium_chrome do |app|
15
22
  Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options, timeout: 30).tap do |driver|
23
+ # Set download dir for Chrome < 77
16
24
  driver.browser.download_path = Capybara.save_path
17
25
  end
18
26
  end
@@ -22,7 +30,28 @@ Capybara.register_driver :selenium_chrome_not_clear_storage do |app|
22
30
  browser: :chrome,
23
31
  options: browser_options
24
32
  }
25
- Capybara::Selenium::Driver.new(app, chrome_options.merge(clear_local_storage: false, clear_session_storage: false))
33
+ Capybara::Selenium::Driver.new(app, **chrome_options.merge(clear_local_storage: false, clear_session_storage: false))
34
+ end
35
+
36
+ Capybara.register_driver :selenium_chrome_not_clear_session_storage do |app|
37
+ chrome_options = {
38
+ browser: :chrome,
39
+ options: browser_options
40
+ }
41
+ Capybara::Selenium::Driver.new(app, **chrome_options.merge(clear_session_storage: false))
42
+ end
43
+
44
+ Capybara.register_driver :selenium_chrome_not_clear_local_storage do |app|
45
+ chrome_options = {
46
+ browser: :chrome,
47
+ options: browser_options
48
+ }
49
+ Capybara::Selenium::Driver.new(app, **chrome_options.merge(clear_local_storage: false))
50
+ end
51
+
52
+ Capybara.register_driver :selenium_driver_subclass_with_chrome do |app|
53
+ subclass = Class.new(Capybara::Selenium::Driver)
54
+ subclass.new(app, browser: :chrome, options: browser_options, timeout: 30)
26
55
  end
27
56
 
28
57
  module TestSessions
@@ -31,7 +60,7 @@ end
31
60
 
32
61
  skipped_tests = %i[response_headers status_code trigger]
33
62
 
34
- $stdout.puts `#{Selenium::WebDriver::Chrome.driver_path} --version` if ENV['CI']
63
+ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::Chrome) if ENV['CI']
35
64
 
36
65
  Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybara_skip: skipped_tests do |example|
37
66
  case example.metadata[:full_description]
@@ -39,13 +68,18 @@ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybar
39
68
  skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
40
69
  when /Capybara::Session selenium_chrome Capybara::Window#maximize/
41
70
  pending "Chrome headless doesn't support maximize" if ENV['HEADLESS']
71
+ when /Capybara::Window#fullscreen should be able to fullscreen the window/
72
+ skip 'Chromedriver hangs on attempts to fullscreen in headless mode' if ENV['HEADLESS']
73
+ when /node #right_click delay should delay the mouse up/
74
+ skip "Legacy selenium doesn't support separate right button down/up" if ENV['W3C'] == 'false'
42
75
  end
43
76
  end
44
77
 
45
78
  RSpec.describe 'Capybara::Session with chrome' do
46
79
  include Capybara::SpecHelper
47
- include_examples 'Capybara::Session', TestSessions::Chrome, CHROME_DRIVER
48
- include_examples Capybara::RSpecMatchers, TestSessions::Chrome, CHROME_DRIVER
80
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
81
+ include_examples examples, TestSessions::Chrome, CHROME_DRIVER
82
+ end
49
83
 
50
84
  context 'storage' do
51
85
  describe '#reset!' do
@@ -68,6 +102,26 @@ RSpec.describe 'Capybara::Session with chrome' do
68
102
  expect(session.evaluate_script('Object.keys(localStorage)')).not_to be_empty
69
103
  expect(session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty
70
104
  end
105
+
106
+ it 'can not clear session storage' do
107
+ session = Capybara::Session.new(:selenium_chrome_not_clear_session_storage, TestApp)
108
+ session.visit('/with_js')
109
+ session.find(:css, '#set-storage').click
110
+ session.reset!
111
+ session.visit('/with_js')
112
+ expect(session.evaluate_script('Object.keys(localStorage)')).to be_empty
113
+ expect(session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty
114
+ end
115
+
116
+ it 'can not clear local storage' do
117
+ session = Capybara::Session.new(:selenium_chrome_not_clear_local_storage, TestApp)
118
+ session.visit('/with_js')
119
+ session.find(:css, '#set-storage').click
120
+ session.reset!
121
+ session.visit('/with_js')
122
+ expect(session.evaluate_script('Object.keys(localStorage)')).not_to be_empty
123
+ expect(session.evaluate_script('Object.keys(sessionStorage)')).to be_empty
124
+ end
71
125
  end
72
126
  end
73
127
 
@@ -104,4 +158,29 @@ RSpec.describe 'Capybara::Session with chrome' do
104
158
  expect(Time.parse(extract_results(session)['datetime'])).to eq datetime
105
159
  end
106
160
  end
161
+
162
+ describe 'using subclass of selenium driver' do
163
+ it 'works' do
164
+ session = Capybara::Session.new(:selenium_driver_subclass_with_chrome, TestApp)
165
+ session.visit('/form')
166
+ expect(session).to have_current_path('/form')
167
+ end
168
+ end
169
+
170
+ describe 'log access' do
171
+ before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
172
+
173
+ it 'does not error getting log types' do
174
+ skip if Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0]) < Gem::Version.new('75.0.3770.90')
175
+ expect do
176
+ session.driver.browser.manage.logs.available_types
177
+ end.not_to raise_error
178
+ end
179
+
180
+ it 'does not error when getting logs' do
181
+ expect do
182
+ session.driver.browser.manage.logs.get(:browser)
183
+ end.not_to raise_error
184
+ end
185
+ end
107
186
  end
@@ -3,6 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
6
7
  require 'rspec/shared_spec_matchers'
7
8
 
8
9
  def selenium_host
@@ -53,12 +54,6 @@ module TestSessions
53
54
  Chrome = Capybara::Session.new(CHROME_REMOTE_DRIVER, TestApp)
54
55
  end
55
56
 
56
- TestSessions::Chrome.driver.browser.file_detector = lambda do |args|
57
- # args => ["/path/to/file"]
58
- str = args.first.to_s
59
- str if File.exist?(str)
60
- end
61
-
62
57
  skipped_tests = %i[response_headers status_code trigger download]
63
58
 
64
59
  Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|
@@ -67,15 +62,35 @@ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s,
67
62
  'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once for each set of files uploaded',
68
63
  'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once when uploading multiple files from empty'
69
64
  pending "Selenium with Remote Chrome doesn't support multiple file upload" unless selenium_gte?(3.14)
65
+ when /node #right_click delay should delay the mouse up/
66
+ skip "Legacy selenium doesn't support separate right button down/up" if ENV['W3C'] == 'false'
70
67
  end
71
68
  end
72
69
 
73
70
  RSpec.describe 'Capybara::Session with remote Chrome' do
74
71
  include Capybara::SpecHelper
75
- include_examples 'Capybara::Session', TestSessions::Chrome, CHROME_REMOTE_DRIVER
76
- include_examples Capybara::RSpecMatchers, TestSessions::Chrome, CHROME_REMOTE_DRIVER
72
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
73
+ include_examples examples, TestSessions::Chrome, CHROME_REMOTE_DRIVER
74
+ end
77
75
 
78
76
  it 'is considered to be chrome' do
79
77
  expect(session.driver.browser.browser).to eq :chrome
80
78
  end
79
+
80
+ describe 'log access' do
81
+ before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
82
+
83
+ it 'does not error when getting log types' do
84
+ skip if Gem::Version.new(session.driver.browser.capabilities['chrome']['chromedriverVersion'].split[0]) < Gem::Version.new('75.0.3770.90')
85
+ expect do
86
+ session.driver.browser.manage.logs.available_types
87
+ end.not_to raise_error
88
+ end
89
+
90
+ it 'does not error when getting logs' do
91
+ expect do
92
+ session.driver.browser.manage.logs.get(:browser)
93
+ end.not_to raise_error
94
+ end
95
+ end
81
96
  end
@@ -3,30 +3,45 @@
3
3
  require 'spec_helper'
4
4
  require 'selenium-webdriver'
5
5
  require 'shared_selenium_session'
6
+ require 'shared_selenium_node'
6
7
  require 'rspec/shared_spec_matchers'
7
8
 
9
+ # unless ENV['CI']
10
+ # Selenium::WebDriver::Edge::Service.driver_path = '/usr/local/bin/msedgedriver'
11
+ # end
12
+
13
+ if ::Selenium::WebDriver::Platform.mac?
14
+ Selenium::WebDriver::EdgeChrome.path = '/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev'
15
+ end
16
+
8
17
  Capybara.register_driver :selenium_edge do |app|
9
18
  # ::Selenium::WebDriver.logger.level = "debug"
10
- Capybara::Selenium::Driver.new(app, browser: :edge)
19
+ # If we don't create an options object the path set above won't be used
20
+ browser_options = ::Selenium::WebDriver::EdgeChrome::Options.new
21
+ Capybara::Selenium::Driver.new(app, browser: :edge_chrome, options: browser_options).tap do |driver|
22
+ driver.browser
23
+ driver.download_path = Capybara.save_path
24
+ end
11
25
  end
12
26
 
13
27
  module TestSessions
14
28
  SeleniumEdge = Capybara::Session.new(:selenium_edge, TestApp)
15
29
  end
16
30
 
17
- skipped_tests = %i[response_headers status_code trigger modals]
31
+ skipped_tests = %i[response_headers status_code trigger]
18
32
 
19
- $stdout.puts `#{Selenium::WebDriver::Edge.driver_path} --version` if ENV['CI']
33
+ Capybara::SpecHelper.log_selenium_driver_version(Selenium::WebDriver::EdgeChrome) if ENV['CI']
20
34
 
21
35
  Capybara::SpecHelper.run_specs TestSessions::SeleniumEdge, 'selenium', capybara_skip: skipped_tests do |example|
22
- case example.metadata[:description]
23
- when /#refresh it reposts$/
24
- skip 'Edge insists on prompting without providing a way to suppress'
36
+ case example.metadata[:full_description]
37
+ when 'Capybara::Session selenium #attach_file with a block can upload by clicking the file input'
38
+ pending "EdgeChrome doesn't allow clicking on file inputs"
25
39
  end
26
40
  end
27
41
 
28
42
  RSpec.describe 'Capybara::Session with Edge', capybara_skip: skipped_tests do
29
43
  include Capybara::SpecHelper
30
- include_examples 'Capybara::Session', TestSessions::SeleniumEdge, :selenium_edge
31
- include_examples Capybara::RSpecMatchers, TestSessions::SeleniumEdge, :selenium_edge
44
+ ['Capybara::Session', 'Capybara::Node', Capybara::RSpecMatchers].each do |examples|
45
+ include_examples examples, TestSessions::SeleniumEdge, :selenium_edge
46
+ end
32
47
  end