capybara 2.1.0 → 2.2.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 (58) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/History.md +48 -1
  4. data/README.md +22 -18
  5. data/lib/capybara/cucumber.rb +0 -2
  6. data/lib/capybara/driver/base.rb +9 -1
  7. data/lib/capybara/empty.html +4 -0
  8. data/lib/capybara/node/actions.rb +1 -1
  9. data/lib/capybara/node/finders.rb +3 -3
  10. data/lib/capybara/node/matchers.rb +22 -18
  11. data/lib/capybara/node/simple.rb +5 -3
  12. data/lib/capybara/query.rb +1 -0
  13. data/lib/capybara/rack_test/browser.rb +5 -4
  14. data/lib/capybara/rack_test/form.rb +5 -2
  15. data/lib/capybara/rack_test/node.rb +2 -1
  16. data/lib/capybara/result.rb +2 -1
  17. data/lib/capybara/rspec/features.rb +2 -0
  18. data/lib/capybara/rspec/matchers.rb +6 -6
  19. data/lib/capybara/rspec.rb +7 -0
  20. data/lib/capybara/selector.rb +3 -1
  21. data/lib/capybara/selenium/driver.rb +14 -2
  22. data/lib/capybara/selenium/node.rb +18 -5
  23. data/lib/capybara/server.rb +3 -7
  24. data/lib/capybara/session.rb +59 -17
  25. data/lib/capybara/spec/public/test.js +1 -1
  26. data/lib/capybara/spec/session/assert_selector.rb +18 -0
  27. data/lib/capybara/spec/session/attach_file_spec.rb +6 -1
  28. data/lib/capybara/spec/session/check_spec.rb +14 -0
  29. data/lib/capybara/spec/session/choose_spec.rb +14 -0
  30. data/lib/capybara/spec/session/click_button_spec.rb +20 -1
  31. data/lib/capybara/spec/session/fill_in_spec.rb +18 -2
  32. data/lib/capybara/spec/session/go_back_spec.rb +10 -0
  33. data/lib/capybara/spec/session/go_forward_spec.rb +12 -0
  34. data/lib/capybara/spec/session/has_button_spec.rb +24 -0
  35. data/lib/capybara/spec/session/has_field_spec.rb +48 -0
  36. data/lib/capybara/spec/session/has_text_spec.rb +18 -0
  37. data/lib/capybara/spec/session/node_spec.rb +36 -1
  38. data/lib/capybara/spec/session/reset_session_spec.rb +17 -2
  39. data/lib/capybara/spec/session/save_page_spec.rb +10 -4
  40. data/lib/capybara/spec/session/visit_spec.rb +16 -0
  41. data/lib/capybara/spec/session/within_frame_spec.rb +7 -0
  42. data/lib/capybara/spec/session/within_window_spec.rb +7 -0
  43. data/lib/capybara/spec/test_app.rb +1 -0
  44. data/lib/capybara/spec/views/form.erb +40 -0
  45. data/lib/capybara/spec/views/with_html.erb +5 -0
  46. data/lib/capybara/spec/views/with_js.erb +8 -0
  47. data/lib/capybara/version.rb +1 -1
  48. data/lib/capybara.rb +28 -3
  49. data/spec/capybara_spec.rb +1 -1
  50. data/spec/result_spec.rb +14 -0
  51. data/spec/rspec/features_spec.rb +15 -0
  52. data/spec/rspec/matchers_spec.rb +24 -1
  53. data/spec/selenium_spec.rb +9 -2
  54. data/spec/selenium_spec_chrome.rb +21 -0
  55. data/spec/server_spec.rb +13 -5
  56. data.tar.gz.sig +0 -0
  57. metadata +59 -97
  58. metadata.gz.sig +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ff8b1c7b127254ed4d7b263f6059404d55f7d2c5
4
+ data.tar.gz: 56a9f3f7468241935f824fbcc6fb531bcc79c9ac
5
+ SHA512:
6
+ metadata.gz: 19aaa439fe5623157eddd25d709dc929d5271adc1e3d5e6f34880cb33e9b51185d4fca4594c2693ad49c4b3cfe400cf47d75098032b7b2539ffe93c322bad2d0
7
+ data.tar.gz: e6a3cf29a04aed9ca5a407d25d02fc1ede00550008e646379aff6018037f82029f697a979d0dfdfac6613f66fc912590272b9d1717994a7c9bb3528893d2b648
checksums.yaml.gz.sig ADDED
Binary file
data/History.md CHANGED
@@ -1,6 +1,53 @@
1
+ # Version 2.2.0
2
+
3
+ Release date: 2013-11-21
4
+
5
+ ### Added
6
+
7
+ * Add `go_back` and `go_forward` methods. [Vasiliy Ermolovich]
8
+ * Support RSpec 3 [Thomas Holmes]
9
+ * `has_button?`, `has_checked_field?` and `has_unchecked_field?` accept
10
+ options, like other matchers. [Carol Nichols]
11
+ * The `assert_selector` and `has_text?` methods now support the `:wait` option
12
+ [Vasiliy Ermolovich]
13
+ * RackTest's visible? method now checks for the HTML5 `hidden` attribute.
14
+ * Results from `#all` now delegate the `sample` method. [Phil Lee]
15
+ * The `set` method now works for contenteditable attributes under Selenium.
16
+ [Jon Rowe]
17
+ * radio buttons and check boxes can be filtered by option value, useful when
18
+ selecting by name [Jonas Nicklas]
19
+ * feature blocks can be nested within other feature blocks in RSpec tests
20
+ [Travis Gaff]
21
+
22
+ ### Fixed
23
+
24
+ * Fixed race conditions causing stale element errors when filtering by text.
25
+ [Jonas Nicklas]
26
+ * Resetting the page is now synchronous and navigates to an empty HTML file,
27
+ instead of `about:blank`, fixing hanging issues in JRuby. [Jonas Nicklas]
28
+ * Fixed cookies not being set when path is blank under RackTest [Thomas Walpole]
29
+ * Clearing fields now correctly causes change events [Jonas Nicklas]
30
+ * Navigating to an absolut URI without trailing slash now works as expected
31
+ under RackTest [Jonas Nicklas]
32
+ * Checkboxes without assigned value default to `on` under RackTest [Nigel Sheridan-Smith]
33
+ * Clicks on buttons with no form associated with them are ignored in RackTest
34
+ instead of raising an obscure exception. [Thomas Walpole]
35
+ * execute_script is now a session method [Andrey Botalov]
36
+ * Nesting `within_window` and `within_frame` inside `within` resets the scope
37
+ so that they behave like a user would expect [Thomas Walpole]
38
+ * Improve handling of newlines in textareas [Thomas Walpole]
39
+ * `Capybara::Result` delegates its inspect method, so as not to confuse users
40
+ [Sam Rawlins]
41
+ * save_page always returns a full path, fixes problems with Launchy [Jonas Nicklas]
42
+ * Selenium driver's `quit` method does nothing when browser hasn't been loaded
43
+ [randoum]
44
+ * Capybara's WEBRick server now propertly respects the server_host option
45
+ [Dmitry Vorotilin]
46
+ * gemspec now includes license information [Jonas Nicklas]
47
+
1
48
  # Version 2.1.0
2
49
 
3
- Release date: Unreleased
50
+ Release date: 2013-04-09
4
51
 
5
52
  ### Changed
6
53
 
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/jnicklas/capybara.png)](http://travis-ci.org/jnicklas/capybara)
4
4
  [![Dependency Status](https://gemnasium.com/jnicklas/capybara.png)](https://gemnasium.com/jnicklas/capybara)
5
- [![Code Quality](https://codeclimate.com/badge.png)](https://codeclimate.com/github/jnicklas/capybara)
5
+ [![Code Climate](https://codeclimate.com/github/jnicklas/capybara.png)](https://codeclimate.com/github/jnicklas/capybara)
6
6
 
7
7
  Capybara helps you test web applications by simulating how a real user would
8
8
  interact with your app. It is agnostic about the driver running your tests and
@@ -96,7 +96,7 @@ Capybara with `:type => :feature`.
96
96
  You can now write your specs like so:
97
97
 
98
98
  ```ruby
99
- describe "the signup process", :type => :feature do
99
+ describe "the signin process", :type => :feature do
100
100
  before :each do
101
101
  User.make(:email => 'user@example.com', :password => 'caplin')
102
102
  end
@@ -108,7 +108,7 @@ describe "the signup process", :type => :feature do
108
108
  fill_in 'Password', :with => 'password'
109
109
  end
110
110
  click_link 'Sign in'
111
- page.should have_content 'Success'
111
+ expect(page).to have_content 'Success'
112
112
  end
113
113
  end
114
114
  ```
@@ -127,7 +127,7 @@ end
127
127
  Finally, Capybara also comes with a built in DSL for creating descriptive acceptance tests:
128
128
 
129
129
  ```ruby
130
- feature "Signing up" do
130
+ feature "Signing in" do
131
131
  background do
132
132
  User.make(:email => 'user@example.com', :password => 'caplin')
133
133
  end
@@ -139,7 +139,7 @@ feature "Signing up" do
139
139
  fill_in 'Password', :with => 'caplin'
140
140
  end
141
141
  click_link 'Sign in'
142
- page.should have_content 'Success'
142
+ expect(page).to have_content 'Success'
143
143
  end
144
144
 
145
145
  given(:other_user) { User.make(:email => 'other@example.com', :password => 'rous') }
@@ -151,7 +151,7 @@ feature "Signing up" do
151
151
  fill_in 'Password', :with => other_user.password
152
152
  end
153
153
  click_link 'Sign in'
154
- page.should have_content 'Invalid email or password'
154
+ expect(page).to have_content 'Invalid email or password'
155
155
  end
156
156
  end
157
157
  ```
@@ -162,7 +162,7 @@ end
162
162
 
163
163
  ## Using Capybara with Test::Unit
164
164
 
165
- * If you are using Rails, add the following code in your `test_helper.rb`
165
+ * If you are using Rails, add the following code in your `test_helper.rb`
166
166
  file to make Capybara available in all test cases deriving from
167
167
  `ActionDispatch::IntegrationTest`:
168
168
 
@@ -209,7 +209,7 @@ end
209
209
  Set up your base class as with Test::Unit. (On Rails, the right base class
210
210
  could be something other than ActionDispatch::IntegrationTest.)
211
211
 
212
- The capybara_minitest_spec gem ([Github](https://github.com/ordinaryzelig/capybara_minitest_spec),
212
+ The capybara_minitest_spec gem ([GitHub](https://github.com/ordinaryzelig/capybara_minitest_spec),
213
213
  [rubygems.org](https://rubygems.org/gems/capybara_minitest_spec)) provides MiniTest::Spec
214
214
  expectations for Capybara. For example:
215
215
 
@@ -271,7 +271,7 @@ RackTest can be configured with a set of headers like this:
271
271
 
272
272
  ```ruby
273
273
  Capybara.register_driver :rack_test do |app|
274
- Capybara::RackTest::Driver.new(app, :browser => :chrome)
274
+ Capybara::RackTest::Driver.new(app, :headers => { 'HTTP_USER_AGENT' => 'Capybara' })
275
275
  end
276
276
  ```
277
277
 
@@ -281,10 +281,12 @@ See the section on adding and configuring drivers.
281
281
 
282
282
  At the moment, Capybara supports [Selenium 2.0
283
283
  (Webdriver)](http://seleniumhq.org/docs/01_introducing_selenium.html#selenium-2-aka-selenium-webdriver),
284
- *not* Selenium RC. Provided Firefox is installed, everything is set up for you,
285
- and you should be able to start using Selenium right away.
284
+ *not* Selenium RC. In order to use Selenium, you'll need to install the
285
+ `selenium-webdriver` gem, and add it to your Gemfile if you're using bundler.
286
+ Provided Firefox is installed, everything is set up for you, and you should be
287
+ able to start using Selenium right away.
286
288
 
287
- **Note**: drivers which run the server in a different thread may not work share the
289
+ **Note**: drivers which run the server in a different thread may not share the
288
290
  same transaction as your tests, causing data not to be shared between your test
289
291
  and test server, see "Transactions and database setup" below.
290
292
 
@@ -325,7 +327,7 @@ Capybara heavily uses XPath, which doesn't support case insensitivity.
325
327
  ### Navigating
326
328
 
327
329
  You can use the
328
- [#visit](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#visit-instance_method)
330
+ <tt>[visit](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#visit-instance_method)</tt>
329
331
  method to navigate to other pages:
330
332
 
331
333
  ```ruby
@@ -450,8 +452,6 @@ within(:xpath, "//li[@id='employee']") do
450
452
  end
451
453
  ```
452
454
 
453
- **Note**: `within` will scope the actions to the _first_ (not _any_) element that matches the selector.
454
-
455
455
  There are special methods for restricting the scope to a specific fieldset,
456
456
  identified by either an id or the text of the fieldset's legend tag, and to a
457
457
  specific table, identified by either id or text of the table's caption tag.
@@ -794,7 +794,7 @@ end
794
794
 
795
795
  Capybara makes it convenient to switch between different drivers. It also exposes
796
796
  an API to tweak those drivers with whatever settings you want, or to add your own
797
- drivers. This is how to switch the selenium driver to use chrome:
797
+ drivers. This is how to override the selenium driver configuration to use chrome:
798
798
 
799
799
  ```ruby
800
800
  Capybara.register_driver :selenium do |app|
@@ -802,8 +802,7 @@ Capybara.register_driver :selenium do |app|
802
802
  end
803
803
  ```
804
804
 
805
- However, it's also possible to give this a different name, so tests can switch
806
- between using different browsers effortlessly:
805
+ However, it's also possible to give this configuration a different name.
807
806
 
808
807
  ```ruby
809
808
  Capybara.register_driver :selenium_chrome do |app|
@@ -811,6 +810,11 @@ Capybara.register_driver :selenium_chrome do |app|
811
810
  end
812
811
  ```
813
812
 
813
+ Then tests can switch between using different browsers effortlessly:
814
+ ```ruby
815
+ Capybara.current_driver = :selenium_chrome
816
+ ```
817
+
814
818
  Whatever is returned from the block should conform to the API described by
815
819
  Capybara::Driver::Base, it does not however have to inherit from this class.
816
820
  Gems can use this API to add their own drivers to Capybara.
@@ -1,6 +1,4 @@
1
1
  require 'capybara'
2
-
3
- require 'capybara/dsl'
4
2
  require 'capybara/rspec/matchers'
5
3
 
6
4
  World(Capybara::DSL)
@@ -10,7 +10,7 @@ class Capybara::Driver::Base
10
10
  def find_xpath(query)
11
11
  raise NotImplementedError
12
12
  end
13
-
13
+
14
14
  def find_css(query)
15
15
  raise NotImplementedError
16
16
  end
@@ -19,6 +19,14 @@ class Capybara::Driver::Base
19
19
  raise NotImplementedError
20
20
  end
21
21
 
22
+ def go_back
23
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#go_back'
24
+ end
25
+
26
+ def go_forward
27
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#go_forward'
28
+ end
29
+
22
30
  def execute_script(script)
23
31
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#execute_script'
24
32
  end
@@ -0,0 +1,4 @@
1
+ <!doctype>
2
+ <html>
3
+ <!-- an empty HTML document, used for resetting the page content -->
4
+ </html>
@@ -19,7 +19,7 @@ module Capybara
19
19
  # Finds a link by id or text and clicks it. Also looks at image
20
20
  # alt text inside the link.
21
21
  #
22
- # @param [String] locator Text, id or text of link
22
+ # @param [String] locator Text or id of link
23
23
  # @param options
24
24
  # @option options [String] :href The value the href attribute must be
25
25
  #
@@ -147,16 +147,16 @@ module Capybara
147
147
  private
148
148
 
149
149
  def resolve_query(query, exact=nil)
150
- elements = synchronize do
151
- if query.selector.format==:css
150
+ synchronize do
151
+ elements = if query.selector.format==:css
152
152
  base.find_css(query.css)
153
153
  else
154
154
  base.find_xpath(query.xpath(exact))
155
155
  end.map do |node|
156
156
  Capybara::Node::Element.new(session, node, self, query)
157
157
  end
158
+ Capybara::Result.new(elements, query)
158
159
  end
159
- Capybara::Result.new(elements, query)
160
160
  end
161
161
  end
162
162
  end
@@ -85,7 +85,8 @@ module Capybara
85
85
  # @raise [Capybara::ExpectationNotMet] If the selector does not exist
86
86
  #
87
87
  def assert_selector(*args)
88
- synchronize do
88
+ query = Capybara::Query.new(*args)
89
+ synchronize(query.wait) do
89
90
  result = all(*args)
90
91
  result.matches_count? or raise Capybara::ExpectationNotMet, result.failure_message
91
92
  end
@@ -101,7 +102,8 @@ module Capybara
101
102
  # @raise [Capybara::ExpectationNotMet] If the selector exists
102
103
  #
103
104
  def assert_no_selector(*args)
104
- synchronize do
105
+ query = Capybara::Query.new(*args)
106
+ synchronize(query.wait) do
105
107
  result = all(*args)
106
108
  result.matches_count? and raise Capybara::ExpectationNotMet, result.negative_failure_message
107
109
  end
@@ -215,7 +217,8 @@ module Capybara
215
217
  # @return [Boolean] Whether it exists
216
218
  #
217
219
  def has_text?(*args)
218
- synchronize do
220
+ query = Capybara::Query.new(*args)
221
+ synchronize(query.wait) do
219
222
  raise ExpectationNotMet unless text_found?(*args)
220
223
  end
221
224
  return true
@@ -233,7 +236,8 @@ module Capybara
233
236
  # @return [Boolean] Whether it doesn't exist
234
237
  #
235
238
  def has_no_text?(*args)
236
- synchronize do
239
+ query = Capybara::Query.new(*args)
240
+ synchronize(query.wait) do
237
241
  raise ExpectationNotMet if text_found?(*args)
238
242
  end
239
243
  return true
@@ -276,8 +280,8 @@ module Capybara
276
280
  # @param [String] locator The text, value or id of a button to check for
277
281
  # @return [Boolean] Whether it exists
278
282
  #
279
- def has_button?(locator)
280
- has_selector?(:button, locator)
283
+ def has_button?(locator, options={})
284
+ has_selector?(:button, locator, options)
281
285
  end
282
286
 
283
287
  ##
@@ -288,8 +292,8 @@ module Capybara
288
292
  # @param [String] locator The text, value or id of a button to check for
289
293
  # @return [Boolean] Whether it doesn't exist
290
294
  #
291
- def has_no_button?(locator)
292
- has_no_selector?(:button, locator)
295
+ def has_no_button?(locator, options={})
296
+ has_no_selector?(:button, locator, options)
293
297
  end
294
298
 
295
299
  ##
@@ -341,8 +345,8 @@ module Capybara
341
345
  # @param [String] locator The label, name or id of a checked field
342
346
  # @return [Boolean] Whether it exists
343
347
  #
344
- def has_checked_field?(locator)
345
- has_selector?(:field, locator, :checked => true)
348
+ def has_checked_field?(locator, options={})
349
+ has_selector?(:field, locator, options.merge(:checked => true))
346
350
  end
347
351
 
348
352
  ##
@@ -352,10 +356,10 @@ module Capybara
352
356
  # checked.
353
357
  #
354
358
  # @param [String] locator The label, name or id of a checked field
355
- # @return [Boolean] Whether it doesn't exists
359
+ # @return [Boolean] Whether it doesn't exist
356
360
  #
357
- def has_no_checked_field?(locator)
358
- has_no_selector?(:field, locator, :checked => true)
361
+ def has_no_checked_field?(locator, options={})
362
+ has_no_selector?(:field, locator, options.merge(:checked => true))
359
363
  end
360
364
 
361
365
  ##
@@ -367,8 +371,8 @@ module Capybara
367
371
  # @param [String] locator The label, name or id of an unchecked field
368
372
  # @return [Boolean] Whether it exists
369
373
  #
370
- def has_unchecked_field?(locator)
371
- has_selector?(:field, locator, :unchecked => true)
374
+ def has_unchecked_field?(locator, options={})
375
+ has_selector?(:field, locator, options.merge(:unchecked => true))
372
376
  end
373
377
 
374
378
  ##
@@ -378,10 +382,10 @@ module Capybara
378
382
  # unchecked.
379
383
  #
380
384
  # @param [String] locator The label, name or id of an unchecked field
381
- # @return [Boolean] Whether it doesn't exists
385
+ # @return [Boolean] Whether it doesn't exist
382
386
  #
383
- def has_no_unchecked_field?(locator)
384
- has_no_selector?(:field, locator, :unchecked => true)
387
+ def has_no_unchecked_field?(locator, options={})
388
+ has_no_selector?(:field, locator, options.merge(:unchecked => true))
385
389
  end
386
390
 
387
391
  ##
@@ -18,7 +18,7 @@ module Capybara
18
18
  attr_reader :native
19
19
 
20
20
  def initialize(native)
21
- native = Nokogiri::HTML(native) if native.is_a?(String)
21
+ native = Capybara::HTML(native) if native.is_a?(String)
22
22
  @native = native
23
23
  end
24
24
 
@@ -74,7 +74,7 @@ module Capybara
74
74
  #
75
75
  def value
76
76
  if tag_name == 'textarea'
77
- native.content.sub(/\A\n/, '')
77
+ native.content
78
78
  elsif tag_name == 'select'
79
79
  if native['multiple'] == 'multiple'
80
80
  native.xpath(".//option[@selected='selected']").map { |option| option[:value] || option.content }
@@ -82,6 +82,8 @@ module Capybara
82
82
  option = native.xpath(".//option[@selected='selected']").first || native.xpath(".//option").first
83
83
  option[:value] || option.content if option
84
84
  end
85
+ elsif tag_name == 'input' && %w(radio checkbox).include?(native[:type])
86
+ native[:value] || 'on'
85
87
  else
86
88
  native[:value]
87
89
  end
@@ -95,7 +97,7 @@ module Capybara
95
97
  # @return [Boolean] Whether the element is visible
96
98
  #
97
99
  def visible?
98
- native.xpath("./ancestor-or-self::*[contains(@style, 'display:none') or contains(@style, 'display: none') or name()='script' or name()='head']").size == 0
100
+ native.xpath("./ancestor-or-self::*[contains(@style, 'display:none') or contains(@style, 'display: none') or @hidden or name()='script' or name()='head']").size == 0
99
101
  end
100
102
 
101
103
  ##
@@ -32,6 +32,7 @@ module Capybara
32
32
  def description
33
33
  @description = "#{label} #{locator.inspect}"
34
34
  @description << " with text #{options[:text].inspect}" if options[:text]
35
+ @description << " with value #{options[:with].inspect}" if options[:with]
35
36
  @description
36
37
  end
37
38
 
@@ -46,6 +46,7 @@ class Capybara::RackTest::Browser
46
46
  method.downcase! unless method.is_a? Symbol
47
47
 
48
48
  new_uri.path = request_path if path.start_with?("?")
49
+ new_uri.path = "/" if new_uri.path.empty?
49
50
  new_uri.path = request_path.sub(%r(/[^/]*$), '/') + new_uri.path unless new_uri.path.start_with?('/')
50
51
  new_uri.scheme ||= @current_scheme
51
52
  new_uri.host ||= @current_host
@@ -77,7 +78,7 @@ class Capybara::RackTest::Browser
77
78
  end
78
79
 
79
80
  def dom
80
- @dom ||= Nokogiri::HTML(html)
81
+ @dom ||= Capybara::HTML(html)
81
82
  end
82
83
 
83
84
  def find(format, selector)
@@ -93,11 +94,11 @@ class Capybara::RackTest::Browser
93
94
  rescue Rack::Test::Error
94
95
  ""
95
96
  end
96
-
97
+
97
98
  def title
98
99
  dom.xpath("//title").text
99
100
  end
100
-
101
+
101
102
  protected
102
103
 
103
104
  def build_rack_mock_session
@@ -108,6 +109,6 @@ protected
108
109
  def request_path
109
110
  last_request.path
110
111
  rescue Rack::Test::Error
111
- ""
112
+ "/"
112
113
  end
113
114
  end
@@ -28,7 +28,10 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
28
28
  case field.name
29
29
  when 'input'
30
30
  if %w(radio checkbox).include? field['type']
31
- merge_param!(params, field['name'].to_s, field['value'].to_s) if field['checked']
31
+ if field['checked']
32
+ node=Capybara::RackTest::Node.new(self.driver, field)
33
+ merge_param!(params, field['name'].to_s, node.value.to_s)
34
+ end
32
35
  elsif %w(submit image).include? field['type']
33
36
  # TO DO identify the click button here (in document order, rather
34
37
  # than leaving until the end of the params)
@@ -60,7 +63,7 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
60
63
  merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s) if option
61
64
  end
62
65
  when 'textarea'
63
- merge_param!(params, field['name'].to_s, field.text.to_s)
66
+ merge_param!(params, field['name'].to_s, field.text.to_s.gsub(/\n/, "\r\n"))
64
67
  end
65
68
  end
66
69
  merge_param!(params, button[:name], button[:value] || "") if button[:name]
@@ -52,7 +52,8 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
52
52
  driver.follow(method, self[:href].to_s)
53
53
  elsif (tag_name == 'input' and %w(submit image).include?(type)) or
54
54
  ((tag_name == 'button') and type.nil? or type == "submit")
55
- Capybara::RackTest::Form.new(driver, form).submit(self)
55
+ associated_form = form
56
+ Capybara::RackTest::Form.new(driver, associated_form).submit(self) if associated_form
56
57
  end
57
58
  end
58
59
 
@@ -29,7 +29,8 @@ module Capybara
29
29
  @query = query
30
30
  end
31
31
 
32
- def_delegators :@result, :each, :[], :at, :size, :count, :length, :first, :last, :empty?
32
+ def_delegators :@result, :each, :[], :at, :size, :count, :length,
33
+ :first, :last, :values_at, :empty?, :inspect, :sample, :index
33
34
 
34
35
  def matches_count?
35
36
  Capybara::Helpers.matches_count?(@result.size, @query.options)
@@ -7,11 +7,13 @@ module Capybara
7
7
  alias :xscenario :xit
8
8
  alias :given :let
9
9
  alias :given! :let!
10
+ alias :feature :describe
10
11
  end
11
12
  end
12
13
  end
13
14
  end
14
15
 
16
+
15
17
  def self.feature(*args, &block)
16
18
  options = if args.last.is_a?(Hash) then args.pop else {} end
17
19
  options[:capybara_feature] = true
@@ -126,20 +126,20 @@ module Capybara
126
126
  HaveSelector.new(:link, locator, options)
127
127
  end
128
128
 
129
- def have_button(locator)
130
- HaveSelector.new(:button, locator)
129
+ def have_button(locator, options={})
130
+ HaveSelector.new(:button, locator, options)
131
131
  end
132
132
 
133
133
  def have_field(locator, options={})
134
134
  HaveSelector.new(:field, locator, options)
135
135
  end
136
136
 
137
- def have_checked_field(locator)
138
- HaveSelector.new(:field, locator, :checked => true)
137
+ def have_checked_field(locator, options={})
138
+ HaveSelector.new(:field, locator, options.merge(:checked => true))
139
139
  end
140
140
 
141
- def have_unchecked_field(locator)
142
- HaveSelector.new(:field, locator, :unchecked => true)
141
+ def have_unchecked_field(locator, options={})
142
+ HaveSelector.new(:field, locator, options.merge(:unchecked => true))
143
143
  end
144
144
 
145
145
  def have_select(locator, options={})
@@ -7,6 +7,12 @@ require 'capybara/rspec/features'
7
7
  RSpec.configure do |config|
8
8
  config.include Capybara::DSL, :type => :feature
9
9
  config.include Capybara::RSpecMatchers, :type => :feature
10
+
11
+ # A work-around to support accessing the current example that works in both
12
+ # RSpec 2 and RSpec 3.
13
+ fetch_current_example = RSpec.respond_to?(:current_example) ?
14
+ proc { RSpec.current_example } : proc { |context| context.example }
15
+
10
16
  # The before and after blocks must run instantaneously, because Capybara
11
17
  # might not actually be used in all examples where it's included.
12
18
  config.after do
@@ -17,6 +23,7 @@ RSpec.configure do |config|
17
23
  end
18
24
  config.before do
19
25
  if self.class.include?(Capybara::DSL)
26
+ example = fetch_current_example.call(self)
20
27
  Capybara.current_driver = Capybara.javascript_driver if example.metadata[:js]
21
28
  Capybara.current_driver = example.metadata[:driver] if example.metadata[:driver]
22
29
  end
@@ -103,7 +103,7 @@ Capybara.add_selector(:field) do
103
103
  filter(:checked) { |node, value| not(value ^ node.checked?) }
104
104
  filter(:unchecked) { |node, value| (value ^ node.checked?) }
105
105
  filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
106
- filter(:with) { |node, with| node.value == with }
106
+ filter(:with) { |node, with| node.value == with.to_s }
107
107
  filter(:type) do |node, type|
108
108
  if ['textarea', 'select'].include?(type)
109
109
  node.tag_name == type
@@ -146,6 +146,7 @@ Capybara.add_selector(:radio_button) do
146
146
  xpath { |locator| XPath::HTML.radio_button(locator) }
147
147
  filter(:checked) { |node, value| not(value ^ node.checked?) }
148
148
  filter(:unchecked) { |node, value| (value ^ node.checked?) }
149
+ filter(:option) { |node, value| node.value == value.to_s }
149
150
  filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
150
151
  end
151
152
 
@@ -153,6 +154,7 @@ Capybara.add_selector(:checkbox) do
153
154
  xpath { |locator| XPath::HTML.checkbox(locator) }
154
155
  filter(:checked) { |node, value| not(value ^ node.checked?) }
155
156
  filter(:unchecked) { |node, value| (value ^ node.checked?) }
157
+ filter(:option) { |node, value| node.value == value.to_s }
156
158
  filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
157
159
  end
158
160
 
@@ -1,3 +1,5 @@
1
+ require "uri"
2
+
1
3
  class Capybara::Selenium::Driver < Capybara::Driver::Base
2
4
  DEFAULT_OPTIONS = {
3
5
  :browser => :firefox
@@ -43,6 +45,14 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
43
45
  browser.navigate.to(path)
44
46
  end
45
47
 
48
+ def go_back
49
+ browser.navigate.back
50
+ end
51
+
52
+ def go_forward
53
+ browser.navigate.forward
54
+ end
55
+
46
56
  def html
47
57
  browser.page_source
48
58
  end
@@ -87,7 +97,9 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
87
97
  # to about:blank, so we rescue this error and do nothing
88
98
  # instead.
89
99
  end
90
- @browser.navigate.to('about:blank')
100
+ uri = URI(Capybara::EMPTY_HTML_FILE_PATH)
101
+ uri.scheme = "file"
102
+ @browser.navigate.to(uri.to_s)
91
103
  end
92
104
  end
93
105
 
@@ -137,7 +149,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
137
149
  end
138
150
 
139
151
  def quit
140
- @browser.quit
152
+ @browser.quit if @browser
141
153
  rescue Errno::ECONNREFUSED
142
154
  # Browser must have already gone
143
155
  end