capybara 1.1.4 → 2.0.0.beta2

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 (84) hide show
  1. data/History.txt +100 -0
  2. data/License.txt +22 -0
  3. data/README.md +829 -0
  4. data/lib/capybara.rb +124 -6
  5. data/lib/capybara/cucumber.rb +2 -5
  6. data/lib/capybara/driver/base.rb +5 -5
  7. data/lib/capybara/driver/node.rb +2 -2
  8. data/lib/capybara/dsl.rb +3 -121
  9. data/lib/capybara/node/actions.rb +12 -28
  10. data/lib/capybara/node/base.rb +5 -13
  11. data/lib/capybara/node/element.rb +21 -21
  12. data/lib/capybara/node/finders.rb +27 -89
  13. data/lib/capybara/node/matchers.rb +107 -69
  14. data/lib/capybara/node/simple.rb +11 -13
  15. data/lib/capybara/query.rb +78 -0
  16. data/lib/capybara/rack_test/browser.rb +16 -27
  17. data/lib/capybara/rack_test/driver.rb +11 -1
  18. data/lib/capybara/rack_test/node.rb +17 -1
  19. data/lib/capybara/result.rb +84 -0
  20. data/lib/capybara/rspec/matchers.rb +28 -63
  21. data/lib/capybara/selector.rb +97 -33
  22. data/lib/capybara/selenium/driver.rb +14 -61
  23. data/lib/capybara/selenium/node.rb +6 -15
  24. data/lib/capybara/server.rb +32 -27
  25. data/lib/capybara/session.rb +54 -30
  26. data/lib/capybara/spec/public/jquery-ui.js +791 -0
  27. data/lib/capybara/spec/public/jquery.js +9046 -0
  28. data/lib/capybara/spec/public/test.js +4 -1
  29. data/lib/capybara/spec/session.rb +56 -27
  30. data/lib/capybara/spec/session/all_spec.rb +8 -4
  31. data/lib/capybara/spec/session/attach_file_spec.rb +12 -9
  32. data/lib/capybara/spec/session/check_spec.rb +6 -3
  33. data/lib/capybara/spec/session/choose_spec.rb +4 -1
  34. data/lib/capybara/spec/session/click_button_spec.rb +5 -14
  35. data/lib/capybara/spec/session/click_link_or_button_spec.rb +2 -1
  36. data/lib/capybara/spec/session/click_link_spec.rb +3 -17
  37. data/lib/capybara/spec/session/current_url_spec.rb +77 -9
  38. data/lib/capybara/spec/session/fill_in_spec.rb +8 -18
  39. data/lib/capybara/spec/session/find_spec.rb +19 -46
  40. data/lib/capybara/spec/session/first_spec.rb +2 -34
  41. data/lib/capybara/spec/session/has_css_spec.rb +1 -1
  42. data/lib/capybara/spec/session/has_field_spec.rb +28 -0
  43. data/lib/capybara/spec/session/has_select_spec.rb +84 -31
  44. data/lib/capybara/spec/session/has_table_spec.rb +7 -69
  45. data/lib/capybara/spec/session/has_text_spec.rb +168 -0
  46. data/lib/capybara/spec/session/javascript.rb +65 -81
  47. data/lib/capybara/spec/session/node_spec.rb +115 -0
  48. data/lib/capybara/spec/session/screenshot.rb +29 -0
  49. data/lib/capybara/spec/session/select_spec.rb +12 -12
  50. data/lib/capybara/spec/session/text_spec.rb +9 -4
  51. data/lib/capybara/spec/session/unselect_spec.rb +12 -6
  52. data/lib/capybara/spec/session/visit_spec.rb +76 -0
  53. data/lib/capybara/spec/session/within_frame_spec.rb +33 -0
  54. data/lib/capybara/spec/session/within_spec.rb +47 -58
  55. data/lib/capybara/spec/session/within_window_spec.rb +40 -0
  56. data/lib/capybara/spec/test_app.rb +27 -3
  57. data/lib/capybara/spec/views/form.erb +11 -10
  58. data/lib/capybara/spec/views/host_links.erb +2 -2
  59. data/lib/capybara/spec/views/tables.erb +6 -66
  60. data/lib/capybara/spec/views/with_html.erb +3 -3
  61. data/lib/capybara/spec/views/with_js.erb +11 -8
  62. data/lib/capybara/util/save_and_open_page.rb +4 -3
  63. data/lib/capybara/version.rb +1 -1
  64. data/spec/basic_node_spec.rb +15 -3
  65. data/spec/dsl_spec.rb +12 -10
  66. data/spec/rack_test_spec.rb +152 -0
  67. data/spec/rspec/features_spec.rb +0 -2
  68. data/spec/rspec/matchers_spec.rb +164 -89
  69. data/spec/rspec_spec.rb +0 -2
  70. data/spec/selenium_spec.rb +67 -0
  71. data/spec/server_spec.rb +35 -23
  72. data/spec/spec_helper.rb +18 -2
  73. metadata +30 -30
  74. data/README.rdoc +0 -722
  75. data/lib/capybara/spec/driver.rb +0 -301
  76. data/lib/capybara/spec/session/current_host_spec.rb +0 -68
  77. data/lib/capybara/spec/session/has_content_spec.rb +0 -106
  78. data/lib/capybara/util/timeout.rb +0 -27
  79. data/spec/driver/rack_test_driver_spec.rb +0 -89
  80. data/spec/driver/selenium_driver_spec.rb +0 -37
  81. data/spec/session/rack_test_session_spec.rb +0 -55
  82. data/spec/session/selenium_session_spec.rb +0 -26
  83. data/spec/string_spec.rb +0 -77
  84. data/spec/timeout_spec.rb +0 -28
@@ -1,11 +1,13 @@
1
1
  require 'timeout'
2
2
  require 'nokogiri'
3
3
  require 'xpath'
4
+
4
5
  module Capybara
5
6
  class CapybaraError < StandardError; end
6
7
  class DriverNotFoundError < CapybaraError; end
7
8
  class FrozenInTime < CapybaraError; end
8
9
  class ElementNotFound < CapybaraError; end
10
+ class Ambiguous < ElementNotFound; end
9
11
  class ExpectationNotMet < ElementNotFound; end
10
12
  class FileNotFound < CapybaraError; end
11
13
  class UnselectNotAllowed < CapybaraError; end
@@ -15,10 +17,12 @@ module Capybara
15
17
  class InfiniteRedirectError < TimeoutError; end
16
18
 
17
19
  class << self
18
- attr_accessor :asset_root, :app_host, :run_server, :default_host
19
- attr_accessor :server_port, :server_boot_timeout
20
- attr_accessor :default_selector, :default_wait_time, :ignore_hidden_elements, :prefer_visible_elements
20
+ attr_accessor :asset_root, :app_host, :run_server, :default_host, :always_include_port
21
+ attr_accessor :server_host, :server_port
22
+ attr_accessor :default_selector, :default_wait_time, :ignore_hidden_elements
21
23
  attr_accessor :save_and_open_page_path, :automatic_reload
24
+ attr_writer :default_driver, :current_driver, :javascript_driver, :session_name
25
+ attr_accessor :app
22
26
 
23
27
  ##
24
28
  #
@@ -33,11 +37,11 @@ module Capybara
33
37
  #
34
38
  # [asset_root = String] Where static assets are located, used by save_and_open_page
35
39
  # [app_host = String] The default host to use when giving a relative URL to visit
40
+ # [always_include_port = Boolean] Whether the Rack server's port should automatically be inserted into every visited URL (Default: false)
36
41
  # [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
37
42
  # [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: CSS)
38
43
  # [default_wait_time = Integer] The number of seconds to wait for asynchronous processes to finish (Default: 2)
39
44
  # [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: false)
40
- # [prefer_visible_elements = Boolean] Whether to prefer visible elements over hidden elements (Default: true)
41
45
  # [automatic_reload = Boolean] Whether to automatically reload elements as Capybara is waiting (Default: true)
42
46
  # [save_and_open_page_path = String] Where to put pages saved through save_and_open_page (Default: Dir.pwd)
43
47
  #
@@ -181,14 +185,129 @@ module Capybara
181
185
  end
182
186
  end
183
187
 
188
+ ##
189
+ #
190
+ # @return [Symbol] The name of the driver to use by default
191
+ #
192
+ def default_driver
193
+ @default_driver || :rack_test
194
+ end
195
+
196
+ ##
197
+ #
198
+ # @return [Symbol] The name of the driver currently in use
199
+ #
200
+ def current_driver
201
+ @current_driver || default_driver
202
+ end
203
+ alias_method :mode, :current_driver
204
+
205
+ ##
206
+ #
207
+ # @return [Symbol] The name of the driver used when JavaScript is needed
208
+ #
209
+ def javascript_driver
210
+ @javascript_driver || :selenium
211
+ end
212
+
213
+ ##
214
+ #
215
+ # Use the default driver as the current driver
216
+ #
217
+ def use_default_driver
218
+ @current_driver = nil
219
+ end
220
+
221
+ ##
222
+ #
223
+ # Yield a block using a specific driver
224
+ #
225
+ def using_driver(driver)
226
+ previous_driver = Capybara.current_driver
227
+ Capybara.current_driver = driver
228
+ yield
229
+ ensure
230
+ @current_driver = previous_driver
231
+ end
232
+
233
+ ##
234
+ #
235
+ # Yield a block using a specific wait time
236
+ #
237
+ def using_wait_time(seconds)
238
+ previous_wait_time = Capybara.default_wait_time
239
+ Capybara.default_wait_time = seconds
240
+ yield
241
+ ensure
242
+ Capybara.default_wait_time = previous_wait_time
243
+ end
244
+
245
+ ##
246
+ #
247
+ # The current Capybara::Session based on what is set as Capybara.app and Capybara.current_driver
248
+ #
249
+ # @return [Capybara::Session] The currently used session
250
+ #
251
+ def current_session
252
+ session_pool["#{current_driver}:#{session_name}:#{app.object_id}"] ||= Capybara::Session.new(current_driver, app)
253
+ end
254
+
255
+ ##
256
+ #
257
+ # Reset sessions, cleaning out the pool of sessions. This will remove any session information such
258
+ # as cookies.
259
+ #
260
+ def reset_sessions!
261
+ session_pool.each { |mode, session| session.reset! }
262
+ end
263
+ alias_method :reset!, :reset_sessions!
264
+
265
+ ##
266
+ #
267
+ # The current session name.
268
+ #
269
+ # @return [Symbol] The name of the currently used session.
270
+ #
271
+ def session_name
272
+ @session_name ||= :default
273
+ end
274
+
275
+ ##
276
+ #
277
+ # Yield a block using a specific session name.
278
+ #
279
+ def using_session(name)
280
+ self.session_name = name
281
+ yield
282
+ ensure
283
+ self.session_name = :default
284
+ end
285
+
286
+ def included(base)
287
+ base.send(:include, Capybara::DSL)
288
+ warn "`include Capybara` is deprecated. Please use `include Capybara::DSL` instead."
289
+ end
290
+
184
291
  def deprecate(method, alternate_method)
185
292
  warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead"
186
293
  end
294
+
295
+ private
296
+
297
+ def session_pool
298
+ @session_pool ||= {}
299
+ end
187
300
  end
188
301
 
302
+ self.default_driver = nil
303
+ self.current_driver = nil
304
+
305
+ autoload :DSL, 'capybara/dsl'
189
306
  autoload :Server, 'capybara/server'
190
307
  autoload :Session, 'capybara/session'
191
308
  autoload :Selector, 'capybara/selector'
309
+ autoload :Query, 'capybara/query'
310
+ autoload :Result, 'capybara/result'
192
311
  autoload :VERSION, 'capybara/version'
193
312
 
194
313
  module Node
@@ -232,13 +351,12 @@ module Capybara
232
351
  end
233
352
 
234
353
  Capybara.configure do |config|
354
+ config.always_include_port = false
235
355
  config.run_server = true
236
356
  config.server {|app, port| Capybara.run_default_server(app, port)}
237
- config.server_boot_timeout = 10
238
357
  config.default_selector = :css
239
358
  config.default_wait_time = 2
240
359
  config.ignore_hidden_elements = false
241
- config.prefer_visible_elements = true
242
360
  config.default_host = "http://www.example.com"
243
361
  config.automatic_reload = true
244
362
  end
@@ -6,8 +6,9 @@ require 'capybara/rspec/matchers'
6
6
  World(Capybara::DSL)
7
7
  World(Capybara::RSpecMatchers)
8
8
 
9
- After do
9
+ Before do
10
10
  Capybara.reset_sessions!
11
+ Capybara.use_default_driver
11
12
  end
12
13
 
13
14
  Before '@javascript' do
@@ -22,7 +23,3 @@ Before do |scenario|
22
23
  end
23
24
  end
24
25
  end
25
-
26
- After do
27
- Capybara.use_default_driver
28
- end
@@ -27,6 +27,10 @@ class Capybara::Driver::Base
27
27
  raise Capybara::NotSupportedByDriverError
28
28
  end
29
29
 
30
+ def save_screenshot(path, options={})
31
+ raise Capybara::NotSupportedByDriverError
32
+ end
33
+
30
34
  def response_headers
31
35
  raise Capybara::NotSupportedByDriverError
32
36
  end
@@ -51,14 +55,10 @@ class Capybara::Driver::Base
51
55
  false
52
56
  end
53
57
 
54
- def wait_until(*args)
55
- end
56
-
57
58
  def reset!
58
59
  end
59
60
 
60
- def has_shortcircuit_timeout?
61
+ def needs_server?
61
62
  false
62
63
  end
63
-
64
64
  end
@@ -65,9 +65,9 @@ module Capybara
65
65
  end
66
66
 
67
67
  def inspect
68
- %(#<Capybara::Driver::Node tag="#{tag_name}" path="#{path}">)
68
+ %(#<#{self.class} tag="#{tag_name}" path="#{path}">)
69
69
  rescue NotSupportedByDriverError
70
- %(#<Capybara::Driver::Node tag="#{tag_name}">)
70
+ %(#<#{self.class} tag="#{tag_name}">)
71
71
  end
72
72
  end
73
73
  end
@@ -1,127 +1,11 @@
1
1
  require 'capybara'
2
2
 
3
3
  module Capybara
4
- def self.included(base)
5
- base.send(:include, Capybara::DSL)
6
- warn "`include Capybara` is deprecated please use `include Capybara::DSL` instead."
7
- end
8
-
9
- class << self
10
- attr_writer :default_driver, :current_driver, :javascript_driver, :session_name
11
-
12
- attr_accessor :app
13
-
14
- ##
15
- #
16
- # @return [Symbol] The name of the driver to use by default
17
- #
18
- def default_driver
19
- @default_driver || :rack_test
20
- end
21
-
22
- ##
23
- #
24
- # @return [Symbol] The name of the driver currently in use
25
- #
26
- def current_driver
27
- @current_driver || default_driver
28
- end
29
- alias_method :mode, :current_driver
30
-
31
- ##
32
- #
33
- # @return [Symbol] The name of the driver used when JavaScript is needed
34
- #
35
- def javascript_driver
36
- @javascript_driver || :selenium
37
- end
38
-
39
- ##
40
- #
41
- # Use the default driver as the current driver
42
- #
43
- def use_default_driver
44
- @current_driver = nil
45
- end
46
-
47
- ##
48
- #
49
- # Yield a block using a specific driver
50
- #
51
- def using_driver(driver)
52
- previous_driver = Capybara.current_driver
53
- Capybara.current_driver = driver
54
- yield
55
- ensure
56
- @current_driver = previous_driver
57
- end
58
-
59
- ##
60
- #
61
- # Yield a block using a specific wait time
62
- #
63
- def using_wait_time(seconds)
64
- previous_wait_time = Capybara.default_wait_time
65
- Capybara.default_wait_time = seconds
66
- yield
67
- ensure
68
- Capybara.default_wait_time = previous_wait_time
69
- end
70
-
71
- ##
72
- #
73
- # The current Capybara::Session base on what is set as Capybara.app and Capybara.current_driver
74
- #
75
- # @return [Capybara::Session] The currently used session
76
- #
77
- def current_session
78
- session_pool["#{current_driver}:#{session_name}:#{app.object_id}"] ||= Capybara::Session.new(current_driver, app)
79
- end
80
-
81
- ##
82
- #
83
- # Reset sessions, cleaning out the pool of sessions. This will remove any session information such
84
- # as cookies.
85
- #
86
- def reset_sessions!
87
- session_pool.each { |mode, session| session.reset! }
88
- end
89
- alias_method :reset!, :reset_sessions!
90
-
91
- ##
92
- #
93
- # The current session name.
94
- #
95
- # @return [Symbol] The name of the currently used session.
96
- #
97
- def session_name
98
- @session_name ||= :default
99
- end
100
-
101
- ##
102
- #
103
- # Yield a block using a specific session name.
104
- #
105
- def using_session(name)
106
- self.session_name = name
107
- yield
108
- ensure
109
- self.session_name = :default
110
- end
111
-
112
- private
113
-
114
- def session_pool
115
- @session_pool ||= {}
116
- end
117
- end
118
-
119
4
  module DSL
120
5
 
121
6
  ##
122
7
  #
123
- # Shortcut to working in a different session. This is useful when Capybara is included
124
- # in a class or module.
8
+ # Shortcut to working in a different session.
125
9
  #
126
10
  def using_session(name, &block)
127
11
  Capybara.using_session(name, &block)
@@ -129,8 +13,7 @@ module Capybara
129
13
 
130
14
  ##
131
15
  #
132
- # Shortcut to working in a different session. This is useful when Capybara is included
133
- # in a class or module.
16
+ # Shortcut to using a different wait time.
134
17
  #
135
18
  def using_wait_time(seconds, &block)
136
19
  Capybara.using_wait_time(seconds, &block)
@@ -138,8 +21,7 @@ module Capybara
138
21
 
139
22
  ##
140
23
  #
141
- # Shortcut to accessing the current session. This is useful when Capybara is included in a
142
- # class or module.
24
+ # Shortcut to accessing the current session.
143
25
  #
144
26
  # class MyClass
145
27
  # include Capybara::DSL
@@ -10,8 +10,7 @@ module Capybara
10
10
  # @param [String] locator Text, id or value of link or button
11
11
  #
12
12
  def click_link_or_button(locator)
13
- msg = "no link or button '#{locator}' found"
14
- find(:xpath, XPath::HTML.link_or_button(locator), :message => msg).click
13
+ find(:link_or_button, locator).click
15
14
  end
16
15
  alias_method :click_on, :click_link_or_button
17
16
 
@@ -23,8 +22,7 @@ module Capybara
23
22
  # @param [String] locator Text, id or text of link
24
23
  #
25
24
  def click_link(locator)
26
- msg = "no link with title, id or text '#{locator}' found"
27
- find(:xpath, XPath::HTML.link(locator), :message => msg).click
25
+ find(:link, locator).click
28
26
  end
29
27
 
30
28
  ##
@@ -34,8 +32,7 @@ module Capybara
34
32
  # @param [String] locator Text, id or value of button
35
33
  #
36
34
  def click_button(locator)
37
- msg = "no button with value or id or text '#{locator}' found"
38
- find(:xpath, XPath::HTML.button(locator), :message => msg).click
35
+ find(:button, locator).click
39
36
  end
40
37
 
41
38
  ##
@@ -49,9 +46,8 @@ module Capybara
49
46
  # @param [Hash{:with => String}] The value to fill in
50
47
  #
51
48
  def fill_in(locator, options={})
52
- msg = "cannot fill in, no text field, text area or password field with id, name, or label '#{locator}' found"
53
49
  raise "Must pass a hash containing 'with'" if not options.is_a?(Hash) or not options.has_key?(:with)
54
- find(:xpath, XPath::HTML.fillable_field(locator), :message => msg).set(options[:with])
50
+ find(:fillable_field, locator).set(options[:with])
55
51
  end
56
52
 
57
53
  ##
@@ -64,8 +60,7 @@ module Capybara
64
60
  # @param [String] locator Which radio button to choose
65
61
  #
66
62
  def choose(locator)
67
- msg = "cannot choose field, no radio button with id, name, or label '#{locator}' found"
68
- find(:xpath, XPath::HTML.radio_button(locator), :message => msg).set(true)
63
+ find(:radio_button, locator).set(true)
69
64
  end
70
65
 
71
66
  ##
@@ -78,8 +73,7 @@ module Capybara
78
73
  # @param [String] locator Which check box to check
79
74
  #
80
75
  def check(locator)
81
- msg = "cannot check field, no checkbox with id, name, or label '#{locator}' found"
82
- find(:xpath, XPath::HTML.checkbox(locator), :message => msg).set(true)
76
+ find(:checkbox, locator).set(true)
83
77
  end
84
78
 
85
79
  ##
@@ -92,8 +86,7 @@ module Capybara
92
86
  # @param [String] locator Which check box to uncheck
93
87
  #
94
88
  def uncheck(locator)
95
- msg = "cannot uncheck field, no checkbox with id, name, or label '#{locator}' found"
96
- find(:xpath, XPath::HTML.checkbox(locator), :message => msg).set(false)
89
+ find(:checkbox, locator).set(false)
97
90
  end
98
91
 
99
92
  ##
@@ -109,13 +102,9 @@ module Capybara
109
102
  #
110
103
  def select(value, options={})
111
104
  if options.has_key?(:from)
112
- no_select_msg = "cannot select option, no select box with id, name, or label '#{options[:from]}' found"
113
- no_option_msg = "cannot select option, no option with text '#{value}' in select box '#{options[:from]}'"
114
- select = find(:xpath, XPath::HTML.select(options[:from]), :message => no_select_msg)
115
- select.find(:xpath, XPath::HTML.option(value), :message => no_option_msg).select_option
105
+ find(:select, options[:from]).find(:option, value).select_option
116
106
  else
117
- no_option_msg = "cannot select option, no option with text '#{value}'"
118
- find(:xpath, XPath::HTML.option(value), :message => no_option_msg).select_option
107
+ find(:option, value).select_option
119
108
  end
120
109
  end
121
110
 
@@ -132,13 +121,9 @@ module Capybara
132
121
  #
133
122
  def unselect(value, options={})
134
123
  if options.has_key?(:from)
135
- no_select_msg = "cannot unselect option, no select box with id, name, or label '#{options[:from]}' found"
136
- no_option_msg = "cannot unselect option, no option with text '#{value}' in select box '#{options[:from]}'"
137
- select = find(:xpath, XPath::HTML.select(options[:from]), :message => no_select_msg)
138
- select.find(:xpath, XPath::HTML.option(value), :message => no_option_msg).unselect_option
124
+ find(:select, options[:from]).find(:option, value).unselect_option
139
125
  else
140
- no_option_msg = "cannot unselect option, no option with text '#{value}'"
141
- find(:xpath, XPath::HTML.option(value), :message => no_option_msg).unselect_option
126
+ find(:option, value).unselect_option
142
127
  end
143
128
  end
144
129
 
@@ -154,8 +139,7 @@ module Capybara
154
139
  #
155
140
  def attach_file(locator, path)
156
141
  raise Capybara::FileNotFound, "cannot attach file, #{path} does not exist" unless File.exist?(path.to_s)
157
- msg = "cannot attach file, no file field with id, name, or label '#{locator}' found"
158
- find(:xpath, XPath::HTML.file_field(locator), :message => msg).set(path)
142
+ find(:file_field, locator).set(path)
159
143
  end
160
144
  end
161
145
  end