capybara 3.35.3 → 3.37.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +57 -1
  3. data/README.md +5 -1
  4. data/lib/capybara/config.rb +16 -4
  5. data/lib/capybara/driver/base.rb +4 -0
  6. data/lib/capybara/driver/node.rb +5 -1
  7. data/lib/capybara/dsl.rb +4 -10
  8. data/lib/capybara/helpers.rb +3 -12
  9. data/lib/capybara/minitest/spec.rb +2 -2
  10. data/lib/capybara/node/actions.rb +10 -5
  11. data/lib/capybara/node/document.rb +2 -2
  12. data/lib/capybara/node/element.rb +13 -2
  13. data/lib/capybara/node/finders.rb +9 -2
  14. data/lib/capybara/node/simple.rb +5 -1
  15. data/lib/capybara/queries/active_element_query.rb +18 -0
  16. data/lib/capybara/queries/ancestor_query.rb +2 -1
  17. data/lib/capybara/queries/current_path_query.rb +1 -1
  18. data/lib/capybara/queries/selector_query.rb +34 -8
  19. data/lib/capybara/queries/sibling_query.rb +2 -1
  20. data/lib/capybara/rack_test/browser.rb +56 -7
  21. data/lib/capybara/rack_test/driver.rb +4 -4
  22. data/lib/capybara/rack_test/node.rb +10 -7
  23. data/lib/capybara/registration_container.rb +0 -3
  24. data/lib/capybara/registrations/drivers.rb +3 -3
  25. data/lib/capybara/rspec/matcher_proxies.rb +3 -3
  26. data/lib/capybara/rspec/matchers/have_selector.rb +5 -5
  27. data/lib/capybara/rspec/matchers.rb +14 -14
  28. data/lib/capybara/selector/builders/css_builder.rb +1 -1
  29. data/lib/capybara/selector/builders/xpath_builder.rb +1 -1
  30. data/lib/capybara/selector/css.rb +1 -1
  31. data/lib/capybara/selector/definition/button.rb +9 -4
  32. data/lib/capybara/selector/definition/checkbox.rb +1 -1
  33. data/lib/capybara/selector/definition/file_field.rb +1 -1
  34. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  35. data/lib/capybara/selector/definition/radio_button.rb +1 -1
  36. data/lib/capybara/selector/definition.rb +3 -1
  37. data/lib/capybara/selector/filter_set.rb +4 -6
  38. data/lib/capybara/selector/selector.rb +5 -1
  39. data/lib/capybara/selector.rb +1 -0
  40. data/lib/capybara/selenium/driver.rb +25 -11
  41. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
  42. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +1 -1
  43. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
  44. data/lib/capybara/selenium/node.rb +22 -8
  45. data/lib/capybara/selenium/nodes/chrome_node.rb +1 -1
  46. data/lib/capybara/selenium/nodes/edge_node.rb +1 -1
  47. data/lib/capybara/selenium/nodes/firefox_node.rb +1 -1
  48. data/lib/capybara/selenium/nodes/safari_node.rb +2 -2
  49. data/lib/capybara/server/animation_disabler.rb +35 -17
  50. data/lib/capybara/session/config.rb +1 -1
  51. data/lib/capybara/session.rb +20 -23
  52. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  53. data/lib/capybara/spec/session/all_spec.rb +9 -13
  54. data/lib/capybara/spec/session/assert_text_spec.rb +17 -17
  55. data/lib/capybara/spec/session/check_spec.rb +9 -0
  56. data/lib/capybara/spec/session/choose_spec.rb +6 -0
  57. data/lib/capybara/spec/session/find_spec.rb +6 -0
  58. data/lib/capybara/spec/session/has_any_selectors_spec.rb +4 -0
  59. data/lib/capybara/spec/session/has_button_spec.rb +24 -0
  60. data/lib/capybara/spec/session/has_current_path_spec.rb +2 -2
  61. data/lib/capybara/spec/session/has_field_spec.rb +25 -1
  62. data/lib/capybara/spec/session/has_link_spec.rb +30 -0
  63. data/lib/capybara/spec/session/has_select_spec.rb +4 -4
  64. data/lib/capybara/spec/session/has_selector_spec.rb +15 -0
  65. data/lib/capybara/spec/session/has_text_spec.rb +2 -6
  66. data/lib/capybara/spec/session/node_spec.rb +43 -1
  67. data/lib/capybara/spec/session/scroll_spec.rb +4 -4
  68. data/lib/capybara/spec/session/visit_spec.rb +20 -0
  69. data/lib/capybara/spec/session/window/window_spec.rb +1 -1
  70. data/lib/capybara/spec/spec_helper.rb +4 -3
  71. data/lib/capybara/spec/test_app.rb +66 -8
  72. data/lib/capybara/spec/views/animated.erb +1 -1
  73. data/lib/capybara/spec/views/form.erb +11 -3
  74. data/lib/capybara/spec/views/frame_child.erb +1 -1
  75. data/lib/capybara/spec/views/frame_one.erb +1 -1
  76. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  77. data/lib/capybara/spec/views/frame_two.erb +1 -1
  78. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  79. data/lib/capybara/spec/views/layout.erb +10 -0
  80. data/lib/capybara/spec/views/obscured.erb +1 -1
  81. data/lib/capybara/spec/views/offset.erb +2 -1
  82. data/lib/capybara/spec/views/path.erb +2 -2
  83. data/lib/capybara/spec/views/popup_one.erb +1 -1
  84. data/lib/capybara/spec/views/popup_two.erb +1 -1
  85. data/lib/capybara/spec/views/react.erb +2 -2
  86. data/lib/capybara/spec/views/scroll.erb +2 -1
  87. data/lib/capybara/spec/views/spatial.erb +1 -1
  88. data/lib/capybara/spec/views/with_animation.erb +2 -3
  89. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  90. data/lib/capybara/spec/views/with_dragula.erb +2 -2
  91. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  92. data/lib/capybara/spec/views/with_hover.erb +2 -2
  93. data/lib/capybara/spec/views/with_html.erb +1 -1
  94. data/lib/capybara/spec/views/with_jquery_animation.erb +1 -1
  95. data/lib/capybara/spec/views/with_js.erb +2 -3
  96. data/lib/capybara/spec/views/with_jstree.erb +1 -1
  97. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  98. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  99. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  100. data/lib/capybara/spec/views/with_sortable_js.erb +2 -2
  101. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  102. data/lib/capybara/spec/views/with_windows.erb +1 -1
  103. data/lib/capybara/spec/views/within_frames.erb +1 -1
  104. data/lib/capybara/version.rb +1 -1
  105. data/lib/capybara/window.rb +1 -1
  106. data/lib/capybara.rb +19 -22
  107. data/spec/basic_node_spec.rb +16 -3
  108. data/spec/dsl_spec.rb +3 -3
  109. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -2
  110. data/spec/fixtures/selenium_driver_rspec_success.rb +2 -2
  111. data/spec/rack_test_spec.rb +20 -10
  112. data/spec/result_spec.rb +32 -35
  113. data/spec/rspec/features_spec.rb +3 -3
  114. data/spec/rspec/scenarios_spec.rb +1 -1
  115. data/spec/rspec/shared_spec_matchers.rb +2 -2
  116. data/spec/sauce_spec_chrome.rb +3 -3
  117. data/spec/selector_spec.rb +2 -2
  118. data/spec/selenium_spec_chrome.rb +9 -10
  119. data/spec/selenium_spec_chrome_remote.rb +9 -8
  120. data/spec/selenium_spec_firefox.rb +8 -3
  121. data/spec/selenium_spec_firefox_remote.rb +2 -2
  122. data/spec/selenium_spec_ie.rb +3 -6
  123. data/spec/selenium_spec_safari.rb +31 -19
  124. data/spec/server_spec.rb +5 -5
  125. data/spec/shared_selenium_node.rb +0 -4
  126. data/spec/shared_selenium_session.rb +20 -10
  127. data/spec/spec_helper.rb +1 -1
  128. metadata +37 -14
  129. data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -0,0 +1,31 @@
1
+ <!DOCTYPE html>
2
+ <%# Borrowed from Titus Fortner %>
3
+ <html>
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
6
+ <title>Shadow DOM</title>
7
+ </head>
8
+ <body>
9
+ <div id="no_host"></div>
10
+ <div id="shadow_host"></div>
11
+ <a href="scroll.html">scroll.html</a>
12
+ <script>
13
+ let shadowRoot = document.getElementById('shadow_host').attachShadow({mode: 'open'});
14
+ shadowRoot.innerHTML = `
15
+ <span class="wrapper" id="shadow_content"><span class="info">some text</span></span>
16
+ <div id="nested_shadow_host"></div>
17
+ <a href="scroll.html">scroll.html</a>
18
+ <div id="controls_wrapper">
19
+ <input type="text" />
20
+ <input type="checkbox" id="shadow_checkbox" />
21
+ <input type="file" />
22
+ </div>
23
+ `;
24
+
25
+ let nestedShadowRoot = shadowRoot.getElementById('nested_shadow_host').attachShadow({mode: 'open'});
26
+ nestedShadowRoot.innerHTML = `
27
+ <div id="nested_shadow_content"><div>nested text</div></div>
28
+ `;
29
+ </script>
30
+ </body>
31
+ </html>
@@ -1,3 +1,4 @@
1
+ <!DOCTYPE html>
1
2
  <html>
2
3
  <head>
3
4
  <script>
@@ -14,4 +15,4 @@
14
15
  <body>
15
16
  <div>This delays unload by 2 seconds</div>
16
17
  </body>
17
- </html>
18
+ </html>
@@ -1,4 +1,5 @@
1
- <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
1
+ <!DOCTYPE html>
2
+ <html lang="en">
2
3
  <head>
3
4
  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
4
5
  <title>with_sortable_js</title>
@@ -18,4 +19,3 @@
18
19
  </script>
19
20
  </body>
20
21
  </html>
21
-
@@ -1,3 +1,4 @@
1
+ <!DOCTYPE html>
1
2
  <html>
2
3
  <head>
3
4
  <script>
@@ -1,4 +1,4 @@
1
-
1
+ <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
4
  <title>With Windows</title>
@@ -1,4 +1,4 @@
1
-
1
+ <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
4
  <title>With Frames</title>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Capybara
4
- VERSION = '3.35.3'
4
+ VERSION = '3.37.1'
5
5
  end
@@ -118,7 +118,7 @@ module Capybara
118
118
  alias_method :==, :eql?
119
119
 
120
120
  def hash
121
- @session.hash ^ @handle.hash
121
+ [@session, @handle].hash
122
122
  end
123
123
 
124
124
  def inspect
data/lib/capybara.rb CHANGED
@@ -39,7 +39,7 @@ module Capybara
39
39
  # See {Capybara.configure}
40
40
  # @!method javascript_driver
41
41
  # See {Capybara.configure}
42
- # @!method allow_gumbo
42
+ # @!method use_html5_parsing
43
43
  # See {Capybara.configure}
44
44
  Config::OPTIONS.each do |method|
45
45
  def_delegators :config, method, "#{method}="
@@ -69,7 +69,7 @@ module Capybara
69
69
  #
70
70
  # #### Configurable options
71
71
  #
72
- # - **allow_gumbo** (Boolean = `false`) - When `nokogumbo` is available, whether it will be used to parse HTML strings.
72
+ # - **use_html5_parsing** (Boolean = `false`) - When Nokogiri >= 1.12.0 or `nokogumbo` is installed, whether HTML5 parsing will be used for HTML strings.
73
73
  # - **always_include_port** (Boolean = `false`) - Whether the Rack server's port should automatically be inserted into every visited URL
74
74
  # unless another port is explicitly specified.
75
75
  # - **app_host** (String, `nil`) - The default host to use when giving a relative URL to visit, must be a valid URL e.g. `http://www.example.com`.
@@ -96,6 +96,7 @@ module Capybara
96
96
  # {Capybara::Session#save_and_open_page save_and_open_page}, or {Capybara::Session#save_and_open_screenshot save_and_open_screenshot}.
97
97
  # - **server** (Symbol = `:default` (which uses puma)) - The name of the registered server to use when running the app under test.
98
98
  # - **server_port** (Integer) - The port Capybara will run the application server on, if not specified a random port will be used.
99
+ # - **server_host** (String = "127.0.0.1") - The IP address Capybara will bind the application server to. If the test application is to be accessed from an external host, you will want to change this to "0.0.0.0" or to a more specific IP address that your test client can reach.
99
100
  # - **server_errors** (Array\<Class> = `[Exception]`) - Error classes that should be raised in the tests if they are raised in the server
100
101
  # and {configure raise_server_errors} is `true`.
101
102
  # - **test_id** (Symbol, String, `nil` = `nil`) - Optional attribute to match locator against with built-in selectors along with id.
@@ -385,26 +386,21 @@ module Capybara
385
386
  # @return [Nokogiri::HTML::Document] HTML document
386
387
  #
387
388
  def HTML(html) # rubocop:disable Naming/MethodName
388
- if Nokogiri.respond_to?(:HTML5) && Capybara.allow_gumbo # Nokogumbo installed and allowed for use
389
- Nokogiri::HTML5(html).tap do |document|
390
- document.xpath('//template').each do |template|
391
- # template elements content is not part of the document
392
- template.inner_html = ''
393
- end
394
- document.xpath('//textarea').each do |textarea|
395
- # The Nokogumbo HTML5 parser already returns spec compliant contents
396
- textarea['_capybara_raw_value'] = textarea.content
397
- end
398
- end
389
+ # Nokogiri >= 1.12.0 or Nokogumbo installed and allowed for use
390
+ html_parser, using_html5 = if defined?(Nokogiri::HTML5) && Capybara.use_html5_parsing
391
+ [Nokogiri::HTML5, true]
399
392
  else
400
- Nokogiri::HTML(html).tap do |document|
401
- document.xpath('//template').each do |template|
402
- # template elements content is not part of the document
403
- template.inner_html = ''
404
- end
405
- document.xpath('//textarea').each do |textarea|
406
- textarea['_capybara_raw_value'] = textarea.content.delete_prefix("\n")
407
- end
393
+ [defined?(Nokogiri::HTML4) ? Nokogiri::HTML4 : Nokogiri::HTML, false]
394
+ end
395
+
396
+ html_parser.parse(html).tap do |document|
397
+ document.xpath('//template').each do |template|
398
+ # template elements content is not part of the document
399
+ template.inner_html = ''
400
+ end
401
+ document.xpath('//textarea').each do |textarea|
402
+ # The Nokogiri HTML5 parser already returns spec compliant contents
403
+ textarea['_capybara_raw_value'] = using_html5 ? textarea.content : textarea.content.delete_prefix("\n")
408
404
  end
409
405
  end
410
406
  end
@@ -467,6 +463,7 @@ module Capybara
467
463
  require 'capybara/queries/ancestor_query'
468
464
  require 'capybara/queries/sibling_query'
469
465
  require 'capybara/queries/style_query'
466
+ require 'capybara/queries/active_element_query'
470
467
 
471
468
  require 'capybara/node/finders'
472
469
  require 'capybara/node/matchers'
@@ -516,6 +513,6 @@ Capybara.configure do |config|
516
513
  config.test_id = nil
517
514
  config.predicates_wait = true
518
515
  config.default_normalize_ws = false
519
- config.allow_gumbo = false
516
+ config.use_html5_parsing = false
520
517
  config.w3c_click_offset = false
521
518
  end
@@ -111,14 +111,27 @@ RSpec.describe Capybara do
111
111
  expect(string.find('//form/input[@name="meh"]')).not_to be_disabled
112
112
  end
113
113
 
114
+ it 'allows finding siblings' do
115
+ h1 = string.find(:css, 'h1')
116
+ expect(h1).to have_sibling(:css, 'p', text: 'Yes it is')
117
+ expect(h1).not_to have_sibling(:css, 'p', text: 'Jonas Nicklas')
118
+ end
119
+
120
+ it 'allows finding ancestor' do
121
+ h1 = string.find(:css, 'h1')
122
+ expect(h1).to have_ancestor(:css, '#content')
123
+ expect(h1).not_to have_ancestor(:css, '#footer')
124
+ end
125
+
114
126
  it 'drops illegal fragments when using gumbo' do
115
127
  skip 'libxml is less strict than Gumbo' unless Nokogiri.respond_to?(:HTML5)
128
+ described_class.use_html5_parsing = true
116
129
  expect(described_class.string('<td>1</td>')).not_to have_css('td')
117
130
  end
118
131
 
119
- it 'can disable use of gumbo' do
120
- skip "Test doesn't make sense unlesss nokogumbo is loaded" unless Nokogiri.respond_to?(:HTML5)
121
- described_class.allow_gumbo = false
132
+ it 'can disable use of HTML5 parsing' do
133
+ skip "Test doesn't make sense unlesss HTML5 parsing is loaded (Nokogumbo or Nokogiri >= 1.12.0)" unless Nokogiri.respond_to?(:HTML5)
134
+ described_class.use_html5_parsing = false
122
135
  expect(described_class.string('<td>1</td>')).to have_css('td')
123
136
  end
124
137
 
data/spec/dsl_spec.rb CHANGED
@@ -8,7 +8,7 @@ class TestClass
8
8
  end
9
9
 
10
10
  Capybara::SpecHelper.run_specs TestClass.new, 'DSL', capybara_skip: %i[
11
- js modals screenshot frames windows send_keys server hover about_scheme psc download css driver scroll spatial html_validation shadow_dom
11
+ js modals screenshot frames windows send_keys server hover about_scheme psc download css driver scroll spatial html_validation shadow_dom active_element
12
12
  ] do |example|
13
13
  case example.metadata[:full_description]
14
14
  when /has_css\? should support case insensitive :class and :id options/
@@ -115,7 +115,7 @@ RSpec.describe Capybara::DSL do
115
115
  it 'should yield the passed block' do
116
116
  called = false
117
117
  Capybara.using_driver(:selenium) { called = true }
118
- expect(called).to eq(true)
118
+ expect(called).to be(true)
119
119
  end
120
120
  end
121
121
 
@@ -220,7 +220,7 @@ RSpec.describe Capybara::DSL do
220
220
  it 'should yield the passed block' do
221
221
  called = false
222
222
  Capybara.using_session(:administrator) { called = true }
223
- expect(called).to eq(true)
223
+ expect(called).to be(true)
224
224
  end
225
225
 
226
226
  it 'should be nestable' do
@@ -5,9 +5,9 @@ require 'selenium-webdriver'
5
5
 
6
6
  RSpec.describe Capybara::Selenium::Driver do
7
7
  it 'should exit with a non-zero exit status' do
8
- options = { browser: (ENV['SELENIUM_BROWSER'] || :firefox).to_sym }
8
+ options = { browser: ENV.fetch('SELENIUM_BROWSER', :firefox).to_sym }
9
9
  browser = described_class.new(TestApp, options).browser
10
10
  expect(browser).to be_truthy
11
- expect(true).to eq(false) # rubocop:disable RSpec/ExpectActual
11
+ expect(true).to be(false) # rubocop:disable RSpec/ExpectActual
12
12
  end
13
13
  end
@@ -5,9 +5,9 @@ require 'selenium-webdriver'
5
5
 
6
6
  RSpec.describe Capybara::Selenium::Driver do
7
7
  it 'should exit with a zero exit status' do
8
- options = { browser: (ENV['SELENIUM_BROWSER'] || :firefox).to_sym }
8
+ options = { browser: ENV.fetch('SELENIUM_BROWSER', :firefox).to_sym }
9
9
  browser = described_class.new(TestApp, **options).browser
10
10
  expect(browser).to be_truthy
11
- expect(true).to eq(true) # rubocop:disable RSpec/ExpectActual
11
+ expect(true).to be(true) # rubocop:disable RSpec/ExpectActual,RSpec/IdenticalEqualityAssertion
12
12
  end
13
13
  end
@@ -1,12 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
- nokogumbo_required = begin
5
- require 'nokogumbo'
6
- true
7
- rescue LoadError
8
- false
9
- end
10
4
 
11
5
  module TestSessions
12
6
  RackTest = Capybara::Session.new(:rack_test, TestApp)
@@ -28,6 +22,7 @@ skipped_tests = %i[
28
22
  spatial
29
23
  html_validation
30
24
  shadow_dom
25
+ active_element
31
26
  ]
32
27
  Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip: skipped_tests do |example|
33
28
  case example.metadata[:full_description]
@@ -153,6 +148,14 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
153
148
  end
154
149
  end
155
150
 
151
+ describe '#active_element' do
152
+ it 'raises an UnsupportedMethodError' do
153
+ session.visit('/form')
154
+
155
+ expect { session.active_element }.to raise_error(Capybara::NotSupportedByDriverError)
156
+ end
157
+ end
158
+
156
159
  describe '#text' do
157
160
  it 'should return original text content for textareas' do
158
161
  session.visit('/with_html')
@@ -213,6 +216,12 @@ RSpec.describe Capybara::RackTest::Driver do
213
216
  expect(driver.current_url).to match %r{/landed$}
214
217
  end
215
218
 
219
+ it 'should not include fragments in the referer header' do
220
+ driver.visit('/header_links#an-anchor')
221
+ driver.find_xpath('.//input').first.click
222
+ expect(driver.request.get_header('HTTP_REFERER')).to eq('http://www.example.com/header_links')
223
+ end
224
+
216
225
  it 'is possible to not follow redirects' do
217
226
  driver = described_class.new(TestApp, follow_redirects: false)
218
227
 
@@ -256,11 +265,12 @@ RSpec.describe Capybara::RackTest::Driver do
256
265
  end
257
266
 
258
267
  RSpec.describe 'Capybara::String' do
259
- it 'should use gumbo' do
260
- skip 'Only valid if gumbo is included' unless nokogumbo_required
261
- allow(Nokogiri).to receive(:HTML5).and_call_original
268
+ it 'should use HTML5 parsing' do
269
+ skip 'Only valid if Nokogiri >= 1.12.0 or gumbo is included' unless defined? Nokogiri::HTML5
270
+ Capybara.use_html5_parsing = true
271
+ allow(Nokogiri::HTML5).to receive(:parse).and_call_original
262
272
  Capybara.string('<div id=test_div></div>')
263
- expect(Nokogiri).to have_received(:HTML5)
273
+ expect(Nokogiri::HTML5).to have_received(:parse)
264
274
  end
265
275
  end
266
276
 
data/spec/result_spec.rb CHANGED
@@ -78,34 +78,31 @@ RSpec.describe Capybara::Result do
78
78
  expect(recalc_result[1...3].map(&:text)).to eq %w[Beta Gamma]
79
79
  expect(recalc_result[1..7].map(&:text)).to eq %w[Beta Gamma Delta]
80
80
  expect(recalc_result[2...-1].map(&:text)).to eq %w[Gamma]
81
- expect(recalc_result[2..-1].map(&:text)).to eq %w[Gamma Delta]
81
+ expect(recalc_result[2..-1].map(&:text)).to eq %w[Gamma Delta] # rubocop:disable Style/SlicingWithRange
82
+ expect(recalc_result[2..].map(&:text)).to eq %w[Gamma Delta]
82
83
  end
83
84
 
84
- eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.5
85
- it 'supports endless ranges' do
86
- expect(result[2..].map(&:text)).to eq %w[Gamma Delta]
87
- end
88
- TEST
85
+ it 'supports endless ranges' do
86
+ expect(result[2..].map(&:text)).to eq %w[Gamma Delta]
87
+ end
89
88
 
90
- eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.6
91
- it 'supports inclusive positive beginless ranges' do
92
- expect(result[..2].map(&:text)).to eq %w[Alpha Beta Gamma]
93
- end
89
+ it 'supports inclusive positive beginless ranges' do
90
+ expect(result[..2].map(&:text)).to eq %w[Alpha Beta Gamma]
91
+ end
94
92
 
95
- it 'supports inclusive negative beginless ranges' do
96
- expect(result[..-2].map(&:text)).to eq %w[Alpha Beta Gamma]
97
- expect(result[..-1].map(&:text)).to eq %w[Alpha Beta Gamma Delta]
98
- end
93
+ it 'supports inclusive negative beginless ranges' do
94
+ expect(result[..-2].map(&:text)).to eq %w[Alpha Beta Gamma]
95
+ expect(result[..-1].map(&:text)).to eq %w[Alpha Beta Gamma Delta]
96
+ end
99
97
 
100
- it 'supports exclusive positive beginless ranges' do
101
- expect(result[...2].map(&:text)).to eq %w[Alpha Beta]
102
- end
98
+ it 'supports exclusive positive beginless ranges' do
99
+ expect(result[...2].map(&:text)).to eq %w[Alpha Beta]
100
+ end
103
101
 
104
- it 'supports exclusive negative beginless ranges' do
105
- expect(result[...-2].map(&:text)).to eq %w[Alpha Beta]
106
- expect(result[...-1].map(&:text)).to eq %w[Alpha Beta Gamma]
107
- end
108
- TEST
102
+ it 'supports exclusive negative beginless ranges' do
103
+ expect(result[...-2].map(&:text)).to eq %w[Alpha Beta]
104
+ expect(result[...-1].map(&:text)).to eq %w[Alpha Beta Gamma]
105
+ end
109
106
 
110
107
  it 'works with filter blocks' do
111
108
  result = string.all('//li') { |node| node.text == 'Alpha' }
@@ -116,52 +113,52 @@ RSpec.describe Capybara::Result do
116
113
  it 'should evaluate filters lazily for idx' do
117
114
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
118
115
  # Not processed until accessed
119
- expect(result.instance_variable_get('@result_cache').size).to be 0
116
+ expect(result.instance_variable_get(:@result_cache).size).to be 0
120
117
 
121
118
  # Only one retrieved when needed
122
119
  result.first
123
- expect(result.instance_variable_get('@result_cache').size).to be 1
120
+ expect(result.instance_variable_get(:@result_cache).size).to be 1
124
121
 
125
122
  # works for indexed access
126
123
  result[0]
127
- expect(result.instance_variable_get('@result_cache').size).to be 1
124
+ expect(result.instance_variable_get(:@result_cache).size).to be 1
128
125
 
129
126
  result[2]
130
- expect(result.instance_variable_get('@result_cache').size).to be 3
127
+ expect(result.instance_variable_get(:@result_cache).size).to be 3
131
128
 
132
129
  # All cached when converted to array
133
130
  result.to_a
134
- expect(result.instance_variable_get('@result_cache').size).to eq 4
131
+ expect(result.instance_variable_get(:@result_cache).size).to eq 4
135
132
  end
136
133
 
137
134
  it 'should evaluate filters lazily for range' do
138
135
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
139
136
  result[0..1]
140
- expect(result.instance_variable_get('@result_cache').size).to be 2
137
+ expect(result.instance_variable_get(:@result_cache).size).to be 2
141
138
 
142
139
  expect(result[0..7].size).to eq 4
143
- expect(result.instance_variable_get('@result_cache').size).to be 4
140
+ expect(result.instance_variable_get(:@result_cache).size).to be 4
144
141
  end
145
142
 
146
143
  it 'should evaluate filters lazily for idx and length' do
147
144
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
148
145
  result[1, 2]
149
- expect(result.instance_variable_get('@result_cache').size).to be 3
146
+ expect(result.instance_variable_get(:@result_cache).size).to be 3
150
147
 
151
148
  expect(result[2, 5].size).to eq 2
152
- expect(result.instance_variable_get('@result_cache').size).to be 4
149
+ expect(result.instance_variable_get(:@result_cache).size).to be 4
153
150
  end
154
151
 
155
152
  it 'should only need to evaluate one result for any?' do
156
153
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
157
154
  result.any?
158
- expect(result.instance_variable_get('@result_cache').size).to be 1
155
+ expect(result.instance_variable_get(:@result_cache).size).to be 1
159
156
  end
160
157
 
161
158
  it 'should evaluate all elements when #to_a called' do
162
159
  # All cached when converted to array
163
160
  result.to_a
164
- expect(result.instance_variable_get('@result_cache').size).to eq 4
161
+ expect(result.instance_variable_get(:@result_cache).size).to eq 4
165
162
  end
166
163
 
167
164
  describe '#each' do
@@ -170,7 +167,7 @@ RSpec.describe Capybara::Result do
170
167
  results = []
171
168
  result.each do |el|
172
169
  results << el
173
- expect(result.instance_variable_get('@result_cache').size).to eq results.size
170
+ expect(result.instance_variable_get(:@result_cache).size).to eq results.size
174
171
  end
175
172
 
176
173
  expect(results.size).to eq 4
@@ -184,7 +181,7 @@ RSpec.describe Capybara::Result do
184
181
  it 'lazily evaluates' do
185
182
  skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
186
183
  result.each.with_index do |_el, idx|
187
- expect(result.instance_variable_get('@result_cache').size).to eq(idx + 1) # 0 indexing
184
+ expect(result.instance_variable_get(:@result_cache).size).to eq(idx + 1) # 0 indexing
188
185
  end
189
186
  end
190
187
  end
@@ -91,11 +91,11 @@ end
91
91
 
92
92
  ffeature 'if ffeature aliases focused tag then' do # rubocop:disable RSpec/Focus
93
93
  scenario 'scenario inside this feature has metatag focus tag' do |example|
94
- expect(example.metadata[:focus]).to eq true
94
+ expect(example.metadata[:focus]).to be true
95
95
  end
96
96
 
97
- scenario 'other scenarios also has metatag focus tag ' do |example|
98
- expect(example.metadata[:focus]).to eq true
97
+ scenario 'other scenarios also has metatag focus tag' do |example|
98
+ expect(example.metadata[:focus]).to be true
99
99
  end
100
100
  end
101
101
  # rubocop:enable RSpec/RepeatedExample, RSpec/MultipleDescribes
@@ -11,7 +11,7 @@ end
11
11
 
12
12
  feature 'if fscenario aliases focused tag then' do
13
13
  fscenario 'scenario should have focused meta tag' do |example| # rubocop:disable RSpec/Focus
14
- expect(example.metadata[:focus]).to eq true
14
+ expect(example.metadata[:focus]).to be true
15
15
  end
16
16
  end
17
17
 
@@ -840,10 +840,10 @@ RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
840
840
  end
841
841
 
842
842
  it 'gives proper description when :visible option passed' do
843
- expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"')
843
+ expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"') # rubocop:disable RSpec/Capybara/VisibilityMatcher
844
844
  expect(have_table('Lovely table', visible: :hidden).description).to eq('have non-visible table "Lovely table"')
845
845
  expect(have_table('Lovely table', visible: :all).description).to eq('have table "Lovely table"')
846
- expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"')
846
+ expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"') # rubocop:disable RSpec/Capybara/VisibilityMatcher
847
847
  end
848
848
 
849
849
  it 'passes if there is such a table' do
@@ -15,9 +15,9 @@ Capybara.register_driver :sauce_chrome do |app|
15
15
  browser_name: 'chrome',
16
16
  version: '65.0',
17
17
  name: 'Capybara test',
18
- build: ENV['TRAVIS_REPO_SLUG'] || "Ruby-RSpec-Selenium: Local-#{Time.now.to_i}",
19
- username: ENV['SAUCE_USERNAME'],
20
- access_key: ENV['SAUCE_ACCESS_KEY']
18
+ build: ENV.fetch('TRAVIS_REPO_SLUG', "Ruby-RSpec-Selenium: Local-#{Time.now.to_i}"),
19
+ username: ENV.fetch('SAUCE_USERNAME', nil),
20
+ access_key: ENV.fetch('SAUCE_ACCESS_KEY', nil)
21
21
  }
22
22
 
23
23
  options.delete(:browser_name)
@@ -159,7 +159,7 @@ RSpec.describe Capybara do
159
159
  end
160
160
 
161
161
  it 'returns nil if no match' do
162
- expect(Capybara::Selector.for('nothing')).to be nil
162
+ expect(Capybara::Selector.for('nothing')).to be_nil
163
163
  end
164
164
  end
165
165
 
@@ -471,7 +471,7 @@ RSpec.describe Capybara do
471
471
  end
472
472
 
473
473
  it 'includes wildcarded keys in description' do
474
- expect { string.find(:element, 'input', not_there: 'bad', presence: true, absence: false, count: 1) }
474
+ expect { string.all(:element, 'input', not_there: 'bad', presence: true, absence: false, count: 1) }
475
475
  .to(raise_error do |e|
476
476
  expect(e).to be_a(Capybara::ElementNotFound)
477
477
  expect(e.message).to include 'not_there => bad'
@@ -8,11 +8,11 @@ require 'rspec/shared_spec_matchers'
8
8
 
9
9
  CHROME_DRIVER = :selenium_chrome
10
10
 
11
- Selenium::WebDriver::Chrome.path = '/usr/bin/google-chrome-beta' if ENV['CI'] && ENV['CHROME_BETA']
11
+ Selenium::WebDriver::Chrome.path = '/usr/bin/google-chrome-beta' if ENV.fetch('CI', nil) && ENV.fetch('CHROME_BETA', nil)
12
12
 
13
13
  browser_options = ::Selenium::WebDriver::Chrome::Options.new
14
14
  browser_options.headless! if ENV['HEADLESS']
15
- browser_options.add_option(:w3c, ENV['W3C'] != 'false')
15
+
16
16
  # Chromedriver 77 requires setting this for headless mode on linux
17
17
  # Different versions of Chrome/selenium-webdriver require setting differently - jus set them all
18
18
  browser_options.add_preference('download.default_directory', Capybara.save_path)
@@ -85,10 +85,6 @@ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybar
85
85
  skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
86
86
  when /Capybara::Session selenium_chrome Capybara::Window#maximize/
87
87
  pending "Chrome headless doesn't support maximize" if ENV['HEADLESS']
88
- when /Capybara::Window#fullscreen should be able to fullscreen the window/
89
- skip 'Chromedriver hangs on attempts to fullscreen in headless mode' if ENV['HEADLESS']
90
- when /node #right_click delay should delay the mouse up/
91
- skip "Legacy selenium doesn't support separate right button down/up" if ENV['W3C'] == 'false'
92
88
  end
93
89
  end
94
90
 
@@ -185,18 +181,21 @@ RSpec.describe 'Capybara::Session with chrome' do
185
181
  end
186
182
 
187
183
  describe 'log access' do
188
- before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
184
+ let(:logs) do
185
+ session.driver.browser.then do |chrome_driver|
186
+ chrome_driver.respond_to?(:logs) ? chrome_driver : chrome_driver.manage
187
+ end.logs
188
+ end
189
189
 
190
190
  it 'does not error getting log types' do
191
- skip if Gem::Requirement.new('< 75.0.3770.90').satisfied_by? chromedriver_version
192
191
  expect do
193
- session.driver.browser.manage.logs.available_types
192
+ logs.available_types
194
193
  end.not_to raise_error
195
194
  end
196
195
 
197
196
  it 'does not error when getting logs' do
198
197
  expect do
199
- session.driver.browser.manage.logs.get(:browser)
198
+ logs.get(:browser)
200
199
  end.not_to raise_error
201
200
  end
202
201
  end
@@ -21,8 +21,8 @@ def ensure_selenium_running!
21
21
  rescue StandardError
22
22
  if timer.expired?
23
23
  raise 'Selenium is not running. ' \
24
- "You can run a selenium server easily with: \n" \
25
- ' $ docker-compose up -d selenium_chrome'
24
+ "You can run a selenium server easily with: \n" \
25
+ ' $ docker-compose up -d selenium_chrome'
26
26
  else
27
27
  puts 'Waiting for Selenium docker instance...'
28
28
  sleep 1
@@ -62,8 +62,6 @@ Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s,
62
62
  'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once for each set of files uploaded',
63
63
  'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once when uploading multiple files from empty'
64
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'
67
65
  end
68
66
  end
69
67
 
@@ -78,18 +76,21 @@ RSpec.describe 'Capybara::Session with remote Chrome' do
78
76
  end
79
77
 
80
78
  describe 'log access' do
81
- before { skip 'Only makes sense in W3C mode' if ENV['W3C'] == 'false' }
79
+ let(:logs) do
80
+ session.driver.browser.then do |chrome_driver|
81
+ chrome_driver.respond_to?(:logs) ? chrome_driver : chrome_driver.manage
82
+ end.logs
83
+ end
82
84
 
83
85
  it 'does not error when getting log types' do
84
- skip unless Gem::Requirement.new('>= 75.0.3770.90').satisfied_by? chromedriver_version
85
86
  expect do
86
- session.driver.browser.manage.logs.available_types
87
+ logs.available_types
87
88
  end.not_to raise_error
88
89
  end
89
90
 
90
91
  it 'does not error when getting logs' do
91
92
  expect do
92
- session.driver.browser.manage.logs.get(:browser)
93
+ logs.get(:browser)
93
94
  end.not_to raise_error
94
95
  end
95
96
  end