capybara 2.10.1 → 2.11.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +22 -0
  3. data/README.md +48 -29
  4. data/lib/capybara/node/actions.rb +39 -48
  5. data/lib/capybara/node/document.rb +4 -0
  6. data/lib/capybara/node/document_matchers.rb +13 -14
  7. data/lib/capybara/node/element.rb +21 -0
  8. data/lib/capybara/node/finders.rb +3 -3
  9. data/lib/capybara/node/matchers.rb +38 -31
  10. data/lib/capybara/node/simple.rb +3 -0
  11. data/lib/capybara/queries/selector_query.rb +4 -2
  12. data/lib/capybara/rack_test/node.rb +1 -1
  13. data/lib/capybara/result.rb +3 -1
  14. data/lib/capybara/rspec/matchers.rb +53 -95
  15. data/lib/capybara/selector/selector.rb +10 -5
  16. data/lib/capybara/selector.rb +7 -7
  17. data/lib/capybara/selenium/driver.rb +34 -7
  18. data/lib/capybara/selenium/node.rb +5 -1
  19. data/lib/capybara/session/matchers.rb +12 -14
  20. data/lib/capybara/session.rb +30 -29
  21. data/lib/capybara/spec/public/test.js +4 -0
  22. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
  23. data/lib/capybara/spec/session/attach_file_spec.rb +1 -1
  24. data/lib/capybara/spec/session/check_spec.rb +8 -0
  25. data/lib/capybara/spec/session/choose_spec.rb +5 -0
  26. data/lib/capybara/spec/session/click_link_or_button_spec.rb +5 -0
  27. data/lib/capybara/spec/session/click_link_spec.rb +5 -0
  28. data/lib/capybara/spec/session/element/assert_match_selector.rb +5 -0
  29. data/lib/capybara/spec/session/element/match_css_spec.rb +6 -0
  30. data/lib/capybara/spec/session/element/matches_selector_spec.rb +2 -0
  31. data/lib/capybara/spec/session/fill_in_spec.rb +5 -0
  32. data/lib/capybara/spec/session/find_spec.rb +1 -1
  33. data/lib/capybara/spec/session/first_spec.rb +10 -0
  34. data/lib/capybara/spec/session/has_selector_spec.rb +11 -0
  35. data/lib/capybara/spec/session/node_spec.rb +12 -1
  36. data/lib/capybara/spec/session/text_spec.rb +3 -4
  37. data/lib/capybara/spec/test_app.rb +10 -1
  38. data/lib/capybara/spec/views/with_js.erb +3 -1
  39. data/lib/capybara/version.rb +1 -1
  40. data/lib/capybara/window.rb +18 -2
  41. data/lib/capybara.rb +8 -9
  42. data/spec/basic_node_spec.rb +1 -1
  43. data/spec/capybara_spec.rb +4 -1
  44. data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -1
  45. data/spec/fixtures/selenium_driver_rspec_success.rb +4 -1
  46. data/spec/result_spec.rb +28 -2
  47. data/spec/rspec/{matchers_spec.rb → shared_spec_matchers.rb} +4 -3
  48. data/spec/selector_spec.rb +1 -1
  49. data/spec/selenium_spec_chrome.rb +36 -5
  50. data/spec/selenium_spec_firefox.rb +67 -0
  51. data/spec/selenium_spec_marionette.rb +114 -0
  52. data/spec/shared_selenium_session.rb +6 -4
  53. metadata +15 -8
  54. data/spec/selenium_firefox_spec.rb +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07946b3e00d76327b735257b253d81a77f0bfd00
4
- data.tar.gz: d374024318381ec84383a452871be665f7645168
3
+ metadata.gz: b4d75941bdc33b8e4b3d26aa8beb1a6d063fabca
4
+ data.tar.gz: 692a680d4d550e566e6c558bfe53608a024b4e49
5
5
  SHA512:
6
- metadata.gz: 0d5d700c0b6473d31e6196ff3def9f259a72038c4bfc4082e2b2351bda87ecbe20d25843d59eaba8f6b50de19f0314e708d9e340149cf0385eb2e8c0874f2bfc
7
- data.tar.gz: 5ce06798a097f56b478b3d1d9345aa50bc21977db980832747dba6429edd9506ea20aecbaebd320aae9e17675c46201f168bbdbc34ddf9cc3923e3458eef6184
6
+ metadata.gz: e9eee2dae8d51f3bff73da658a08d2aeefd6383c16cec7b269abbb2c99203239c996c83b0145946d473cc0d3d1076abd623f672dfa07dd4ad0ed9a74ea2ef001
7
+ data.tar.gz: 2fef0e0fb22d31ccbd4879df37100feb6c717508c57266539245d07a3ba74c3849ae02cab2dfc735054b6344effb2c4f6783658e95a3513737aa81cabb39f83e
data/History.md CHANGED
@@ -1,3 +1,25 @@
1
+ #2.11.0
2
+ Release date: 2016-12-05
3
+
4
+ ### Added
5
+ * Options for clearing session/local storage on reset added to the Selenium driver
6
+ * Window size changes wait for the size to stabilize
7
+ * Defined return value for most actions
8
+ * Ignore specific error when qutting selenium driver instance - Issue #1773 [Dylan Reichstadt, Thomas Walpole]
9
+ * Warn on selenium unknown errors rather than raising when quitting driver [Adam Pohorecki, Thomas Walpole]
10
+ * Capybara::Result#each now returns an `Enumerator` when called without a block - Issue #1777 [Thomas Walpole]
11
+
12
+ ### Fixed
13
+ * Selenium driver with Chrome should support multiple file upload [Thomas Walpole]
14
+ * Fix visible: :hidden with :text option behavior [Thomas Walpole]
15
+
16
+ #2.10.2
17
+ Release date: 2016-11-30
18
+
19
+ ### Fixed
20
+ * App exceptions with multiple parameter initializers now re-raised correctly - Issue #1785 [Michael Lutsiuk]
21
+ * Use Addressable::URI when parsing current_path since it's more lenient of technically invalid URLs - Issue #1801 [Marcos Duque, Thomas Walpole]
22
+
1
23
  #2.10.1
2
24
  Release date: 2016-10-08
3
25
 
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Capybara
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/jnicklas/capybara.svg)](https://travis-ci.org/jnicklas/capybara)
4
- [![Dependency Status](https://gemnasium.com/jnicklas/capybara.svg)](https://gemnasium.com/jnicklas/capybara)
5
- [![Code Climate](https://codeclimate.com/github/jnicklas/capybara.svg)](https://codeclimate.com/github/jnicklas/capybara)
3
+ [![Build Status](https://secure.travis-ci.org/teamcapybara/capybara.svg)](https://travis-ci.org/teamcapybara/capybara)
4
+ [![Dependency Status](https://gemnasium.com/teamcapybara/capybara.svg)](https://gemnasium.com/teamcapybara/capybara)
5
+ [![Code Climate](https://codeclimate.com/github/teamcapybara/capybara.svg)](https://codeclimate.com/github/teamcapybara/capybara)
6
6
  [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jnicklas/capybara?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
7
7
 
8
8
  Capybara helps you test web applications by simulating how a real user would
@@ -13,7 +13,21 @@ through an external gem.
13
13
  **Need help?** Ask on the mailing list (please do not open an issue on
14
14
  GitHub): http://groups.google.com/group/ruby-capybara
15
15
 
16
- **Note: Firefox 48+** If you're using Firefox with selenium-webdriver, stay on either Firefox [45.0esr](https://ftp.mozilla.org/pub/firefox/releases/45.0esr/) or [47.0.1](https://ftp.mozilla.org/pub/firefox/releases/47.0.1/) and selenium-webdriver 2.53.4. Firefox 48+ requires geckodriver and selenium-webdriver v3, the combo of which currently has multiple issues and is feature incomplete.
16
+ **Note: Firefox 48+** If you're using Firefox with selenium-webdriver and want full functionality stay on either Firefox [45.0esr](https://ftp.mozilla.org/pub/firefox/releases/45.0esr/) or [47.0.1](https://ftp.mozilla.org/pub/firefox/releases/47.0.1/).
17
+ If using selenium-webdriver 3.0+ this will require configuring your driver with the `marionette: false` option as shown below
18
+
19
+ ```ruby
20
+ Capybara.register_driver :selenium do |app|
21
+ Capybara::Selenium::Driver.new(
22
+ app,
23
+ browser: :firefox,
24
+ desired_capabilities: Selenium::WebDriver::Remote::Capabilities.firefox(marionette: false)
25
+ )
26
+ end
27
+ ```
28
+
29
+ Using Firefox 48+ requires geckodriver and selenium-webdriver v3, the combo of which currently has multiple issues and is feature incomplete.
30
+ You can read more about the missing features [here](https://github.com/teamcapybara/capybara/issues/1710).
17
31
 
18
32
  ## Table of contents
19
33
 
@@ -129,7 +143,7 @@ tags set up for you.
129
143
 
130
144
  ## <a name="using-capybara-with-rspec"></a>Using Capybara with RSpec
131
145
 
132
- Load RSpec 2.x support by adding the following line (typically to your
146
+ Load RSpec 2+ support by adding the following line (typically to your
133
147
  `spec_helper.rb` file):
134
148
 
135
149
  ```ruby
@@ -392,7 +406,7 @@ any Javascript errors that happen within the page.
392
406
  ## <a name="the-dsl"></a>The DSL
393
407
 
394
408
  *A complete reference is available at
395
- [rubydoc.info](http://rubydoc.info/github/jnicklas/capybara/master)*.
409
+ [rubydoc.info](http://rubydoc.info/github/teamcapybara/capybara/master)*.
396
410
 
397
411
  **Note: By default Capybara will only locate visible elements. This is because
398
412
  a real user would not be able to interact with non-visible elements.**
@@ -403,7 +417,7 @@ Capybara heavily uses XPath, which doesn't support case insensitivity.
403
417
  ### <a name="navigating"></a>Navigating
404
418
 
405
419
  You can use the
406
- <tt>[visit](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#visit-instance_method)</tt>
420
+ <tt>[visit](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#visit-instance_method)</tt>
407
421
  method to navigate to other pages:
408
422
 
409
423
  ```ruby
@@ -414,8 +428,8 @@ visit(post_comments_path(post))
414
428
  The visit method only takes a single parameter, the request method is **always**
415
429
  GET.
416
430
 
417
- You can get the [current path](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#current_path-instance_method)
418
- of the browsing session, and test it using the [`have_current_path`](http://www.rubydoc.info/github/jnicklas/capybara/master/Capybara/RSpecMatchers#have_current_path-instance_method) matcher:
431
+ You can get the [current path](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#current_path-instance_method)
432
+ of the browsing session, and test it using the [`have_current_path`](http://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/RSpecMatchers#have_current_path-instance_method) matcher:
419
433
 
420
434
  ```ruby
421
435
  expect(page).to have_current_path(post_comments_path(post))
@@ -428,7 +442,7 @@ to ensure that preceding actions (such as a `click_link`) have completed.
428
442
 
429
443
  ### <a name="clicking-links-and-buttons"></a>Clicking links and buttons
430
444
 
431
- *Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions)*
445
+ *Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Actions)*
432
446
 
433
447
  You can interact with the webapp by following links and buttons. Capybara
434
448
  automatically follows any redirects, and submits forms associated with buttons.
@@ -443,7 +457,7 @@ click_on('Button Value')
443
457
 
444
458
  ### <a name="interacting-with-forms"></a>Interacting with forms
445
459
 
446
- *Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions)*
460
+ *Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Actions)*
447
461
 
448
462
  There are a number of tools for interacting with form elements:
449
463
 
@@ -460,16 +474,16 @@ select('Option', from: 'Select Box')
460
474
 
461
475
  ### <a name="querying"></a>Querying
462
476
 
463
- *Full reference: [Capybara::Node::Matchers](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Matchers)*
477
+ *Full reference: [Capybara::Node::Matchers](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Matchers)*
464
478
 
465
479
  Capybara has a rich set of options for querying the page for the existence of
466
480
  certain elements, and working with and manipulating those elements.
467
481
 
468
482
  ```ruby
469
483
  page.has_selector?('table tr')
470
- page.has_selector?(:xpath, '//table/tr')
484
+ page.has_selector?(:xpath, './/table/tr')
471
485
 
472
- page.has_xpath?('//table/tr')
486
+ page.has_xpath?('.//table/tr')
473
487
  page.has_css?('table tr.foo')
474
488
  page.has_content?('foo')
475
489
  ```
@@ -481,34 +495,39 @@ You can use these with RSpec's magic matchers:
481
495
 
482
496
  ```ruby
483
497
  expect(page).to have_selector('table tr')
484
- expect(page).to have_selector(:xpath, '//table/tr')
498
+ expect(page).to have_selector(:xpath, './/table/tr')
485
499
 
486
- expect(page).to have_xpath('//table/tr')
500
+ expect(page).to have_xpath('.//table/tr')
487
501
  expect(page).to have_css('table tr.foo')
488
502
  expect(page).to have_content('foo')
489
503
  ```
490
504
 
491
505
  ### <a name="finding"></a>Finding
492
506
 
493
- _Full reference: [Capybara::Node::Finders](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Finders)_
507
+ _Full reference: [Capybara::Node::Finders](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders)_
494
508
 
495
509
  You can also find specific elements, in order to manipulate them:
496
510
 
497
511
  ```ruby
498
512
  find_field('First Name').value
513
+ find_field(id: 'my_field').value
499
514
  find_link('Hello', :visible => :all).visible?
515
+ find_link(class: ['some_class', 'some_other_class'], :visible => :all).visible?
516
+
500
517
  find_button('Send').click
518
+ find_button(value: '1234').click
501
519
 
502
- find(:xpath, "//table/tr").click
520
+ find(:xpath, ".//table/tr").click
503
521
  find("#overlay").find("h1").click
504
522
  all('a').each { |a| a[:href] }
505
523
  ```
506
524
 
507
525
  If you need to find elements by additional attributes/properties you can also pass a filter block, which will be checked inside the normal waiting behavior.
508
- If you find yourself needing to use this a lot you may be better off adding a [custom selector](http://www.rubydoc.info/github/jnicklas/capybara/Capybara#add_selector-class_method) or [adding a filter to an existing selector](http://www.rubydoc.info/github/jnicklas/capybara/Capybara#modify_selector-class_method).
526
+ If you find yourself needing to use this a lot you may be better off adding a [custom selector](http://www.rubydoc.info/github/teamcapybara/capybara/Capybara#add_selector-class_method) or [adding a filter to an existing selector](http://www.rubydoc.info/github/teamcapybara/capybara/Capybara#modify_selector-class_method).
509
527
 
510
528
  ```ruby
511
529
  find_field('First Name'){ |el| el['data-xyz'] == '123' }
530
+ find("#img_loading"){ |img| img['complete'] == true }
512
531
  ````
513
532
 
514
533
  **Note**: `find` will wait for an element to appear on the page, as explained in the
@@ -527,7 +546,7 @@ expect(find('#navigation')).to have_button('Sign out')
527
546
  Capybara makes it possible to restrict certain actions, such as interacting with
528
547
  forms or clicking links and buttons, to within a specific area of the page. For
529
548
  this purpose you can use the generic
530
- <tt>[within](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#within-instance_method)</tt>
549
+ <tt>[within](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#within-instance_method)</tt>
531
550
  method. Optionally you can specify which kind of selector to use.
532
551
 
533
552
  ```ruby
@@ -535,7 +554,7 @@ within("li#employee") do
535
554
  fill_in 'Name', with: 'Jimmy'
536
555
  end
537
556
 
538
- within(:xpath, "//li[@id='employee']") do
557
+ within(:xpath, ".//li[@id='employee']") do
539
558
  fill_in 'Name', with: 'Jimmy'
540
559
  end
541
560
  ```
@@ -632,7 +651,7 @@ save_and_open_page
632
651
  ```
633
652
 
634
653
  You can also retrieve the current state of the DOM as a string using
635
- <tt>[page.html](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#html-instance_method)</tt>.
654
+ <tt>[page.html](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session#html-instance_method)</tt>.
636
655
 
637
656
  ```ruby
638
657
  print page.html
@@ -788,7 +807,7 @@ module MyModule
788
807
  include Capybara::DSL
789
808
 
790
809
  def login!
791
- within(:xpath, "//form[@id='session']") do
810
+ within(:xpath, ".//form[@id='session']") do
792
811
  fill_in 'Email', with: 'user@example.com'
793
812
  fill_in 'Password', with: 'password'
794
813
  end
@@ -852,7 +871,7 @@ Capybara.session_name = "some other session"
852
871
  ### <a name="using-sessions-manually"></a>Using sessions manually
853
872
 
854
873
  For ultimate control, you can instantiate and use a
855
- [Session](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session)
874
+ [Session](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session)
856
875
  manually.
857
876
 
858
877
  ```ruby
@@ -873,16 +892,16 @@ and will always use CSS by default. If you want to use XPath, you'll need to
873
892
  do:
874
893
 
875
894
  ```ruby
876
- within(:xpath, '//ul/li') { ... }
877
- find(:xpath, '//ul/li').text
878
- find(:xpath, '//li[contains(.//a[@href = "#"]/text(), "foo")]').value
895
+ within(:xpath, './/ul/li') { ... }
896
+ find(:xpath, './/ul/li').text
897
+ find(:xpath, './/li[contains(.//a[@href = "#"]/text(), "foo")]').value
879
898
  ```
880
899
 
881
900
  Alternatively you can set the default selector to XPath:
882
901
 
883
902
  ```ruby
884
903
  Capybara.default_selector = :xpath
885
- find('//ul/li').text
904
+ find('.//ul/li').text
886
905
  ```
887
906
 
888
907
  Capybara allows you to add custom selectors, which can be very useful if you
@@ -1010,5 +1029,5 @@ bundle exec rake # run the test suite
1010
1029
  ```
1011
1030
 
1012
1031
  See
1013
- [CONTRIBUTING.md](https://github.com/jnicklas/capybara/blob/master/CONTRIBUTING.md)
1032
+ [CONTRIBUTING.md](https://github.com/teamcapybara/capybara/blob/master/CONTRIBUTING.md)
1014
1033
  for how to send issues and pull requests.
@@ -18,6 +18,8 @@ module Capybara
18
18
  #
19
19
  # @param [String] locator Text, id or value of link or button
20
20
  #
21
+ # @return [Capybara::Node::Element] The element clicked
22
+ #
21
23
  def click_link_or_button(locator=nil, options={})
22
24
  locator, options = nil, locator if locator.is_a? Hash
23
25
  find(:link_or_button, locator, options).click
@@ -35,6 +37,7 @@ module Capybara
35
37
  # @param [String] locator text, id, title or nested image's alt attribute
36
38
  # @param options See {Capybara::Node::Finders#find_link}
37
39
  #
40
+ # @return [Capybara::Node::Element] The element clicked
38
41
  def click_link(locator=nil, options={})
39
42
  locator, options = nil, locator if locator.is_a? Hash
40
43
  find(:link, locator, options).click
@@ -52,6 +55,7 @@ module Capybara
52
55
  # @overload click_button([locator], options)
53
56
  # @param [String] locator Which button to find
54
57
  # @param options See {Capybara::Node::Finders#find_button}
58
+ # @return [Capybara::Node::Element] The element clicked
55
59
  def click_button(locator=nil, options={})
56
60
  locator, options = nil, locator if locator.is_a? Hash
57
61
  find(:button, locator, options).click
@@ -77,6 +81,7 @@ module Capybara
77
81
  # @option options [String] :placeholder Match fields that match the placeholder attribute
78
82
  # @option options [String, Array<String>] :class Match links that match the class(es) provided
79
83
  #
84
+ # @return [Capybara::Node::Element] The element filled_in
80
85
  def fill_in(locator, options={})
81
86
  locator, options = nil, locator if locator.is_a? Hash
82
87
  raise "Must pass a hash containing 'with'" if not options.is_a?(Hash) or not options.has_key?(:with)
@@ -104,23 +109,10 @@ module Capybara
104
109
  # @option options [String, Array<String>] :class Match links that match the class(es) provided
105
110
  # @macro waiting_behavior
106
111
  # @macro label_click
112
+ #
113
+ # @return [Capybara::Node::Element] The element chosen or the label clicked
107
114
  def choose(locator, options={})
108
- locator, options = nil, locator if locator.is_a? Hash
109
- allow_label_click = options.delete(:allow_label_click) { Capybara.automatic_label_click }
110
-
111
- begin
112
- radio = find(:radio_button, locator, options)
113
- radio.set(true)
114
- rescue => e
115
- raise unless allow_label_click && catch_error?(e)
116
- begin
117
- radio ||= find(:radio_button, locator, options.merge({wait: 0, visible: :all}))
118
- label = find(:label, for: radio, wait: 0, visible: true)
119
- label.click unless radio.checked?
120
- rescue
121
- raise e
122
- end
123
- end
115
+ _check_with_label(:radio_button, true, locator, options)
124
116
  end
125
117
 
126
118
  ##
@@ -141,23 +133,9 @@ module Capybara
141
133
  # @macro label_click
142
134
  # @macro waiting_behavior
143
135
  #
136
+ # @return [Capybara::Node::Element] The element checked or the label clicked
144
137
  def check(locator, options={})
145
- locator, options = nil, locator if locator.is_a? Hash
146
- allow_label_click = options.delete(:allow_label_click) { Capybara.automatic_label_click }
147
-
148
- begin
149
- cbox = find(:checkbox, locator, options)
150
- cbox.set(true)
151
- rescue => e
152
- raise unless allow_label_click && catch_error?(e)
153
- begin
154
- cbox ||= find(:checkbox, locator, options.merge({wait: 0, visible: :all}))
155
- label = find(:label, for: cbox, wait: 0, visible: true)
156
- label.click unless cbox.checked?
157
- rescue
158
- raise e
159
- end
160
- end
138
+ _check_with_label(:checkbox, true, locator, options)
161
139
  end
162
140
 
163
141
  ##
@@ -178,23 +156,9 @@ module Capybara
178
156
  # @macro label_click
179
157
  # @macro waiting_behavior
180
158
  #
159
+ # @return [Capybara::Node::Element] The element unchecked or the label clicked
181
160
  def uncheck(locator, options={})
182
- locator, options = nil, locator if locator.is_a? Hash
183
- allow_label_click = options.delete(:allow_label_click) { Capybara.automatic_label_click }
184
-
185
- begin
186
- cbox = find(:checkbox, locator, options)
187
- cbox.set(false)
188
- rescue => e
189
- raise unless allow_label_click && catch_error?(e)
190
- begin
191
- cbox ||= find(:checkbox, locator, options.merge({wait: 0, visible: :all}))
192
- label = find(:label, for: cbox, wait: 0, visible: true)
193
- label.click if cbox.checked?
194
- rescue
195
- raise e
196
- end
197
- end
161
+ _check_with_label(:checkbox, false, locator, options)
198
162
  end
199
163
 
200
164
  ##
@@ -213,6 +177,7 @@ module Capybara
213
177
  # @param [String] value Which option to select
214
178
  # @option options [String] :from The id, name or label of the select box
215
179
  #
180
+ # @return [Capybara::Node::Element] The option element selected
216
181
  def select(value, options={})
217
182
  if options.has_key?(:from)
218
183
  from = options.delete(:from)
@@ -235,6 +200,7 @@ module Capybara
235
200
  # @param [String] value Which option to unselect
236
201
  # @param [Hash{:from => String}] options The id, name or label of the select box
237
202
  #
203
+ # @return [Capybara::Node::Element] The option element unselected
238
204
  def unselect(value, options={})
239
205
  if options.has_key?(:from)
240
206
  from = options.delete(:from)
@@ -263,6 +229,7 @@ module Capybara
263
229
  # @option options [String] name Match fields that match the name attribute
264
230
  # @option options [String, Array<String>] :class Match links that match the class(es) provided
265
231
  #
232
+ # @return [Capybara::Node::Element] The file field element
266
233
  def attach_file(locator, path, options={})
267
234
  locator, path, options = nil, locator, path if path.is_a? Hash
268
235
  Array(path).each do |p|
@@ -270,6 +237,30 @@ module Capybara
270
237
  end
271
238
  find(:file_field, locator, options).set(path)
272
239
  end
240
+
241
+ private
242
+
243
+ def _check_with_label(selector, checked, locator, options)
244
+ locator, options = nil, locator if locator.is_a? Hash
245
+ allow_label_click = options.delete(:allow_label_click) { Capybara.automatic_label_click }
246
+
247
+ synchronize(Capybara::Queries::BaseQuery::wait(options)) do
248
+ begin
249
+ el = find(selector, locator, options)
250
+ el.set(checked)
251
+ rescue => e
252
+ raise unless allow_label_click && catch_error?(e)
253
+ begin
254
+ el ||= find(selector, locator, options.merge(visible: :all))
255
+ label = find(:label, for: el, visible: true)
256
+ label.click unless (el.checked? == checked)
257
+ rescue
258
+ raise e
259
+ end
260
+ end
261
+ end
262
+ end
263
+
273
264
  end
274
265
  end
275
266
  end
@@ -24,6 +24,10 @@ module Capybara
24
24
  find(:xpath, '/html').text(type)
25
25
  end
26
26
 
27
+ ##
28
+ #
29
+ # @return [String] The title of the document
30
+ #
27
31
  def title
28
32
  session.driver.title
29
33
  end
@@ -15,13 +15,7 @@ module Capybara
15
15
  # @return [true]
16
16
  #
17
17
  def assert_title(title, options = {})
18
- query = Capybara::Queries::TitleQuery.new(title, options)
19
- synchronize(query.wait) do
20
- unless query.resolves_for?(self)
21
- raise Capybara::ExpectationNotMet, query.failure_message
22
- end
23
- end
24
- return true
18
+ _verify_title(title,options) { |query| raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self) }
25
19
  end
26
20
 
27
21
  ##
@@ -32,13 +26,7 @@ module Capybara
32
26
  # @return [true]
33
27
  #
34
28
  def assert_no_title(title, options = {})
35
- query = Capybara::Queries::TitleQuery.new(title, options)
36
- synchronize(query.wait) do
37
- if query.resolves_for?(self)
38
- raise Capybara::ExpectationNotMet, query.negative_failure_message
39
- end
40
- end
41
- return true
29
+ _verify_title(title,options) { |query| raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self) }
42
30
  end
43
31
 
44
32
  ##
@@ -64,6 +52,17 @@ module Capybara
64
52
  rescue Capybara::ExpectationNotMet
65
53
  return false
66
54
  end
55
+
56
+ private
57
+
58
+ def _verify_title(title, options)
59
+ query = Capybara::Queries::TitleQuery.new(title, options)
60
+ synchronize(query.wait) do
61
+ yield(query)
62
+ end
63
+ return true
64
+ end
65
+
67
66
  end
68
67
  end
69
68
  end
@@ -27,6 +27,7 @@ module Capybara
27
27
  super(session, base)
28
28
  @query_scope = query_scope
29
29
  @query = query
30
+ @allow_reload = false
30
31
  end
31
32
 
32
33
  def allow_reload!
@@ -92,6 +93,7 @@ module Capybara
92
93
  # @param [String] value The new value
93
94
  # @param [Hash{}] options Driver specific options for how to set the value
94
95
  #
96
+ # @return [Capybara::Node::Element] The element
95
97
  def set(value, options={})
96
98
  options ||= {}
97
99
 
@@ -108,47 +110,58 @@ module Capybara
108
110
  base.set(value)
109
111
  end
110
112
  end
113
+ return self
111
114
  end
112
115
 
113
116
  ##
114
117
  #
115
118
  # Select this node if is an option element inside a select tag
116
119
  #
120
+ # @return [Capybara::Node::Element] The element
117
121
  def select_option
118
122
  warn "Attempt to select disabled option: #{value || text}" if disabled?
119
123
  synchronize { base.select_option }
124
+ return self
120
125
  end
121
126
 
122
127
  ##
123
128
  #
124
129
  # Unselect this node if is an option element inside a multiple select tag
125
130
  #
131
+ # @return [Capybara::Node::Element] The element
126
132
  def unselect_option
127
133
  synchronize { base.unselect_option }
134
+ return self
128
135
  end
129
136
 
130
137
  ##
131
138
  #
132
139
  # Click the Element
133
140
  #
141
+ # @return [Capybara::Node::Element] The element
134
142
  def click
135
143
  synchronize { base.click }
144
+ return self
136
145
  end
137
146
 
138
147
  ##
139
148
  #
140
149
  # Right Click the Element
141
150
  #
151
+ # @return [Capybara::Node::Element] The element
142
152
  def right_click
143
153
  synchronize { base.right_click }
154
+ return self
144
155
  end
145
156
 
146
157
  ##
147
158
  #
148
159
  # Double Click the Element
149
160
  #
161
+ # @return [Capybara::Node::Element] The element
150
162
  def double_click
151
163
  synchronize { base.double_click }
164
+ return self
152
165
  end
153
166
 
154
167
  ##
@@ -221,16 +234,20 @@ module Capybara
221
234
  # :meta
222
235
  # :command - alias of :meta
223
236
  #
237
+ # @return [Capybara::Node::Element] The element
224
238
  def send_keys(*args)
225
239
  synchronize { base.send_keys(*args) }
240
+ return self
226
241
  end
227
242
 
228
243
  ##
229
244
  #
230
245
  # Hover on the Element
231
246
  #
247
+ # @return [Capybara::Node::Element] The element
232
248
  def hover
233
249
  synchronize { base.hover }
250
+ return self
234
251
  end
235
252
 
236
253
  ##
@@ -319,8 +336,10 @@ module Capybara
319
336
  #
320
337
  # @param [String] event The name of the event to trigger
321
338
  #
339
+ # @return [Capybara::Node::Element] The element
322
340
  def trigger(event)
323
341
  synchronize { base.trigger(event) }
342
+ return self
324
343
  end
325
344
 
326
345
  ##
@@ -333,8 +352,10 @@ module Capybara
333
352
  #
334
353
  # @param [Capybara::Node::Element] node The element to drag to
335
354
  #
355
+ # @return [Capybara::Node::Element] The element
336
356
  def drag_to(node)
337
357
  synchronize { base.drag_to(node.base) }
358
+ return self
338
359
  end
339
360
 
340
361
  def reload
@@ -18,7 +18,7 @@ module Capybara
18
18
  # +find+ takes the same options as +all+.
19
19
  #
20
20
  # page.find('#foo').find('.bar')
21
- # page.find(:xpath, '//div[contains(., "bar")]')
21
+ # page.find(:xpath, './/div[contains(., "bar")]')
22
22
  # page.find('li', text: 'Quox').click_link('Delete')
23
23
  #
24
24
  # @param (see Capybara::Node::Finders#all)
@@ -155,7 +155,7 @@ module Capybara
155
155
  # following statements are equivalent:
156
156
  #
157
157
  # page.all(:css, 'a#person_123')
158
- # page.all(:xpath, '//a[@id="person_123"]')
158
+ # page.all(:xpath, './/a[@id="person_123"]')
159
159
  #
160
160
  #
161
161
  # If the type of selector is left out, Capybara uses
@@ -164,7 +164,7 @@ module Capybara
164
164
  # page.all("a#person_123")
165
165
  #
166
166
  # Capybara.default_selector = :xpath
167
- # page.all('//a[@id="person_123"]')
167
+ # page.all('.//a[@id="person_123"]')
168
168
  #
169
169
  # The set of found elements can further be restricted by specifying
170
170
  # options. It's possible to select elements by their text or visibility: