capybara 3.35.2 → 3.38.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +99 -7
  3. data/README.md +28 -12
  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 +8 -13
  9. data/lib/capybara/minitest/spec.rb +2 -2
  10. data/lib/capybara/node/actions.rb +10 -5
  11. data/lib/capybara/node/base.rb +2 -1
  12. data/lib/capybara/node/document.rb +2 -2
  13. data/lib/capybara/node/element.rb +13 -2
  14. data/lib/capybara/node/finders.rb +9 -2
  15. data/lib/capybara/node/simple.rb +5 -1
  16. data/lib/capybara/queries/active_element_query.rb +18 -0
  17. data/lib/capybara/queries/ancestor_query.rb +2 -1
  18. data/lib/capybara/queries/base_query.rb +2 -2
  19. data/lib/capybara/queries/current_path_query.rb +1 -1
  20. data/lib/capybara/queries/selector_query.rb +38 -10
  21. data/lib/capybara/queries/sibling_query.rb +2 -1
  22. data/lib/capybara/queries/text_query.rb +1 -1
  23. data/lib/capybara/rack_test/browser.rb +63 -8
  24. data/lib/capybara/rack_test/driver.rb +4 -4
  25. data/lib/capybara/rack_test/form.rb +29 -7
  26. data/lib/capybara/rack_test/node.rb +10 -7
  27. data/lib/capybara/registration_container.rb +0 -3
  28. data/lib/capybara/registrations/drivers.rb +3 -3
  29. data/lib/capybara/registrations/servers.rb +17 -9
  30. data/lib/capybara/rspec/matcher_proxies.rb +3 -3
  31. data/lib/capybara/rspec/matchers/have_selector.rb +5 -5
  32. data/lib/capybara/rspec/matchers.rb +14 -14
  33. data/lib/capybara/selector/builders/css_builder.rb +1 -1
  34. data/lib/capybara/selector/builders/xpath_builder.rb +1 -1
  35. data/lib/capybara/selector/css.rb +1 -1
  36. data/lib/capybara/selector/definition/button.rb +9 -4
  37. data/lib/capybara/selector/definition/checkbox.rb +1 -1
  38. data/lib/capybara/selector/definition/file_field.rb +1 -1
  39. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  40. data/lib/capybara/selector/definition/radio_button.rb +1 -1
  41. data/lib/capybara/selector/definition.rb +4 -2
  42. data/lib/capybara/selector/filter_set.rb +4 -7
  43. data/lib/capybara/selector/regexp_disassembler.rb +2 -5
  44. data/lib/capybara/selector/selector.rb +5 -1
  45. data/lib/capybara/selector.rb +1 -0
  46. data/lib/capybara/selenium/driver.rb +28 -11
  47. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +1 -1
  48. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +1 -1
  49. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
  50. data/lib/capybara/selenium/extensions/html5_drag.rb +2 -4
  51. data/lib/capybara/selenium/logger_suppressor.rb +4 -0
  52. data/lib/capybara/selenium/node.rb +74 -23
  53. data/lib/capybara/selenium/nodes/chrome_node.rb +1 -1
  54. data/lib/capybara/selenium/nodes/edge_node.rb +1 -1
  55. data/lib/capybara/selenium/nodes/firefox_node.rb +3 -3
  56. data/lib/capybara/selenium/nodes/safari_node.rb +4 -4
  57. data/lib/capybara/server/animation_disabler.rb +41 -23
  58. data/lib/capybara/server/middleware.rb +1 -1
  59. data/lib/capybara/session/config.rb +4 -2
  60. data/lib/capybara/session.rb +31 -32
  61. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  62. data/lib/capybara/spec/session/all_spec.rb +9 -13
  63. data/lib/capybara/spec/session/assert_text_spec.rb +17 -17
  64. data/lib/capybara/spec/session/attach_file_spec.rb +6 -0
  65. data/lib/capybara/spec/session/check_spec.rb +10 -0
  66. data/lib/capybara/spec/session/choose_spec.rb +6 -0
  67. data/lib/capybara/spec/session/current_scope_spec.rb +1 -1
  68. data/lib/capybara/spec/session/fill_in_spec.rb +6 -0
  69. data/lib/capybara/spec/session/find_spec.rb +6 -0
  70. data/lib/capybara/spec/session/has_ancestor_spec.rb +2 -2
  71. data/lib/capybara/spec/session/has_any_selectors_spec.rb +4 -0
  72. data/lib/capybara/spec/session/has_button_spec.rb +30 -0
  73. data/lib/capybara/spec/session/has_current_path_spec.rb +2 -2
  74. data/lib/capybara/spec/session/has_field_spec.rb +25 -1
  75. data/lib/capybara/spec/session/has_link_spec.rb +36 -0
  76. data/lib/capybara/spec/session/has_select_spec.rb +10 -4
  77. data/lib/capybara/spec/session/has_selector_spec.rb +15 -0
  78. data/lib/capybara/spec/session/has_text_spec.rb +6 -14
  79. data/lib/capybara/spec/session/node_spec.rb +66 -1
  80. data/lib/capybara/spec/session/reset_session_spec.rb +13 -0
  81. data/lib/capybara/spec/session/scroll_spec.rb +4 -4
  82. data/lib/capybara/spec/session/visit_spec.rb +20 -0
  83. data/lib/capybara/spec/session/window/window_spec.rb +1 -1
  84. data/lib/capybara/spec/session/within_spec.rb +13 -0
  85. data/lib/capybara/spec/spec_helper.rb +12 -5
  86. data/lib/capybara/spec/test_app.rb +91 -14
  87. data/lib/capybara/spec/views/animated.erb +1 -1
  88. data/lib/capybara/spec/views/form.erb +24 -3
  89. data/lib/capybara/spec/views/frame_child.erb +1 -1
  90. data/lib/capybara/spec/views/frame_one.erb +1 -1
  91. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  92. data/lib/capybara/spec/views/frame_two.erb +1 -1
  93. data/lib/capybara/spec/views/initial_alert.erb +2 -1
  94. data/lib/capybara/spec/views/layout.erb +10 -0
  95. data/lib/capybara/spec/views/obscured.erb +1 -1
  96. data/lib/capybara/spec/views/offset.erb +2 -1
  97. data/lib/capybara/spec/views/path.erb +2 -2
  98. data/lib/capybara/spec/views/popup_one.erb +1 -1
  99. data/lib/capybara/spec/views/popup_two.erb +1 -1
  100. data/lib/capybara/spec/views/react.erb +2 -2
  101. data/lib/capybara/spec/views/scroll.erb +2 -1
  102. data/lib/capybara/spec/views/spatial.erb +1 -1
  103. data/lib/capybara/spec/views/with_animation.erb +2 -3
  104. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  105. data/lib/capybara/spec/views/with_dragula.erb +2 -2
  106. data/lib/capybara/spec/views/with_fixed_header_footer.erb +2 -1
  107. data/lib/capybara/spec/views/with_hover.erb +2 -2
  108. data/lib/capybara/spec/views/with_html.erb +3 -3
  109. data/lib/capybara/spec/views/with_jquery_animation.erb +1 -1
  110. data/lib/capybara/spec/views/with_js.erb +2 -3
  111. data/lib/capybara/spec/views/with_jstree.erb +1 -1
  112. data/lib/capybara/spec/views/with_namespace.erb +1 -0
  113. data/lib/capybara/spec/views/with_scope.erb +2 -2
  114. data/lib/capybara/spec/views/with_shadow.erb +31 -0
  115. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  116. data/lib/capybara/spec/views/with_sortable_js.erb +2 -2
  117. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  118. data/lib/capybara/spec/views/with_windows.erb +1 -1
  119. data/lib/capybara/spec/views/within_frames.erb +1 -1
  120. data/lib/capybara/version.rb +1 -1
  121. data/lib/capybara/window.rb +1 -1
  122. data/lib/capybara.rb +23 -24
  123. data/spec/basic_node_spec.rb +16 -3
  124. data/spec/capybara_spec.rb +12 -0
  125. data/spec/counter_spec.rb +35 -0
  126. data/spec/dsl_spec.rb +5 -3
  127. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -2
  128. data/spec/fixtures/selenium_driver_rspec_success.rb +2 -2
  129. data/spec/minitest_spec.rb +4 -0
  130. data/spec/minitest_spec_spec.rb +4 -0
  131. data/spec/per_session_config_spec.rb +1 -1
  132. data/spec/rack_test_spec.rb +28 -10
  133. data/spec/result_spec.rb +32 -35
  134. data/spec/rspec/features_spec.rb +3 -3
  135. data/spec/rspec/scenarios_spec.rb +1 -1
  136. data/spec/rspec/shared_spec_matchers.rb +3 -3
  137. data/spec/rspec_spec.rb +2 -2
  138. data/spec/sauce_spec_chrome.rb +3 -3
  139. data/spec/selector_spec.rb +4 -4
  140. data/spec/selenium_spec_chrome.rb +11 -10
  141. data/spec/selenium_spec_chrome_remote.rb +11 -8
  142. data/spec/selenium_spec_edge.rb +2 -0
  143. data/spec/selenium_spec_firefox.rb +15 -4
  144. data/spec/selenium_spec_firefox_remote.rb +4 -2
  145. data/spec/selenium_spec_ie.rb +6 -7
  146. data/spec/selenium_spec_safari.rb +33 -19
  147. data/spec/server_spec.rb +5 -5
  148. data/spec/shared_selenium_node.rb +0 -4
  149. data/spec/shared_selenium_session.rb +23 -14
  150. data/spec/spec_helper.rb +1 -1
  151. metadata +38 -14
  152. data/lib/capybara/spec/views/with_title.erb +0 -5
@@ -1,5 +1,5 @@
1
-
2
- <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
3
  <head>
4
4
  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
5
5
  <title>with_animation</title>
@@ -79,4 +79,3 @@
79
79
  </a>
80
80
  </body>
81
81
  </html>
82
-
@@ -1,5 +1,5 @@
1
-
2
- <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
3
  <head>
4
4
  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
5
5
  <base href="http://example2.com" />
@@ -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_dragula</title>
@@ -21,4 +22,3 @@
21
22
  </script>
22
23
  </body>
23
24
  </html>
24
-
@@ -1,3 +1,4 @@
1
+ <!DOCTYPE html>
1
2
  <html>
2
3
  <head>
3
4
  <style>
@@ -14,4 +15,4 @@
14
15
  <a href="/">Go to root</a>
15
16
  </div>
16
17
  <footer>My footer</footer>
17
- </body>
18
+ </body>
@@ -1,5 +1,5 @@
1
-
2
- <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
3
  <head>
4
4
  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
5
5
  <title>with_hover</title>
@@ -19,7 +19,7 @@
19
19
 
20
20
  <p class="para" id="first" data-random="abc\def" style="line-height: 25px;">
21
21
  Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
22
- tempor incididunt ut <a href="/with_simple_html" title="awesome title" class="simple">labore</a>
22
+ tempor incididunt ut <a href="/with_simple_html" title="awesome title" class="simple" tabindex="1">labore</a>
23
23
  et dolore magna aliqua. Ut enim ad minim veniam,
24
24
  quis nostrud exercitation <a href="/foo" id="foo" data-test-id="test-foo">ullamco</a> laboris nisi
25
25
  ut aliquip ex ea commodo consequat.
@@ -88,7 +88,7 @@ banana</textarea>
88
88
  </div>
89
89
 
90
90
  <div style="display: none;">
91
- <a id="first_invisble" class="hidden">first hidden link</a>
91
+ <a id="first_invisible" class="hidden">first hidden link</a>
92
92
  </div>
93
93
 
94
94
  <div style="display: none;">
@@ -138,7 +138,7 @@ banana</textarea>
138
138
  Ancestor
139
139
  <div id="child">Child</div>
140
140
  </div>
141
- <div id="ancestor1_sibiling">
141
+ <div id="ancestor1_sibling">
142
142
  ASibling
143
143
  </div>
144
144
  </div>
@@ -1,4 +1,4 @@
1
-
1
+ <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
4
  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
@@ -1,5 +1,5 @@
1
-
2
- <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
3
  <head>
4
4
  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
5
5
  <title>with_js</title>
@@ -160,4 +160,3 @@
160
160
  </script>
161
161
  </body>
162
162
  </html>
163
-
@@ -1,4 +1,4 @@
1
- <!doctype html>
1
+ <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
4
  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
@@ -1,3 +1,4 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
1
2
  <html xmlns="http://www.w3.org/1999/xhtml">
2
3
  <head>
3
4
  <title>Namespace</title>
@@ -35,8 +35,8 @@
35
35
  </ul>
36
36
  </div>
37
37
 
38
- <div id="another_foo">
38
+ <div id="another_foo" onclick="this.innerHTML = 'I was clicked';">
39
39
  <ul>
40
- <li>With Simple HTML: <a href="/">Go</a>
40
+ <li>With Simple HTML: <a href="/">Go</a></li>
41
41
  </ul>
42
42
  </div>
@@ -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.2'
4
+ VERSION = '3.38.0'
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`.
@@ -79,6 +79,7 @@ module Capybara
79
79
  # - **automatic_reload** (Boolean = `true`) - Whether to automatically reload elements as Capybara is waiting.
80
80
  # - **default_max_wait_time** (Numeric = `2`) - The maximum number of seconds to wait for asynchronous processes to finish.
81
81
  # - **default_normalize_ws** (Boolean = `false`) - Whether text predicates and matchers use normalize whitespace behavior.
82
+ # - **default_retry_interval** (Numeric = `0.01`) - The number of seconds to delay the next check in asynchronous processes.
82
83
  # - **default_selector** (`:css`, `:xpath` = `:css`) - Methods which take a selector use the given type by default. See also {Capybara::Selector}.
83
84
  # - **default_set_options** (Hash = `{}`) - The default options passed to {Capybara::Node::Element#set Element#set}.
84
85
  # - **enable_aria_label** (Boolean = `false`) - Whether fields, links, and buttons will match against `aria-label` attribute.
@@ -96,11 +97,12 @@ module Capybara
96
97
  # {Capybara::Session#save_and_open_page save_and_open_page}, or {Capybara::Session#save_and_open_screenshot save_and_open_screenshot}.
97
98
  # - **server** (Symbol = `:default` (which uses puma)) - The name of the registered server to use when running the app under test.
98
99
  # - **server_port** (Integer) - The port Capybara will run the application server on, if not specified a random port will be used.
100
+ # - **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
101
  # - **server_errors** (Array\<Class> = `[Exception]`) - Error classes that should be raised in the tests if they are raised in the server
100
102
  # and {configure raise_server_errors} is `true`.
101
103
  # - **test_id** (Symbol, String, `nil` = `nil`) - Optional attribute to match locator against with built-in selectors along with id.
102
104
  # - **threadsafe** (Boolean = `false`) - Whether sessions can be configured individually.
103
- # - **w3c_click_offset** (Boolean = 'false') - Whether click offsets should be from element center (true) or top left (false)
105
+ # - **w3c_click_offset** (Boolean = 'true') - Whether click offsets should be from element center (true) or top left (false)
104
106
  #
105
107
  # #### DSL Options
106
108
  #
@@ -385,26 +387,21 @@ module Capybara
385
387
  # @return [Nokogiri::HTML::Document] HTML document
386
388
  #
387
389
  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
390
+ # Nokogiri >= 1.12.0 or Nokogumbo installed and allowed for use
391
+ html_parser, using_html5 = if defined?(Nokogiri::HTML5) && Capybara.use_html5_parsing
392
+ [Nokogiri::HTML5, true]
399
393
  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
394
+ [defined?(Nokogiri::HTML4) ? Nokogiri::HTML4 : Nokogiri::HTML, false]
395
+ end
396
+
397
+ html_parser.parse(html).tap do |document|
398
+ document.xpath('//template').each do |template|
399
+ # template elements content is not part of the document
400
+ template.inner_html = ''
401
+ end
402
+ document.xpath('//textarea').each do |textarea|
403
+ # The Nokogiri HTML5 parser already returns spec compliant contents
404
+ textarea['_capybara_raw_value'] = using_html5 ? textarea.content : textarea.content.delete_prefix("\n")
408
405
  end
409
406
  end
410
407
  end
@@ -467,6 +464,7 @@ module Capybara
467
464
  require 'capybara/queries/ancestor_query'
468
465
  require 'capybara/queries/sibling_query'
469
466
  require 'capybara/queries/style_query'
467
+ require 'capybara/queries/active_element_query'
470
468
 
471
469
  require 'capybara/node/finders'
472
470
  require 'capybara/node/matchers'
@@ -499,6 +497,7 @@ Capybara.configure do |config|
499
497
  config.server = :default
500
498
  config.default_selector = :css
501
499
  config.default_max_wait_time = 2
500
+ config.default_retry_interval = 0.01
502
501
  config.ignore_hidden_elements = true
503
502
  config.default_host = 'http://www.example.com'
504
503
  config.automatic_reload = true
@@ -516,6 +515,6 @@ Capybara.configure do |config|
516
515
  config.test_id = nil
517
516
  config.predicates_wait = true
518
517
  config.default_normalize_ws = false
519
- config.allow_gumbo = false
520
- config.w3c_click_offset = false
518
+ config.use_html5_parsing = false
519
+ config.w3c_click_offset = true
521
520
  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
 
@@ -15,6 +15,18 @@ RSpec.describe Capybara do
15
15
  end
16
16
  end
17
17
 
18
+ describe 'default_retry_interval' do
19
+ before { @previous_default_interval = described_class.default_retry_interval }
20
+
21
+ after { described_class.default_retry_interval = @previous_default_interval } # rubocop:disable RSpec/InstanceVariable
22
+
23
+ it 'should be changeable' do
24
+ expect(described_class.default_retry_interval).not_to eq(0.1)
25
+ described_class.default_retry_interval = 0.1
26
+ expect(described_class.default_retry_interval).to eq(0.1)
27
+ end
28
+ end
29
+
18
30
  describe '.register_driver' do
19
31
  it 'should add a new driver' do
20
32
  described_class.register_driver :schmoo do |app|
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Capybara::Server::Middleware::Counter do
6
+ let(:counter) { described_class.new }
7
+ let(:uri) { '/example' }
8
+
9
+ describe '#increment' do
10
+ it 'successfully' do
11
+ counter.increment(uri)
12
+ expect(counter).to be_positive
13
+ end
14
+ end
15
+
16
+ describe '#decrement' do
17
+ before do
18
+ counter.increment(uri)
19
+ end
20
+
21
+ context 'successfully' do
22
+ it 'with same uri' do
23
+ expect(counter).to be_positive
24
+ counter.decrement(uri)
25
+ expect(counter).not_to be_positive
26
+ end
27
+
28
+ it 'with changed uri' do
29
+ expect(counter).to be_positive
30
+ counter.decrement('/')
31
+ expect(counter).not_to be_positive
32
+ end
33
+ end
34
+ end
35
+ end
data/spec/dsl_spec.rb CHANGED
@@ -8,13 +8,15 @@ 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/
15
15
  pending "Nokogiri doesn't support case insensitive CSS attribute matchers"
16
16
  when /#click_button should follow permanent redirects that maintain method/
17
17
  pending "Rack < 2 doesn't support 308" if Gem.loaded_specs['rack'].version < Gem::Version.new('2.0.0')
18
+ when /#attach_file with multipart form should send prior hidden field if no file submitted/
19
+ skip 'Rack-test < 2 needs an empty file to detect multipart form' if Gem.loaded_specs['rack-test'].version < Gem::Version.new('2.0.0')
18
20
  end
19
21
  end
20
22
 
@@ -115,7 +117,7 @@ RSpec.describe Capybara::DSL do
115
117
  it 'should yield the passed block' do
116
118
  called = false
117
119
  Capybara.using_driver(:selenium) { called = true }
118
- expect(called).to eq(true)
120
+ expect(called).to be(true)
119
121
  end
120
122
  end
121
123
 
@@ -220,7 +222,7 @@ RSpec.describe Capybara::DSL do
220
222
  it 'should yield the passed block' do
221
223
  called = false
222
224
  Capybara.using_session(:administrator) { called = true }
223
- expect(called).to eq(true)
225
+ expect(called).to be(true)
224
226
  end
225
227
 
226
228
  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
@@ -15,6 +15,10 @@ class MinitestTest < Minitest::Test
15
15
  Capybara.reset_sessions!
16
16
  end
17
17
 
18
+ def self.test_order
19
+ :sorted
20
+ end
21
+
18
22
  def test_assert_text
19
23
  assert_text('Form', normalize_ws: false)
20
24
  assert_no_text('Not on the page')
@@ -16,6 +16,10 @@ class MinitestSpecTest < Minitest::Spec
16
16
  Capybara.reset_sessions!
17
17
  end
18
18
 
19
+ def self.test_order
20
+ :sorted
21
+ end
22
+
19
23
  it 'supports text expectations' do
20
24
  _(page).must_have_text('Form', minimum: 1)
21
25
  _(page).wont_have_text('Not a form')
@@ -12,7 +12,7 @@ RSpec.describe Capybara::SessionConfig do
12
12
  default_selector default_max_wait_time ignore_hidden_elements
13
13
  automatic_reload match exact raise_server_errors visible_text_only
14
14
  automatic_label_click enable_aria_label save_path
15
- asset_host].each do |m|
15
+ asset_host default_retry_interval].each do |m|
16
16
  expect(session.config.public_send(m)).to eq Capybara.public_send(m)
17
17
  end
18
18
  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]
@@ -35,6 +30,8 @@ Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip
35
30
  skip "Nokogiri doesn't support case insensitive CSS attribute matchers"
36
31
  when /#click_button should follow permanent redirects that maintain method/
37
32
  skip "Rack < 2 doesn't support 308" if Gem.loaded_specs['rack'].version < Gem::Version.new('2.0.0')
33
+ when /#attach_file with multipart form should send prior hidden field if no file submitted/
34
+ skip 'Rack-test < 2 needs an empty file to detect multipart form' if Gem.loaded_specs['rack-test'].version < Gem::Version.new('2.0.0')
38
35
  end
39
36
  end
40
37
 
@@ -98,6 +95,12 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
98
95
  session.click_button('Upload Empty')
99
96
  expect(session.html).to include('Successfully ignored empty file field.')
100
97
  end
98
+
99
+ it 'should submit multipart even if no file is submitted' do
100
+ session.visit('/form')
101
+ session.click_button('Upload Empty')
102
+ expect(session.html).to include('Content type was multipart/form-data;')
103
+ end
101
104
  end
102
105
 
103
106
  it 'should not submit an obsolete mime type' do
@@ -153,6 +156,14 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
153
156
  end
154
157
  end
155
158
 
159
+ describe '#active_element' do
160
+ it 'raises an UnsupportedMethodError' do
161
+ session.visit('/form')
162
+
163
+ expect { session.active_element }.to raise_error(Capybara::NotSupportedByDriverError)
164
+ end
165
+ end
166
+
156
167
  describe '#text' do
157
168
  it 'should return original text content for textareas' do
158
169
  session.visit('/with_html')
@@ -213,6 +224,12 @@ RSpec.describe Capybara::RackTest::Driver do
213
224
  expect(driver.current_url).to match %r{/landed$}
214
225
  end
215
226
 
227
+ it 'should not include fragments in the referer header' do
228
+ driver.visit('/header_links#an-anchor')
229
+ driver.find_xpath('.//input').first.click
230
+ expect(driver.request.get_header('HTTP_REFERER')).to eq('http://www.example.com/header_links')
231
+ end
232
+
216
233
  it 'is possible to not follow redirects' do
217
234
  driver = described_class.new(TestApp, follow_redirects: false)
218
235
 
@@ -256,11 +273,12 @@ RSpec.describe Capybara::RackTest::Driver do
256
273
  end
257
274
 
258
275
  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
276
+ it 'should use HTML5 parsing' do
277
+ skip 'Only valid if Nokogiri >= 1.12.0 or gumbo is included' unless defined? Nokogiri::HTML5
278
+ Capybara.use_html5_parsing = true
279
+ allow(Nokogiri::HTML5).to receive(:parse).and_call_original
262
280
  Capybara.string('<div id=test_div></div>')
263
- expect(Nokogiri).to have_received(:HTML5)
281
+ expect(Nokogiri::HTML5).to have_received(:parse)
264
282
  end
265
283
  end
266
284