capybara 2.2.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +26 -0
  3. data/README.md +36 -14
  4. data/lib/capybara.rb +6 -3
  5. data/lib/capybara/driver/base.rb +37 -1
  6. data/lib/capybara/driver/node.rb +10 -2
  7. data/lib/capybara/helpers.rb +21 -13
  8. data/lib/capybara/node/base.rb +12 -7
  9. data/lib/capybara/node/element.rb +17 -1
  10. data/lib/capybara/node/finders.rb +22 -1
  11. data/lib/capybara/node/matchers.rb +26 -5
  12. data/lib/capybara/node/simple.rb +9 -2
  13. data/lib/capybara/rack_test/css_handlers.rb +3 -1
  14. data/lib/capybara/rack_test/form.rb +3 -2
  15. data/lib/capybara/rack_test/node.rb +3 -3
  16. data/lib/capybara/rspec.rb +1 -0
  17. data/lib/capybara/rspec/features.rb +2 -1
  18. data/lib/capybara/rspec/matchers.rb +50 -5
  19. data/lib/capybara/selenium/driver.rb +76 -12
  20. data/lib/capybara/selenium/node.rb +8 -0
  21. data/lib/capybara/server.rb +1 -1
  22. data/lib/capybara/session.rb +234 -29
  23. data/lib/capybara/spec/public/jquery.js +1 -1
  24. data/lib/capybara/spec/public/test.js +7 -0
  25. data/lib/capybara/spec/session/all_spec.rb +88 -17
  26. data/lib/capybara/spec/session/assert_selector.rb +6 -0
  27. data/lib/capybara/spec/session/attach_file_spec.rb +15 -15
  28. data/lib/capybara/spec/session/body_spec.rb +4 -4
  29. data/lib/capybara/spec/session/check_spec.rb +16 -16
  30. data/lib/capybara/spec/session/choose_spec.rb +5 -5
  31. data/lib/capybara/spec/session/click_button_spec.rb +93 -84
  32. data/lib/capybara/spec/session/click_link_or_button_spec.rb +8 -8
  33. data/lib/capybara/spec/session/click_link_spec.rb +26 -19
  34. data/lib/capybara/spec/session/current_scope_spec.rb +3 -3
  35. data/lib/capybara/spec/session/current_url_spec.rb +8 -8
  36. data/lib/capybara/spec/session/evaluate_script_spec.rb +1 -1
  37. data/lib/capybara/spec/session/execute_script_spec.rb +2 -2
  38. data/lib/capybara/spec/session/fill_in_spec.rb +22 -22
  39. data/lib/capybara/spec/session/find_button_spec.rb +4 -4
  40. data/lib/capybara/spec/session/find_by_id_spec.rb +3 -3
  41. data/lib/capybara/spec/session/find_field_spec.rb +7 -7
  42. data/lib/capybara/spec/session/find_link_spec.rb +4 -4
  43. data/lib/capybara/spec/session/find_spec.rb +46 -46
  44. data/lib/capybara/spec/session/first_spec.rb +23 -23
  45. data/lib/capybara/spec/session/go_back_spec.rb +3 -3
  46. data/lib/capybara/spec/session/go_forward_spec.rb +4 -4
  47. data/lib/capybara/spec/session/has_button_spec.rb +13 -13
  48. data/lib/capybara/spec/session/has_css_spec.rb +87 -87
  49. data/lib/capybara/spec/session/has_field_spec.rb +87 -87
  50. data/lib/capybara/spec/session/has_link_spec.rb +11 -11
  51. data/lib/capybara/spec/session/has_select_spec.rb +58 -58
  52. data/lib/capybara/spec/session/has_selector_spec.rb +48 -48
  53. data/lib/capybara/spec/session/has_table_spec.rb +7 -7
  54. data/lib/capybara/spec/session/has_text_spec.rb +73 -73
  55. data/lib/capybara/spec/session/has_title_spec.rb +10 -10
  56. data/lib/capybara/spec/session/has_xpath_spec.rb +44 -44
  57. data/lib/capybara/spec/session/headers.rb +1 -1
  58. data/lib/capybara/spec/session/html_spec.rb +9 -9
  59. data/lib/capybara/spec/session/node_spec.rb +81 -65
  60. data/lib/capybara/spec/session/reset_session_spec.rb +15 -15
  61. data/lib/capybara/spec/session/response_code.rb +1 -1
  62. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +46 -0
  63. data/lib/capybara/spec/session/save_page_spec.rb +9 -9
  64. data/lib/capybara/spec/session/{screenshot.rb → screenshot_spec.rb} +4 -2
  65. data/lib/capybara/spec/session/select_spec.rb +22 -22
  66. data/lib/capybara/spec/session/text_spec.rb +15 -10
  67. data/lib/capybara/spec/session/title_spec.rb +2 -2
  68. data/lib/capybara/spec/session/uncheck_spec.rb +7 -7
  69. data/lib/capybara/spec/session/unselect_spec.rb +14 -14
  70. data/lib/capybara/spec/session/visit_spec.rb +24 -17
  71. data/lib/capybara/spec/session/window/become_closed_spec.rb +84 -0
  72. data/lib/capybara/spec/session/window/current_window_spec.rb +25 -0
  73. data/lib/capybara/spec/session/window/open_new_window_spec.rb +28 -0
  74. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +114 -0
  75. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +83 -0
  76. data/lib/capybara/spec/session/window/window_spec.rb +141 -0
  77. data/lib/capybara/spec/session/window/windows_spec.rb +31 -0
  78. data/lib/capybara/spec/session/window/within_window_spec.rb +188 -0
  79. data/lib/capybara/spec/session/within_frame_spec.rb +9 -9
  80. data/lib/capybara/spec/session/within_spec.rb +16 -16
  81. data/lib/capybara/spec/spec_helper.rb +14 -4
  82. data/lib/capybara/spec/views/form.erb +7 -0
  83. data/lib/capybara/spec/views/popup_one.erb +1 -1
  84. data/lib/capybara/spec/views/popup_two.erb +1 -1
  85. data/lib/capybara/spec/views/with_js.erb +2 -0
  86. data/lib/capybara/spec/views/with_windows.erb +38 -0
  87. data/lib/capybara/version.rb +1 -1
  88. data/lib/capybara/window.rb +123 -0
  89. data/spec/basic_node_spec.rb +32 -32
  90. data/spec/capybara_spec.rb +6 -7
  91. data/spec/dsl_spec.rb +48 -48
  92. data/spec/fixtures/selenium_driver_rspec_failure.rb +2 -2
  93. data/spec/fixtures/selenium_driver_rspec_success.rb +2 -2
  94. data/spec/rack_test_spec.rb +33 -19
  95. data/spec/result_spec.rb +13 -13
  96. data/spec/rspec/features_spec.rb +20 -15
  97. data/spec/rspec/matchers_spec.rb +109 -109
  98. data/spec/rspec_spec.rb +10 -10
  99. data/spec/selenium_spec.rb +31 -6
  100. data/spec/selenium_spec_chrome.rb +2 -2
  101. data/spec/server_spec.rb +13 -13
  102. metadata +51 -62
  103. checksums.yaml.gz.sig +0 -0
  104. data.tar.gz.sig +0 -0
  105. data/lib/capybara/spec/session/within_window_spec.rb +0 -45
  106. data/lib/capybara/spec/views/within_popups.erb +0 -25
  107. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f461ce522452cc01f332856bf2d2adc68364c19a
4
- data.tar.gz: 2ecab34b9e3dfd9d2df9a027d094e52995fe33fc
3
+ metadata.gz: 9aa9a8cc20ae71dd404a731f98867ba19be9d4f2
4
+ data.tar.gz: 58b4097a52c34c878ceca8b9bf8477bc20a6e32a
5
5
  SHA512:
6
- metadata.gz: 68b4bca1f71303ea1d24aaf849615d89773fcfacdff28c506e1d93de4592ad5b3f12d5c01ba3ff09756c36094421361207e0345651aa55544d124c636409e88e
7
- data.tar.gz: 1bcafd2a83f248ccdfa86c5fe01b81b7865687b622464245594e307e875d4dba3c9acaddf909df84b1a392eb2f4fc012bd4457901d0e245b9dcebb291cf0d921
6
+ metadata.gz: 4f49792d051b3a87893c10becbb4866eff4cee8a6e9d146a3adfec388df1373c1fe382c390ac9f982de24845c8ea4297a0f168ade5318c628611d1043752cafb
7
+ data.tar.gz: c707670017ac8f9b9cd335c1cd006724f84d56747c79f7e4ebf4203b4cdac39fa3e211b11c7c8e2819dbd8556bb2c49876e945c37328c47e84bc465e679aa034
data/History.md CHANGED
@@ -1,3 +1,29 @@
1
+ # Version 2.3.0
2
+
3
+ Release date: 2014-06-02
4
+
5
+ ### Added
6
+ * New window management API [Andrey Botalov]
7
+ * Speed improvement for visible text detection in RackTest [Thomas Walpole]
8
+ Thanks to Phillipe Creux for instigating this
9
+ * RSpec 3 compatability
10
+ * 'save_and_open_screenshot' functionality [Greg Lazarev]
11
+ * Server errors raised on visit and synchronize [Jonas Nicklas]
12
+
13
+ ### Fixed
14
+
15
+ * CSSHandlers now derives from BasicObject so globally included functions (concat, etc) shouldn't cause issues [Thomas Walpole]
16
+ * touched reset after session is reset [lesliepc16]
17
+
18
+ # Version 2.2.1
19
+
20
+ Release date: 2014-01-06
21
+
22
+ ### Fixed
23
+
24
+ * Reverted a change in 2.2.0 which navigates to an empty file on `reset`.
25
+ Capybara, now visits `about:blank` like it did before. [Jonas Nicklas]
26
+
1
27
  # Version 2.2.0
2
28
 
3
29
  Release date: 2013-11-21
data/README.md CHANGED
@@ -23,10 +23,11 @@ GitHub): http://groups.google.com/group/ruby-capybara
23
23
 
24
24
  ## Setup
25
25
 
26
- Capybara requires Ruby 1.9.3 or later. To install, type:
26
+ Capybara requires Ruby 1.9.3 or later. To install, add this line to your
27
+ `Gemfile` and run `bundle install`:
27
28
 
28
- ```bash
29
- gem install capybara
29
+ ```ruby
30
+ gem 'capybara'
30
31
  ```
31
32
 
32
33
  If the application that you are testing is a Rails app, add this line to your test helper file:
@@ -342,7 +343,7 @@ You can get the [current path](http://rubydoc.info/github/jnicklas/capybara/mast
342
343
  of the browsing session for test assertions:
343
344
 
344
345
  ```ruby
345
- current_path.should == post_comments_path(post)
346
+ expect(current_path).to eq(post_comments_path(post))
346
347
  ```
347
348
 
348
349
  ### Clicking links and buttons
@@ -399,12 +400,12 @@ has_selector?`. Read the section on asynchronous JavaScript for an explanation.
399
400
  You can use these with RSpec's magic matchers:
400
401
 
401
402
  ```ruby
402
- page.should have_selector('table tr')
403
- page.should have_selector(:xpath, '//table/tr')
403
+ expect(page).to have_selector('table tr')
404
+ expect(page).to have_selector(:xpath, '//table/tr')
404
405
 
405
- page.should have_xpath('//table/tr')
406
- page.should have_css('table tr.foo')
407
- page.should have_content('foo')
406
+ expect(page).to have_xpath('//table/tr')
407
+ expect(page).to have_css('table tr.foo')
408
+ expect(page).to have_content('foo')
408
409
  ```
409
410
 
410
411
  ### Finding
@@ -431,7 +432,7 @@ to specific parts of the page:
431
432
 
432
433
  ```ruby
433
434
  find('#navigation').click_link('Home')
434
- find('#navigation').should have_button('Sign out')
435
+ expect(find('#navigation')).to have_button('Sign out')
435
436
  ```
436
437
 
437
438
  ### Scoping
@@ -466,6 +467,21 @@ within_table('Employee') do
466
467
  end
467
468
  ```
468
469
 
470
+ ### Working with windows
471
+
472
+ Capybara provides some methods to ease finding and switching windows:
473
+
474
+ ```ruby
475
+ facebook_window = window_opened_by do
476
+ click_button 'Like'
477
+ end
478
+ within_window facebook_window do
479
+ find('#login_email').set('a@example.com')
480
+ find('#login_password').set('qwerty')
481
+ click_button 'Submit'
482
+ end
483
+ ```
484
+
469
485
  ### Scripting
470
486
 
471
487
  In drivers which support it, you can easily execute JavaScript:
@@ -506,6 +522,12 @@ Finally, in drivers that support it, you can save a screenshot:
506
522
  page.save_screenshot('screenshot.png')
507
523
  ```
508
524
 
525
+ Or have it save and automatically open:
526
+
527
+ ```ruby
528
+ save_and_open_screenshot
529
+ ```
530
+
509
531
  ## Matching
510
532
 
511
533
  It is possible to customize how Capybara finds elements. At your disposal
@@ -594,7 +616,7 @@ When issuing instructions to the DSL such as:
594
616
  ```ruby
595
617
  click_link('foo')
596
618
  click_link('bar')
597
- page.should have_content('baz')
619
+ expect(page).to have_content('baz')
598
620
  ```
599
621
 
600
622
  If clicking on the *foo* link triggers an asynchronous process, such as
@@ -626,15 +648,15 @@ Capybara's Rspec matchers, however, are smart enough to handle either form.
626
648
  The two following statements are functionally equivalent:
627
649
 
628
650
  ```ruby
629
- page.should_not have_xpath('a')
630
- page.should have_no_xpath('a')
651
+ expect(page).not_to have_xpath('a')
652
+ expect(page).to have_no_xpath('a')
631
653
  ```
632
654
 
633
655
  Capybara's waiting behaviour is quite advanced, and can deal with situations
634
656
  such as the following line of code:
635
657
 
636
658
  ```ruby
637
- find('#sidebar').find('h1').should have_content('Something')
659
+ expect(find('#sidebar').find('h1')).to have_content('Something')
638
660
  ```
639
661
 
640
662
  Even if JavaScript causes `#sidebar` to disappear off the page, Capybara
@@ -13,6 +13,8 @@ module Capybara
13
13
  class UnselectNotAllowed < CapybaraError; end
14
14
  class NotSupportedByDriverError < CapybaraError; end
15
15
  class InfiniteRedirectError < CapybaraError; end
16
+ class ScopeError < CapybaraError; end
17
+ class WindowError < CapybaraError; end
16
18
 
17
19
  class << self
18
20
  attr_accessor :asset_host, :app_host, :run_server, :default_host, :always_include_port
@@ -39,7 +41,7 @@ module Capybara
39
41
  # [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
40
42
  # [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: CSS)
41
43
  # [default_wait_time = Integer] The number of seconds to wait for asynchronous processes to finish (Default: 2)
42
- # [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: false)
44
+ # [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: true)
43
45
  # [automatic_reload = Boolean] Whether to automatically reload elements as Capybara is waiting (Default: true)
44
46
  # [save_and_open_page_path = String] Where to put pages saved through save_and_open_page (Default: Dir.pwd)
45
47
  #
@@ -86,7 +88,7 @@ module Capybara
86
88
  # find(:row, 3)
87
89
  # page.find('table#myTable').find(:row, 3).text
88
90
  # page.find('table#myTable').has_selector?(:row, 3)
89
- # within(:row, 3) { page.should have_content('$100.000') }
91
+ # within(:row, 3) { expect(page).to have_content('$100.000') }
90
92
  #
91
93
  # Here is another example:
92
94
  #
@@ -118,7 +120,7 @@ module Capybara
118
120
  #
119
121
  # By default, Capybara will try to run webrick.
120
122
  #
121
- # @yield [app, port] This block recieves a rack app and port and should run a Rack handler
123
+ # @yield [app, port] This block receives a rack app and port and should run a Rack handler
122
124
  #
123
125
  def server(&block)
124
126
  if block_given?
@@ -316,6 +318,7 @@ module Capybara
316
318
  require 'capybara/helpers'
317
319
  require 'capybara/session'
318
320
  require 'capybara/dsl'
321
+ require 'capybara/window'
319
322
  require 'capybara/server'
320
323
  require 'capybara/selector'
321
324
  require 'capybara/query'
@@ -51,10 +51,46 @@ class Capybara::Driver::Base
51
51
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#within_frame'
52
52
  end
53
53
 
54
- def within_window(handle)
54
+ def current_window_handle
55
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#current_window_handle'
56
+ end
57
+
58
+ def window_size(handle)
59
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#window_size'
60
+ end
61
+
62
+ def resize_window_to(handle, width, height)
63
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#resize_window_to'
64
+ end
65
+
66
+ def maximize_window(handle)
67
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#maximize_current_window'
68
+ end
69
+
70
+ def close_window(handle)
71
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#close_window'
72
+ end
73
+
74
+ def window_handles
75
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#window_handles'
76
+ end
77
+
78
+ def open_new_window
79
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#open_new_window'
80
+ end
81
+
82
+ def switch_to_window(handle)
83
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#switch_to_window'
84
+ end
85
+
86
+ def within_window(locator)
55
87
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#within_window'
56
88
  end
57
89
 
90
+ def no_such_window_error
91
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#no_such_window_error'
92
+ end
93
+
58
94
  def invalid_element_errors
59
95
  []
60
96
  end
@@ -40,7 +40,15 @@ module Capybara
40
40
  def click
41
41
  raise NotImplementedError
42
42
  end
43
-
43
+
44
+ def right_click
45
+ raise NotImplmentedError
46
+ end
47
+
48
+ def double_click
49
+ raise NotImplementedError
50
+ end
51
+
44
52
  def hover
45
53
  raise NotImplementedError
46
54
  end
@@ -79,7 +87,7 @@ module Capybara
79
87
 
80
88
  def inspect
81
89
  %(#<#{self.class} tag="#{tag_name}" path="#{path}">)
82
- rescue NotSupportedByDriverError, 'Capybara::Driver::Node#inspect'
90
+ rescue NotSupportedByDriverError
83
91
  %(#<#{self.class} tag="#{tag_name}">)
84
92
  end
85
93
 
@@ -51,8 +51,10 @@ module Capybara
51
51
 
52
52
  ##
53
53
  #
54
- # Checks if the given count matches the given count options. By default,
55
- # when no options are given, count should be larger than zero.
54
+ # Checks if the given count matches the given count options.
55
+ # Defaults to true if no options are specified. If multiple
56
+ # options are provided, it tests that all conditions are met;
57
+ # however, if :count is supplied, all other options are ignored.
56
58
  #
57
59
  # @param [Integer] count The actual number. Should be coercible via Integer()
58
60
  # @option [Range] between Count must be within the given range
@@ -61,17 +63,23 @@ module Capybara
61
63
  # @option [Integer] minimum Count must be larger than or equal to this value
62
64
  #
63
65
  def matches_count?(count, options={})
64
- case
65
- when options[:between]
66
- options[:between] === count
67
- when options[:count]
68
- Integer(options[:count]) == count
69
- when options[:maximum]
70
- Integer(options[:maximum]) >= count
71
- when options[:minimum]
72
- Integer(options[:minimum]) <= count
66
+ return (Integer(options[:count]) == count) if options[:count]
67
+ return false if options[:maximum] && (Integer(options[:maximum]) < count)
68
+ return false if options[:minimum] && (Integer(options[:minimum]) > count)
69
+ return false if options[:between] && !(options[:between] === count)
70
+ return true
71
+ end
72
+
73
+ ##
74
+ #
75
+ # Checks if a count of 0 is valid for the given options hash.
76
+ # Returns false if options hash does not specify any count options.
77
+ #
78
+ def expects_none?(options={})
79
+ if [:count, :maximum, :minimum, :between].any? { |k| options.has_key? k }
80
+ matches_count?(0,options)
73
81
  else
74
- count > 0
82
+ false
75
83
  end
76
84
  end
77
85
 
@@ -104,7 +112,7 @@ module Capybara
104
112
  #
105
113
  # A poor man's `pluralize`. Given two declensions, one singular and one
106
114
  # plural, as well as a count, this will pick the correct declension. This
107
- # way we can generate gramatically correct error message.
115
+ # way we can generate grammatically correct error message.
108
116
  #
109
117
  # @param [String] singular The singular form of the word
110
118
  # @param [String] plural The plural form of the word
@@ -40,14 +40,14 @@ module Capybara
40
40
 
41
41
  ##
42
42
  #
43
- # This method is Capybara's primary defence agains asynchronicity
43
+ # This method is Capybara's primary defence against asynchronicity
44
44
  # problems. It works by attempting to run a given block of code until it
45
45
  # succeeds. The exact behaviour of this method depends on a number of
46
46
  # factors. Basically there are certain exceptions which, when raised
47
47
  # from the block, instead of bubbling up, are caught, and the block is
48
48
  # re-run.
49
49
  #
50
- # Certain drivers, such as RackTest, have no support for aynchronous
50
+ # Certain drivers, such as RackTest, have no support for asynchronous
51
51
  # processes, these drivers run the block, and any error raised bubbles up
52
52
  # immediately. This allows faster turn around in the case where an
53
53
  # expectation fails.
@@ -61,16 +61,19 @@ module Capybara
61
61
  #
62
62
  # As long as any of these exceptions are thrown, the block is re-run,
63
63
  # until a certain amount of time passes. The amount of time defaults to
64
- # {Capybara.default_wait_time} and can be overriden through the `seconds`
64
+ # {Capybara.default_wait_time} and can be overridden through the `seconds`
65
65
  # argument. This time is compared with the system time to see how much
66
66
  # time has passed. If the return value of `Time.now` is stubbed out,
67
67
  # Capybara will raise `Capybara::FrozenInTime`.
68
68
  #
69
69
  # @param [Integer] seconds Number of seconds to retry this block
70
+ # @param options [Hash]
71
+ # @option options [Array<Exception>] :errors (driver.invalid_element_errors +
72
+ # [Capybara::ElementNotFound]) exception types that cause the block to be rerun
70
73
  # @return [Object] The result of the given block
71
74
  # @raise [Capybara::FrozenInTime] If the return value of `Time.now` appears stuck
72
75
  #
73
- def synchronize(seconds=Capybara.default_wait_time)
76
+ def synchronize(seconds=Capybara.default_wait_time, options = {})
74
77
  start_time = Time.now
75
78
 
76
79
  if session.synchronized
@@ -80,8 +83,9 @@ module Capybara
80
83
  begin
81
84
  yield
82
85
  rescue => e
86
+ session.raise_server_error!
83
87
  raise e unless driver.wait?
84
- raise e unless catch_error?(e)
88
+ raise e unless catch_error?(e, options[:errors])
85
89
  raise e if (Time.now - start_time) >= seconds
86
90
  sleep(0.05)
87
91
  raise Capybara::FrozenInTime, "time appears to be frozen, Capybara does not work with libraries which freeze time, consider using time travelling instead" if Time.now == start_time
@@ -95,8 +99,9 @@ module Capybara
95
99
 
96
100
  protected
97
101
 
98
- def catch_error?(error)
99
- (driver.invalid_element_errors + [Capybara::ElementNotFound]).any? do |type|
102
+ def catch_error?(error, errors = nil)
103
+ errors ||= (driver.invalid_element_errors + [Capybara::ElementNotFound])
104
+ errors.any? do |type|
100
105
  error.is_a?(type)
101
106
  end
102
107
  end
@@ -118,6 +118,22 @@ module Capybara
118
118
  synchronize { base.click }
119
119
  end
120
120
 
121
+ ##
122
+ #
123
+ # Right Click the Element
124
+ #
125
+ def right_click
126
+ synchronize { base.right_click }
127
+ end
128
+
129
+ ##
130
+ #
131
+ # Double Click the Element
132
+ #
133
+ def double_click
134
+ synchronize { base.double_click }
135
+ end
136
+
121
137
  ##
122
138
  #
123
139
  # Hover on the Element
@@ -224,7 +240,7 @@ module Capybara
224
240
 
225
241
  def inspect
226
242
  %(#<Capybara::Element tag="#{tag_name}" path="#{path}">)
227
- rescue NotSupportedByDriverError, 'Capybara::Node::Element#inspect'
243
+ rescue NotSupportedByDriverError
228
244
  %(#<Capybara::Element tag="#{tag_name}">)
229
245
  end
230
246
  end
@@ -116,17 +116,38 @@ module Capybara
116
116
  # page.all('a', :text => 'Home')
117
117
  # page.all('#menu li', :visible => true)
118
118
  #
119
+ # By default if no elements are found, an empty array is returned;
120
+ # however, expectations can be set on the number of elements to be
121
+ # found using:
122
+ #
123
+ # page.assert_selector('p#foo', :count => 4)
124
+ # page.assert_selector('p#foo', :maximum => 10)
125
+ # page.assert_selector('p#foo', :minimum => 1)
126
+ # page.assert_selector('p#foo', :between => 1..10)
127
+ #
128
+ # See {Capybara::Helpers#matches_count?} for additional information about
129
+ # count matching.
130
+ #
119
131
  # @overload all([kind], locator, options)
120
132
  # @param [:css, :xpath] kind The type of selector
121
133
  # @param [String] locator The selector
122
134
  # @option options [String, Regexp] text Only find elements which contain this text or match this regexp
123
135
  # @option options [Boolean] visible Only find elements that are visible on the page. Setting this to false
124
136
  # finds invisible _and_ visible elements.
137
+ # @option options [Integer] count Exact number of matches that are expected to be found
138
+ # @option options [Integer] maximum Maximum number of matches that are expected to be found
139
+ # @option options [Integer] minimum Minimum number of matches that are expected to be found
140
+ # @option options [Range] between Number of matches found must be within the given range
125
141
  # @option options [Boolean] exact Control whether `is` expressions in the given XPath match exactly or partially
126
142
  # @return [Capybara::Result] A collection of found elements
127
143
  #
128
144
  def all(*args)
129
- resolve_query(Capybara::Query.new(*args))
145
+ query = Capybara::Query.new(*args)
146
+ synchronize(query.wait) do
147
+ result = resolve_query(query)
148
+ raise(Capybara::ExpectationNotMet, result.failure_message) unless result.matches_count?
149
+ result
150
+ end
130
151
  end
131
152
 
132
153
  ##