capybara 0.3.9 → 0.4.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/History.txt +43 -1
  2. data/README.rdoc +168 -98
  3. data/lib/capybara.rb +77 -15
  4. data/lib/capybara/driver/base.rb +21 -16
  5. data/lib/capybara/driver/celerity_driver.rb +39 -41
  6. data/lib/capybara/driver/culerity_driver.rb +2 -1
  7. data/lib/capybara/driver/node.rb +66 -0
  8. data/lib/capybara/driver/rack_test_driver.rb +66 -67
  9. data/lib/capybara/driver/selenium_driver.rb +43 -47
  10. data/lib/capybara/dsl.rb +44 -6
  11. data/lib/capybara/node.rb +185 -24
  12. data/lib/capybara/node/actions.rb +170 -0
  13. data/lib/capybara/node/finders.rb +150 -0
  14. data/lib/capybara/node/matchers.rb +360 -0
  15. data/lib/capybara/rails.rb +1 -0
  16. data/lib/capybara/selector.rb +52 -0
  17. data/lib/capybara/server.rb +68 -87
  18. data/lib/capybara/session.rb +221 -207
  19. data/lib/capybara/spec/driver.rb +45 -35
  20. data/lib/capybara/spec/public/test.js +1 -1
  21. data/lib/capybara/spec/session.rb +28 -53
  22. data/lib/capybara/spec/session/all_spec.rb +7 -3
  23. data/lib/capybara/spec/session/check_spec.rb +50 -52
  24. data/lib/capybara/spec/session/click_button_spec.rb +9 -0
  25. data/lib/capybara/spec/session/click_link_or_button_spec.rb +37 -0
  26. data/lib/capybara/spec/session/current_url_spec.rb +7 -0
  27. data/lib/capybara/spec/session/find_button_spec.rb +4 -2
  28. data/lib/capybara/spec/session/find_by_id_spec.rb +4 -2
  29. data/lib/capybara/spec/session/find_field_spec.rb +7 -3
  30. data/lib/capybara/spec/session/find_link_spec.rb +5 -3
  31. data/lib/capybara/spec/session/find_spec.rb +71 -6
  32. data/lib/capybara/spec/session/has_field_spec.rb +1 -1
  33. data/lib/capybara/spec/session/has_selector_spec.rb +129 -0
  34. data/lib/capybara/spec/session/has_xpath_spec.rb +4 -4
  35. data/lib/capybara/spec/session/javascript.rb +25 -5
  36. data/lib/capybara/spec/session/select_spec.rb +16 -2
  37. data/lib/capybara/spec/session/unselect_spec.rb +8 -1
  38. data/lib/capybara/spec/session/within_spec.rb +5 -5
  39. data/lib/capybara/spec/views/form.erb +65 -1
  40. data/lib/capybara/spec/views/popup_one.erb +8 -0
  41. data/lib/capybara/spec/views/popup_two.erb +8 -0
  42. data/lib/capybara/spec/views/with_html.erb +5 -0
  43. data/lib/capybara/spec/views/within_popups.erb +25 -0
  44. data/lib/capybara/{save_and_open_page.rb → util/save_and_open_page.rb} +3 -3
  45. data/lib/capybara/util/timeout.rb +27 -0
  46. data/lib/capybara/version.rb +1 -1
  47. data/spec/capybara_spec.rb +18 -8
  48. data/spec/driver/celerity_driver_spec.rb +10 -14
  49. data/spec/driver/culerity_driver_spec.rb +4 -3
  50. data/spec/driver/rack_test_driver_spec.rb +39 -2
  51. data/spec/driver/remote_culerity_driver_spec.rb +5 -7
  52. data/spec/driver/remote_selenium_driver_spec.rb +7 -10
  53. data/spec/driver/selenium_driver_spec.rb +3 -2
  54. data/spec/dsl_spec.rb +5 -14
  55. data/spec/save_and_open_page_spec.rb +19 -19
  56. data/spec/server_spec.rb +22 -10
  57. data/spec/session/celerity_session_spec.rb +17 -21
  58. data/spec/session/culerity_session_spec.rb +3 -3
  59. data/spec/session/rack_test_session_spec.rb +2 -2
  60. data/spec/session/selenium_session_spec.rb +2 -2
  61. data/spec/spec_helper.rb +27 -6
  62. data/spec/{wait_until_spec.rb → timeout_spec.rb} +14 -14
  63. metadata +88 -46
  64. data/lib/capybara/searchable.rb +0 -54
  65. data/lib/capybara/spec/session/click_spec.rb +0 -24
  66. data/lib/capybara/spec/session/locate_spec.rb +0 -65
  67. data/lib/capybara/wait_until.rb +0 -28
  68. data/lib/capybara/xpath.rb +0 -179
  69. data/spec/searchable_spec.rb +0 -66
  70. data/spec/xpath_spec.rb +0 -180
@@ -1,6 +1,48 @@
1
+ # Version 0.4.0.rc
2
+
3
+ Release date:
4
+
5
+ ### Changed
6
+
7
+ * within and find/locate now follow the XPath spec in that //foo finds all nodes in the document, instead of
8
+ only for the context node. See this post for details: http://groups.google.com/group/ruby-capybara/browse_thread/thread/b129067979df21b3
9
+ * within now executes within the first found instance of the selector, not in all of them
10
+ * find now waits for AJAX requests and raises an exception when the element is not found (same as locate used to do)
11
+ * The default selector is now CSS, not XPath
12
+
13
+ ### Deprecated
14
+
15
+ * Session#click has been renamed click_link_or_button and the old click has been deprecated
16
+ * Node#node has been renamed native
17
+ * Node#locate is deprecated in favor of Node#find, which now behaves identically
18
+ * Session#drag is deprecated, please use Node#drag_to(other_node) instead
19
+
20
+ ### Added
21
+
22
+ * Pretty much everything is properly documented now
23
+ * It's now possible to call all session methods on nodes, like `find('#foo').fill_in(...)`
24
+ * Custom selectors can be added with Capybara::Selector.add
25
+ * The :id selector is added by default, use it lile `find(:id, 'foo')` or `find(:foo)`
26
+ * Added Node#has_selector? so any kind of selector can be queried.
27
+ * Added Capybara.configure for less wordy configuration
28
+ * Added within_window to switch between different windows (currently Selenium only)
29
+ * Capybara.server_port to provide a fixed port if wanted (defaults to automatic selection)
30
+
31
+ ### Fixed
32
+
33
+ * CSS selectors with multiple selectors, such as "h1, h2" now work correctly
34
+ * Port is automatically assigned instead of guessing
35
+ * Strip encodings in rack-test, no more warnings!
36
+ * RackTest no longer submits disabled fields
37
+ * Servers no longer output annoying debug information when started
38
+ * TCP port selection is left to Ruby to decide, no more port guessing
39
+ * Select boxes now return option value instead of text if present
40
+ * The default has been changed from localhost to 127.0.0.1, should fix some obscure selenium bugs
41
+ * RackTest now supports complex field names, such as foo[bar][][baz]
42
+
1
43
  # Version 0.3.9
2
44
 
3
- Release data: 2010-07-03
45
+ Release date: 2010-07-03
4
46
 
5
47
  ### Added
6
48
 
@@ -1,16 +1,19 @@
1
- = capybara
1
+ = Capybara
2
2
 
3
3
  * http://github.com/jnicklas/capybara
4
4
 
5
5
  == Description:
6
6
 
7
7
  Capybara aims to simplify the process of integration testing Rack applications,
8
- such as Rails, Sinatra or Merb. It is inspired by and aims to replace Webrat as
9
- a DSL for interacting with a webapplication. It is agnostic about the driver
10
- running your tests and currently comes bundled with rack-test, Culerity,
11
- Celerity and Selenium support built in. env.js support is available as the
8
+ such as Rails, Sinatra or Merb. Capybara simulates how a real user would
9
+ interact with a web application. It is agnostic about the driver running your
10
+ tests and currently comes bundled with rack-test, Culerity, Celerity and Selenium
11
+ support built in. env.js support is available as the
12
12
  {capybara-envjs gem}[http://github.com/smparkes/capybara-envjs].
13
13
 
14
+ Online documentation is availbable
15
+ {at rdoc.info}[http://rdoc.info/projects/jnicklas/capybara].
16
+
14
17
  == Install:
15
18
 
16
19
  Install as a gem:
@@ -31,18 +34,22 @@ Pull requests are very welcome! Make sure your patches are well tested, Capybara
31
34
  a testing tool after all. Please create a topic branch for every separate change
32
35
  you make.
33
36
 
37
+ Capybara uses bundler in development. To set up a development environment, simply do:
38
+
39
+ gem install bundler --pre
40
+ bundle install
41
+
34
42
  == Using Capybara with Cucumber
35
43
 
36
- Capybara is built to work nicely with Cucumber. The API is very similar to
37
- Webrat, so if you know Webrat you should feel right at home. Support for
38
- Capybara is built into cucumber-rails 0.2. In your Rails app, just run:
44
+ Capybara is built to work nicely with Cucumber. Support for Capybara is built into
45
+ cucumber-rails. In your Rails app, just run:
39
46
 
40
- script/generate cucumber --capybara
47
+ rails generate cucumber:install --capybara
41
48
 
42
49
  And everything should be set up and ready to go.
43
50
 
44
51
  If you want to use Capybara with Cucumber outside Rails (for example with Merb
45
- or Sinatra), you'll need require capybara and set the Rack app manually:
52
+ or Sinatra), you'll need to require Capybara and set the Rack app manually:
46
53
 
47
54
  require 'capybara/cucumber'
48
55
  Capybara.app = MyRackApp
@@ -50,16 +57,13 @@ or Sinatra), you'll need require capybara and set the Rack app manually:
50
57
  Now you can use it in your steps:
51
58
 
52
59
  When /I sign in/ do
53
- within("//form[@id='session']") do
60
+ within("#session") do
54
61
  fill_in 'Login', :with => 'user@example.com'
55
62
  fill_in 'Password', :with => 'password'
56
63
  end
57
64
  click_link 'Sign in'
58
65
  end
59
66
 
60
- Please note that while Capybara uses XPath selectors by default, Cucumber explicitly
61
- changes this to CSS in `env.rb`. See "XPath and CSS" below.
62
-
63
67
  == Default and current driver
64
68
 
65
69
  You can set up a default driver for your features. For example if you'd prefer
@@ -103,11 +107,6 @@ At the moment, Capybara supports Webdriver, also called Selenium 2.0, *not*
103
107
  Selenium RC. Provided Firefox is installed, everything is set up for you, and
104
108
  you should be able to start using Selenium right away.
105
109
 
106
- If desired, you can change Selenium browser to :chrome or :ie:
107
-
108
- require "selenium-webdriver"
109
- Selenium::WebDriver.for :chrome
110
-
111
110
  == Celerity
112
111
 
113
112
  Celerity only runs on JRuby, so you'll need to install the celerity gem under
@@ -115,10 +114,6 @@ JRuby:
115
114
 
116
115
  jruby -S gem install celerity
117
116
 
118
- Note that some specs currently fail on celerity 0.7.5, due to a bug in recent
119
- versions of HTMLUnit. It is recommended you use celerity 0.7.4 for the time
120
- being.
121
-
122
117
  == Culerity
123
118
 
124
119
  Install celerity as noted above, make sure JRuby is in your path. Note that
@@ -130,7 +125,9 @@ The {capybara-envjs driver}[http://github.com/smparkes/capybara-envjs]
130
125
  uses the envjs gem ({GitHub}[http://github.com/smparkes/env-js],
131
126
  {rubygems.org}[http://rubygems.org/gems/envjs]) to interpret
132
127
  JavaScript outside the browser. The driver is installed by installing the capybara-envjs gem:
128
+
133
129
  gem install capybara-envjs
130
+
134
131
  More info about the driver and env.js are available through the links above. The envjs gem only supports
135
132
  Ruby 1.8.7 at this time.
136
133
 
@@ -164,8 +161,8 @@ automatically follows any redirects, and submits forms associated with buttons.
164
161
  click_link('id-of-link')
165
162
  click_link('Link Text')
166
163
  click_button('Save')
167
- click('Link Text') # Click either a link or a button
168
- click('Button Value')
164
+ click_link_or_button('Link Text')
165
+ click_link_or_button('Button Value')
169
166
 
170
167
  === Interacting with forms
171
168
 
@@ -181,57 +178,24 @@ with the various form elements:
181
178
  attach_file('Image', '/path/to/image.jpg')
182
179
  select('Option', :from => 'Select Box')
183
180
 
184
- === Scoping
185
-
186
- Capybara makes it possible to restrict certain actions, such as interacting with
187
- forms or clicking links and buttons, to within a specific area of the page. For
188
- this purpose you can use the generic <tt>within</tt> method. Optionally you can
189
- specify which kind of selector (CSS or XPath to use).
190
-
191
- within("//li[@id='employee']") do
192
- fill_in 'Name', :with => 'Jimmy'
193
- end
194
-
195
- within(:css, "li#employee") do
196
- fill_in 'Name', :with => 'Jimmy'
197
- end
198
-
199
- You can choose which kind of selector Capybara uses by default, by setting
200
- <tt>Capybara.default_selector</tt>.
201
-
202
- There are special methods for restricting the scope to a specific fieldset,
203
- identified by either an id or the text of the fieldet's legend tag, and to a
204
- specific table, identified by either id or text of the table's caption tag.
205
-
206
- within_fieldset('Employee') do
207
- fill_in 'Name', :with => 'Jimmy'
208
- end
209
-
210
- within_table('Employee') do
211
- fill_in 'Name', :with => 'Jimmy'
212
- end
213
-
214
- You can also specify a scope to be used for future searches with the <tt>scope_to</tt>.
215
- It returns a handle to the session scoped to the provided selector.
216
-
217
- scope = page.scope_to("//div[@id='foo']")
218
- scope.has_xpath("//a[@class='bar']")
219
-
220
- You can also chain scopes by calling <tt>scope_to</tt> on an existing scope.
221
-
222
- more_scope = scope.scope_to("//p")
223
- more_scope.has_xpath("//a[@class='baz']")
224
-
225
181
  === Querying
226
182
 
227
183
  Capybara has a rich set of options for querying the page for the existence of
228
184
  certain elements, and working with and manipulating those elements.
229
185
 
186
+ page.has_selector?('table tr')
187
+ page.has_selector?(:xpath, '//table/tr')
188
+ page.has_no_selector?(:content)
189
+
230
190
  page.has_xpath?('//table/tr')
231
191
  page.has_css?('table tr.foo')
232
192
  page.has_content?('foo')
233
193
 
234
- You can use with RSpecs magic matchers:
194
+ You can these use with RSpec's magic matchers:
195
+
196
+ page.should have_selector('table tr')
197
+ page.should have_selector(:xpath, '//table/tr')
198
+ page.should have_no_selector(:content)
235
199
 
236
200
  page.should have_xpath('//table/tr')
237
201
  page.should have_css('table tr.foo')
@@ -242,16 +206,54 @@ Note that <tt>page.should have_no_xpath</tt> is preferred over
242
206
  <tt>page.should_not have_xpath</tt>. Read the section on asynchronous JavaScript
243
207
  for an explanation.
244
208
 
209
+ === Finding
210
+
245
211
  You can also find specific elements, in order to manipulate them:
246
212
 
247
213
  find_field('First Name').value
248
214
  find_link('Hello').visible?
249
215
  find_button('Send').click
250
216
 
251
- find('//table/tr').click
252
- locate("//*[@id='overlay'").find("//h1").click
217
+ find(:xpath, "//table/tr").click
218
+ find("#overlay").find("h1").click
253
219
  all('a').each { |a| a[:href] }
254
220
 
221
+ Note that <tt>find</tt> will wait for an element to appear on the page, as explained in the
222
+ AJAX section. If the element does not appear it will raise an error.
223
+
224
+ These elements all have all the Capybara DSL methods available, so you can restrict them
225
+ to specific parts of the page:
226
+
227
+ find('#navigation').click_link('Home')
228
+ find('#navigation').should have_button('Sign out')
229
+
230
+ === Scoping
231
+
232
+ Capybara makes it possible to restrict certain actions, such as interacting with
233
+ forms or clicking links and buttons, to within a specific area of the page. For
234
+ this purpose you can use the generic <tt>within</tt> method. Optionally you can
235
+ specify which kind of selector to use.
236
+
237
+ within("li#employee") do
238
+ fill_in 'Name', :with => 'Jimmy'
239
+ end
240
+
241
+ within(:xpath, "//li[@id='employee']") do
242
+ fill_in 'Name', :with => 'Jimmy'
243
+ end
244
+
245
+ There are special methods for restricting the scope to a specific fieldset,
246
+ identified by either an id or the text of the fieldet's legend tag, and to a
247
+ specific table, identified by either id or text of the table's caption tag.
248
+
249
+ within_fieldset('Employee') do
250
+ fill_in 'Name', :with => 'Jimmy'
251
+ end
252
+
253
+ within_table('Employee') do
254
+ fill_in 'Name', :with => 'Jimmy'
255
+ end
256
+
255
257
  === Scripting
256
258
 
257
259
  In drivers which support it, you can easily execute JavaScript:
@@ -297,8 +299,8 @@ is (the default is 2 seconds):
297
299
  Be aware that because of this behaviour, the following two statements are *not*
298
300
  equivalent, and you should *always* use the latter!
299
301
 
300
- page.should_not have_xpath('//a')
301
- page.should have_no_xpath('//a')
302
+ page.should_not have_xpath('a')
303
+ page.should have_no_xpath('a')
302
304
 
303
305
  The former would incorrectly wait for the content to appear, since the
304
306
  asynchronous process has not yet removed the element from the page, it would
@@ -329,18 +331,23 @@ examples. Just load the DSL and include it anywhere:
329
331
 
330
332
  == Calling remote servers
331
333
 
332
- Normally Capybara expects to be testing an in-process Rack application, but you can also use it to talk to a web server running anywhere on the internets, by setting app_host:
334
+ Normally Capybara expects to be testing an in-process Rack application, but you
335
+ can also use it to talk to a web server running anywhere on the internets, by
336
+ setting app_host:
333
337
 
334
338
  Capybara.current_driver = :selenium
335
339
  Capybara.app_host = 'http://www.google.com'
336
- ...
340
+ ...
337
341
  visit('/')
338
342
 
339
- Note that rack-test does not support running against a remote server. With drivers that support it, you can also visit any URL directly:
343
+ Note that rack-test does not support running against a remote server. With
344
+ drivers that support it, you can also visit any URL directly:
340
345
 
341
346
  visit('http://www.google.com')
342
347
 
343
- By default Capybara will try to boot a rack application automatically. You might want to switch off Capybara's rack server if you are running against a remote application:
348
+ By default Capybara will try to boot a rack application automatically. You
349
+ might want to switch off Capybara's rack server if you are running against a
350
+ remote application:
344
351
 
345
352
  Capybara.run_server = false
346
353
 
@@ -357,42 +364,105 @@ For ultimate control, you can instantiate and use a session manually.
357
364
  end
358
365
  session.click_link 'Sign in'
359
366
 
360
- == XPath and CSS
367
+ == XPath, CSS and selectors
361
368
 
362
369
  Capybara does not try to guess what kind of selector you are going to give it,
363
- if you want to use CSS with your 'within' declarations for example, you'll need
370
+ if you want to use XPath with your 'within' declarations for example, you'll need
364
371
  to do:
365
372
 
366
- within(:css, 'ul li') { ... }
367
- find(:css, 'ul li').text
368
- locate(:css, 'input#name').value
373
+ within(:xpath, '//ul/li') { ... }
374
+ find(:xpath, '//ul/li').text
375
+ find(:xpath, '//li[contains(.//a[@href = "#"]/text(), "foo")]').value
369
376
 
370
- Alternatively you can set the default selector to CSS, which may help if you are
371
- moving from Webrat and used CSS a lot, or simply generally prefer CSS:
377
+ Alternatively you can set the default selector to XPath:
372
378
 
373
- Capybara.default_selector = :css
374
- within('ul li') { ... }
375
- find('ul li').text
376
- locate('input#name').value
379
+ Capybara.default_selector = :xpath
380
+ find('//ul/li').text
377
381
 
378
- == Gotchas:
382
+ Capybara allows you to add custom selectors, which can be very useful if you
383
+ find yourself using the same kinds of selectors very often:
384
+
385
+ Capybara::Selector.add(:id) { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
386
+ Capybara::Selector.add(:row) { |num| ".//tbody/tr[#{num}]" }
387
+
388
+ These must always return an XPath expression as a String, or an XPath expression
389
+ generated through the XPath gem. You can now use these selectors like this:
390
+
391
+ find(:id, 'post_123')
392
+ find(:row, 3)
379
393
 
380
- * Domain names (including subdomains) don't work under rack-test. Since it's a
381
- pain to set up subdomains for the other drivers anyway, you should consider an
382
- alternate solution. You might use
383
- {default_url_options}[https://gist.github.com/643a758320a2926bd2ed] in Rails
384
- for example.
394
+ You can specify an optional :for option which will automatically use the
395
+ selector if it matches the argument to find using ===:
396
+
397
+ Capybara::Selector.add(:id, :for => Symbol) { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
398
+
399
+ Now use it like this:
400
+
401
+ find(:post_123)
402
+
403
+ This :id selector is already built into Capybara by default, so you don't
404
+ need to add it yourself.
405
+
406
+ == Beware the XPath // trap
407
+
408
+ In XPath the expression // means something very specific, and it might not be what
409
+ you think. Contrary to common belief, // means "anywhere in the document" not "anywhere
410
+ in the current context". As an example:
411
+
412
+ page.find(:xpath, '//body').all(:xpath, '//script')
413
+
414
+ You might expect this to find all script tags in the body, but actually, it finds all
415
+ script tags in the entire document, not only those in the body! What you're looking
416
+ for is the .// expression which means "any descendant of the current node":
417
+
418
+ page.find(:xpath, '//body').all(:xpath, './/script')
419
+
420
+ The same thing goes for within:
421
+
422
+ within(:xpath, '//body') do
423
+ page.find(:xpath, './/script')
424
+ within(:xpath, './/table/tbody') do
425
+ ...
426
+ end
427
+ end
428
+
429
+ == Configuring and adding drivers
430
+
431
+ Capybara makes it convenient to switch between different drivers. It also exposes
432
+ an API to tweak those drivers with whatever settings you want, or to add your own
433
+ drivers. This is how to switch the selenium driver to use chrome:
434
+
435
+ Capybara.register_driver :selenium do |app|
436
+ Capybara::Driver::Selenium.new(app, :browser => :chrome)
437
+ end
438
+
439
+ However, it's also possible to give this a different name, so tests can switch
440
+ between using different browsers effortlessly:
441
+
442
+ Capybara.register_driver :selenium_chrome do |app|
443
+ Capybara::Driver::Selenium.new(app, :browser => :chrome)
444
+ end
445
+
446
+ Whatever is returned from the block should conform to the API described by
447
+ Capybara::Driver::Base, it does not however have to inherit from this class.
448
+ Gems can use this API to add their own drivers to Capybara.
449
+
450
+ == Gotchas:
385
451
 
386
- * Access to session, request and response from the test is not possible. Maybe
387
- we'll do response headers at some point in the future, but the others really
388
- shouldn't be touched in an integration test anyway.
452
+ * Access to session and request is not possible from the test, Access to
453
+ response is limited. Some drivers allow access to response headers and HTTP
454
+ status code, but this kind of functionality is not provided by some drivers,
455
+ such as Selenium.
389
456
 
390
457
  * Access to Rails specific stuff (such as <tt>controller</tt>) is unavailable,
391
458
  since we're not using Rails' integration testing.
392
459
 
393
- * <tt><a href="#"></tt> Will cause problems under rack-test, please do
394
- <tt><a href="/same/url#"></tt> instead. You can achieve this in Rails with
395
- <tt>link_to('foo', :anchor => '')</tt>
460
+ * Freezing time: It's common practice to mock out the Time so that features
461
+ that depend on the current Date work as expected. This can be problematic,
462
+ since Capybara's AJAX timing uses the system time, resulting in Capybara
463
+ never timing out and just hanging when a failure occurs. It's still possible to
464
+ use plugins which allow you to travel in time, rather than freeze time.
465
+ One such plugin is {Timecop}[http://github.com/jtrupiano/timecop].
396
466
 
397
467
  == License:
398
468
 
@@ -1,11 +1,11 @@
1
1
  require 'timeout'
2
2
  require 'nokogiri'
3
+ require 'xpath'
3
4
 
4
5
  module Capybara
5
6
  class CapybaraError < StandardError; end
6
7
  class DriverNotFoundError < CapybaraError; end
7
8
  class ElementNotFound < CapybaraError; end
8
- class OptionNotFound < ElementNotFound; end
9
9
  class UnselectNotAllowed < CapybaraError; end
10
10
  class NotSupportedByDriverError < CapybaraError; end
11
11
  class TimeoutError < CapybaraError; end
@@ -13,33 +13,77 @@ module Capybara
13
13
  class InfiniteRedirectError < TimeoutError; end
14
14
 
15
15
  class << self
16
- attr_accessor :debug, :asset_root, :app_host, :run_server, :default_host
16
+ attr_accessor :asset_root, :app_host, :run_server, :default_host
17
+ attr_accessor :server_port
17
18
  attr_accessor :default_selector, :default_wait_time, :ignore_hidden_elements
18
19
  attr_accessor :save_and_open_page_path
19
20
 
20
- def default_selector
21
- @default_selector ||= :xpath
21
+ ##
22
+ #
23
+ # Configure Capybara to suit your needs.
24
+ #
25
+ # Capybara.configure do |config|
26
+ # config.run_server = false
27
+ # config.app_host = 'http://www.google.com'
28
+ # end
29
+ #
30
+ # === Configurable options
31
+ #
32
+ # [asset_root = String] Where static assets are located, used by save_and_open_page
33
+ # [app_host = String] The default host to use when giving a relative URL to visit
34
+ # [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
35
+ # [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: CSS)
36
+ # [default_wait_time = Integer] The number of seconds to wait for asynchronous processes to finish (Default: 2)
37
+ # [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: false)
38
+ #
39
+ # === DSL Options
40
+ #
41
+ # when using capybara/dsl, the following options are also available:
42
+ #
43
+ # [default_driver = Symbol] The name of the driver to use by default. (Default: :rack_test)
44
+ # [javascript_driver = Symbol] The name of a driver to use for JavaScript enabled tests. (Default: :selenium)
45
+ #
46
+ def configure
47
+ yield self
22
48
  end
23
49
 
24
- def default_wait_time
25
- @default_wait_time ||= 2
50
+ ##
51
+ #
52
+ # Register a new driver for Capybara.
53
+ #
54
+ # Capybara.register_driver :rack_test do |app|
55
+ # Capybara::Driver::RackTest.new(app)
56
+ # end
57
+ #
58
+ # @param [Symbol] name The name of the new driver
59
+ # @yield [app] This block takes a rack app and returns a Capybara driver
60
+ # @yieldparam [<Rack>] app The rack application that this driver runs agains. May be nil.
61
+ # @yieldreturn [Capybara::Driver::Base] A Capybara driver instance
62
+ #
63
+ def register_driver(name, &block)
64
+ drivers[name] = block
26
65
  end
27
66
 
28
- def log(message)
29
- puts "[capybara] #{message}" if debug
30
- true
67
+ def drivers
68
+ @drivers ||= {}
69
+ end
70
+
71
+ def deprecate(method, alternate_method)
72
+ warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead"
31
73
  end
32
74
  end
33
75
 
34
76
  autoload :Server, 'capybara/server'
35
77
  autoload :Session, 'capybara/session'
36
78
  autoload :Node, 'capybara/node'
37
- autoload :XPath, 'capybara/xpath'
38
- autoload :Searchable, 'capybara/searchable'
79
+ autoload :Document, 'capybara/node'
80
+ autoload :Element, 'capybara/node'
81
+ autoload :Selector, 'capybara/selector'
39
82
  autoload :VERSION, 'capybara/version'
40
83
 
41
84
  module Driver
42
85
  autoload :Base, 'capybara/driver/base'
86
+ autoload :Node, 'capybara/driver/node'
43
87
  autoload :RackTest, 'capybara/driver/rack_test_driver'
44
88
  autoload :Celerity, 'capybara/driver/celerity_driver'
45
89
  autoload :Culerity, 'capybara/driver/culerity_driver'
@@ -47,7 +91,25 @@ module Capybara
47
91
  end
48
92
  end
49
93
 
50
- Capybara.run_server = true
51
- Capybara.default_selector = :xpath
52
- Capybara.default_wait_time = 2
53
- Capybara.ignore_hidden_elements = false
94
+ Capybara.configure do |config|
95
+ config.run_server = true
96
+ config.default_selector = :css
97
+ config.default_wait_time = 2
98
+ config.ignore_hidden_elements = false
99
+ end
100
+
101
+ Capybara.register_driver :rack_test do |app|
102
+ Capybara::Driver::RackTest.new(app)
103
+ end
104
+
105
+ Capybara.register_driver :celerity do |app|
106
+ Capybara::Driver::Culerity.new(app)
107
+ end
108
+
109
+ Capybara.register_driver :culerity do |app|
110
+ Capybara::Driver::Culerity.new(app)
111
+ end
112
+
113
+ Capybara.register_driver :selenium do |app|
114
+ Capybara::Driver::Selenium.new(app)
115
+ end