capybara 2.5.0 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. checksums.yaml +5 -5
  2. data/.yard/templates_custom/default/class/html/selectors.erb +38 -0
  3. data/.yard/templates_custom/default/class/html/setup.rb +17 -0
  4. data/.yard/yard_extensions.rb +78 -0
  5. data/.yardopts +1 -0
  6. data/History.md +413 -10
  7. data/License.txt +1 -1
  8. data/README.md +237 -130
  9. data/lib/capybara/config.rb +132 -0
  10. data/lib/capybara/cucumber.rb +3 -1
  11. data/lib/capybara/driver/base.rb +27 -6
  12. data/lib/capybara/driver/node.rb +14 -5
  13. data/lib/capybara/dsl.rb +2 -3
  14. data/lib/capybara/helpers.rb +13 -65
  15. data/lib/capybara/minitest/spec.rb +177 -0
  16. data/lib/capybara/minitest.rb +278 -0
  17. data/lib/capybara/node/actions.rb +180 -24
  18. data/lib/capybara/node/base.rb +17 -5
  19. data/lib/capybara/node/document.rb +5 -0
  20. data/lib/capybara/node/document_matchers.rb +15 -14
  21. data/lib/capybara/node/element.rb +55 -7
  22. data/lib/capybara/node/finders.rb +179 -67
  23. data/lib/capybara/node/matchers.rb +301 -105
  24. data/lib/capybara/node/simple.rb +15 -4
  25. data/lib/capybara/queries/ancestor_query.rb +25 -0
  26. data/lib/capybara/queries/base_query.rb +69 -3
  27. data/lib/capybara/queries/current_path_query.rb +17 -8
  28. data/lib/capybara/queries/match_query.rb +19 -0
  29. data/lib/capybara/queries/selector_query.rb +251 -0
  30. data/lib/capybara/queries/sibling_query.rb +25 -0
  31. data/lib/capybara/queries/text_query.rb +67 -16
  32. data/lib/capybara/queries/title_query.rb +4 -2
  33. data/lib/capybara/query.rb +3 -131
  34. data/lib/capybara/rack_test/browser.rb +14 -5
  35. data/lib/capybara/rack_test/css_handlers.rb +1 -0
  36. data/lib/capybara/rack_test/driver.rb +15 -8
  37. data/lib/capybara/rack_test/form.rb +34 -12
  38. data/lib/capybara/rack_test/node.rb +29 -12
  39. data/lib/capybara/rails.rb +3 -3
  40. data/lib/capybara/result.rb +104 -9
  41. data/lib/capybara/rspec/compound.rb +95 -0
  42. data/lib/capybara/rspec/features.rb +17 -6
  43. data/lib/capybara/rspec/matcher_proxies.rb +45 -0
  44. data/lib/capybara/rspec/matchers.rb +199 -80
  45. data/lib/capybara/rspec.rb +4 -2
  46. data/lib/capybara/selector/css.rb +30 -0
  47. data/lib/capybara/selector/filter.rb +20 -0
  48. data/lib/capybara/selector/filter_set.rb +74 -0
  49. data/lib/capybara/selector/filters/base.rb +33 -0
  50. data/lib/capybara/selector/filters/expression_filter.rb +40 -0
  51. data/lib/capybara/selector/filters/node_filter.rb +27 -0
  52. data/lib/capybara/selector/selector.rb +276 -0
  53. data/lib/capybara/selector.rb +452 -157
  54. data/lib/capybara/selenium/driver.rb +282 -81
  55. data/lib/capybara/selenium/node.rb +144 -46
  56. data/lib/capybara/server.rb +59 -16
  57. data/lib/capybara/session/config.rb +114 -0
  58. data/lib/capybara/session/matchers.rb +29 -19
  59. data/lib/capybara/session.rb +378 -143
  60. data/lib/capybara/spec/fixtures/no_extension +1 -0
  61. data/lib/capybara/spec/public/jquery-ui.js +13 -791
  62. data/lib/capybara/spec/public/jquery.js +4 -9045
  63. data/lib/capybara/spec/public/test.js +45 -11
  64. data/lib/capybara/spec/session/accept_alert_spec.rb +30 -7
  65. data/lib/capybara/spec/session/accept_confirm_spec.rb +14 -2
  66. data/lib/capybara/spec/session/accept_prompt_spec.rb +35 -6
  67. data/lib/capybara/spec/session/all_spec.rb +45 -32
  68. data/lib/capybara/spec/session/ancestor_spec.rb +85 -0
  69. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +110 -0
  70. data/lib/capybara/spec/session/assert_current_path.rb +15 -2
  71. data/lib/capybara/spec/session/assert_selector.rb +29 -28
  72. data/lib/capybara/spec/session/assert_text.rb +59 -20
  73. data/lib/capybara/spec/session/assert_title.rb +25 -11
  74. data/lib/capybara/spec/session/attach_file_spec.rb +42 -4
  75. data/lib/capybara/spec/session/body_spec.rb +1 -0
  76. data/lib/capybara/spec/session/check_spec.rb +90 -14
  77. data/lib/capybara/spec/session/choose_spec.rb +31 -5
  78. data/lib/capybara/spec/session/click_button_spec.rb +20 -9
  79. data/lib/capybara/spec/session/click_link_or_button_spec.rb +15 -9
  80. data/lib/capybara/spec/session/click_link_spec.rb +39 -15
  81. data/lib/capybara/spec/session/current_scope_spec.rb +2 -1
  82. data/lib/capybara/spec/session/current_url_spec.rb +12 -3
  83. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +6 -5
  84. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +4 -3
  85. data/lib/capybara/spec/session/element/assert_match_selector.rb +36 -0
  86. data/lib/capybara/spec/session/element/match_css_spec.rb +23 -0
  87. data/lib/capybara/spec/session/element/match_xpath_spec.rb +23 -0
  88. data/lib/capybara/spec/session/element/matches_selector_spec.rb +106 -0
  89. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +22 -0
  90. data/lib/capybara/spec/session/evaluate_script_spec.rb +23 -1
  91. data/lib/capybara/spec/session/execute_script_spec.rb +22 -3
  92. data/lib/capybara/spec/session/fill_in_spec.rb +50 -32
  93. data/lib/capybara/spec/session/find_button_spec.rb +43 -2
  94. data/lib/capybara/spec/session/find_by_id_spec.rb +3 -2
  95. data/lib/capybara/spec/session/find_field_spec.rb +42 -6
  96. data/lib/capybara/spec/session/find_link_spec.rb +22 -3
  97. data/lib/capybara/spec/session/find_spec.rb +103 -57
  98. data/lib/capybara/spec/session/first_spec.rb +34 -18
  99. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +103 -0
  100. data/lib/capybara/spec/session/{within_frame_spec.rb → frame/within_frame_spec.rb} +44 -2
  101. data/lib/capybara/spec/session/go_back_spec.rb +2 -1
  102. data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
  103. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  104. data/lib/capybara/spec/session/has_button_spec.rb +17 -8
  105. data/lib/capybara/spec/session/has_css_spec.rb +85 -73
  106. data/lib/capybara/spec/session/has_current_path_spec.rb +91 -7
  107. data/lib/capybara/spec/session/has_field_spec.rb +93 -58
  108. data/lib/capybara/spec/session/has_link_spec.rb +9 -8
  109. data/lib/capybara/spec/session/has_none_selectors_spec.rb +76 -0
  110. data/lib/capybara/spec/session/has_select_spec.rb +159 -59
  111. data/lib/capybara/spec/session/has_selector_spec.rb +64 -28
  112. data/lib/capybara/spec/session/has_table_spec.rb +1 -0
  113. data/lib/capybara/spec/session/has_text_spec.rb +27 -12
  114. data/lib/capybara/spec/session/has_title_spec.rb +22 -4
  115. data/lib/capybara/spec/session/has_xpath_spec.rb +32 -29
  116. data/lib/capybara/spec/session/headers.rb +2 -1
  117. data/lib/capybara/spec/session/html_spec.rb +4 -3
  118. data/lib/capybara/spec/session/node_spec.rb +198 -38
  119. data/lib/capybara/spec/session/refresh_spec.rb +28 -0
  120. data/lib/capybara/spec/session/reset_session_spec.rb +46 -5
  121. data/lib/capybara/spec/session/response_code.rb +2 -1
  122. data/lib/capybara/spec/session/save_and_open_page_spec.rb +1 -0
  123. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +6 -5
  124. data/lib/capybara/spec/session/save_page_spec.rb +34 -2
  125. data/lib/capybara/spec/session/save_screenshot_spec.rb +31 -1
  126. data/lib/capybara/spec/session/screenshot_spec.rb +4 -2
  127. data/lib/capybara/spec/session/select_spec.rb +34 -32
  128. data/lib/capybara/spec/session/selectors_spec.rb +65 -0
  129. data/lib/capybara/spec/session/sibling_spec.rb +52 -0
  130. data/lib/capybara/spec/session/text_spec.rb +4 -4
  131. data/lib/capybara/spec/session/title_spec.rb +2 -1
  132. data/lib/capybara/spec/session/uncheck_spec.rb +42 -2
  133. data/lib/capybara/spec/session/unselect_spec.rb +17 -16
  134. data/lib/capybara/spec/session/visit_spec.rb +77 -2
  135. data/lib/capybara/spec/session/window/become_closed_spec.rb +12 -11
  136. data/lib/capybara/spec/session/window/current_window_spec.rb +1 -0
  137. data/lib/capybara/spec/session/window/open_new_window_spec.rb +1 -0
  138. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +16 -11
  139. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +7 -4
  140. data/lib/capybara/spec/session/window/window_spec.rb +36 -29
  141. data/lib/capybara/spec/session/window/windows_spec.rb +1 -0
  142. data/lib/capybara/spec/session/window/within_window_spec.rb +31 -7
  143. data/lib/capybara/spec/session/within_spec.rb +14 -6
  144. data/lib/capybara/spec/spec_helper.rb +37 -4
  145. data/lib/capybara/spec/test_app.rb +15 -3
  146. data/lib/capybara/spec/views/buttons.erb +1 -0
  147. data/lib/capybara/spec/views/fieldsets.erb +2 -1
  148. data/lib/capybara/spec/views/form.erb +169 -9
  149. data/lib/capybara/spec/views/frame_child.erb +10 -2
  150. data/lib/capybara/spec/views/frame_one.erb +2 -1
  151. data/lib/capybara/spec/views/frame_parent.erb +3 -2
  152. data/lib/capybara/spec/views/frame_two.erb +2 -1
  153. data/lib/capybara/spec/views/header_links.erb +1 -0
  154. data/lib/capybara/spec/views/host_links.erb +1 -0
  155. data/lib/capybara/spec/views/initial_alert.erb +10 -0
  156. data/lib/capybara/spec/views/path.erb +1 -0
  157. data/lib/capybara/spec/views/popup_one.erb +1 -0
  158. data/lib/capybara/spec/views/popup_two.erb +1 -0
  159. data/lib/capybara/spec/views/postback.erb +2 -1
  160. data/lib/capybara/spec/views/tables.erb +1 -0
  161. data/lib/capybara/spec/views/with_base_tag.erb +1 -0
  162. data/lib/capybara/spec/views/with_count.erb +2 -1
  163. data/lib/capybara/spec/views/with_fixed_header_footer.erb +17 -0
  164. data/lib/capybara/spec/views/with_hover.erb +7 -1
  165. data/lib/capybara/spec/views/with_html.erb +40 -2
  166. data/lib/capybara/spec/views/with_html_entities.erb +1 -0
  167. data/lib/capybara/spec/views/with_js.erb +32 -1
  168. data/lib/capybara/spec/views/with_scope.erb +1 -0
  169. data/lib/capybara/spec/views/with_simple_html.erb +2 -1
  170. data/lib/capybara/spec/views/with_slow_unload.erb +17 -0
  171. data/lib/capybara/spec/views/with_title.erb +2 -1
  172. data/lib/capybara/spec/views/with_unload_alert.erb +14 -0
  173. data/lib/capybara/spec/views/with_windows.erb +7 -0
  174. data/lib/capybara/spec/views/within_frames.erb +3 -2
  175. data/lib/capybara/version.rb +2 -1
  176. data/lib/capybara/window.rb +20 -3
  177. data/lib/capybara.rb +189 -93
  178. data/spec/basic_node_spec.rb +7 -6
  179. data/spec/capybara_spec.rb +90 -4
  180. data/spec/dsl_spec.rb +3 -1
  181. data/spec/filter_set_spec.rb +28 -0
  182. data/spec/fixtures/capybara.csv +1 -0
  183. data/spec/fixtures/selenium_driver_rspec_failure.rb +5 -1
  184. data/spec/fixtures/selenium_driver_rspec_success.rb +5 -1
  185. data/spec/minitest_spec.rb +130 -0
  186. data/spec/minitest_spec_spec.rb +135 -0
  187. data/spec/per_session_config_spec.rb +67 -0
  188. data/spec/rack_test_spec.rb +50 -7
  189. data/spec/result_spec.rb +76 -0
  190. data/spec/rspec/features_spec.rb +21 -8
  191. data/spec/rspec/scenarios_spec.rb +21 -0
  192. data/spec/rspec/{matchers_spec.rb → shared_spec_matchers.rb} +160 -54
  193. data/spec/rspec/views_spec.rb +5 -0
  194. data/spec/rspec_matchers_spec.rb +46 -0
  195. data/spec/rspec_spec.rb +79 -1
  196. data/spec/selector_spec.rb +199 -0
  197. data/spec/selenium_spec_chrome.rb +54 -9
  198. data/spec/selenium_spec_firefox.rb +68 -0
  199. data/spec/selenium_spec_marionette.rb +127 -0
  200. data/spec/server_spec.rb +102 -14
  201. data/spec/session_spec.rb +54 -0
  202. data/spec/shared_selenium_session.rb +215 -0
  203. data/spec/spec_helper.rb +7 -0
  204. metadata +140 -15
  205. data/spec/selenium_spec.rb +0 -128
data/lib/capybara.rb CHANGED
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  require 'timeout'
2
3
  require 'nokogiri'
3
4
  require 'xpath'
5
+ require 'forwardable'
6
+ require 'capybara/config'
4
7
 
5
8
  module Capybara
6
9
  class CapybaraError < StandardError; end
@@ -18,13 +21,41 @@ module Capybara
18
21
  class WindowError < CapybaraError; end
19
22
  class ReadOnlyElementError < CapybaraError; end
20
23
 
24
+
21
25
  class << self
22
- attr_accessor :asset_host, :app_host, :run_server, :default_host, :always_include_port
23
- attr_accessor :server_port, :exact, :match, :exact_options, :visible_text_only
24
- attr_accessor :default_selector, :default_max_wait_time, :ignore_hidden_elements
25
- attr_accessor :save_and_open_page_path, :wait_on_first_by_default, :automatic_reload, :raise_server_errors, :server_errors
26
- attr_writer :default_driver, :current_driver, :javascript_driver, :session_name, :server_host
27
- attr_accessor :app
26
+ extend Forwardable
27
+
28
+ # DelegateCapybara global configurations
29
+ # @!method app
30
+ # See {Capybara.configure}
31
+ # @!method reuse_server
32
+ # See {Capybara.configure}
33
+ # @!method threadsafe
34
+ # See {Capybara.configure}
35
+ # @!method server
36
+ # See {Capybara.configure}
37
+ # @!method default_driver
38
+ # See {Capybara.configure}
39
+ # @!method javascript_driver
40
+ # See {Capybara.configure}
41
+ Config::OPTIONS.each do |method|
42
+ def_delegators :config, method, "#{method}="
43
+ end
44
+
45
+ # Delegate Capybara global configurations
46
+ # @!method default_selector
47
+ # See {Capybara.configure}
48
+ # @!method default_max_wait_time
49
+ # See {Capybara.configure}
50
+ # @!method app_host
51
+ # See {Capybara.configure}
52
+ # @!method always_include_port
53
+ # See {Capybara.configure}
54
+ # @!method wait_on_first_by_default
55
+ # See {Capybara.configure}
56
+ SessionConfig::OPTIONS.each do |method|
57
+ def_delegators :config, method, "#{method}="
58
+ end
28
59
 
29
60
  ##
30
61
  #
@@ -37,27 +68,33 @@ module Capybara
37
68
  #
38
69
  # === Configurable options
39
70
  #
40
- # [app_host = String] The default host to use when giving a relative URL to visit
41
- # [always_include_port = Boolean] Whether the Rack server's port should automatically be inserted into every visited URL (Default: false)
42
- # [asset_host = String] Where dynamic assets are hosted - will be prepended to relative asset locations if present (Default: nil)
43
- # [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
44
- # [raise_server_errors = Boolean] Should errors raised in the server be raised in the tests? (Default: true)
45
- # [server_errors = Array\<Class\>] Error classes that should be raised in the tests if they are raised in the server and Capybara.raise_server_errors is true (Default: [StandardError])
46
- # [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: :css)
47
- # [default_max_wait_time = Numeric] The maximum number of seconds to wait for asynchronous processes to finish (Default: 2)
48
- # [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: true)
49
- # [automatic_reload = Boolean] Whether to automatically reload elements as Capybara is waiting (Default: true)
50
- # [save_and_open_page_path = String] Where to put pages saved through save_and_open_page (Default: Dir.pwd)
51
- # [wait_on_first_by_default = Boolean] Whether Node#first defaults to Capybara waiting behavior for at least 1 element to match (Default: false)
71
+ # [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
72
+ # [always_include_port = Boolean] Whether the Rack server's port should automatically be inserted into every visited URL unless another port is explicitly specified (Default: false)
73
+ # [asset_host = String] Where dynamic assets are hosted - will be prepended to relative asset locations if present (Default: nil)
74
+ # [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
75
+ # [raise_server_errors = Boolean] Should errors raised in the server be raised in the tests? (Default: true)
76
+ # [server_errors = Array\<Class\>] Error classes that should be raised in the tests if they are raised in the server and Capybara.raise_server_errors is true (Default: [StandardError])
77
+ # [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: :css)
78
+ # [default_max_wait_time = Numeric] The maximum number of seconds to wait for asynchronous processes to finish (Default: 2)
79
+ # [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: true)
80
+ # [automatic_reload = Boolean] Whether to automatically reload elements as Capybara is waiting (Default: true)
81
+ # [save_path = String] Where to put pages saved through save_(page|screenshot), save_and_open_(page|screenshot) (Default: Dir.pwd)
82
+ # [wait_on_first_by_default = Boolean] Whether Node#first defaults to Capybara waiting behavior for at least 1 element to match (Default: false)
83
+ # [automatic_label_click = Boolean] Whether Node#choose, Node#check, Node#uncheck will attempt to click the associated label element if the checkbox/radio button are non-visible (Default: false)
84
+ # [enable_aria_label = Boolean] Whether fields, links, and buttons will match against aria-label attribute (Default: false)
85
+ # [reuse_server = Boolean] Reuse the server thread between multiple sessions using the same app object (Default: true)
86
+ # [threadsafe = Boolean] Whether sessions can be configured individually (Default: false)
87
+ # [server = Symbol] The name of the registered server to use when running the app under test (Default: :webrick)
88
+ #
52
89
  # === DSL Options
53
90
  #
54
91
  # when using capybara/dsl, the following options are also available:
55
92
  #
56
- # [default_driver = Symbol] The name of the driver to use by default. (Default: :rack_test)
57
- # [javascript_driver = Symbol] The name of a driver to use for JavaScript enabled tests. (Default: :selenium)
93
+ # [default_driver = Symbol] The name of the driver to use by default. (Default: :rack_test)
94
+ # [javascript_driver = Symbol] The name of a driver to use for JavaScript enabled tests. (Default: :selenium)
58
95
  #
59
96
  def configure
60
- yield self
97
+ yield ConfigureDeprecator.new(config)
61
98
  end
62
99
 
63
100
  ##
@@ -77,6 +114,26 @@ module Capybara
77
114
  drivers[name] = block
78
115
  end
79
116
 
117
+ ##
118
+ #
119
+ # Register a new server for Capybara.
120
+ #
121
+ # Capybara.register_server :webrick do |app, port, host|
122
+ # require 'rack/handler/webrick'
123
+ # Rack::Handler::WEBrick.run(app, ...)
124
+ # end
125
+ #
126
+ # @param [Symbol] name The name of the new driver
127
+ # @yield [app, port, host] This block takes a rack app and a port and returns a rack server listening on that port
128
+ # @yieldparam [<Rack>] app The rack application that this server will contain.
129
+ # @yieldparam port The port number the server should listen on
130
+ # @yieldparam host The host/ip to bind to
131
+ # @yieldreturn [Capybara::Driver::Base] A Capybara driver instance
132
+ #
133
+ def register_server(name, &block)
134
+ servers[name.to_sym] = block
135
+ end
136
+
80
137
  ##
81
138
  #
82
139
  # Add a new selector to Capybara. Selectors can be used by various methods in Capybara
@@ -109,29 +166,30 @@ module Capybara
109
166
  Capybara::Selector.add(name, &block)
110
167
  end
111
168
 
112
- def drivers
113
- @drivers ||= {}
114
- end
115
-
116
169
  ##
117
170
  #
118
- # Register a proc that Capybara will call to run the Rack application.
171
+ # Modify a selector previously created by {Capybara.add_selector}.
172
+ # For example, adding a new filter to the :button selector to filter based on
173
+ # button style (a class) might look like this
119
174
  #
120
- # Capybara.server do |app, port|
121
- # require 'rack/handler/mongrel'
122
- # Rack::Handler::Mongrel.run(app, :Port => port)
175
+ # Capybara.modify_selector(:button) do
176
+ # filter (:style, valid_values: [:primary, :secondary]) { |node, style| node[:class].split.include? "btn-#{style}" }
123
177
  # end
124
178
  #
125
- # By default, Capybara will try to run webrick.
126
179
  #
127
- # @yield [app, port] This block receives a rack app and port and should run a Rack handler
180
+ # @param [Symbol] name The name of the selector to modify
181
+ # @yield A block executed in the context of the existing {Capybara::Selector}
128
182
  #
129
- def server(&block)
130
- if block_given?
131
- @server = block
132
- else
133
- @server
134
- end
183
+ def modify_selector(name, &block)
184
+ Capybara::Selector.update(name, &block)
185
+ end
186
+
187
+ def drivers
188
+ @drivers ||= {}
189
+ end
190
+
191
+ def servers
192
+ @servers ||= {}
135
193
  end
136
194
 
137
195
  ##
@@ -140,7 +198,16 @@ module Capybara
140
198
  # in a {Capybara::Node::Simple} which exposes all {Capybara::Node::Matchers},
141
199
  # {Capybara::Node::Finders} and {Capybara::Node::DocumentMatchers}. This allows you to query
142
200
  # any string containing HTML in the exact same way you would query the current document in a Capybara
143
- # session. For example:
201
+ # session.
202
+ #
203
+ # Example: A single element
204
+ #
205
+ # node = Capybara.string('<a href="foo">bar</a>')
206
+ # anchor = node.first('a')
207
+ # anchor[:href] #=> 'foo'
208
+ # anchor.text #=> 'bar'
209
+ #
210
+ # Example: Multiple elements
144
211
  #
145
212
  # node = Capybara.string <<-HTML
146
213
  # <ul>
@@ -150,7 +217,7 @@ module Capybara
150
217
  # HTML
151
218
  #
152
219
  # node.find('#projects').text # => 'Projects'
153
- # node.has_selector?('li#home', :text => 'Home')
220
+ # node.has_selector?('li#home', text: 'Home')
154
221
  # node.has_selector?('#projects')
155
222
  # node.find('ul').find('li:first-child').text # => 'Home'
156
223
  #
@@ -168,19 +235,10 @@ module Capybara
168
235
  # manually.
169
236
  #
170
237
  # @param [Rack Application] app The rack application to run
171
- # @param [Fixnum] port The port to run the application on
238
+ # @param [Integer] port The port to run the application on
172
239
  #
173
240
  def run_default_server(app, port)
174
- require 'rack/handler/webrick'
175
- Rack::Handler::WEBrick.run(app, :Host => server_host, :Port => port, :AccessLog => [], :Logger => WEBrick::Log::new(nil, 0))
176
- end
177
-
178
- ##
179
- #
180
- # @return [Symbol] The name of the driver to use by default
181
- #
182
- def default_driver
183
- @default_driver || :rack_test
241
+ servers[:webrick].call(app, port, server_host)
184
242
  end
185
243
 
186
244
  ##
@@ -188,16 +246,20 @@ module Capybara
188
246
  # @return [Symbol] The name of the driver currently in use
189
247
  #
190
248
  def current_driver
191
- @current_driver || default_driver
249
+ if threadsafe
250
+ Thread.current['capybara_current_driver']
251
+ else
252
+ @current_driver
253
+ end || default_driver
192
254
  end
193
255
  alias_method :mode, :current_driver
194
256
 
195
- ##
196
- #
197
- # @return [Symbol] The name of the driver used when JavaScript is needed
198
- #
199
- def javascript_driver
200
- @javascript_driver || :selenium
257
+ def current_driver=(name)
258
+ if threadsafe
259
+ Thread.current['capybara_current_driver'] = name
260
+ else
261
+ @current_driver = name
262
+ end
201
263
  end
202
264
 
203
265
  ##
@@ -205,7 +267,7 @@ module Capybara
205
267
  # Use the default driver as the current driver
206
268
  #
207
269
  def use_default_driver
208
- @current_driver = nil
270
+ self.current_driver = nil
209
271
  end
210
272
 
211
273
  ##
@@ -217,15 +279,7 @@ module Capybara
217
279
  Capybara.current_driver = driver
218
280
  yield
219
281
  ensure
220
- @current_driver = previous_driver
221
- end
222
-
223
- ##
224
- #
225
- # @return [String] The IP address bound by default server
226
- #
227
- def server_host
228
- @server_host || '127.0.0.1'
282
+ self.current_driver = previous_driver
229
283
  end
230
284
 
231
285
  ##
@@ -256,7 +310,8 @@ module Capybara
256
310
  # as cookies.
257
311
  #
258
312
  def reset_sessions!
259
- session_pool.each { |mode, session| session.reset! }
313
+ #reset in reverse so sessions that started servers are reset last
314
+ session_pool.reverse_each { |_mode, session| session.reset! }
260
315
  end
261
316
  alias_method :reset!, :reset_sessions!
262
317
 
@@ -267,7 +322,19 @@ module Capybara
267
322
  # @return [Symbol] The name of the currently used session.
268
323
  #
269
324
  def session_name
270
- @session_name ||= :default
325
+ if threadsafe
326
+ Thread.current['capybara_session_name'] ||= :default
327
+ else
328
+ @session_name ||= :default
329
+ end
330
+ end
331
+
332
+ def session_name=(name)
333
+ if threadsafe
334
+ Thread.current['capybara_session_name'] = name
335
+ else
336
+ @session_name = name
337
+ end
271
338
  end
272
339
 
273
340
  ##
@@ -275,11 +342,19 @@ module Capybara
275
342
  # Yield a block using a specific session name.
276
343
  #
277
344
  def using_session(name)
278
- previous_session_name = self.session_name
345
+ previous_session_info = {
346
+ session_name: session_name,
347
+ current_driver: current_driver,
348
+ app: app
349
+ }
279
350
  self.session_name = name
280
351
  yield
281
352
  ensure
282
- self.session_name = previous_session_name
353
+ self.session_name = previous_session_info[:session_name]
354
+ if threadsafe
355
+ self.current_driver = previous_session_info[:current_driver]
356
+ self.app = previous_session_info[:app]
357
+ end
283
358
  end
284
359
 
285
360
  ##
@@ -292,21 +367,13 @@ module Capybara
292
367
  def HTML(html)
293
368
  Nokogiri::HTML(html).tap do |document|
294
369
  document.xpath('//textarea').each do |textarea|
295
- textarea.content=textarea.content.sub(/\A\n/,'')
370
+ textarea['_capybara_raw_value'] = textarea.content.sub(/\A\n/,'')
296
371
  end
297
372
  end
298
373
  end
299
-
300
- # @deprecated Use default_max_wait_time instead
301
- def default_wait_time
302
- deprecate('default_wait_time', 'default_max_wait_time', true)
303
- default_max_wait_time
304
- end
305
-
306
- # @deprecated Use default_max_wait_time= instead
307
- def default_wait_time=(t)
308
- deprecate('default_wait_time=', 'default_max_wait_time=')
309
- self.default_max_wait_time = t
374
+
375
+ def session_options
376
+ config.session_options
310
377
  end
311
378
 
312
379
  def included(base)
@@ -314,13 +381,10 @@ module Capybara
314
381
  warn "`include Capybara` is deprecated. Please use `include Capybara::DSL` instead."
315
382
  end
316
383
 
317
- def deprecate(method, alternate_method, once=false)
318
- @deprecation_notified ||= {}
319
- warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead" unless once and @deprecation_notified[method]
320
- @deprecation_notified[method]=true
321
- end
322
-
323
384
  private
385
+ def config
386
+ @config ||= Capybara::Config.new
387
+ end
324
388
 
325
389
  def session_pool
326
390
  @session_pool ||= {}
@@ -337,7 +401,6 @@ module Capybara
337
401
 
338
402
  require 'capybara/helpers'
339
403
  require 'capybara/session'
340
- require 'capybara/dsl'
341
404
  require 'capybara/window'
342
405
  require 'capybara/server'
343
406
  require 'capybara/selector'
@@ -345,11 +408,15 @@ module Capybara
345
408
  require 'capybara/version'
346
409
 
347
410
  require 'capybara/queries/base_query'
348
- require 'capybara/query'
411
+ require 'capybara/queries/selector_query'
349
412
  require 'capybara/queries/text_query'
350
413
  require 'capybara/queries/title_query'
351
414
  require 'capybara/queries/current_path_query'
352
-
415
+ require 'capybara/queries/match_query'
416
+ require 'capybara/queries/ancestor_query'
417
+ require 'capybara/queries/sibling_query'
418
+ require 'capybara/query'
419
+
353
420
  require 'capybara/node/finders'
354
421
  require 'capybara/node/matchers'
355
422
  require 'capybara/node/actions'
@@ -372,10 +439,24 @@ module Capybara
372
439
  require 'capybara/selenium/driver'
373
440
  end
374
441
 
442
+ Capybara.register_server :default do |app, port, _host|
443
+ Capybara.run_default_server(app, port)
444
+ end
445
+
446
+ Capybara.register_server :webrick do |app, port, host, options={}|
447
+ require 'rack/handler/webrick'
448
+ Rack::Handler::WEBrick.run(app, {Host: host, Port: port, AccessLog: [], Logger: WEBrick::Log::new(nil, 0)}.merge(options))
449
+ end
450
+
451
+ Capybara.register_server :puma do |app, port, host, options={}|
452
+ require 'rack/handler/puma'
453
+ Rack::Handler::Puma.run(app, {Host: host, Port: port, Threads: "0:4", workers: 0, daemon: false}.merge(options))
454
+ end
455
+
375
456
  Capybara.configure do |config|
376
457
  config.always_include_port = false
377
458
  config.run_server = true
378
- config.server {|app, port| Capybara.run_default_server(app, port)}
459
+ config.server = :default
379
460
  config.default_selector = :css
380
461
  config.default_max_wait_time = 2
381
462
  config.ignore_hidden_elements = true
@@ -383,10 +464,14 @@ Capybara.configure do |config|
383
464
  config.automatic_reload = true
384
465
  config.match = :smart
385
466
  config.exact = false
467
+ config.exact_text = false
386
468
  config.raise_server_errors = true
387
469
  config.server_errors = [StandardError]
388
470
  config.visible_text_only = false
389
471
  config.wait_on_first_by_default = false
472
+ config.automatic_label_click = false
473
+ config.enable_aria_label = false
474
+ config.reuse_server = true
390
475
  end
391
476
 
392
477
  Capybara.register_driver :rack_test do |app|
@@ -396,3 +481,14 @@ end
396
481
  Capybara.register_driver :selenium do |app|
397
482
  Capybara::Selenium::Driver.new(app)
398
483
  end
484
+
485
+ Capybara.register_driver :selenium_chrome do |app|
486
+ Capybara::Selenium::Driver.new(app, :browser => :chrome)
487
+ end
488
+
489
+ Capybara.register_driver :selenium_chrome_headless do |app|
490
+ browser_options = ::Selenium::WebDriver::Chrome::Options.new()
491
+ browser_options.args << '--headless'
492
+ browser_options.args << '--disable-gpu'
493
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
494
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
 
3
4
  RSpec.describe Capybara do
@@ -51,7 +52,7 @@ RSpec.describe Capybara do
51
52
 
52
53
  it "allows using custom matchers" do
53
54
  Capybara.add_selector :lifeform do
54
- xpath { |name| "//option[contains(.,'#{name}')]" }
55
+ xpath { |name| ".//option[contains(.,'#{name}')]" }
55
56
  end
56
57
  expect(string).to have_selector(:id, "page")
57
58
  expect(string).not_to have_selector(:id, 'does-not-exist')
@@ -68,13 +69,13 @@ RSpec.describe Capybara do
68
69
  end
69
70
 
70
71
  it "allows using matchers with text option" do
71
- expect(string).to have_css('h1', :text => 'Totally awesome')
72
- expect(string).not_to have_css('h1', :text => 'Not so awesome')
72
+ expect(string).to have_css('h1', text: 'Totally awesome')
73
+ expect(string).not_to have_css('h1', text: 'Not so awesome')
73
74
  end
74
75
 
75
76
  it "allows finding only visible nodes" do
76
- expect(string.all(:css, '#secret', :visible => true)).to be_empty
77
- expect(string.all(:css, '#secret', :visible => false).size).to eq(1)
77
+ expect(string.all(:css, '#secret', visible: true)).to be_empty
78
+ expect(string.all(:css, '#secret', visible: false).size).to eq(1)
78
79
  end
79
80
 
80
81
  it "allows finding elements and extracting text from them" do
@@ -100,7 +101,7 @@ RSpec.describe Capybara do
100
101
 
101
102
  it "allows finding elements and checking if they are visible" do
102
103
  expect(string.find('//h1')).to be_visible
103
- expect(string.find(:css, "#secret", :visible => false)).not_to be_visible
104
+ expect(string.find(:css, "#secret", visible: false)).not_to be_visible
104
105
  end
105
106
 
106
107
  it "allows finding elements and checking if they are disabled" do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
 
3
4
  RSpec.describe Capybara do
@@ -13,8 +14,8 @@ RSpec.describe Capybara do
13
14
  end
14
15
 
15
16
  it "should be accesible as the deprecated default_wait_time" do
16
- expect_any_instance_of(Kernel).to receive(:warn).once.with('DEPRECATED: #default_wait_time= is deprecated, please use #default_max_wait_time= instead')
17
- expect_any_instance_of(Kernel).to receive(:warn).once.with('DEPRECATED: #default_wait_time is deprecated, please use #default_max_wait_time instead')
17
+ expect(Capybara.send(:config)).to receive(:warn).ordered.with('DEPRECATED: #default_wait_time= is deprecated, please use #default_max_wait_time= instead')
18
+ expect(Capybara.send(:config)).to receive(:warn).ordered.with('DEPRECATED: #default_wait_time is deprecated, please use #default_max_wait_time instead')
18
19
  @previous_default_time = Capybara.default_max_wait_time
19
20
  Capybara.default_wait_time = 5
20
21
  expect(Capybara.default_wait_time).to eq(5)
@@ -33,9 +34,24 @@ RSpec.describe Capybara do
33
34
  end
34
35
  end
35
36
 
37
+ describe '.register_server' do
38
+ it "should add a new server" do
39
+ handler = double("handler")
40
+ Capybara.register_server :blob do |app, port, host|
41
+ handler.run
42
+ end
43
+
44
+ expect(Capybara.servers).to have_key(:blob)
45
+ end
46
+ end
47
+
36
48
  describe ".server" do
49
+ before do
50
+ @old_server = Capybara.server
51
+ end
52
+
37
53
  after do
38
- Capybara.server {|app, port| Capybara.run_default_server(app, port)}
54
+ Capybara.server(&@old_server)
39
55
  end
40
56
 
41
57
  it "should default to a proc that calls run_default_server" do
@@ -49,11 +65,81 @@ RSpec.describe Capybara do
49
65
  Capybara.server(&server)
50
66
  expect(Capybara.server).to eq(server)
51
67
  end
68
+
69
+ it "should have :webrick registered" do
70
+ require 'rack/handler/webrick'
71
+ mock_app = double('app')
72
+ Capybara.server = :webrick
73
+ expect(Rack::Handler::WEBrick).to receive(:run)
74
+ Capybara.server.call(mock_app, 8000)
75
+ end
76
+
77
+ it "should have :puma registered" do
78
+ require 'rack/handler/puma'
79
+ mock_app = double('app')
80
+ Capybara.server = :puma
81
+ expect(Rack::Handler::Puma).to receive(:run).with(mock_app, hash_including(Host: nil, Port: 8000))
82
+ Capybara.server.call(mock_app, 8000)
83
+ end
84
+
85
+ it "should pass options to server" do
86
+ require 'rack/handler/puma'
87
+ mock_app = double('app')
88
+ Capybara.server = :puma, { Silent: true }
89
+ expect(Rack::Handler::Puma).to receive(:run).with(mock_app, hash_including(Host: nil, Port: 9000, Silent: true))
90
+ Capybara.server.call(mock_app, 9000)
91
+ end
92
+ end
93
+
94
+ describe 'app_host' do
95
+ after do
96
+ Capybara.app_host = nil
97
+ end
98
+
99
+ it "should warn if not a valid URL" do
100
+ expect { Capybara.app_host = "www.example.com" }.to raise_error(ArgumentError, /Capybara\.app_host should be set to a url/)
101
+ end
102
+
103
+ it "should not warn if a valid URL" do
104
+ expect { Capybara.app_host = "http://www.example.com" }.not_to raise_error
105
+ end
106
+
107
+ it "should not warn if nil" do
108
+ expect { Capybara.app_host = nil }.not_to raise_error
109
+ end
110
+ end
111
+
112
+ describe 'default_host' do
113
+ around do |test|
114
+ old_default = Capybara.default_host
115
+ test.run
116
+ Capybara.default_host = old_default
117
+ end
118
+
119
+ it "should warn if not a valid URL" do
120
+ expect { Capybara.default_host = "www.example.com" }.to raise_error(ArgumentError, /Capybara\.default_host should be set to a url/)
121
+ end
122
+
123
+ it "should not warn if a valid URL" do
124
+ expect { Capybara.default_host = "http://www.example.com" }.not_to raise_error
125
+ end
126
+ end
127
+
128
+ describe "configure" do
129
+ it 'deprecates calling non configuration option methods in configure' do
130
+ expect_any_instance_of(Kernel).to receive(:warn).
131
+ with('Calling register_driver from Capybara.configure is deprecated - please call it on Capybara directly ( Capybara.register_driver(...) )')
132
+ Capybara.configure do |config|
133
+ config.register_driver(:random_name) do
134
+ #just a random block
135
+ end
136
+ end
137
+ end
52
138
  end
53
139
  end
54
140
 
55
141
  RSpec.describe Capybara::Session do
56
- context 'with non-existant driver' do
142
+ context 'with nonexistent driver' do
57
143
  it "should raise an error" do
58
144
  expect {
59
145
  Capybara::Session.new(:quox, TestApp).driver
data/spec/dsl_spec.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'spec_helper'
2
3
  require 'capybara/dsl'
3
4
 
@@ -5,7 +6,7 @@ class TestClass
5
6
  include Capybara::DSL
6
7
  end
7
8
 
8
- Capybara::SpecHelper.run_specs TestClass.new, "DSL", :capybara_skip => [
9
+ Capybara::SpecHelper.run_specs TestClass.new, "DSL", capybara_skip: [
9
10
  :js,
10
11
  :modals,
11
12
  :screenshot,
@@ -15,6 +16,7 @@ Capybara::SpecHelper.run_specs TestClass.new, "DSL", :capybara_skip => [
15
16
  :server,
16
17
  :hover,
17
18
  :about_scheme,
19
+ :psc
18
20
  ]
19
21
 
20
22
  RSpec.describe Capybara::DSL do
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ RSpec.describe Capybara::Selector::FilterSet do
5
+ after do
6
+ Capybara::Selector::FilterSet.remove(:test)
7
+ end
8
+
9
+ it "allows node filters" do
10
+ fs = Capybara::Selector::FilterSet.add(:test) do
11
+ filter(:node_test, :boolean) { |node, value| true }
12
+ expression_filter(:expression_test, :boolean) { |expr, value| true }
13
+ end
14
+
15
+ expect(fs.node_filters.keys).to include(:node_test)
16
+ expect(fs.node_filters.keys).not_to include(:expression_test)
17
+ end
18
+
19
+ it "allows expression filters" do
20
+ fs = Capybara::Selector::FilterSet.add(:test) do
21
+ filter(:node_test, :boolean) { |node, value| true }
22
+ expression_filter(:expression_test, :boolean) { |expr, value| true }
23
+ end
24
+
25
+ expect(fs.expression_filters.keys).to include(:expression_test)
26
+ expect(fs.expression_filters.keys).not_to include(:node_test)
27
+ end
28
+ end
@@ -0,0 +1 @@
1
+ test, mime-type, file