capybara 1.1.4 → 2.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
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