capybara 2.10.2 → 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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +15 -0
  3. data/README.md +48 -29
  4. data/lib/capybara.rb +8 -9
  5. data/lib/capybara/node/actions.rb +39 -48
  6. data/lib/capybara/node/document.rb +4 -0
  7. data/lib/capybara/node/document_matchers.rb +13 -14
  8. data/lib/capybara/node/element.rb +21 -0
  9. data/lib/capybara/node/finders.rb +3 -3
  10. data/lib/capybara/node/matchers.rb +38 -31
  11. data/lib/capybara/node/simple.rb +3 -0
  12. data/lib/capybara/queries/selector_query.rb +4 -2
  13. data/lib/capybara/rack_test/node.rb +1 -1
  14. data/lib/capybara/result.rb +3 -1
  15. data/lib/capybara/rspec/matchers.rb +53 -95
  16. data/lib/capybara/selector.rb +7 -7
  17. data/lib/capybara/selector/selector.rb +10 -5
  18. data/lib/capybara/selenium/driver.rb +34 -7
  19. data/lib/capybara/selenium/node.rb +5 -1
  20. data/lib/capybara/session.rb +22 -27
  21. data/lib/capybara/session/matchers.rb +12 -14
  22. data/lib/capybara/spec/public/test.js +4 -0
  23. data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
  24. data/lib/capybara/spec/session/attach_file_spec.rb +1 -1
  25. data/lib/capybara/spec/session/check_spec.rb +8 -0
  26. data/lib/capybara/spec/session/choose_spec.rb +5 -0
  27. data/lib/capybara/spec/session/click_link_or_button_spec.rb +5 -0
  28. data/lib/capybara/spec/session/click_link_spec.rb +5 -0
  29. data/lib/capybara/spec/session/element/assert_match_selector.rb +5 -0
  30. data/lib/capybara/spec/session/element/match_css_spec.rb +6 -0
  31. data/lib/capybara/spec/session/element/matches_selector_spec.rb +2 -0
  32. data/lib/capybara/spec/session/fill_in_spec.rb +5 -0
  33. data/lib/capybara/spec/session/find_spec.rb +1 -1
  34. data/lib/capybara/spec/session/first_spec.rb +10 -0
  35. data/lib/capybara/spec/session/has_selector_spec.rb +11 -0
  36. data/lib/capybara/spec/session/node_spec.rb +3 -3
  37. data/lib/capybara/spec/session/text_spec.rb +3 -4
  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/spec/basic_node_spec.rb +1 -1
  42. data/spec/capybara_spec.rb +4 -1
  43. data/spec/fixtures/selenium_driver_rspec_failure.rb +4 -1
  44. data/spec/fixtures/selenium_driver_rspec_success.rb +4 -1
  45. data/spec/result_spec.rb +28 -2
  46. data/spec/rspec/{matchers_spec.rb → shared_spec_matchers.rb} +4 -3
  47. data/spec/selector_spec.rb +1 -1
  48. data/spec/selenium_spec_chrome.rb +36 -5
  49. data/spec/selenium_spec_firefox.rb +67 -0
  50. data/spec/selenium_spec_marionette.rb +114 -0
  51. data/spec/shared_selenium_session.rb +6 -4
  52. metadata +13 -6
  53. data/spec/selenium_firefox_spec.rb +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 21fdd89225cd5ecf58f6e1eb72da29832f70ba9a
4
- data.tar.gz: edada38839bc4b98461a27b02f196ec2e2e58ac7
3
+ metadata.gz: b4d75941bdc33b8e4b3d26aa8beb1a6d063fabca
4
+ data.tar.gz: 692a680d4d550e566e6c558bfe53608a024b4e49
5
5
  SHA512:
6
- metadata.gz: 4f2ed74c7e278e93c5dcf3f92ab35b51a2b31578bff67e25c83076f65ab8e7edd50a2b63afd41ddd65e0a7bc438e6d27adcaae17fcafad6f0e4cd52b241e5797
7
- data.tar.gz: a97567024d5a9d18858e8b4b1b9920819a6655708f87206ad5c281de9bb39cb5e2185dd1f710618e745483c925ba6e09bbba143d17f7ded222c80acab7be9ce2
6
+ metadata.gz: e9eee2dae8d51f3bff73da658a08d2aeefd6383c16cec7b269abbb2c99203239c996c83b0145946d473cc0d3d1076abd623f672dfa07dd4ad0ed9a74ea2ef001
7
+ data.tar.gz: 2fef0e0fb22d31ccbd4879df37100feb6c717508c57266539245d07a3ba74c3849ae02cab2dfc735054b6344effb2c4f6783658e95a3513737aa81cabb39f83e
data/History.md CHANGED
@@ -1,3 +1,18 @@
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
+
1
16
  #2.10.2
2
17
  Release date: 2016-11-30
3
18
 
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.
@@ -25,7 +25,8 @@ module Capybara
25
25
  attr_accessor :server_port, :exact, :match, :exact_options, :visible_text_only, :enable_aria_label
26
26
  attr_accessor :default_selector, :default_max_wait_time, :ignore_hidden_elements
27
27
  attr_accessor :save_path, :wait_on_first_by_default, :automatic_label_click, :automatic_reload
28
- attr_accessor :reuse_server, :raise_server_errors, :server_errors
28
+ attr_reader :reuse_server
29
+ attr_accessor :raise_server_errors, :server_errors
29
30
  attr_writer :default_driver, :current_driver, :javascript_driver, :session_name, :server_host
30
31
  attr_reader :save_and_open_page_path
31
32
  attr_accessor :app
@@ -331,7 +332,7 @@ module Capybara
331
332
  #
332
333
  def reset_sessions!
333
334
  #reset in reverse so sessions that started servers are reset last
334
- session_pool.reverse_each { |mode, session| session.reset! }
335
+ session_pool.reverse_each { |_mode, session| session.reset! }
335
336
  end
336
337
  alias_method :reset!, :reset_sessions!
337
338
 
@@ -391,12 +392,12 @@ module Capybara
391
392
  end
392
393
 
393
394
  def app_host=(url)
394
- raise ArgumentError.new("Capybara.app_host should be set to a url (http://www.example.com)") unless url.nil? || (url =~ URI::regexp)
395
+ raise ArgumentError.new("Capybara.app_host should be set to a url (http://www.example.com)") unless url.nil? || (url =~ URI::Parser.new.make_regexp)
395
396
  @app_host = url
396
397
  end
397
398
 
398
399
  def default_host=(url)
399
- raise ArgumentError.new("Capybara.default_host should be set to a url (http://www.example.com)") unless url.nil? || (url =~ URI::regexp)
400
+ raise ArgumentError.new("Capybara.default_host should be set to a url (http://www.example.com)") unless url.nil? || (url =~ URI::Parser.new.make_regexp)
400
401
  @default_host = url
401
402
  end
402
403
 
@@ -469,7 +470,7 @@ module Capybara
469
470
  require 'capybara/selenium/driver'
470
471
  end
471
472
 
472
- Capybara.register_server :default do |app, port, host|
473
+ Capybara.register_server :default do |app, port, _host|
473
474
  Capybara.run_default_server(app, port)
474
475
  end
475
476
 
@@ -479,10 +480,8 @@ Capybara.register_server :webrick do |app, port, host|
479
480
  end
480
481
 
481
482
  Capybara.register_server :puma do |app, port, host|
482
- require 'puma'
483
- Puma::Server.new(app).tap do |s|
484
- s.add_tcp_listener host, port
485
- end.run.join
483
+ require 'rack/handler/puma'
484
+ Rack::Handler::Puma.run(app, Host: host, Port: port, Threads: "0:4")
486
485
  end
487
486
 
488
487
  Capybara.configure do |config|
@@ -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