capybara-2.5.0/ 0000755 0001750 0001750 00000000000 12573712570 012335 5 ustar lunar lunar capybara-2.5.0/History.md 0000644 0001750 0001750 00000075413 12573712570 014332 0 ustar lunar lunar # Version 2.5.0
Release date: 2015-08-25
### Fixed
* Error message now raised correctly when invalid options passed to 'have_text'/'have_content' [Tom Walpole]
* Rack-test driver correctly gets document title when elements on the page have nested title elements (SVG) [Tom Walpole]
* 'save_page' no longer errors when using Capybara.asset_host if the page has no \
element [Travis Grathwell]
* rack-test driver will ignore clicks on links with href starting with '#' or 'javascript:'
### Added
* has_current_path? and associated asserts/matchers added [Tom Walpole]
* Implement Node#path in selenium driver [Soutaro Matsumoto]
* 'using_session' is now nestable [Tom Walpole]
* 'switch_to_window' will now use waiting behavior for a matching window to appear [Tom Walpole]
* Capybara.default_wait_time deprecated in favor of Capybara.default_max_wait_time to more clearly explain its purpose [Paul Pettengill]
* Warning when attempting to select a disabled option
* Capybara matchers are now available in RSpec view specs by default [Joshua Clayton]
* 'have_link' and 'click_link' now accept Regexp for href matching [Yaniv Savir]
* 'find_all' as an alias of 'all' due to collision with RSpec
* Capybara.wait_on_first_by_default setting (default is false)
If set to true 'first' will use Capybaras waiting behavior to wait for at least one element to appear by default
* Capybara waiting behavior uses the monotonic clock if supported to ease restrictions on freezing time in tests [Dmitry Maksyoma, Tom Walpole]
* Capybara.server_errors setting that allows to configure what type of errors will be raised from the server thread [Tom Walpole]
* Node#send_keys to allow for sending keypresses directly to elements [Tom Walpole]
* 'formmethod' attribute support in RackTest driver [Emilia Andrzejewska]
* Clear field using backspaces in Selenium driver by using `:fill_options => { :clear => :backspace }` [Joe Lencioni]
#Version 2.4.4
Release date: 2014-10-13
### Fixed
* Test for visit behavior updated [Phil Baker]
* Removed concurrency prevention in favor of a note in the README - due to load order issues
# Version 2.4.3
Relase date: 2014-09-21
### Fixed
* Update concurrency prevention to match Rails 4.2 behavior
# Version 2.4.2
Release date: 2014-09-20
### Fixed
* Prevent concurrency issue when testing Rails app with default test environment [Thomas Walpole]
* Tags for windows API tests fixed [Dmitry Vorotilin]
* Documentation Fixes [Andrey Botalov]
* Always convert visit url to string, fixes issue with visit when always_include_port was enabled [Jake Goulding]
* Check correct rspec version before including ::RSpec::Matchers::Composable in Capybara RSpec matchers [Thomas Walpole, Justin Ko]
# Version 2.4.1
Release date: 2014-07-03
### Added
* 'assert_text', 'assert_no_text', 'assert_title', 'assert_no_title' methods added [Andrey Botalov]
* have_title matcher now supports :wait option [Andrey Botalov]
* More descriptive have_text error messages [Andrey Botalov]
* New modal API ('accept_alert', 'accept_confirm', 'dismiss_confirm', 'accept_prompt', 'dismiss_prompt') - [Mike Pack, Thomas Walpole]
* Warning when attempting to set contents of a readonly element
* Suport for and/or compounding of Capybara's RSpec matchers for RSpec 3 [Thomas Walpole]
* :fill_options option for 'fill_in' method that propagates to 'set' to allow for driver specific modification of how fields are filled in [Gabriel Sobrinho, Thomas Walpole]
* Improved selector/filter description in failure messages [Thomas Walpole]
### Fixed
* HaveText error message now shows the text checked all the time
* RackTest driver no longer attempts to follow an anchor tag without an href attribute
* Warnings under RSpec 3
* Handle URI schemes like about: correctly [Andrey Botalov]
* RSpecs expose_dsl_globally option is now followed [Myron Marston, Thomas Walpole]
# Version 2.3.0
Release date: 2014-06-02
### Added
* New window management API [Andrey Botalov]
* Speed improvement for visible text detection in RackTest [Thomas Walpole]
Thanks to Phillipe Creux for instigating this
* RSpec 3 compatability
* 'save_and_open_screenshot' functionality [Greg Lazarev]
* Server errors raised on visit and synchronize [Jonas Nicklas]
### Fixed
* CSSHandlers now derives from BasicObject so globally included functions (concat, etc) shouldn't cause issues [Thomas Walpole]
* touched reset after session is reset [lesliepc16]
# Version 2.2.1
Release date: 2014-01-06
### Fixed
* Reverted a change in 2.2.0 which navigates to an empty file on `reset`.
Capybara, now visits `about:blank` like it did before. [Jonas Nicklas]
# Version 2.2.0
Release date: 2013-11-21
### Added
* Add `go_back` and `go_forward` methods. [Vasiliy Ermolovich]
* Support RSpec 3 [Thomas Holmes]
* `has_button?`, `has_checked_field?` and `has_unchecked_field?` accept
options, like other matchers. [Carol Nichols]
* The `assert_selector` and `has_text?` methods now support the `:wait` option
[Vasiliy Ermolovich]
* RackTest's visible? method now checks for the HTML5 `hidden` attribute.
* Results from `#all` now delegate the `sample` method. [Phil Lee]
* The `set` method now works for contenteditable attributes under Selenium.
[Jon Rowe]
* radio buttons and check boxes can be filtered by option value, useful when
selecting by name [Jonas Nicklas]
* feature blocks can be nested within other feature blocks in RSpec tests
[Travis Gaff]
### Fixed
* Fixed race conditions causing stale element errors when filtering by text.
[Jonas Nicklas]
* Resetting the page is now synchronous and navigates to an empty HTML file,
instead of `about:blank`, fixing hanging issues in JRuby. [Jonas Nicklas]
* Fixed cookies not being set when path is blank under RackTest [Thomas Walpole]
* Clearing fields now correctly causes change events [Jonas Nicklas]
* Navigating to an absolute URI without trailing slash now works as expected
under RackTest [Jonas Nicklas]
* Checkboxes without assigned value default to `on` under RackTest [Nigel Sheridan-Smith]
* Clicks on buttons with no form associated with them are ignored in RackTest
instead of raising an obscure exception. [Thomas Walpole]
* execute_script is now a session method [Andrey Botalov]
* Nesting `within_window` and `within_frame` inside `within` resets the scope
so that they behave like a user would expect [Thomas Walpole]
* Improve handling of newlines in textareas [Thomas Walpole]
* `Capybara::Result` delegates its inspect method, so as not to confuse users
[Sam Rawlins]
* save_page always returns a full path, fixes problems with Launchy [Jonas Nicklas]
* Selenium driver's `quit` method does nothing when browser hasn't been loaded
[randoum]
* Capybara's WEBRick server now propertly respects the server_host option
[Dmitry Vorotilin]
* gemspec now includes license information [Jonas Nicklas]
# Version 2.1.0
Release date: 2013-04-09
### Changed
* Hard version requirement on Ruby >= 1.9.3. Capybara will no longer install
on 1.8.7. [Felix Schäfer]
* Capybara no longer depends on the `selenium-webdriver` gem. Add it to
your Gemfile if you wish to use the Selenium driver. [Jonas Nicklas]
* `Capybara.ignore_hidden_elements` defaults to `true`. [Jonas Nicklas]
* In case of multiple matches `smart` matching is used by default. Set
`Capybara.match = :one` to revert to old behaviour. [Jonas Nicklas].
* Options in select boxes use smart matching and no longer need to match
exactly. Set `Capybara.exact_options = false` to revert to old behaviour.
[Jonas Nicklas].
* Visibility of text depends on `Capybara.ignore_hidden_elements` instead of
always returning only visible text. Set `Capybara.visible_text_only = true`
to revert to old behaviour. [Jonas Nicklas]
* Cucumber cleans up session after scenario instead. This is consistent with
RSpec and makes more sense, since we raise server errors in `reset!`.
[Jonas Nicklas]
### Added
* All actions (`click_link`, `fill_in`, etc...) and finders now take an options
hash, which is passed through to `find`. [Jonas Nicklas]
* CSS selectors are sent straight through to driver instead of being converted
to XPath first. Enables the use of some pseudo selectors, such as `invalid`
in some drivers. [Thomas Walpole]
* `Capybara.asset_host` option, which inserts a `base` tag into the page on
`save_and_open_page`, eases debugging with the Rails asset pipeline.
[Steve Hull]
* `exact` option, can specify whether to match substrings or entire text.
[Jonas Nicklas]
* `match` option, can specify behaviour in case of multiple matches.
[Jonas Nicklas]
* `wait` option, can specify how long to wait for a given action/finder.
[Jonas Nicklas]
* Config option which disables bubbling of errors raised inside server.
[Jonas Nicklas]
* `text` now takes a parameter which makes it possible to return either all
text or only visible text. The default depends on
`Capybara.ignore_hidden_elements`. `Capybara.visible_text_only` option is
available for compatibility. [Jonas Nicklas]
* `has_content?` and `has_text?` now take the same count options as `has_selector?`
[Andrey Botalov]
* `current_scope` is now public API, returns the current element when `within`
is used. [Martijn Walraven]
* `find("input").disabled?` returns true if a node is disabled. [Ben Lovell]
* Find disabled fields and buttons with `:disabled => false`. [Jonas Nicklas]
* `find("input").hover` moves the mouse to the element in supported drivers.
[Thomas Walpole]
* RackTest driver now support `form` attribute on form elements.
[Thomas Walpole]
* `page.title` returns the page title. [Terry Progetto]
* `has_title?` matcher to assert on page title. [Jonas Nicklas]
* The gem is now signed with a certicficate. The public key is available in the
repo. [Jonas Nicklas]
* `:select` and `:textarea` are valid options for the `:type` filter on `find_field`
and `has_field?`. [Yann Plancqueel]
### Fixed
* Fixed race conditions when synchronizing across multiple nodes [Jonas Nicklas]
* Fixed race conditions in deeply nested selectors [Jonas Nicklas]
* Fix issue with `within_frame`, where selecting multiple nested frames didn't
work as intended. [Thomas Walpole]
* RackTest no longer fills in readonly textareas. [Thomas Walpole]
* Don't use autoload to load files, require them directly instead. [Jonas Nicklas]
* Rescue weird exceptions when booting server [John Wilger]
* Non strings are now properly cast when using the maxlength attribute [Jonas Nicklas]
# Version 2.0.3
Release date: 2013-03-26
* Check against Rails version fixed to work with Rails' master branch now returning
a Gem::Version [Jonas Nicklas]
* Use posix character class for whitespace replace, solves various encoding
problems on Ruby 2.0.0 and JRuby. [Ben Cates]
# Version 2.0.2
Release date: 2012-12-31
### Changed
* Capybara no longer uses thin as a server if it is available, due to thread
safety issues. Now Capybara always defaults to WEBrick. [Jonas Nicklas]
### Fixed
* Suppress several warnings [Kouhei Sutou]
* Fix default host becoming nil [Brian Cardarella]
* Fix regression in 2.0.1 which caused node comparisons with non node objects
to throw an exception [Kouhei Sotou]
* A few changes to the specs, only relevant to driver authors [Jonas Nicklas]
* Encoding error under JRuby [Piotr Krawiec]
* Ruby 2 encoding fix [Murahashi Sanemat Kenichi]
* Catch correct exception on server timeout [Jonathan del Strother]
# Version 2.0.1
Release date: 2012-12-21
### Changed
* Move the RackTest driver override with the `:respect_data_method` option
enabled from capybara/rspec to capybara/rails, so that it is enabled in
Rails projects that don't use RSpec. [Carlos Antonio da Silva]
* `source` is now an alias for `html`. RackTest no longer returns modifications
to `html`. This basically codifies the behaviour which we've had for a while
anyway, and should have minimal impact for end users. For driver authors, it
means that they only have to implement `html`, and not `source`. [Jonas
Nicklas]
### Fixed
* Visiting relative URLs when `app_host` is set and no server is running works
as expected. [Jonas Nicklas]
* `fill_in` works properly under Selenium again when the caret is not at the
end of the field before the method is called. [Douwe Maan, Jonas Nicklas, Jari
Bakken]
* `attach_file` can once again be given a Pathname [Jake Goulding]
# Version 2.0.0
Release date: 2012-11-05
### Changed
* Dropped official support for Ruby 1.8.x. [Jonas Nicklas]
* `respect_data_method` default to `false` for the RackTest driver in non-rails
applications. That means that Capybara no longer picks up `data-method="post"`
et. al. from links by default when you haven't required capybara/rails
[Jonas Nicklas]
* `find` now raises an error if more than one element was found. Since `find` is
used by most actions, like `click_link` under the surface, this means that all
actions need to unambiguous in the future. [Jonas Nicklas]
* All methods which find or manipulate fields or buttons now ignore them when
they are disabled. [Jonas Nicklas]
* Can no longer find elements by id via `find(:foo)`, use `find("#foo")` or
`find_by_id("foo")` instead. [Jonas Nicklas]
* `Element#text` on RackTest now only returns visible text and normalizes
(strips) whitespace, as with Selenium [Mark Dodwell, Jo Liss]
* `has_content?` now checks the text value returned by `Element#text`, as opposed to
querying the DOM. Which means it does not match hidden text.
[Ryan Montgomery, Mark Dodwell, Jo Liss]
* #394: `#body` now returns the unmodified source (like `#source`), not the current
state of the DOM (like `#html`), by popular request [Jonas Nicklas]
* `Node#all` no longer returns an array, but rather an enumerable `Capybara::Result`
[Jonas Nicklas]
* The arguments to `select` and `unselect` needs to be the exact text of an option
in a select box, substrings are no longer allowed [Jonas Nicklas]
* The `options` option to `has_select?` must match the exact set of options. Use
`with_options` for the old behaviour. [Gonzalo Rodriguez]
* The `selected` option to `has_select?` must match all selected options for multiple
selects. [Gonzalo Rodriguez]
* Various internals for running driver specs, this should only affect driver authors
[Jonas Nicklas]
* Rename `Driver#body` to `Driver#html` (relevant only for driver authors) [Jo
Liss]
### Removed
* No longer possible to specify `failure_message` for custom selectors. [Jonas Nicklas]
* #589: `Capybara.server_boot_timeout` has been removed in favor of a higher
(60-second) hard-coded timeout [Jo Liss]
* `Capybara.prefer_visible_elements` has been removed, as it is no longer needed
with the changed find semantics [Jonas Nicklas]
* `Node#wait_until` and `Session#wait_until` have been removed. See `Node#synchronize`
for an alternative [Jonas Nicklas]
* `Capybara.timeout` has been removed [Jonas Nicklas]
* The `:resynchronize` option has been removed from the Selenium driver [Jonas Nicklas]
* The `rows` option to `has_table?` has been removed without replacement.
[Jonas Nicklas]
### Added
* Much improved error message [Jonas Nicklas]
* Errors from inside the session for apps running in a server are raised when
session is reset [James Tucker, Jonas Nicklas]
* A ton of new selectors built in out of the box, like `field`, `link`, `button`,
etc... [Adam McCrea, Jonas Nicklas]
* `has_text?` has been added as an alias for `has_content?` [Jonas Nicklas]
* Add `Capybara.server_host` option (default: 127.0.0.1) [David Balatero]
* Add `:type` option for `page.has_field?` [Gonzalo Rodríguez]
* Custom matchers can now be specified in CSS in addition to XPath [Jonas Nicklas]
* `Node#synchronize` method to rerun a block of code if certain errors are raised
[Jonas Nicklas]
* `Capybara.always_include_port` config option always includes the server port in
URLs when using `visit`. Facilitates testing different domain names. [Douwe Maan]
* Redirect limit for RackTest driver is configurable [Josh Lane]
* Server port can be manually specified during initialization of server.
[Jonas Nicklas, John Wilger]
* `has_content?` and `has_text?` can be given a regular expression [Vasiliy Ermolovich]
* Multiple files can be uploaded with `attach_file` [Jarl Friis]
### Fixed
* Nodes found via `all` are no longer reloaded. This fixes weird quirks where
nodes would seemingly randomly replace themselves with other nodes [Jonas Nicklas]
* Session is only reset if it has been modified, dramatically improves performance if
only part of the test suite runs Capybara. [Jonas Nicklas]
* Test suite now passes on Ruby 1.8 [Jo Liss]
* #565: `require 'capybara/dsl'` is no longer necessary [Jo Liss]
* `Rack::Test` now respects ports when changing hosts [Jo Liss]
* #603: `Rack::Test` now preserves the original referer URL when following a
redirect [Rob van Dijk]
* Rack::Test now does not send a referer when calling `visit` multiple times
[Jo Liss]
* Exceptions during server boot now propagate to main thread [James Tucker]
* RSpec integration now cleans up before the test instead of after [Darwin]
* If `respect_data_method` is true, the data-method attribute can be capitalized
[Marco Antonio]
* Rack app boot timing out raises an error as opposed to just logging to STDOUT
[Adrian Irving-Beer]
* `#source` returns an empty string instead of nil if no pages have been visited
[Jonas Nicklas]
* Ignore first leading newline in textareas in RackTest [Vitalii Khustochka]
* `within_frame` returns the value of the given block [Alistair Hutchison]
* Running `Node.set` on text fields will not trigger more than one change event
[Andrew Kasper]
* Throw an error when an option is given to a finder method, like `all` or
`has_selector?` which Capybara doesn't understand [Jonas Nicklas]
* Two references to the node now register as equal when comparing them with `==`
[Jonas Nicklas]
* `has_text` (`has_content`) now accepts non-string arguments, like numbers.
[Jo Liss]
* `has_text` and `text` now correctly normalize Unicode whitespace, such as
` `. [Jo Liss]
* RackTest allows protocol relative URLs [Jonas Nicklas]
* Arguments are cast to string where necessary, so that e.g. `click_link(:foo)` works
as expected. [Jonas Nicklas]
* `:count => 0` now works as expected [Jarl Friis]
* Fixed race conditions on negative assertions when removing nodes [Jonas Nicklas]
# Version 1.1.4
Release date: 2012-11-28
### Fixed
* Fix more race conditions on negative assertions. [Jonas Nicklas]
# Version 1.1.3
Release date: 2012-10-30
### Fixed:
* RackTest driver ignores leading newline in textareas, this is consistent with
the spec and how browsers behave. [Vitalii Khustochka]
* Nodes found via `all` and `first` are never reloaded. This fixes issues where
a node would sometimes magically turn into a completely different node.
[Jonas Nicklas]
* Fix race conditions on negative assertions. This fixes issues where removing
an element and asserting on its non existence could cause
StaleElementReferenceError and similar to be thrown. [Jonas Nicklas]
* Options are no longer lost when reloading elements. This fixes issues where
reloading an element would cause a non-matching element to be found, because
options to `find` were ignored. [Jonas Nicklas]
# Version 1.1.2
Release date: 2011-11-15
### Fixed
* #541: Make attach_file work with selenium-webdriver >=2.12 [Jonas Nicklas]
# Version 1.1.0
Release date: 2011-09-02
### Fixed
* Sensible inspect for Capybara::Session [Jo Liss]
* Fix headers and host on redirect [Matt Colyer, Jonas Nicklas, Kim Burgestrand]
* using_driver now restores the old driver instead of reverting to the default [Carol Nichols]
* Errors when following links relative to the root path under rack-test [Jonas Nicklas, Kim Burgestrand]
* Make sure exit codes are propagated properly [Edgar Beigarts]
### Changed
* resynchronization is off by default under Selenium
### Added
* Elements are automatically reloaded (including parents) during wait [Jonas Nicklas]
* Rescue driver specific element errors, such as the dreaded ObsoleteElementError and retry [Jonas Nicklas]
* Raise an error if something has frozen time [Jonas Nicklas]
* Allow within to take a node instead of a selector [Peter Williams]
* Using wait_time_time to change wait time for a block of code [Jonas Nicklas, Kim Burgestrand]
* Option for rack-test driver to disable data-method hack [Jonas Nicklas, Kim Burgestrand]
# Version 1.0.1
Release date: 2011-08-12
### Fixed
* Dependend on selenium-webdriver ~>2.0 and fix deprecations [Thomas Walpole, Jo Liss]
* Depend on Launch 2.0 [Jeremy Hinegardner]
* Rack-Test ignores fill in on fields with maxlength=""
# Version 1.0.0
Release date: 2011-06-14
### Added
* Added DSL for acceptance tests, inspired by Luismi Cavallé's Steak [Luismi Cavalle and Jonas Nicklas]
* Selenium driver automatically waits for AJAX requests to finish [mgiambalvo, Nicklas Ramhöj and Jonas Nicklas]
* Support for switching between multiple named sessions [Tristan Dunn]
* failure_message can be specified for Selectors [Jonas Nicklas]
* RSpec matchers [David Chelimsky and Jonas Nicklas]
* Added save_page to save tempfile without opening in browser [Jeff Kreeftmeijer]
* Cucumber now switches automatically to a registered driver if the tag matches the name [Jonas Nicklas]
* Added Session#text [Jonas Nicklas and Scott Cytacki]
* Added Session#html as an alias for Session#body [Jo Liss]
* Added Session#current_host method [Jonas Nicklas]
* Buttons can now be clicked by title [Javier Martin]
* :headers option for RackTest driver to set custom HTTP headers [Jonas Nicklas]
### Removed
* Culerity and Celerity drivers have been removed and split into separate gems [Gabriel Sobrinho]
### Deprecated
* `include Capybara` has been deprecated in favour of `include Capybara::DSL` [Jonas Nicklas]
### Changed
* Rack test driver class has been renamed from Capybara::Driver::RackTest to Capybara::RackTest::Driver [Jonas Nicklas]
* Selenium driver class has been renamed from Capybara::Driver::Selenium to Capybara::Selenium::Driver [Jonas Nicklas]
* Capybara now prefers visible elements over hidden elements, disable by setting Capybara.prefer_visible_elements = false [Jonas Nicklas and Nicklas Ramhöj]
* For RSpec, :type => :request is now supported (and preferred over :acceptance) [Jo Liss]
* Selenium driver tried to wait for AJAX requests to finish before proceeding [Jonas Nicklas and Nicklas Ramhöj]
* Session no longer uses method missing, uses explicit delegates instead [Jonas Nicklas]
### Fixed
* The Rack::Test driver now respects maxlength on text fields [Guilherme Carvalho]
* Allow for more than one save_and_open_page call per second [Jo Liss]
* Automatically convert options to :count, :minimum, :maximum, etc. to integers [Keith Marcum]
* Rack::Test driver honours maxlength on input fields [Guilherme Carvalho]
* Rack::Test now works as expected with domains and subdomains [Jonas Nicklas]
* Session is reset more thoroughly between tests. [Jonas Nicklas]
* Raise error when uploading non-existant file [Jonas Nicklas]
* Rack reponse body should respond to #each [Piotr Sarnacki]
* Deprecation warnings with selenium webdriver 0.2.0 [Aaron Gibraltar]
* Selenium Chrome no longer YELLS tagname [Carl Jackson & David W. Frank]
* Capybara no longer strips encoding before sending to Rack [Jonas Nicklas]
* Improve handling of relative URLs [John Barton]
* Readd and fix build_rack_mock_session [Jonas Nicklas, Jon Leighton]
# Version 0.4.1
Release date: 2011-01-21
### Added
* New click_on alias for click_link_or_button, shorter yet unambiguous. [Jonas Nicklas]
* Finders now accept :visible => false which will find all elements regardless of Capybara.ignore_hidden_elements [Jonas Nicklas]
* Configure how the server is started via Capybara.server { |app, port| ... }. [John Firebough]
* Added :between, :maximum and :minimum options to has_selector and friends [James B. Byrne]
* New Capybara.string util function which allows matchers on arbitrary strings, mostly for helper and view specs [David Chelimsky and Jonas Nicklas]
* Server boot timeout is now configurable, via Capybara.server_boot_timeout [Adam Cigánek]
* Built in support for RSpec [Jonas Nicklas]
* Capybara.using_driver to switch to a different driver temporarily [Jeff Kreeftmeijer]
* Added Session#first which is somewhat speedier than Session#all, use it internally for speed boost [John Firebaugh]
### Changed
* Session#within now accepts the same arguments as other finders, like Session#all and Session#find [Jonas Nicklas]
### Removed
* All deprecations from 0.4.0 have been removed. [Jonas Nicklas]
### Fixed
* Don't mangle URLs in save_and_open_page when using self-closing tags [Adam Spiers]
* Catch correct error when server boot times out [Jonas Nicklas]
* Celerity driver now properly passes through options, making it configurable [Jonas Nicklas]
* Better implementation of attributes in C[ue]lerity, should fix issues with attributes with strange names [Jonas Nicklas]
* Session#find no longer swallows errors [Jonas Nicklas]
* Fix problems with multiple file inputs [Philip Arndt]
* Submit multipart forms as multipart under rack-test even if they contain no files [Ryan Kinderman]
* Matchers like has_select? and has_checked_field? now work with dynamically changed values [John Firebaugh]
* Preserve order of rack params [Joel Chippindale]
* RackTest#reset! is more thorough [Joel Chippindale]
# Version 0.4.0
Release date: 2010-10-22
### Changed
* The Selector API was changed slightly, use Capybara.add_selector, see README
### Fixed
* Celerity driver is registered properly
* has_selector? and has_no_selector? added to DSL
* Multiple selects return correct values under C[cu]lerity
* Naked query strings are handled correctly by rack-test
# Version 0.4.0.rc
Release date: 2010-10-12
### Changed
* within and find/locate now follow the XPath spec in that //foo finds all nodes in the document, instead of
only for the context node. See this post for details: http://groups.google.com/group/ruby-capybara/browse_thread/thread/b129067979df21b3
* within now executes within the first found instance of the selector, not in all of them
* find now waits for AJAX requests and raises an exception when the element is not found (same as locate used to do)
* The default selector is now CSS, not XPath
### Deprecated
* Session#click has been renamed click_link_or_button and the old click has been deprecated
* Node#node has been renamed native
* Node#locate is deprecated in favor of Node#find, which now behaves identically
* Session#drag is deprecated, please use Node#drag_to(other_node) instead
### Added
* Pretty much everything is properly documented now
* It's now possible to call all session methods on nodes, like `find('#foo').fill_in(...)`
* Custom selectors can be added with Capybara::Selector.add
* The :id selector is added by default, use it lile `find(:id, 'foo')` or `find(:foo)`
* Added Node#has_selector? so any kind of selector can be queried.
* Added Capybara.configure for less wordy configuration
* Added within_window to switch between different windows (currently Selenium only)
* Capybara.server_port to provide a fixed port if wanted (defaults to automatic selection)
### Fixed
* CSS selectors with multiple selectors, such as "h1, h2" now work correctly
* Port is automatically assigned instead of guessing
* Strip encodings in rack-test, no more warnings!
* RackTest no longer submits disabled fields
* Servers no longer output annoying debug information when started
* TCP port selection is left to Ruby to decide, no more port guessing
* Select boxes now return option value instead of text if present
* The default has been changed from localhost to 127.0.0.1, should fix some obscure selenium bugs
* RackTest now supports complex field names, such as foo[bar][][baz]
# Version 0.3.9
Release date: 2010-07-03
### Added
* status_code which returns the HTTP status code of the last response (no Selenium!)
* Capybara.save_and_open_page to store tempfiles
* RackTest and Culerity drivers now clean up after themselves properly
### Fixed
* When no rack app is set and the app is called, a more descriptive error is raised
* select now works with optgroups
* Don't submit image buttons unless they were clicked under rack-test
* Support custom field types under Selenium
* Support input fields without a type, treat them as though they were text fields
* Redirect now throws an error after 5 redirects, as per RFC
* Selenium now properly raises an error when Node#trigger is called
* Node#value now returns the correct value for textareas under rack-test
# Version 0.3.8
Release date: 2010-05-12
### Added
* Within_frame method to execute a block of code within a particular iframe (Selenium only!)
### Fixed
* Single quotes are properly escaped with `select` under rack-test and Selenium.
* The :text option for searches now escapes regexp special characters when a string is given.
* Selenium now correctly checks already checked checkboxes (same with uncheck)
* Timing issue which caused Selenium to hang under certain circumstances.
* Selenium now resolves attributes even if they are given as a Symbol
# Version 0.3.7
Release date: 2010-04-09
This is a drop in compatible maintainance release. It's mostly
important for driver authors.
### Added
* RackTest scans for data-method which rails3 uses to change the request method
### Fixed
* Don't hang when starting server on Windoze
### Changed
* The driver and session specs are now located inside lib! Driver authors can simply require them.
# Version 0.3.6
Release date: 2010-03-22
This is a maintainance release with minor bug fixes, should be
drop in compatible.
### Added
* It's now possible to load in external drivers
### Fixed
* has_content? ignores whitespace
* Trigger events when choosing radios and checking checkboxes under Selenium
* Make Capybara.app totally optional when running without server
* Changed fallback host so it matches the one set up by Rails' integration tests
# Version 0.3.5
Release date: 2010-02-26
This is a mostly backwards compatible release, it does break
the API in some minor places, which should hopefully not affect
too many users, please read the release notes carefully!
### Breaking
* Relative searching in a node (e.g. find('//p').all('//a')) will now follow XPath standard
this means that if you want to find descendant nodes only, you'll need to prefix a dot!
* `visit` now accepts fully qualified URLs for drivers that support it.
* Capybara will always try to run a rack server, unless you set Capybara.run_sever = false
### Changed
* thin is preferred over mongrel and webrick, since it is Ruby 1.9 compatible
* click_button and click will find , clicking them does nothing in RackTest
### Added
* Much improved error messages in a multitude of places
* More semantic page querying with has_link?, has_button?, etc...
* Option to ignore hidden elements when querying and interacting with the page
* Support for multiple selects
### Fixed
* find_by_id is no longer broken
* clicking links where the image's alt attribute contains the text is now possible
* within_fieldset and within_table work when the default selector is CSS
* boolean attributes work the same across drivers (return true/false)
capybara-2.5.0/README.md 0000644 0001750 0001750 00000074244 12573712570 013627 0 ustar lunar lunar # Capybara
[](http://travis-ci.org/jnicklas/capybara)
[](https://gemnasium.com/jnicklas/capybara)
[](https://codeclimate.com/github/jnicklas/capybara)
Capybara helps you test web applications by simulating how a real user would
interact with your app. It is agnostic about the driver running your tests and
comes with Rack::Test and Selenium support built in. WebKit is supported
through an external gem.
**Need help?** Ask on the mailing list (please do not open an issue on
GitHub): http://groups.google.com/group/ruby-capybara
## Table of contents
- [Key benefits](#key-benefits)
- [Setup](#setup)
- [Using Capybara with Cucumber](#using-capybara-with-cucumber)
- [Using Capybara with RSpec](#using-capybara-with-rspec)
- [Using Capybara with Test::Unit](#using-capybara-with-testunit)
- [Using Capybara with MiniTest::Spec](#using-capybara-with-minitestspec)
- [Drivers](#drivers)
- [Selecting the Driver](#selecting-the-driver)
- [RackTest](#racktest)
- [Selenium](#selenium)
- [Capybara-webkit](#capybara-webkit)
- [Poltergeist](#poltergeist)
- [The DSL](#the-dsl)
- [Navigating](#navigating)
- [Clicking links and buttons](#clicking-links-and-buttons)
- [Interacting with forms](#interacting-with-forms)
- [Querying](#querying)
- [Finding](#finding)
- [Scoping](#scoping)
- [Working with windows](#working-with-windows)
- [Scripting](#scripting)
- [Modals](#modals)
- [Debugging](#debugging)
- [Matching](#matching)
- [Exactness](#exactness)
- [Strategy](#strategy)
- [Transactions and database setup](#transactions-and-database-setup)
- [Asynchronous JavaScript (Ajax and friends)](#asynchronous-javascript-ajax-and-friends)
- [Using the DSL elsewhere](#using-the-dsl-elsewhere)
- [Calling remote servers](#calling-remote-servers)
- [Using the sessions manually](#using-the-sessions-manually)
- [XPath, CSS and selectors](#xpath-css-and-selectors)
- [Beware the XPath // trap](#beware-the-xpath--trap)
- [Configuring and adding drivers](#configuring-and-adding-drivers)
- [Gotchas:](#gotchas)
- [Development](#development)
## Key benefits
- **No setup** necessary for Rails and Rack application. Works out of the box.
- **Intuitive API** which mimics the language an actual user would use.
- **Switch the backend** your tests run against from fast headless mode
to an actual browser with no changes to your tests.
- **Powerful synchronization** features mean you never have to manually wait
for asynchronous processes to complete.
## Setup
Capybara requires Ruby 1.9.3 or later. To install, add this line to your
`Gemfile` and run `bundle install`:
```ruby
gem 'capybara'
```
If the application that you are testing is a Rails app, add this line to your test helper file:
```ruby
require 'capybara/rails'
```
**Note:** In Rails 4.0/4.1 the default test environment (`config/environments/test.rb`) is [not threadsafe](https://github.com/rails/rails/issues/15089).
If you experience random errors about missing constants, add `config.allow_concurrency = false` to `config/environments/test.rb`.
If the application that you are testing is a Rack app, but not Rails, set Capybara.app to your Rack app:
```ruby
Capybara.app = MyRackApp
```
If you need to test JavaScript, or if your app interacts with (or is located at)
a remote URL, you'll need to [use a different driver](#drivers).
## Using Capybara with Cucumber
The `cucumber-rails` gem comes with Capybara support built-in. If you
are not using Rails, manually load the `capybara/cucumber` module:
```ruby
require 'capybara/cucumber'
Capybara.app = MyRackApp
```
You can use the Capybara DSL in your steps, like so:
```ruby
When /I sign in/ do
within("#session") do
fill_in 'Email', :with => 'user@example.com'
fill_in 'Password', :with => 'password'
end
click_button 'Sign in'
end
```
You can switch to the `Capybara.javascript_driver` (`:selenium`
by default) by tagging scenarios (or features) with `@javascript`:
```ruby
@javascript
Scenario: do something Ajaxy
When I click the Ajax link
...
```
There are also explicit `@selenium` and `@rack_test`
tags set up for you.
## Using Capybara with RSpec
Load RSpec 2.x support by adding the following line (typically to your
`spec_helper.rb` file):
```ruby
require 'capybara/rspec'
```
If you are using Rails, put your Capybara specs in `spec/features`.
If you are not using Rails, tag all the example groups in which you want to use
Capybara with `:type => :feature`.
You can now write your specs like so:
```ruby
describe "the signin process", :type => :feature do
before :each do
User.make(:email => 'user@example.com', :password => 'password')
end
it "signs me in" do
visit '/sessions/new'
within("#session") do
fill_in 'Email', :with => 'user@example.com'
fill_in 'Password', :with => 'password'
end
click_button 'Sign in'
expect(page).to have_content 'Success'
end
end
```
Use `:js => true` to switch to the `Capybara.javascript_driver`
(`:selenium` by default), or provide a `:driver` option to switch
to one specific driver. For example:
```ruby
describe 'some stuff which requires js', :js => true do
it 'will use the default js driver'
it 'will switch to one specific driver', :driver => :webkit
end
```
Capybara also comes with a built in DSL for creating descriptive acceptance tests:
```ruby
feature "Signing in" do
background do
User.make(:email => 'user@example.com', :password => 'caplin')
end
scenario "Signing in with correct credentials" do
visit '/sessions/new'
within("#session") do
fill_in 'Email', :with => 'user@example.com'
fill_in 'Password', :with => 'caplin'
end
click_button 'Sign in'
expect(page).to have_content 'Success'
end
given(:other_user) { User.make(:email => 'other@example.com', :password => 'rous') }
scenario "Signing in as another user" do
visit '/sessions/new'
within("#session") do
fill_in 'Email', :with => other_user.email
fill_in 'Password', :with => other_user.password
end
click_button 'Sign in'
expect(page).to have_content 'Invalid email or password'
end
end
```
`feature` is in fact just an alias for `describe ..., :type => :feature`,
`background` is an alias for `before`, `scenario` for `it`, and
`given`/`given!` aliases for `let`/`let!`, respectively.
Finally, Capybara matchers are supported in view specs:
```ruby
RSpec.describe "todos/show.html.erb", type: :view do
it "displays the todo title" do
assign :todo, Todo.new(title: "Buy milk")
render
expect(rendered).to have_css("header h1", text: "Buy milk")
end
end
```
## Using Capybara with Test::Unit
* If you are using Rails, add the following code in your `test_helper.rb`
file to make Capybara available in all test cases deriving from
`ActionDispatch::IntegrationTest`:
```ruby
class ActionDispatch::IntegrationTest
# Make the Capybara DSL available in all integration tests
include Capybara::DSL
end
```
* If you are not using Rails, define a base class for your Capybara tests like
so:
```ruby
class CapybaraTestCase < Test::Unit::TestCase
include Capybara::DSL
def teardown
Capybara.reset_sessions!
Capybara.use_default_driver
end
end
```
Remember to call `super` in any subclasses that override
`teardown`.
To switch the driver, set `Capybara.current_driver`. For instance,
```ruby
class BlogTest < ActionDispatch::IntegrationTest
setup do
Capybara.current_driver = Capybara.javascript_driver # :selenium by default
end
test 'shows blog posts' do
# ... this test is run with Selenium ...
end
end
```
## Using Capybara with MiniTest::Spec
Set up your base class as with Test::Unit. (On Rails, the right base class
could be something other than ActionDispatch::IntegrationTest.)
The capybara_minitest_spec gem ([GitHub](https://github.com/ordinaryzelig/capybara_minitest_spec),
[rubygems.org](https://rubygems.org/gems/capybara_minitest_spec)) provides MiniTest::Spec
expectations for Capybara. For example:
```ruby
page.must_have_content('Important!')
```
## Drivers
Capybara uses the same DSL to drive a variety of browser and headless drivers.
### Selecting the Driver
By default, Capybara uses the `:rack_test` driver, which is fast but limited: it
does not support JavaScript, nor is it able to access HTTP resources outside of
your Rack application, such as remote APIs and OAuth services. To get around
these limitations, you can set up a different default driver for your features.
For example if you'd prefer to run everything in Selenium, you could do:
```ruby
Capybara.default_driver = :selenium
```
However, if you are using RSpec or Cucumber, you may instead want to consider
leaving the faster `:rack_test` as the __default_driver__, and marking only those
tests that require a JavaScript-capable driver using `:js => true` or
`@javascript`, respectively. By default, JavaScript tests are run using the
`:selenium` driver. You can change this by setting
`Capybara.javascript_driver`.
You can also change the driver temporarily (typically in the Before/setup and
After/teardown blocks):
```ruby
Capybara.current_driver = :webkit # temporarily select different driver
# tests here
Capybara.use_default_driver # switch back to default driver
```
**Note**: switching the driver creates a new session, so you may not be able to
switch in the middle of a test.
### RackTest
RackTest is Capybara's default driver. It is written in pure Ruby and does not
have any support for executing JavaScript. Since the RackTest driver interacts
directly with Rack interfaces, it does not require a server to be started.
However, this means that if your application is not a Rack application (Rails,
Sinatra and most other Ruby frameworks are Rack applications) then you cannot
use this driver. Furthermore, you cannot use the RackTest driver to test a
remote application, or to access remote URLs (e.g., redirects to external
sites, external APIs, or OAuth services) that your application might interact
with.
[capybara-mechanize](https://github.com/jeroenvandijk/capybara-mechanize)
provides a similar driver that can access remote servers.
RackTest can be configured with a set of headers like this:
```ruby
Capybara.register_driver :rack_test do |app|
Capybara::RackTest::Driver.new(app, :headers => { 'HTTP_USER_AGENT' => 'Capybara' })
end
```
See the section on adding and configuring drivers.
### Selenium
At the moment, Capybara supports [Selenium 2.0
(Webdriver)](http://seleniumhq.org/docs/01_introducing_selenium.html#selenium-2-aka-selenium-webdriver),
*not* Selenium RC. In order to use Selenium, you'll need to install the
`selenium-webdriver` gem, and add it to your Gemfile if you're using bundler.
Provided Firefox is installed, everything is set up for you, and you should be
able to start using Selenium right away.
**Note**: drivers which run the server in a different thread may not share the
same transaction as your tests, causing data not to be shared between your test
and test server, see "Transactions and database setup" below.
### Capybara-webkit
The [capybara-webkit driver](https://github.com/thoughtbot/capybara-webkit) is for true headless
testing. It uses QtWebKit to start a rendering engine process. It can execute JavaScript as well.
It is significantly faster than drivers like Selenium since it does not load an entire browser.
You can install it with:
```bash
gem install capybara-webkit
```
And you can use it by:
```ruby
Capybara.javascript_driver = :webkit
```
### Poltergeist
[Poltergeist](https://github.com/jonleighton/poltergeist) is another
headless driver which integrates Capybara with
[PhantomJS](http://phantomjs.org/). It is truly headless, so doesn't
require Xvfb to run on your CI server. It will also detect and report
any Javascript errors that happen within the page.
## The DSL
*A complete reference is available at
[rubydoc.info](http://rubydoc.info/github/jnicklas/capybara/master)*.
**Note: By default Capybara will only locate visible elements. This is because
a real user would not be able to interact with non-visible elements.**
**Note**: All searches in Capybara are *case sensitive*. This is because
Capybara heavily uses XPath, which doesn't support case insensitivity.
### Navigating
You can use the
[visit](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#visit-instance_method)
method to navigate to other pages:
```ruby
visit('/projects')
visit(post_comments_path(post))
```
The visit method only takes a single parameter, the request method is **always**
GET.
You can get the [current path](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#current_path-instance_method)
of the browsing session for test assertions:
```ruby
expect(current_path).to eq(post_comments_path(post))
```
### Clicking links and buttons
*Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions)*
You can interact with the webapp by following links and buttons. Capybara
automatically follows any redirects, and submits forms associated with buttons.
```ruby
click_link('id-of-link')
click_link('Link Text')
click_button('Save')
click_on('Link Text') # clicks on either links or buttons
click_on('Button Value')
```
### Interacting with forms
*Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions)*
There are a number of tools for interacting with form elements:
```ruby
fill_in('First Name', :with => 'John')
fill_in('Password', :with => 'Seekrit')
fill_in('Description', :with => 'Really Long Text...')
choose('A Radio Button')
check('A Checkbox')
uncheck('A Checkbox')
attach_file('Image', '/path/to/image.jpg')
select('Option', :from => 'Select Box')
```
### Querying
*Full reference: [Capybara::Node::Matchers](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Matchers)*
Capybara has a rich set of options for querying the page for the existence of
certain elements, and working with and manipulating those elements.
```ruby
page.has_selector?('table tr')
page.has_selector?(:xpath, '//table/tr')
page.has_xpath?('//table/tr')
page.has_css?('table tr.foo')
page.has_content?('foo')
```
**Note:** The negative forms like `has_no_selector?` are different from `not
has_selector?`. Read the section on asynchronous JavaScript for an explanation.
You can use these with RSpec's magic matchers:
```ruby
expect(page).to have_selector('table tr')
expect(page).to have_selector(:xpath, '//table/tr')
expect(page).to have_xpath('//table/tr')
expect(page).to have_css('table tr.foo')
expect(page).to have_content('foo')
```
### Finding
_Full reference: [Capybara::Node::Finders](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Finders)_
You can also find specific elements, in order to manipulate them:
```ruby
find_field('First Name').value
find_link('Hello', :visible => :all).visible?
find_button('Send').click
find(:xpath, "//table/tr").click
find("#overlay").find("h1").click
all('a').each { |a| a[:href] }
```
**Note**: `find` will wait for an element to appear on the page, as explained in the
Ajax section. If the element does not appear it will raise an error.
These elements all have all the Capybara DSL methods available, so you can restrict them
to specific parts of the page:
```ruby
find('#navigation').click_link('Home')
expect(find('#navigation')).to have_button('Sign out')
```
### Scoping
Capybara makes it possible to restrict certain actions, such as interacting with
forms or clicking links and buttons, to within a specific area of the page. For
this purpose you can use the generic
[within](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#within-instance_method)
method. Optionally you can specify which kind of selector to use.
```ruby
within("li#employee") do
fill_in 'Name', :with => 'Jimmy'
end
within(:xpath, "//li[@id='employee']") do
fill_in 'Name', :with => 'Jimmy'
end
```
There are special methods for restricting the scope to a specific fieldset,
identified by either an id or the text of the fieldset's legend tag, and to a
specific table, identified by either id or text of the table's caption tag.
```ruby
within_fieldset('Employee') do
fill_in 'Name', :with => 'Jimmy'
end
within_table('Employee') do
fill_in 'Name', :with => 'Jimmy'
end
```
### Working with windows
Capybara provides some methods to ease finding and switching windows:
```ruby
facebook_window = window_opened_by do
click_button 'Like'
end
within_window facebook_window do
find('#login_email').set('a@example.com')
find('#login_password').set('qwerty')
click_button 'Submit'
end
```
### Scripting
In drivers which support it, you can easily execute JavaScript:
```ruby
page.execute_script("$('body').empty()")
```
For simple expressions, you can return the result of the script. Note
that this may break with more complicated expressions:
```ruby
result = page.evaluate_script('4 + 4');
```
### Modals
In drivers which support it, you can accept, dismiss and respond to alerts, confirms and prompts.
You can accept or dismiss alert messages by wrapping the code that produces an alert in a block:
```ruby
accept_alert do
click_link('Show Alert')
end
```
You can accept or dismiss a confirmation by wrapping it in a block, as well:
```ruby
dismiss_confirm do
click_link('Show Confirm')
end
```
You can accept or dismiss prompts as well, and also provide text to fill in for the response:
```ruby
accept_prompt(with: 'Linus Torvalds') do
click_link('Show Prompt About Linux')
end
```
All modal methods return the message that was presented. So, you can access the prompt message
by assigning the return to a variable:
```ruby
message = accept_prompt(with: 'Linus Torvalds') do
click_link('Show Prompt About Linux')
end
expect(message).to eq('Who is the chief architect of Linux?')
```
### Debugging
It can be useful to take a snapshot of the page as it currently is and take a
look at it:
```ruby
save_and_open_page
```
You can also retrieve the current state of the DOM as a string using
[page.html](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session#html-instance_method).
```ruby
print page.html
```
This is mostly useful for debugging. You should avoid testing against the
contents of `page.html` and use the more expressive finder methods instead.
Finally, in drivers that support it, you can save a screenshot:
```ruby
page.save_screenshot('screenshot.png')
```
Or have it save and automatically open:
```ruby
save_and_open_screenshot
```
## Matching
It is possible to customize how Capybara finds elements. At your disposal
are two options, `Capybara.exact` and `Capybara.match`.
### Exactness
`Capybara.exact` and the `exact` option work together with the `is` expression
inside the XPath gem. When `exact` is true, all `is` expressions match exactly,
when it is false, they allow substring matches. Many of the selectors built into
Capybara use the `is` expression. This way you can specify whether you want to
allow substring matches or not. `Capybara.exact` is false by default.
For example:
```ruby
click_link("Password") # also matches "Password confirmation"
Capybara.exact = true
click_link("Password") # does not match "Password confirmation"
click_link("Password", exact: false) # can be overridden
```
### Strategy
Using `Capybara.match` and the equivalent `match` option, you can control how
Capybara behaves when multiple elements all match a query. There are currently
four different strategies built into Capybara:
1. **first:** Just picks the first element that matches.
2. **one:** Raises an error if more than one element matches.
3. **smart:** If `exact` is `true`, raises an error if more than one element
matches, just like `one`. If `exact` is `false`, it will first try to find
an exact match. An error is raised if more than one element is found. If no
element is found, a new search is performed which allows partial matches. If
that search returns multiple matches, an error is raised.
4. **prefer_exact:** If multiple matches are found, some of which are exact,
and some of which are not, then the first exactly matching element is
returned.
The default for `Capybara.match` is `:smart`. To emulate the behaviour in
Capybara 2.0.x, set `Capybara.match` to `:one`. To emulate the behaviour in
Capybara 1.x, set `Capybara.match` to `:prefer_exact`.
## Transactions and database setup
Some Capybara drivers need to run against an actual HTTP server. Capybara takes
care of this and starts one for you in the same process as your test, but on
another thread. Selenium is one of those drivers, whereas RackTest is not.
If you are using a SQL database, it is common to run every test in a
transaction, which is rolled back at the end of the test, rspec-rails does this
by default out of the box for example. Since transactions are usually not
shared across threads, this will cause data you have put into the database in
your test code to be invisible to Capybara.
Cucumber handles this by using truncation instead of transactions, i.e. they
empty out the entire database after each test. You can get the same behaviour
by using a gem such as [database_cleaner](https://github.com/bmabey/database_cleaner).
It is also possible to force your ORM to use the same transaction for all
threads. This may have thread safety implications and could cause strange
failures, so use caution with this approach. It can be implemented in
ActiveRecord through the following monkey patch:
```ruby
class ActiveRecord::Base
mattr_accessor :shared_connection
@@shared_connection = nil
def self.connection
@@shared_connection || retrieve_connection
end
end
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
```
## Asynchronous JavaScript (Ajax and friends)
When working with asynchronous JavaScript, you might come across situations
where you are attempting to interact with an element which is not yet present
on the page. Capybara automatically deals with this by waiting for elements
to appear on the page.
When issuing instructions to the DSL such as:
```ruby
click_link('foo')
click_link('bar')
expect(page).to have_content('baz')
```
If clicking on the *foo* link triggers an asynchronous process, such as
an Ajax request, which, when complete will add the *bar* link to the page,
clicking on the *bar* link would be expected to fail, since that link doesn't
exist yet. However Capybara is smart enough to retry finding the link for a
brief period of time before giving up and throwing an error. The same is true of
the next line, which looks for the content *baz* on the page; it will retry
looking for that content for a brief time. You can adjust how long this period
is (the default is 2 seconds):
```ruby
Capybara.default_max_wait_time = 5
```
Be aware that because of this behaviour, the following two statements are **not**
equivalent, and you should **always** use the latter!
```ruby
!page.has_xpath?('a')
page.has_no_xpath?('a')
```
The former would immediately fail because the content has not yet been removed.
Only the latter would wait for the asynchronous process to remove the content
from the page.
Capybara's Rspec matchers, however, are smart enough to handle either form.
The two following statements are functionally equivalent:
```ruby
expect(page).not_to have_xpath('a')
expect(page).to have_no_xpath('a')
```
Capybara's waiting behaviour is quite advanced, and can deal with situations
such as the following line of code:
```ruby
expect(find('#sidebar').find('h1')).to have_content('Something')
```
Even if JavaScript causes `#sidebar` to disappear off the page, Capybara
will automatically reload it and any elements it contains. So if an AJAX
request causes the contents of `#sidebar` to change, which would update
the text of the `h1` to "Something", and this happened, this test would
pass. If you do not want this behaviour, you can set
`Capybara.automatic_reload` to `false`.
## Using the DSL elsewhere
You can mix the DSL into any context by including Capybara::DSL:
```ruby
require 'capybara'
require 'capybara/dsl'
Capybara.default_driver = :webkit
module MyModule
include Capybara::DSL
def login!
within("//form[@id='session']") do
fill_in 'Email', :with => 'user@example.com'
fill_in 'Password', :with => 'password'
end
click_button 'Sign in'
end
end
```
This enables its use in unsupported testing frameworks, and for general-purpose scripting.
## Calling remote servers
Normally Capybara expects to be testing an in-process Rack application, but you
can also use it to talk to a web server running anywhere on the internet, by
setting app_host:
```ruby
Capybara.current_driver = :selenium
Capybara.app_host = 'http://www.google.com'
...
visit('/')
```
**Note**: the default driver (`:rack_test`) does not support running
against a remote server. With drivers that support it, you can also visit any
URL directly:
```ruby
visit('http://www.google.com')
```
By default Capybara will try to boot a rack application automatically. You
might want to switch off Capybara's rack server if you are running against a
remote application:
```ruby
Capybara.run_server = false
```
## Using the sessions manually
For ultimate control, you can instantiate and use a
[Session](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session)
manually.
```ruby
require 'capybara'
session = Capybara::Session.new(:webkit, my_rack_app)
session.within("//form[@id='session']") do
session.fill_in 'Email', :with => 'user@example.com'
session.fill_in 'Password', :with => 'password'
end
session.click_button 'Sign in'
```
## XPath, CSS and selectors
Capybara does not try to guess what kind of selector you are going to give it,
and will always use CSS by default. If you want to use XPath, you'll need to
do:
```ruby
within(:xpath, '//ul/li') { ... }
find(:xpath, '//ul/li').text
find(:xpath, '//li[contains(.//a[@href = "#"]/text(), "foo")]').value
```
Alternatively you can set the default selector to XPath:
```ruby
Capybara.default_selector = :xpath
find('//ul/li').text
```
Capybara allows you to add custom selectors, which can be very useful if you
find yourself using the same kinds of selectors very often:
```ruby
Capybara.add_selector(:id) do
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
end
Capybara.add_selector(:row) do
xpath { |num| ".//tbody/tr[#{num}]" }
end
Capybara.add_selector(:flash_type) do
css { |type| "#flash.#{type}" }
end
```
The block given to xpath must always return an XPath expression as a String, or
an XPath expression generated through the XPath gem. You can now use these
selectors like this:
```ruby
find(:id, 'post_123')
find(:row, 3)
find(:flash_type, :notice)
```
## Beware the XPath // trap
In XPath the expression // means something very specific, and it might not be what
you think. Contrary to common belief, // means "anywhere in the document" not "anywhere
in the current context". As an example:
```ruby
page.find(:xpath, '//body').all(:xpath, '//script')
```
You might expect this to find all script tags in the body, but actually, it finds all
script tags in the entire document, not only those in the body! What you're looking
for is the .// expression which means "any descendant of the current node":
```ruby
page.find(:xpath, '//body').all(:xpath, './/script')
```
The same thing goes for within:
```ruby
within(:xpath, '//body') do
page.find(:xpath, './/script')
within(:xpath, './/table/tbody') do
...
end
end
```
## Configuring and adding drivers
Capybara makes it convenient to switch between different drivers. It also exposes
an API to tweak those drivers with whatever settings you want, or to add your own
drivers. This is how to override the selenium driver configuration to use chrome:
```ruby
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, :browser => :chrome)
end
```
However, it's also possible to give this configuration a different name.
```ruby
Capybara.register_driver :selenium_chrome do |app|
Capybara::Selenium::Driver.new(app, :browser => :chrome)
end
```
Then tests can switch between using different browsers effortlessly:
```ruby
Capybara.current_driver = :selenium_chrome
```
Whatever is returned from the block should conform to the API described by
Capybara::Driver::Base, it does not however have to inherit from this class.
Gems can use this API to add their own drivers to Capybara.
The [Selenium wiki](http://code.google.com/p/selenium/wiki/RubyBindings) has
additional info about how the underlying driver can be configured.
## Gotchas:
* Access to session and request is not possible from the test, Access to
response is limited. Some drivers allow access to response headers and HTTP
status code, but this kind of functionality is not provided by some drivers,
such as Selenium.
* Access to Rails specific stuff (such as `controller`) is unavailable,
since we're not using Rails' integration testing.
* Freezing time: It's common practice to mock out the Time so that features
that depend on the current Date work as expected. This can be problematic on
ruby/platform combinations that don't support access to a monotonic process clock,
since Capybara's Ajax timing uses the system time, resulting in Capybara
never timing out and just hanging when a failure occurs. It's still possible to
use gems which allow you to travel in time, rather than freeze time.
One such gem is [Timecop](http://github.com/travisjeffery/timecop).
* When using Rack::Test, beware if attempting to visit absolute URLs. For
example, a session might not be shared between visits to `posts_path`
and `posts_url`. If testing an absolute URL in an Action Mailer email,
set `default_url_options` to match the Rails default of
`www.example.com`.
* Server errors will only be raised in the session that initiates the server thread. If you
are testing for specific server errors and using multiple sessions make sure to test for the
errors using the initial session (usually :default)
## Development
To set up a development environment, simply do:
```bash
bundle install
bundle exec rake # run the test suite
```
See
[CONTRIBUTING.md](https://github.com/jnicklas/capybara/blob/master/CONTRIBUTING.md)
for how to send issues and pull requests.
capybara-2.5.0/metadata.yml 0000644 0001750 0001750 00000030136 12573712570 014643 0 ustar lunar lunar --- !ruby/object:Gem::Specification
name: capybara
version: !ruby/object:Gem::Version
version: 2.5.0
platform: ruby
authors:
- Jonas Nicklas
autorequire:
bindir: bin
cert_chain:
- gem-public_cert.pem
date: 2015-08-26 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: nokogiri
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 1.3.3
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 1.3.3
- !ruby/object:Gem::Dependency
name: mime-types
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '1.16'
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '1.16'
- !ruby/object:Gem::Dependency
name: rack
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 1.0.0
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 1.0.0
- !ruby/object:Gem::Dependency
name: rack-test
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 0.5.4
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 0.5.4
- !ruby/object:Gem::Dependency
name: xpath
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: '2.0'
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: '2.0'
- !ruby/object:Gem::Dependency
name: selenium-webdriver
requirement: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: '2.0'
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - "~>"
- !ruby/object:Gem::Version
version: '2.0'
- !ruby/object:Gem::Dependency
name: sinatra
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 0.9.4
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 0.9.4
- !ruby/object:Gem::Dependency
name: rspec
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 2.2.0
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 2.2.0
- !ruby/object:Gem::Dependency
name: launchy
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 2.0.4
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 2.0.4
- !ruby/object:Gem::Dependency
name: yard
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 0.5.8
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 0.5.8
- !ruby/object:Gem::Dependency
name: fuubar
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 0.0.1
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 0.0.1
- !ruby/object:Gem::Dependency
name: cucumber
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 0.10.5
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 0.10.5
- !ruby/object:Gem::Dependency
name: rake
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '0'
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '0'
- !ruby/object:Gem::Dependency
name: pry
requirement: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '0'
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '0'
description: Capybara is an integration testing tool for rack based web applications.
It simulates how a user would interact with a website
email:
- jonas.nicklas@gmail.com
executables: []
extensions: []
extra_rdoc_files: []
files:
- History.md
- License.txt
- README.md
- lib/capybara.rb
- lib/capybara/cucumber.rb
- lib/capybara/driver/base.rb
- lib/capybara/driver/node.rb
- lib/capybara/dsl.rb
- lib/capybara/helpers.rb
- lib/capybara/node/actions.rb
- lib/capybara/node/base.rb
- lib/capybara/node/document.rb
- lib/capybara/node/document_matchers.rb
- lib/capybara/node/element.rb
- lib/capybara/node/finders.rb
- lib/capybara/node/matchers.rb
- lib/capybara/node/simple.rb
- lib/capybara/queries/base_query.rb
- lib/capybara/queries/current_path_query.rb
- lib/capybara/queries/text_query.rb
- lib/capybara/queries/title_query.rb
- lib/capybara/query.rb
- lib/capybara/rack_test/browser.rb
- lib/capybara/rack_test/css_handlers.rb
- lib/capybara/rack_test/driver.rb
- lib/capybara/rack_test/form.rb
- lib/capybara/rack_test/node.rb
- lib/capybara/rails.rb
- lib/capybara/result.rb
- lib/capybara/rspec.rb
- lib/capybara/rspec/features.rb
- lib/capybara/rspec/matchers.rb
- lib/capybara/selector.rb
- lib/capybara/selenium/driver.rb
- lib/capybara/selenium/node.rb
- lib/capybara/server.rb
- lib/capybara/session.rb
- lib/capybara/session/matchers.rb
- lib/capybara/spec/fixtures/another_test_file.txt
- lib/capybara/spec/fixtures/capybara.jpg
- lib/capybara/spec/fixtures/test_file.txt
- lib/capybara/spec/public/jquery-ui.js
- lib/capybara/spec/public/jquery.js
- lib/capybara/spec/public/test.js
- lib/capybara/spec/session/accept_alert_spec.rb
- lib/capybara/spec/session/accept_confirm_spec.rb
- lib/capybara/spec/session/accept_prompt_spec.rb
- lib/capybara/spec/session/all_spec.rb
- lib/capybara/spec/session/assert_current_path.rb
- lib/capybara/spec/session/assert_selector.rb
- lib/capybara/spec/session/assert_text.rb
- lib/capybara/spec/session/assert_title.rb
- lib/capybara/spec/session/attach_file_spec.rb
- lib/capybara/spec/session/body_spec.rb
- lib/capybara/spec/session/check_spec.rb
- lib/capybara/spec/session/choose_spec.rb
- lib/capybara/spec/session/click_button_spec.rb
- lib/capybara/spec/session/click_link_or_button_spec.rb
- lib/capybara/spec/session/click_link_spec.rb
- lib/capybara/spec/session/current_scope_spec.rb
- lib/capybara/spec/session/current_url_spec.rb
- lib/capybara/spec/session/dismiss_confirm_spec.rb
- lib/capybara/spec/session/dismiss_prompt_spec.rb
- lib/capybara/spec/session/evaluate_script_spec.rb
- lib/capybara/spec/session/execute_script_spec.rb
- lib/capybara/spec/session/fill_in_spec.rb
- lib/capybara/spec/session/find_button_spec.rb
- lib/capybara/spec/session/find_by_id_spec.rb
- lib/capybara/spec/session/find_field_spec.rb
- lib/capybara/spec/session/find_link_spec.rb
- lib/capybara/spec/session/find_spec.rb
- lib/capybara/spec/session/first_spec.rb
- lib/capybara/spec/session/go_back_spec.rb
- lib/capybara/spec/session/go_forward_spec.rb
- lib/capybara/spec/session/has_button_spec.rb
- lib/capybara/spec/session/has_css_spec.rb
- lib/capybara/spec/session/has_current_path_spec.rb
- lib/capybara/spec/session/has_field_spec.rb
- lib/capybara/spec/session/has_link_spec.rb
- lib/capybara/spec/session/has_select_spec.rb
- lib/capybara/spec/session/has_selector_spec.rb
- lib/capybara/spec/session/has_table_spec.rb
- lib/capybara/spec/session/has_text_spec.rb
- lib/capybara/spec/session/has_title_spec.rb
- lib/capybara/spec/session/has_xpath_spec.rb
- lib/capybara/spec/session/headers.rb
- lib/capybara/spec/session/html_spec.rb
- lib/capybara/spec/session/node_spec.rb
- lib/capybara/spec/session/reset_session_spec.rb
- lib/capybara/spec/session/response_code.rb
- lib/capybara/spec/session/save_and_open_page_spec.rb
- lib/capybara/spec/session/save_and_open_screenshot_spec.rb
- lib/capybara/spec/session/save_page_spec.rb
- lib/capybara/spec/session/save_screenshot_spec.rb
- lib/capybara/spec/session/screenshot_spec.rb
- lib/capybara/spec/session/select_spec.rb
- lib/capybara/spec/session/source_spec.rb
- lib/capybara/spec/session/text_spec.rb
- lib/capybara/spec/session/title_spec.rb
- lib/capybara/spec/session/uncheck_spec.rb
- lib/capybara/spec/session/unselect_spec.rb
- lib/capybara/spec/session/visit_spec.rb
- lib/capybara/spec/session/window/become_closed_spec.rb
- lib/capybara/spec/session/window/current_window_spec.rb
- lib/capybara/spec/session/window/open_new_window_spec.rb
- lib/capybara/spec/session/window/switch_to_window_spec.rb
- lib/capybara/spec/session/window/window_opened_by_spec.rb
- lib/capybara/spec/session/window/window_spec.rb
- lib/capybara/spec/session/window/windows_spec.rb
- lib/capybara/spec/session/window/within_window_spec.rb
- lib/capybara/spec/session/within_frame_spec.rb
- lib/capybara/spec/session/within_spec.rb
- lib/capybara/spec/spec_helper.rb
- lib/capybara/spec/test_app.rb
- lib/capybara/spec/views/buttons.erb
- lib/capybara/spec/views/fieldsets.erb
- lib/capybara/spec/views/form.erb
- lib/capybara/spec/views/frame_child.erb
- lib/capybara/spec/views/frame_one.erb
- lib/capybara/spec/views/frame_parent.erb
- lib/capybara/spec/views/frame_two.erb
- lib/capybara/spec/views/header_links.erb
- lib/capybara/spec/views/host_links.erb
- lib/capybara/spec/views/path.erb
- lib/capybara/spec/views/popup_one.erb
- lib/capybara/spec/views/popup_two.erb
- lib/capybara/spec/views/postback.erb
- lib/capybara/spec/views/tables.erb
- lib/capybara/spec/views/with_base_tag.erb
- lib/capybara/spec/views/with_count.erb
- lib/capybara/spec/views/with_hover.erb
- lib/capybara/spec/views/with_html.erb
- lib/capybara/spec/views/with_html_entities.erb
- lib/capybara/spec/views/with_js.erb
- lib/capybara/spec/views/with_scope.erb
- lib/capybara/spec/views/with_simple_html.erb
- lib/capybara/spec/views/with_title.erb
- lib/capybara/spec/views/with_windows.erb
- lib/capybara/spec/views/within_frames.erb
- lib/capybara/version.rb
- lib/capybara/window.rb
- spec/basic_node_spec.rb
- spec/capybara_spec.rb
- spec/dsl_spec.rb
- spec/fixtures/selenium_driver_rspec_failure.rb
- spec/fixtures/selenium_driver_rspec_success.rb
- spec/rack_test_spec.rb
- spec/result_spec.rb
- spec/rspec/features_spec.rb
- spec/rspec/matchers_spec.rb
- spec/rspec/views_spec.rb
- spec/rspec_spec.rb
- spec/selenium_spec.rb
- spec/selenium_spec_chrome.rb
- spec/server_spec.rb
- spec/spec_helper.rb
homepage: http://github.com/jnicklas/capybara
licenses:
- MIT
metadata: {}
post_install_message:
rdoc_options: []
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: 1.9.3
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
version: '0'
requirements: []
rubyforge_project:
rubygems_version: 2.4.5.1
signing_key:
specification_version: 4
summary: Capybara aims to simplify the process of integration testing Rack applications,
such as Rails, Sinatra or Merb
test_files: []
has_rdoc:
capybara-2.5.0/spec/ 0000755 0001750 0001750 00000000000 12573712570 013267 5 ustar lunar lunar capybara-2.5.0/spec/capybara_spec.rb 0000644 0001750 0001750 00000004022 12573712570 016406 0 ustar lunar lunar require 'spec_helper'
RSpec.describe Capybara do
describe 'default_max_wait_time' do
after do
Capybara.default_max_wait_time = @previous_default_time
end
it "should be changeable" do
@previous_default_time = Capybara.default_max_wait_time
Capybara.default_max_wait_time = 5
expect(Capybara.default_max_wait_time).to eq(5)
end
it "should be accesible as the deprecated default_wait_time" do
expect_any_instance_of(Kernel).to receive(:warn).once.with('DEPRECATED: #default_wait_time= is deprecated, please use #default_max_wait_time= instead')
expect_any_instance_of(Kernel).to receive(:warn).once.with('DEPRECATED: #default_wait_time is deprecated, please use #default_max_wait_time instead')
@previous_default_time = Capybara.default_max_wait_time
Capybara.default_wait_time = 5
expect(Capybara.default_wait_time).to eq(5)
expect(Capybara.default_max_wait_time).to eq(5)
end
end
describe '.register_driver' do
it "should add a new driver" do
Capybara.register_driver :schmoo do |app|
Capybara::RackTest::Driver.new(app)
end
session = Capybara::Session.new(:schmoo, TestApp)
session.visit('/')
expect(session.body).to include("Hello world!")
end
end
describe ".server" do
after do
Capybara.server {|app, port| Capybara.run_default_server(app, port)}
end
it "should default to a proc that calls run_default_server" do
mock_app = double('app')
expect(Capybara).to receive(:run_default_server).with(mock_app, 8000)
Capybara.server.call(mock_app, 8000)
end
it "should return a custom server proc" do
server = lambda {|app, port|}
Capybara.server(&server)
expect(Capybara.server).to eq(server)
end
end
end
RSpec.describe Capybara::Session do
context 'with non-existant driver' do
it "should raise an error" do
expect {
Capybara::Session.new(:quox, TestApp).driver
}.to raise_error(Capybara::DriverNotFoundError)
end
end
end
capybara-2.5.0/spec/selenium_spec_chrome.rb 0000644 0001750 0001750 00000000773 12573712570 020013 0 ustar lunar lunar require 'spec_helper'
require 'selenium-webdriver'
Capybara.register_driver :selenium_chrome do |app|
args = ENV['TRAVIS'] ? ['no-sandbox' ] : []
Capybara::Selenium::Driver.new(app, :browser => :chrome, :args => args)
end
module TestSessions
Chrome = Capybara::Session.new(:selenium_chrome, TestApp)
end
Capybara::SpecHelper.run_specs TestSessions::Chrome, "selenium_chrome", :capybara_skip => [
:response_headers,
:status_code,
:trigger
] unless ENV['TRAVIS'] && (RUBY_PLATFORM == 'java')
capybara-2.5.0/spec/rspec_spec.rb 0000644 0001750 0001750 00000002603 12573712570 015743 0 ustar lunar lunar require 'spec_helper'
RSpec.describe 'capybara/rspec', :type => :feature do
it "should include Capybara in rspec" do
visit('/foo')
expect(page.body).to include('Another World')
end
context "resetting session" do
it "sets a cookie in one example..." do
visit('/set_cookie')
expect(page.body).to include('Cookie set to test_cookie')
end
it "...then it is not available in the next" do
visit('/get_cookie')
expect(page.body).not_to include('test_cookie')
end
end
context "setting the current driver" do
it "sets the current driver in one example..." do
Capybara.current_driver = :selenium
end
it "...then it has returned to the default in the next example" do
expect(Capybara.current_driver).to eq(:rack_test)
end
end
it "switches to the javascript driver when giving it as metadata", :js => true do
expect(Capybara.current_driver).to eq(Capybara.javascript_driver)
end
it "switches to the given driver when giving it as metadata", :driver => :culerity do
expect(Capybara.current_driver).to eq(:culerity)
end
end
RSpec.describe 'capybara/rspec', :type => :other do
it "should not include Capybara" do
expect { visit('/') }.to raise_error(NoMethodError)
end
end
feature "Feature DSL" do
scenario "is pulled in" do
visit('/foo')
expect(page.body).to include('Another World')
end
end
capybara-2.5.0/spec/rack_test_spec.rb 0000644 0001750 0001750 00000013107 12573712570 016607 0 ustar lunar lunar require 'spec_helper'
module TestSessions
RackTest = Capybara::Session.new(:rack_test, TestApp)
end
Capybara::SpecHelper.run_specs TestSessions::RackTest, "RackTest", :capybara_skip => [
:js,
:modals,
:screenshot,
:frames,
:windows,
:send_keys,
:server,
:hover,
:about_scheme,
]
RSpec.describe Capybara::Session do
context 'with rack test driver' do
before do
@session = TestSessions::RackTest
end
describe '#driver' do
it "should be a rack test driver" do
expect(@session.driver).to be_an_instance_of(Capybara::RackTest::Driver)
end
end
describe '#mode' do
it "should remember the mode" do
expect(@session.mode).to eq(:rack_test)
end
end
describe '#click_link' do
it "should use data-method if option is true" do
@session.driver.options[:respect_data_method] = true
@session.visit "/with_html"
@session.click_link "A link with data-method"
expect(@session.html).to include('The requested object was deleted')
end
it "should not use data-method if option is false" do
@session.driver.options[:respect_data_method] = false
@session.visit "/with_html"
@session.click_link "A link with data-method"
expect(@session.html).to include('Not deleted')
end
it "should use data-method if available even if it's capitalized" do
@session.driver.options[:respect_data_method] = true
@session.visit "/with_html"
@session.click_link "A link with capitalized data-method"
expect(@session.html).to include('The requested object was deleted')
end
after do
@session.driver.options[:respect_data_method] = false
end
end
describe "#fill_in" do
it "should warn that :fill_options are not supported" do
expect_any_instance_of(Capybara::Node::Element).to receive(:warn)
.with("Options passed to Capybara::Node#set but the driver doesn't support them")
@session.visit "/with_html"
@session.fill_in 'test_field', with: 'not_moneky', fill_options: { random: true }
end
end
describe "#attach_file" do
context "with multipart form" do
it "should submit an empty form-data section if no file is submitted" do
@session.visit("/form")
@session.click_button("Upload Empty")
expect(@session.html).to include('Successfully ignored empty file field.')
end
end
end
end
end
RSpec.describe Capybara::RackTest::Driver do
before do
@driver = TestSessions::RackTest.driver
end
describe ':headers option' do
it 'should always set headers' do
@driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
@driver.visit('/get_header')
expect(@driver.html).to include('foobar')
end
it 'should keep headers on link clicks' do
@driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
@driver.visit('/header_links')
@driver.find_xpath('.//a').first.click
expect(@driver.html).to include('foobar')
end
it 'should keep headers on form submit' do
@driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
@driver.visit('/header_links')
@driver.find_xpath('.//input').first.click
expect(@driver.html).to include('foobar')
end
it 'should keep headers on redirects' do
@driver = Capybara::RackTest::Driver.new(TestApp, :headers => {'HTTP_FOO' => 'foobar'})
@driver.visit('/get_header_via_redirect')
expect(@driver.html).to include('foobar')
end
end
describe ':follow_redirects option' do
it "defaults to following redirects" do
@driver = Capybara::RackTest::Driver.new(TestApp)
@driver.visit('/redirect')
expect(@driver.response.header['Location']).to be_nil
expect(@driver.current_url).to match %r{/landed$}
end
it "is possible to not follow redirects" do
@driver = Capybara::RackTest::Driver.new(TestApp, :follow_redirects => false)
@driver.visit('/redirect')
expect(@driver.response.header['Location']).to match %r{/redirect_again$}
expect(@driver.current_url).to match %r{/redirect$}
end
end
describe ':redirect_limit option' do
context "with default redirect limit" do
before do
@driver = Capybara::RackTest::Driver.new(TestApp)
end
it "should follow 5 redirects" do
@driver.visit("/redirect/5/times")
expect(@driver.html).to include('redirection complete')
end
it "should not follow more than 6 redirects" do
expect do
@driver.visit("/redirect/6/times")
end.to raise_error(Capybara::InfiniteRedirectError)
end
end
context "with 21 redirect limit" do
before do
@driver = Capybara::RackTest::Driver.new(TestApp, :redirect_limit => 21)
end
it "should follow 21 redirects" do
@driver.visit("/redirect/21/times")
expect(@driver.html).to include('redirection complete')
end
it "should not follow more than 21 redirects" do
expect do
@driver.visit("/redirect/22/times")
end.to raise_error(Capybara::InfiniteRedirectError)
end
end
end
end
module CSSHandlerIncludeTester
def dont_extend_css_handler
raise 'should never be called'
end
end
include CSSHandlerIncludeTester
RSpec.describe Capybara::RackTest::CSSHandlers do
it "should not be extended by global includes" do
expect(Capybara::RackTest::CSSHandlers.new).not_to respond_to(:dont_extend_css_handler)
end
end
capybara-2.5.0/spec/selenium_spec.rb 0000644 0001750 0001750 00000010064 12573712570 016450 0 ustar lunar lunar require 'spec_helper'
require "selenium-webdriver"
Capybara.register_driver :selenium_focus do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile["focusmanager.testmode"] = true
Capybara::Selenium::Driver.new(app, browser: :firefox, profile: profile)
end
module TestSessions
Selenium = Capybara::Session.new(:selenium_focus, TestApp)
end
Capybara::SpecHelper.run_specs TestSessions::Selenium, "selenium", :capybara_skip => [
:response_headers,
:status_code,
:trigger
]
RSpec.describe Capybara::Session do
context 'with selenium driver' do
before do
@session = TestSessions::Selenium
end
describe '#driver' do
it "should be a selenium driver" do
expect(@session.driver).to be_an_instance_of(Capybara::Selenium::Driver)
end
end
describe '#mode' do
it "should remember the mode" do
expect(@session.mode).to eq(:selenium_focus)
end
end
describe "#reset!" do
it "freshly reset session should not be touched" do
@session.instance_variable_set(:@touched, true)
@session.reset!
expect(@session.instance_variable_get(:@touched)).to eq false
end
end
describe "exit codes" do
before do
@current_dir = Dir.getwd
Dir.chdir(File.join(File.dirname(__FILE__), '..'))
end
after do
Dir.chdir(@current_dir)
end
it "should have return code 1 when running selenium_driver_rspec_failure.rb" do
`rspec spec/fixtures/selenium_driver_rspec_failure.rb`
expect($?.exitstatus).to be 1
end
it "should have return code 0 when running selenium_driver_rspec_success.rb" do
`rspec spec/fixtures/selenium_driver_rspec_success.rb`
expect($?.exitstatus).to be 0
end
end
describe "#accept_alert" do
it "supports a blockless mode" do
@session.visit('/with_js')
@session.click_link('Open alert')
@session.accept_alert
expect{@session.driver.browser.switch_to.alert}.to raise_error("No alert is present")
end
end
context "#fill_in with { :clear => :backspace } fill_option", :requires => [:js] do
it 'should fill in a field, replacing an existing value' do
@session.visit('/form')
@session.fill_in('form_first_name', :with => 'Harry',
fill_options: { clear: :backspace} )
expect(@session.find(:fillable_field, 'form_first_name').value).to eq('Harry')
end
it 'should only trigger onchange once' do
@session.visit('/with_js')
@session.fill_in('with_change_event', :with => 'some value',
:fill_options => { :clear => :backspace })
# click outside the field to trigger the change event
@session.find(:css, 'body').click
expect(@session.find(:css, '.change_event_triggered', :match => :one)).to have_text 'some value'
end
it 'should trigger change when clearing field' do
@session.visit('/with_js')
@session.fill_in('with_change_event', :with => '',
:fill_options => { :clear => :backspace })
# click outside the field to trigger the change event
@session.find(:css, 'body').click
expect(@session).to have_selector(:css, '.change_event_triggered', :match => :one)
end
end
describe "#path" do
it "returns xpath" do
# this is here because it is testing for an XPath that is specific to the algorithm used in the selenium driver
@session.visit('/path')
element = @session.find(:link, 'Second Link')
expect(element.path).to eq('/html/body/div[2]/a[1]')
end
end
end
end
RSpec.describe Capybara::Selenium::Driver do
before do
@driver = Capybara::Selenium::Driver.new(TestApp, browser: :firefox)
end
describe '#quit' do
it "should reset browser when quit" do
expect(@driver.browser).to be
@driver.quit
#access instance variable directly so we don't create a new browser instance
expect(@driver.instance_variable_get(:@browser)).to be_nil
end
end
end
capybara-2.5.0/spec/spec_helper.rb 0000644 0001750 0001750 00000000231 12573712570 016101 0 ustar lunar lunar require 'rspec/expectations'
require "capybara/spec/spec_helper"
require "pry"
RSpec.configure do |config|
Capybara::SpecHelper.configure(config)
end
capybara-2.5.0/spec/basic_node_spec.rb 0000644 0001750 0001750 00000011016 12573712570 016713 0 ustar lunar lunar require 'spec_helper'
RSpec.describe Capybara do
describe '.string' do
let :string do
Capybara.string <<-STRING
simple_node
Totally awesome
Yes it is
Secret
STRING
end
it "allows using matchers" do
expect(string).to have_css('#page')
expect(string).not_to have_css('#does-not-exist')
end
it "allows using custom matchers" do
Capybara.add_selector :lifeform do
xpath { |name| "//option[contains(.,'#{name}')]" }
end
expect(string).to have_selector(:id, "page")
expect(string).not_to have_selector(:id, 'does-not-exist')
expect(string).to have_selector(:lifeform, "Monkey")
expect(string).not_to have_selector(:lifeform, "Gorilla")
end
it 'allows custom matcher using css' do
Capybara.add_selector :section do
css { |css_class| "section .#{css_class}" }
end
expect(string).to have_selector(:section, 'subsection')
expect(string).not_to have_selector(:section, 'section_8')
end
it "allows using matchers with text option" do
expect(string).to have_css('h1', :text => 'Totally awesome')
expect(string).not_to have_css('h1', :text => 'Not so awesome')
end
it "allows finding only visible nodes" do
expect(string.all(:css, '#secret', :visible => true)).to be_empty
expect(string.all(:css, '#secret', :visible => false).size).to eq(1)
end
it "allows finding elements and extracting text from them" do
expect(string.find('//h1').text).to eq('Totally awesome')
end
it "allows finding elements and extracting attributes from them" do
expect(string.find('//h1')[:data]).to eq('fantastic')
end
it "allows finding elements and extracting the tag name from them" do
expect(string.find('//h1').tag_name).to eq('h1')
end
it "allows finding elements and extracting the path" do
expect(string.find('//h1').path).to eq('/html/body/div/div[1]/h1')
end
it "allows finding elements and extracting the path" do
expect(string.find('//div/input').value).to eq('bar')
expect(string.find('//select').value).to eq('Capybara')
end
it "allows finding elements and checking if they are visible" do
expect(string.find('//h1')).to be_visible
expect(string.find(:css, "#secret", :visible => false)).not_to be_visible
end
it "allows finding elements and checking if they are disabled" do
expect(string.find('//form/input[@name="bleh"]')).to be_disabled
expect(string.find('//form/input[@name="meh"]')).not_to be_disabled
end
describe "#title" do
it "returns the page title" do
expect(string.title).to eq("simple_node")
end
end
describe "#has_title?" do
it "returns whether the page has the given title" do
expect(string.has_title?('simple_node')).to be_truthy
expect(string.has_title?('monkey')).to be_falsey
end
it "allows regexp matches" do
expect(string.has_title?(/s[a-z]+_node/)).to be_truthy
expect(string.has_title?(/monkey/)).to be_falsey
end
end
describe '#has_no_title?' do
it "returns whether the page does not have the given title" do
expect(string.has_no_title?('simple_node')).to be_falsey
expect(string.has_no_title?('monkey')).to be_truthy
end
it "allows regexp matches" do
expect(string.has_no_title?(/s[a-z]+_node/)).to be_falsey
expect(string.has_no_title?(/monkey/)).to be_truthy
end
end
end
end
capybara-2.5.0/spec/server_spec.rb 0000644 0001750 0001750 00000007242 12573712570 016141 0 ustar lunar lunar require 'spec_helper'
RSpec.describe Capybara::Server do
it "should spool up a rack server" do
@app = proc { |env| [200, {}, ["Hello Server!"]]}
@server = Capybara::Server.new(@app).boot
@res = Net::HTTP.start(@server.host, @server.port) { |http| http.get('/') }
expect(@res.body).to include('Hello Server')
end
it "should do nothing when no server given" do
expect do
@server = Capybara::Server.new(nil).boot
end.not_to raise_error
end
it "should bind to the specified host" do
begin
app = proc { |env| [200, {}, ['Hello Server!']] }
Capybara.server_host = '127.0.0.1'
server = Capybara::Server.new(app).boot
res = Net::HTTP.get(URI("http://127.0.0.1:#{server.port}"))
expect(res).to eq('Hello Server!')
Capybara.server_host = '0.0.0.0'
server = Capybara::Server.new(app).boot
res = Net::HTTP.get(URI("http://127.0.0.1:#{server.port}"))
expect(res).to eq('Hello Server!')
ensure
Capybara.server_host = nil
end
end
it "should use specified port" do
Capybara.server_port = 22789
@app = proc { |env| [200, {}, ["Hello Server!"]]}
@server = Capybara::Server.new(@app).boot
@res = Net::HTTP.start(@server.host, 22789) { |http| http.get('/') }
expect(@res.body).to include('Hello Server')
Capybara.server_port = nil
end
it "should use given port" do
@app = proc { |env| [200, {}, ["Hello Server!"]]}
@server = Capybara::Server.new(@app, 22790).boot
@res = Net::HTTP.start(@server.host, 22790) { |http| http.get('/') }
expect(@res.body).to include('Hello Server')
Capybara.server_port = nil
end
it "should find an available port" do
@app1 = proc { |env| [200, {}, ["Hello Server!"]]}
@app2 = proc { |env| [200, {}, ["Hello Second Server!"]]}
@server1 = Capybara::Server.new(@app1).boot
@server2 = Capybara::Server.new(@app2).boot
@res1 = Net::HTTP.start(@server1.host, @server1.port) { |http| http.get('/') }
expect(@res1.body).to include('Hello Server')
@res2 = Net::HTTP.start(@server2.host, @server2.port) { |http| http.get('/') }
expect(@res2.body).to include('Hello Second Server')
end
it "should use the server if it already running" do
@app1 = proc { |env| [200, {}, ["Hello Server!"]]}
@app2 = proc { |env| [200, {}, ["Hello Second Server!"]]}
@server1a = Capybara::Server.new(@app1).boot
@server1b = Capybara::Server.new(@app1).boot
@server2a = Capybara::Server.new(@app2).boot
@server2b = Capybara::Server.new(@app2).boot
@res1 = Net::HTTP.start(@server1b.host, @server1b.port) { |http| http.get('/') }
expect(@res1.body).to include('Hello Server')
@res2 = Net::HTTP.start(@server2b.host, @server2b.port) { |http| http.get('/') }
expect(@res2.body).to include('Hello Second Server')
expect(@server1a.port).to eq(@server1b.port)
expect(@server2a.port).to eq(@server2b.port)
end
it "should raise server errors when the server errors before the timeout" do
begin
Capybara.server do
sleep 0.1
raise 'kaboom'
end
expect do
Capybara::Server.new(proc {|e|}).boot
end.to raise_error(RuntimeError, 'kaboom')
ensure
# TODO refactor out the defaults so it's reliant on unset state instead of
# a one-time call in capybara.rb
Capybara.server {|app, port| Capybara.run_default_server(app, port)}
end
end
it "is not #responsive? when Net::HTTP raises a SystemCallError" do
app = lambda { [200, {}, ['Hello, world']] }
server = Capybara::Server.new(app)
expect(Net::HTTP).to receive(:start).and_raise(SystemCallError.allocate)
expect(server.responsive?).to eq false
end
end
capybara-2.5.0/spec/result_spec.rb 0000644 0001750 0001750 00000002405 12573712570 016145 0 ustar lunar lunar require 'spec_helper'
RSpec.describe Capybara::Result do
let :string do
Capybara.string <<-STRING
Alpha
Beta
Gamma
Delta
STRING
end
let :result do
string.all '//li'
end
it "has a length" do
expect(result.length).to eq(4)
end
it "has a first element" do
result.first.text == 'Alpha'
end
it "has a last element" do
result.last.text == 'Delta'
end
it 'can supports values_at method' do
expect(result.values_at(0, 2).map(&:text)).to eq(%w(Alpha Gamma))
end
it "can return an element by its index" do
expect(result.at(1).text).to eq('Beta')
expect(result[2].text).to eq('Gamma')
end
it "can be mapped" do
expect(result.map(&:text)).to eq(%w(Alpha Beta Gamma Delta))
end
it "can be selected" do
expect(result.select do |element|
element.text.include? 't'
end.length).to eq(2)
end
it "can be reduced" do
expect(result.reduce('') do |memo, element|
memo += element.text[0]
end).to eq('ABGD')
end
it 'can be sampled' do
expect(result).to include(result.sample)
end
it 'can be indexed' do
expect(result.index do |el|
el.text == 'Gamma'
end).to eq(2)
end
end
capybara-2.5.0/spec/dsl_spec.rb 0000644 0001750 0001750 00000017406 12573712570 015420 0 ustar lunar lunar require 'spec_helper'
require 'capybara/dsl'
class TestClass
include Capybara::DSL
end
Capybara::SpecHelper.run_specs TestClass.new, "DSL", :capybara_skip => [
:js,
:modals,
:screenshot,
:frames,
:windows,
:send_keys,
:server,
:hover,
:about_scheme,
]
RSpec.describe Capybara::DSL do
after do
Capybara.session_name = nil
Capybara.default_driver = nil
Capybara.javascript_driver = nil
Capybara.use_default_driver
Capybara.app = TestApp
end
describe '#default_driver' do
it "should default to rack_test" do
expect(Capybara.default_driver).to eq(:rack_test)
end
it "should be changeable" do
Capybara.default_driver = :culerity
expect(Capybara.default_driver).to eq(:culerity)
end
end
describe '#current_driver' do
it "should default to the default driver" do
expect(Capybara.current_driver).to eq(:rack_test)
Capybara.default_driver = :culerity
expect(Capybara.current_driver).to eq(:culerity)
end
it "should be changeable" do
Capybara.current_driver = :culerity
expect(Capybara.current_driver).to eq(:culerity)
end
end
describe '#javascript_driver' do
it "should default to selenium" do
expect(Capybara.javascript_driver).to eq(:selenium)
end
it "should be changeable" do
Capybara.javascript_driver = :culerity
expect(Capybara.javascript_driver).to eq(:culerity)
end
end
describe '#use_default_driver' do
it "should restore the default driver" do
Capybara.current_driver = :culerity
Capybara.use_default_driver
expect(Capybara.current_driver).to eq(:rack_test)
end
end
describe '#using_driver' do
before do
expect(Capybara.current_driver).not_to eq(:selenium)
end
it 'should set the driver using Capybara.current_driver=' do
driver = nil
Capybara.using_driver(:selenium) { driver = Capybara.current_driver }
expect(driver).to eq(:selenium)
end
it 'should return the driver to default if it has not been changed' do
Capybara.using_driver(:selenium) do
expect(Capybara.current_driver).to eq(:selenium)
end
expect(Capybara.current_driver).to eq(Capybara.default_driver)
end
it 'should reset the driver even if an exception occurs' do
driver_before_block = Capybara.current_driver
begin
Capybara.using_driver(:selenium) { raise "ohnoes!" }
rescue Exception
end
expect(Capybara.current_driver).to eq(driver_before_block)
end
it 'should return the driver to what it was previously' do
Capybara.current_driver = :selenium
Capybara.using_driver(:culerity) do
Capybara.using_driver(:rack_test) do
expect(Capybara.current_driver).to eq(:rack_test)
end
expect(Capybara.current_driver).to eq(:culerity)
end
expect(Capybara.current_driver).to eq(:selenium)
end
it 'should yield the passed block' do
called = false
Capybara.using_driver(:selenium) { called = true }
expect(called).to eq(true)
end
end
describe '#using_wait_time' do
before do
@previous_wait_time = Capybara.default_max_wait_time
end
after do
Capybara.default_max_wait_time = @previous_wait_time
end
it "should switch the wait time and switch it back" do
in_block = nil
Capybara.using_wait_time 6 do
in_block = Capybara.default_max_wait_time
end
expect(in_block).to eq(6)
expect(Capybara.default_max_wait_time).to eq(@previous_wait_time)
end
it "should ensure wait time is reset" do
expect do
Capybara.using_wait_time 6 do
raise "hell"
end
end.to raise_error(RuntimeError, "hell")
expect(Capybara.default_max_wait_time).to eq(@previous_wait_time)
end
end
describe '#app' do
it "should be changeable" do
Capybara.app = "foobar"
expect(Capybara.app).to eq('foobar')
end
end
describe '#current_session' do
it "should choose a session object of the current driver type" do
expect(Capybara.current_session).to be_a(Capybara::Session)
end
it "should use #app as the application" do
Capybara.app = proc {}
expect(Capybara.current_session.app).to eq(Capybara.app)
end
it "should change with the current driver" do
expect(Capybara.current_session.mode).to eq(:rack_test)
Capybara.current_driver = :selenium
expect(Capybara.current_session.mode).to eq(:selenium)
end
it "should be persistent even across driver changes" do
object_id = Capybara.current_session.object_id
expect(Capybara.current_session.object_id).to eq(object_id)
Capybara.current_driver = :selenium
expect(Capybara.current_session.mode).to eq(:selenium)
expect(Capybara.current_session.object_id).not_to eq(object_id)
Capybara.current_driver = :rack_test
expect(Capybara.current_session.object_id).to eq(object_id)
end
it "should change when changing application" do
object_id = Capybara.current_session.object_id
expect(Capybara.current_session.object_id).to eq(object_id)
Capybara.app = proc {}
expect(Capybara.current_session.object_id).not_to eq(object_id)
expect(Capybara.current_session.app).to eq(Capybara.app)
end
it "should change when the session name changes" do
object_id = Capybara.current_session.object_id
Capybara.session_name = :administrator
expect(Capybara.session_name).to eq(:administrator)
expect(Capybara.current_session.object_id).not_to eq(object_id)
Capybara.session_name = :default
expect(Capybara.session_name).to eq(:default)
expect(Capybara.current_session.object_id).to eq(object_id)
end
end
describe "#using_session" do
it "should change the session name for the duration of the block" do
expect(Capybara.session_name).to eq(:default)
Capybara.using_session(:administrator) do
expect(Capybara.session_name).to eq(:administrator)
end
expect(Capybara.session_name).to eq(:default)
end
it "should reset the session to the default, even if an exception occurs" do
begin
Capybara.using_session(:raise) do
raise
end
rescue Exception
end
expect(Capybara.session_name).to eq(:default)
end
it "should yield the passed block" do
called = false
Capybara.using_session(:administrator) { called = true }
expect(called).to eq(true)
end
it "should be nestable" do
Capybara.using_session(:outer) do
expect(Capybara.session_name).to eq(:outer)
Capybara.using_session(:inner) do
expect(Capybara.session_name).to eq(:inner)
end
expect(Capybara.session_name).to eq(:outer)
end
expect(Capybara.session_name).to eq(:default)
end
end
describe "#session_name" do
it "should default to :default" do
expect(Capybara.session_name).to eq(:default)
end
end
describe 'the DSL' do
before do
@session = Class.new { include Capybara::DSL }.new
end
it "should be possible to include it in another class" do
@session.visit('/with_html')
@session.click_link('ullamco')
expect(@session.body).to include('Another World')
end
it "should provide a 'page' shortcut for more expressive tests" do
@session.page.visit('/with_html')
@session.page.click_link('ullamco')
expect(@session.page.body).to include('Another World')
end
it "should provide an 'using_session' shortcut" do
expect(Capybara).to receive(:using_session).with(:name)
@session.using_session(:name)
end
it "should provide a 'using_wait_time' shortcut" do
expect(Capybara).to receive(:using_wait_time).with(6)
@session.using_wait_time(6)
end
end
end
capybara-2.5.0/spec/fixtures/ 0000755 0001750 0001750 00000000000 12573712570 015140 5 ustar lunar lunar capybara-2.5.0/spec/fixtures/selenium_driver_rspec_success.rb 0000644 0001750 0001750 00000000327 12573712570 023607 0 ustar lunar lunar require 'spec_helper'
RSpec.describe Capybara::Selenium::Driver do
it "should exit with a zero exit status" do
browser = Capybara::Selenium::Driver.new(TestApp).browser
expect(true).to eq(true)
end
end
capybara-2.5.0/spec/fixtures/selenium_driver_rspec_failure.rb 0000644 0001750 0001750 00000000334 12573712570 023564 0 ustar lunar lunar require 'spec_helper'
RSpec.describe Capybara::Selenium::Driver do
it "should exit with a non-zero exit status" do
browser = Capybara::Selenium::Driver.new(TestApp).browser
expect(true).to eq(false)
end
end
capybara-2.5.0/spec/rspec/ 0000755 0001750 0001750 00000000000 12573712570 014403 5 ustar lunar lunar capybara-2.5.0/spec/rspec/views_spec.rb 0000644 0001750 0001750 00000000314 12573712570 017075 0 ustar lunar lunar require 'spec_helper'
RSpec.describe "capybara/rspec", type: :view do
it "allows matchers to be used on strings" do
expect(%{
Test header
}).to have_css("h1", text: "Test header")
end
end
capybara-2.5.0/spec/rspec/matchers_spec.rb 0000644 0001750 0001750 00000066443 12573712570 017565 0 ustar lunar lunar require 'spec_helper'
require 'capybara/dsl'
require 'capybara/rspec/matchers'
RSpec.describe Capybara::RSpecMatchers do
include Capybara::DSL
include Capybara::RSpecMatchers
describe "have_css matcher" do
it "gives proper description" do
expect(have_css('h1').description).to eq("have css \"h1\"")
end
context "on a string" do
context "with should" do
it "passes if has_css? returns true" do
expect("
Text
").to have_css('h1')
end
it "fails if has_css? returns false" do
expect do
expect("
Text
").to have_css('h2')
end.to raise_error(/expected to find css "h2" but there were no matches/)
end
it "passes if matched node count equals expected count" do
expect("
Text
").to have_css('h1', :count => 1)
end
it "fails if matched node count does not equal expected count" do
expect do
expect("
Text
").to have_css('h1', count: 2)
end.to raise_error("expected to find css \"h1\" 2 times, found 1 match: \"Text\"")
end
it "fails if matched node count is less than expected minimum count" do
expect do
expect("
Text
").to have_css('p', minimum: 1)
end.to raise_error("expected to find css \"p\" at least 1 time but there were no matches")
end
it "fails if matched node count is more than expected maximum count" do
expect do
expect("
Text
Text
Text
").to have_css('h1', maximum: 2)
end.to raise_error('expected to find css "h1" at most 2 times, found 3 matches: "Text", "Text", "Text"')
end
it "fails if matched node count does not belong to expected range" do
expect do
expect("
Text
").to have_css('h1', between: 2..3)
end.to raise_error("expected to find css \"h1\" between 2 and 3 times, found 1 match: \"Text\"")
end
end
context "with should_not" do
it "passes if has_no_css? returns true" do
expect("
Text
").not_to have_css('h2')
end
it "fails if has_no_css? returns false" do
expect do
expect("
Text
").not_to have_css('h1')
end.to raise_error(/expected not to find css "h1"/)
end
it "passes if matched node count does not equal expected count" do
expect("
Text
").not_to have_css('h1', :count => 2)
end
it "fails if matched node count equals expected count" do
expect do
expect("
Text
").not_to have_css('h1', :count => 1)
end.to raise_error(/expected not to find css "h1"/)
end
end
it "supports compounding" do
expect("
Text
Text
").to have_css('h1').and have_css('h2')
expect("
Text
Text
").to have_css('h3').or have_css('h1')
end if RSpec::Version::STRING.to_f >= 3.0
end
context "on a page or node" do
before do
visit('/with_html')
end
context "with should" do
it "passes if has_css? returns true" do
expect(page).to have_css('h1')
end
it "fails if has_css? returns false" do
expect do
expect(page).to have_css('h1#doesnotexist')
end.to raise_error(/expected to find css "h1#doesnotexist" but there were no matches/)
end
end
context "with should_not" do
it "passes if has_no_css? returns true" do
expect(page).not_to have_css('h1#doesnotexist')
end
it "fails if has_no_css? returns false" do
expect do
expect(page).not_to have_css('h1')
end.to raise_error(/expected not to find css "h1"/)
end
end
end
end
describe "have_xpath matcher" do
it "gives proper description" do
expect(have_xpath('//h1').description).to eq("have xpath \"\/\/h1\"")
end
context "on a string" do
context "with should" do
it "passes if has_xpath? returns true" do
expect("
Text
").to have_xpath('//h1')
end
it "fails if has_xpath? returns false" do
expect do
expect("
Text
").to have_xpath('//h2')
end.to raise_error(%r(expected to find xpath "//h2" but there were no matches))
end
end
context "with should_not" do
it "passes if has_no_xpath? returns true" do
expect("
Text
").not_to have_xpath('//h2')
end
it "fails if has_no_xpath? returns false" do
expect do
expect("
Text
").not_to have_xpath('//h1')
end.to raise_error(%r(expected not to find xpath "//h1"))
end
end
it "supports compounding" do
expect("
").to have_xpath('//h3').or have_xpath('//h1')
end if RSpec::Version::STRING.to_f >= 3.0
end
context "on a page or node" do
before do
visit('/with_html')
end
context "with should" do
it "passes if has_xpath? returns true" do
expect(page).to have_xpath('//h1')
end
it "fails if has_xpath? returns false" do
expect do
expect(page).to have_xpath("//h1[@id='doesnotexist']")
end.to raise_error(%r(expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches))
end
end
context "with should_not" do
it "passes if has_no_xpath? returns true" do
expect(page).not_to have_xpath('//h1[@id="doesnotexist"]')
end
it "fails if has_no_xpath? returns false" do
expect do
expect(page).not_to have_xpath('//h1')
end.to raise_error(%r(expected not to find xpath "//h1"))
end
end
end
end
describe "have_selector matcher" do
it "gives proper description" do
matcher = have_selector('//h1')
expect("
Text
").to matcher
expect(matcher.description).to eq("have xpath \"//h1\"")
end
context "on a string" do
context "with should" do
it "passes if has_selector? returns true" do
expect("
Text
").to have_selector('//h1')
end
it "fails if has_selector? returns false" do
expect do
expect("
Text
").to have_selector('//h2')
end.to raise_error(%r(expected to find xpath "//h2" but there were no matches))
end
end
context "with should_not" do
it "passes if has_no_selector? returns true" do
expect("
Text
").not_to have_selector(:css, 'h2')
end
it "fails if has_no_selector? returns false" do
expect do
expect("
Text
").not_to have_selector(:css, 'h1')
end.to raise_error(%r(expected not to find css "h1"))
end
end
end
context "on a page or node" do
before do
visit('/with_html')
end
context "with should" do
it "passes if has_selector? returns true" do
expect(page).to have_selector('//h1', :text => 'test')
end
it "fails if has_selector? returns false" do
expect do
expect(page).to have_selector("//h1[@id='doesnotexist']")
end.to raise_error(%r(expected to find xpath "//h1\[@id='doesnotexist'\]" but there were no matches))
end
it "includes text in error message" do
expect do
expect(page).to have_selector("//h1", :text => 'wrong text')
end.to raise_error(%r(expected to find xpath "//h1" with text "wrong text" but there were no matches))
end
end
context "with should_not" do
it "passes if has_no_css? returns true" do
expect(page).not_to have_selector(:css, 'h1#doesnotexist')
end
it "fails if has_no_selector? returns false" do
expect do
expect(page).not_to have_selector(:css, 'h1', :text => 'test')
end.to raise_error(%r(expected not to find css "h1" with text "test"))
end
end
end
it "supports compounding" do
expect("
").to have_selector('//h3').or have_selector('//h1')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_content matcher" do
it "gives proper description" do
expect(have_content('Text').description).to eq("text \"Text\"")
end
context "on a string" do
context "with should" do
it "passes if has_content? returns true" do
expect("
Text
").to have_content('Text')
end
it "passes if has_content? returns true using regexp" do
expect("
Text
").to have_content(/ext/)
end
it "fails if has_content? returns false" do
expect do
expect("
Text
").to have_content('No such Text')
end.to raise_error(/expected to find text "No such Text" in "Text"/)
end
end
context "with should_not" do
it "passes if has_no_content? returns true" do
expect("
Text
").not_to have_content('No such Text')
end
it "passes because escapes any characters that would have special meaning in a regexp" do
expect("
Text
").not_to have_content('.')
end
it "fails if has_no_content? returns false" do
expect do
expect("
Text
").not_to have_content('Text')
end.to raise_error(/expected not to find text "Text" in "Text"/)
end
end
end
context "on a page or node" do
before do
visit('/with_html')
end
context "with should" do
it "passes if has_content? returns true" do
expect(page).to have_content('This is a test')
end
it "passes if has_content? returns true using regexp" do
expect(page).to have_content(/test/)
end
it "fails if has_content? returns false" do
expect do
expect(page).to have_content('No such Text')
end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
end
context "with default selector CSS" do
before { Capybara.default_selector = :css }
it "fails if has_content? returns false" do
expect do
expect(page).to have_content('No such Text')
end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
end
after { Capybara.default_selector = :xpath }
end
end
context "with should_not" do
it "passes if has_no_content? returns true" do
expect(page).not_to have_content('No such Text')
end
it "fails if has_no_content? returns false" do
expect do
expect(page).not_to have_content('This is a test')
end.to raise_error(/expected not to find text "This is a test"/)
end
end
end
it "supports compounding" do
expect("
").to have_content('XYZ').or have_content('Or')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_text matcher" do
it "gives proper description" do
expect(have_text('Text').description).to eq("text \"Text\"")
end
context "on a string" do
context "with should" do
it "passes if text contains given string" do
expect("
Text
").to have_text('Text')
end
it "passes if text matches given regexp" do
expect("
Text
").to have_text(/ext/)
end
it "fails if text doesn't contain given string" do
expect do
expect("
Text
").to have_text('No such Text')
end.to raise_error(/expected to find text "No such Text" in "Text"/)
end
it "fails if text doesn't match given regexp" do
expect do
expect("
Text
").to have_text(/No such Text/)
end.to raise_error('expected to find text matching /No such Text/ in "Text"')
end
it "casts Fixnum to string" do
expect do
expect("
Text
").to have_text(3)
end.to raise_error(/expected to find text "3" in "Text"/)
end
it "fails if matched text count does not equal to expected count" do
expect do
expect("
Text
").to have_text('Text', count: 2)
end.to raise_error('expected to find text "Text" 2 times but found 1 time in "Text"')
end
it "fails if matched text count is less than expected minimum count" do
expect do
expect("
Text
").to have_text('Lorem', minimum: 1)
end.to raise_error('expected to find text "Lorem" at least 1 time but found 0 times in "Text"')
end
it "fails if matched text count is more than expected maximum count" do
expect do
expect("
Text TextText
").to have_text('Text', maximum: 2)
end.to raise_error('expected to find text "Text" at most 2 times but found 3 times in "Text TextText"')
end
it "fails if matched text count does not belong to expected range" do
expect do
expect("
Text
").to have_text('Text', between: 2..3)
end.to raise_error('expected to find text "Text" between 2 and 3 times but found 1 time in "Text"')
end
end
context "with should_not" do
it "passes if text doesn't contain a string" do
expect("
Text
").not_to have_text('No such Text')
end
it "passes because escapes any characters that would have special meaning in a regexp" do
expect("
Text
").not_to have_text('.')
end
it "fails if text contains a string" do
expect do
expect("
Text
").not_to have_text('Text')
end.to raise_error(/expected not to find text "Text" in "Text"/)
end
end
end
context "on a page or node" do
before do
visit('/with_html')
end
context "with should" do
it "passes if has_text? returns true" do
expect(page).to have_text('This is a test')
end
it "passes if has_text? returns true using regexp" do
expect(page).to have_text(/test/)
end
it "can check for all text" do
expect(page).to have_text(:all, 'Some of this text is hidden!')
end
it "can check for visible text" do
expect(page).to have_text(:visible, 'Some of this text is')
expect(page).not_to have_text(:visible, 'Some of this text is hidden!')
end
it "fails if has_text? returns false" do
expect do
expect(page).to have_text('No such Text')
end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
end
context "with default selector CSS" do
before { Capybara.default_selector = :css }
it "fails if has_text? returns false" do
expect do
expect(page).to have_text('No such Text')
end.to raise_error(/expected to find text "No such Text" in "(.*)This is a test(.*)"/)
end
after { Capybara.default_selector = :xpath }
end
end
context "with should_not" do
it "passes if has_no_text? returns true" do
expect(page).not_to have_text('No such Text')
end
it "fails if has_no_text? returns false" do
expect do
expect(page).not_to have_text('This is a test')
end.to raise_error(/expected not to find text "This is a test"/)
end
end
end
it "supports compounding" do
expect("
").to have_text('Not here').or have_text('Or')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_link matcher" do
let(:html) { 'Just a linkAnother link' }
it "gives proper description" do
expect(have_link('Just a link').description).to eq("have link \"Just a link\"")
end
it "passes if there is such a button" do
expect(html).to have_link('Just a link')
end
it "fails if there is no such button" do
expect do
expect(html).to have_link('No such Link')
end.to raise_error(/expected to find link "No such Link"/)
end
it "supports compounding" do
expect(html).to have_link('Just a link').and have_link('Another link')
expect(html).to have_link('Not a link').or have_link('Another link')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_title matcher" do
it "gives proper description" do
expect(have_title('Just a title').description).to eq("have title \"Just a title\"")
end
context "on a string" do
let(:html) { 'Just a title' }
it "passes if there is such a title" do
expect(html).to have_title('Just a title')
end
it "fails if there is no such title" do
expect do
expect(html).to have_title('No such title')
end.to raise_error('expected "Just a title" to include "No such title"')
end
it "fails if title doesn't match regexp" do
expect do
expect(html).to have_title(/[[:upper:]]+[[:lower:]]+l{2}o/)
end.to raise_error('expected "Just a title" to match /[[:upper:]]+[[:lower:]]+l{2}o/')
end
end
context "on a page or node" do
it "passes if there is such a title" do
visit('/with_js')
expect(page).to have_title('with_js')
end
it "fails if there is no such title" do
visit('/with_js')
expect do
expect(page).to have_title('No such title')
end.to raise_error('expected "with_js" to include "No such title"')
end
context 'with wait' do
before(:each) do
@session = TestSessions::Selenium
@session.visit('/with_js')
end
it 'waits if wait time is more than timeout' do
@session.click_link("Change title")
using_wait_time 0 do
expect(@session).to have_title('changed title', wait: 0.5)
end
end
it "doesn't wait if wait time is less than timeout" do
@session.click_link("Change title")
using_wait_time 0 do
expect(@session).not_to have_title('changed title')
end
end
end
end
it "supports compounding" do
expect("I compound").to have_title('I dont compound').or have_title('I compound')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_current_path matcher" do
it "gives proper description" do
expect(have_current_path('http://www.example.com').description).to eq("have current path \"http://www.example.com\"")
end
context "on a page or node" do
it "passes if there is such a current path" do
visit('/with_js')
expect(page).to have_current_path('/with_js')
end
it "fails if there is no such current_path" do
visit('/with_js')
expect do
expect(page).to have_current_path('/not_with_js')
end.to raise_error('expected "/with_js" to equal "/not_with_js"')
end
context 'with wait' do
before(:each) do
@session = TestSessions::Selenium
@session.visit('/with_js')
end
it 'waits if wait time is more than timeout' do
@session.click_link("Change page")
using_wait_time 0 do
expect(@session).to have_current_path('/with_html', wait: 1)
end
end
it "doesn't wait if wait time is less than timeout" do
@session.click_link("Change page")
using_wait_time 0 do
expect(@session).not_to have_current_path('/with_html')
end
end
end
end
it "supports compounding" do
visit('/with_html')
expect(page).to have_current_path('/not_with_html').or have_current_path('/with_html')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_button matcher" do
let(:html) { '' }
it "gives proper description" do
expect(have_button('A button').description).to eq("have button \"A button\"")
end
it "passes if there is such a button" do
expect(html).to have_button('A button')
end
it "fails if there is no such button" do
expect do
expect(html).to have_button('No such Button')
end.to raise_error(/expected to find button "No such Button"/)
end
it "supports compounding" do
expect(html).to have_button('Not this button').or have_button('A button')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_field matcher" do
let(:html) { '' }
it "gives proper description" do
expect(have_field('Text field').description).to eq("have field \"Text field\"")
end
it "gives proper description for a given value" do
expect(have_field('Text field', with: 'some value').description).to eq("have field \"Text field\" with value \"some value\"")
end
it "passes if there is such a field" do
expect(html).to have_field('Text field')
end
it "passes if there is such a field with value" do
expect(html).to have_field('Text field', with: 'some value')
end
it "fails if there is no such field" do
expect do
expect(html).to have_field('No such Field')
end.to raise_error(/expected to find field "No such Field"/)
end
it "fails if there is such field but with false value" do
expect do
expect(html).to have_field('Text field', with: 'false value')
end.to raise_error(/expected to find field "Text field"/)
end
it "treats a given value as a string" do
class Foo
def to_s
"some value"
end
end
expect(html).to have_field('Text field', with: Foo.new)
end
it "supports compounding" do
expect(html).to have_field('Not this one').or have_field('Text field')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_checked_field matcher" do
let(:html) do
'
'
end
it "gives proper description" do
expect(have_checked_field('it is checked').description).to eq("have field \"it is checked\" that is checked")
end
context "with should" do
it "passes if there is such a field and it is checked" do
expect(html).to have_checked_field('it is checked')
end
it "fails if there is such a field but it is not checked" do
expect do
expect(html).to have_checked_field('unchecked field')
end.to raise_error(/expected to find field "unchecked field"/)
end
it "fails if there is no such field" do
expect do
expect(html).to have_checked_field('no such field')
end.to raise_error(/expected to find field "no such field"/)
end
end
context "with should not" do
it "fails if there is such a field and it is checked" do
expect do
expect(html).not_to have_checked_field('it is checked')
end.to raise_error(/expected not to find field "it is checked"/)
end
it "passes if there is such a field but it is not checked" do
expect(html).not_to have_checked_field('unchecked field')
end
it "passes if there is no such field" do
expect(html).not_to have_checked_field('no such field')
end
end
it "supports compounding" do
expect(html).to have_checked_field('not this one').or have_checked_field('it is checked')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_unchecked_field matcher" do
let(:html) do
'
'
end
it "gives proper description" do
expect(have_unchecked_field('unchecked field').description).to eq("have field \"unchecked field\" that is not checked")
end
context "with should" do
it "passes if there is such a field and it is not checked" do
expect(html).to have_unchecked_field('unchecked field')
end
it "fails if there is such a field but it is checked" do
expect do
expect(html).to have_unchecked_field('it is checked')
end.to raise_error(/expected to find field "it is checked"/)
end
it "fails if there is no such field" do
expect do
expect(html).to have_unchecked_field('no such field')
end.to raise_error(/expected to find field "no such field"/)
end
end
context "with should not" do
it "fails if there is such a field and it is not checked" do
expect do
expect(html).not_to have_unchecked_field('unchecked field')
end.to raise_error(/expected not to find field "unchecked field"/)
end
it "passes if there is such a field but it is checked" do
expect(html).not_to have_unchecked_field('it is checked')
end
it "passes if there is no such field" do
expect(html).not_to have_unchecked_field('no such field')
end
end
it "supports compounding" do
expect(html).to have_unchecked_field('it is checked').or have_unchecked_field('unchecked field')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_select matcher" do
let(:html) { '' }
it "gives proper description" do
expect(have_select('Select Box').description).to eq("have select box \"Select Box\"")
end
it "gives proper description for a given selected value" do
expect(have_select('Select Box', selected: 'some value').description).to eq("have select box \"Select Box\" with \"some value\" selected")
end
it "passes if there is such a select" do
expect(html).to have_select('Select Box')
end
it "fails if there is no such select" do
expect do
expect(html).to have_select('No such Select box')
end.to raise_error(/expected to find select box "No such Select box"/)
end
it "supports compounding" do
expect(html).to have_select('Not this one').or have_select('Select Box')
end if RSpec::Version::STRING.to_f >= 3.0
end
describe "have_table matcher" do
let(:html) { '
Lovely table
' }
it "gives proper description" do
expect(have_table('Lovely table').description).to eq("have table \"Lovely table\"")
end
it "passes if there is such a select" do
expect(html).to have_table('Lovely table')
end
it "fails if there is no such select" do
expect do
expect(html).to have_table('No such Table')
end.to raise_error(/expected to find table "No such Table"/)
end
it "supports compounding" do
expect(html).to have_table('nope').or have_table('Lovely table')
end if RSpec::Version::STRING.to_f >= 3.0
end
end
capybara-2.5.0/spec/rspec/features_spec.rb 0000644 0001750 0001750 00000004144 12573712570 017563 0 ustar lunar lunar require 'spec_helper'
require 'capybara/rspec'
RSpec.configuration.before(:each, { file_path: "./spec/rspec/features_spec.rb" } ) do
@in_filtered_hook = true
end
feature "Capybara's feature DSL" do
background do
@in_background = true
end
def current_example(context)
RSpec.respond_to?(:current_example) ? RSpec.current_example : context.example
end
scenario "includes Capybara" do
visit('/')
expect(page).to have_content('Hello world!')
end
scenario "preserves description" do
expect(current_example(self).metadata[:full_description])
.to eq("Capybara's feature DSL preserves description")
end
scenario "allows driver switching", :driver => :selenium do
expect(Capybara.current_driver).to eq(:selenium)
end
scenario "runs background" do
expect(@in_background).to be_truthy
end
scenario "runs hooks filtered by file path" do
expect(@in_filtered_hook).to be_truthy
end
scenario "doesn't pollute the Object namespace" do
expect(Object.new.respond_to?(:feature, true)).to be_falsey
end
feature 'nested features' do
scenario 'work as expected' do
visit '/'
expect(page).to have_content 'Hello world!'
end
scenario 'are marked in the metadata as capybara_feature' do
expect(current_example(self).metadata[:capybara_feature]).to be_truthy
end
scenario 'have a type of :feature' do
expect(current_example(self).metadata[:type]).to eq :feature
end
end
end
feature "given and given! aliases to let and let!" do
given(:value) { :available }
given!(:value_in_background) { :available }
background do
expect(value_in_background).to be(:available)
end
scenario "given and given! work as intended" do
expect(value).to be(:available)
expect(value_in_background).to be(:available)
end
end
feature "if xscenario aliases to pending then" do
xscenario "this test should be 'temporarily disabled with xscenario'" do
end
end
feature "Capybara's feature DSL with driver", :driver => :culerity do
scenario "switches driver" do
expect(Capybara.current_driver).to eq(:culerity)
end
end
capybara-2.5.0/lib/ 0000755 0001750 0001750 00000000000 12573712570 013103 5 ustar lunar lunar capybara-2.5.0/lib/capybara.rb 0000644 0001750 0001750 00000031515 12573712570 015217 0 ustar lunar lunar require 'timeout'
require 'nokogiri'
require 'xpath'
module Capybara
class CapybaraError < StandardError; end
class DriverNotFoundError < CapybaraError; end
class FrozenInTime < CapybaraError; end
class ElementNotFound < CapybaraError; end
class ModalNotFound < CapybaraError; end
class Ambiguous < ElementNotFound; end
class ExpectationNotMet < ElementNotFound; end
class FileNotFound < CapybaraError; end
class UnselectNotAllowed < CapybaraError; end
class NotSupportedByDriverError < CapybaraError; end
class InfiniteRedirectError < CapybaraError; end
class ScopeError < CapybaraError; end
class WindowError < CapybaraError; end
class ReadOnlyElementError < CapybaraError; end
class << self
attr_accessor :asset_host, :app_host, :run_server, :default_host, :always_include_port
attr_accessor :server_port, :exact, :match, :exact_options, :visible_text_only
attr_accessor :default_selector, :default_max_wait_time, :ignore_hidden_elements
attr_accessor :save_and_open_page_path, :wait_on_first_by_default, :automatic_reload, :raise_server_errors, :server_errors
attr_writer :default_driver, :current_driver, :javascript_driver, :session_name, :server_host
attr_accessor :app
##
#
# Configure Capybara to suit your needs.
#
# Capybara.configure do |config|
# config.run_server = false
# config.app_host = 'http://www.google.com'
# end
#
# === Configurable options
#
# [app_host = String] The default host to use when giving a relative URL to visit
# [always_include_port = Boolean] Whether the Rack server's port should automatically be inserted into every visited URL (Default: false)
# [asset_host = String] Where dynamic assets are hosted - will be prepended to relative asset locations if present (Default: nil)
# [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
# [raise_server_errors = Boolean] Should errors raised in the server be raised in the tests? (Default: true)
# [server_errors = Array\] Error classes that should be raised in the tests if they are raised in the server and Capybara.raise_server_errors is true (Default: [StandardError])
# [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: :css)
# [default_max_wait_time = Numeric] The maximum number of seconds to wait for asynchronous processes to finish (Default: 2)
# [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: true)
# [automatic_reload = Boolean] Whether to automatically reload elements as Capybara is waiting (Default: true)
# [save_and_open_page_path = String] Where to put pages saved through save_and_open_page (Default: Dir.pwd)
# [wait_on_first_by_default = Boolean] Whether Node#first defaults to Capybara waiting behavior for at least 1 element to match (Default: false)
# === DSL Options
#
# when using capybara/dsl, the following options are also available:
#
# [default_driver = Symbol] The name of the driver to use by default. (Default: :rack_test)
# [javascript_driver = Symbol] The name of a driver to use for JavaScript enabled tests. (Default: :selenium)
#
def configure
yield self
end
##
#
# Register a new driver for Capybara.
#
# Capybara.register_driver :rack_test do |app|
# Capybara::RackTest::Driver.new(app)
# end
#
# @param [Symbol] name The name of the new driver
# @yield [app] This block takes a rack app and returns a Capybara driver
# @yieldparam [] app The rack application that this driver runs against. May be nil.
# @yieldreturn [Capybara::Driver::Base] A Capybara driver instance
#
def register_driver(name, &block)
drivers[name] = block
end
##
#
# Add a new selector to Capybara. Selectors can be used by various methods in Capybara
# to find certain elements on the page in a more convenient way. For example adding a
# selector to find certain table rows might look like this:
#
# Capybara.add_selector(:row) do
# xpath { |num| ".//tbody/tr[#{num}]" }
# end
#
# This makes it possible to use this selector in a variety of ways:
#
# find(:row, 3)
# page.find('table#myTable').find(:row, 3).text
# page.find('table#myTable').has_selector?(:row, 3)
# within(:row, 3) { expect(page).to have_content('$100.000') }
#
# Here is another example:
#
# Capybara.add_selector(:id) do
# xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
# end
#
# Note that this particular selector already ships with Capybara.
#
# @param [Symbol] name The name of the selector to add
# @yield A block executed in the context of the new {Capybara::Selector}
#
def add_selector(name, &block)
Capybara::Selector.add(name, &block)
end
def drivers
@drivers ||= {}
end
##
#
# Register a proc that Capybara will call to run the Rack application.
#
# Capybara.server do |app, port|
# require 'rack/handler/mongrel'
# Rack::Handler::Mongrel.run(app, :Port => port)
# end
#
# By default, Capybara will try to run webrick.
#
# @yield [app, port] This block receives a rack app and port and should run a Rack handler
#
def server(&block)
if block_given?
@server = block
else
@server
end
end
##
#
# Wraps the given string, which should contain an HTML document or fragment
# in a {Capybara::Node::Simple} which exposes all {Capybara::Node::Matchers},
# {Capybara::Node::Finders} and {Capybara::Node::DocumentMatchers}. This allows you to query
# any string containing HTML in the exact same way you would query the current document in a Capybara
# session. For example:
#
# node = Capybara.string <<-HTML
#
#
Home
#
Projects
#
# HTML
#
# node.find('#projects').text # => 'Projects'
# node.has_selector?('li#home', :text => 'Home')
# node.has_selector?('#projects')
# node.find('ul').find('li:first-child').text # => 'Home'
#
# @param [String] html An html fragment or document
# @return [Capybara::Node::Simple] A node which has Capybara's finders and matchers
#
def string(html)
Capybara::Node::Simple.new(html)
end
##
#
# Runs Capybara's default server for the given application and port
# under most circumstances you should not have to call this method
# manually.
#
# @param [Rack Application] app The rack application to run
# @param [Fixnum] port The port to run the application on
#
def run_default_server(app, port)
require 'rack/handler/webrick'
Rack::Handler::WEBrick.run(app, :Host => server_host, :Port => port, :AccessLog => [], :Logger => WEBrick::Log::new(nil, 0))
end
##
#
# @return [Symbol] The name of the driver to use by default
#
def default_driver
@default_driver || :rack_test
end
##
#
# @return [Symbol] The name of the driver currently in use
#
def current_driver
@current_driver || default_driver
end
alias_method :mode, :current_driver
##
#
# @return [Symbol] The name of the driver used when JavaScript is needed
#
def javascript_driver
@javascript_driver || :selenium
end
##
#
# Use the default driver as the current driver
#
def use_default_driver
@current_driver = nil
end
##
#
# Yield a block using a specific driver
#
def using_driver(driver)
previous_driver = Capybara.current_driver
Capybara.current_driver = driver
yield
ensure
@current_driver = previous_driver
end
##
#
# @return [String] The IP address bound by default server
#
def server_host
@server_host || '127.0.0.1'
end
##
#
# Yield a block using a specific wait time
#
def using_wait_time(seconds)
previous_wait_time = Capybara.default_max_wait_time
Capybara.default_max_wait_time = seconds
yield
ensure
Capybara.default_max_wait_time = previous_wait_time
end
##
#
# The current Capybara::Session based on what is set as Capybara.app and Capybara.current_driver
#
# @return [Capybara::Session] The currently used session
#
def current_session
session_pool["#{current_driver}:#{session_name}:#{app.object_id}"] ||= Capybara::Session.new(current_driver, app)
end
##
#
# Reset sessions, cleaning out the pool of sessions. This will remove any session information such
# as cookies.
#
def reset_sessions!
session_pool.each { |mode, session| session.reset! }
end
alias_method :reset!, :reset_sessions!
##
#
# The current session name.
#
# @return [Symbol] The name of the currently used session.
#
def session_name
@session_name ||= :default
end
##
#
# Yield a block using a specific session name.
#
def using_session(name)
previous_session_name = self.session_name
self.session_name = name
yield
ensure
self.session_name = previous_session_name
end
##
#
# Parse raw html into a document using Nokogiri, and adjust textarea contents as defined by the spec.
#
# @param [String] html The raw html
# @return [Nokogiri::HTML::Document] HTML document
#
def HTML(html)
Nokogiri::HTML(html).tap do |document|
document.xpath('//textarea').each do |textarea|
textarea.content=textarea.content.sub(/\A\n/,'')
end
end
end
# @deprecated Use default_max_wait_time instead
def default_wait_time
deprecate('default_wait_time', 'default_max_wait_time', true)
default_max_wait_time
end
# @deprecated Use default_max_wait_time= instead
def default_wait_time=(t)
deprecate('default_wait_time=', 'default_max_wait_time=')
self.default_max_wait_time = t
end
def included(base)
base.send(:include, Capybara::DSL)
warn "`include Capybara` is deprecated. Please use `include Capybara::DSL` instead."
end
def deprecate(method, alternate_method, once=false)
@deprecation_notified ||= {}
warn "DEPRECATED: ##{method} is deprecated, please use ##{alternate_method} instead" unless once and @deprecation_notified[method]
@deprecation_notified[method]=true
end
private
def session_pool
@session_pool ||= {}
end
end
self.default_driver = nil
self.current_driver = nil
self.server_host = nil
module Driver; end
module RackTest; end
module Selenium; end
require 'capybara/helpers'
require 'capybara/session'
require 'capybara/dsl'
require 'capybara/window'
require 'capybara/server'
require 'capybara/selector'
require 'capybara/result'
require 'capybara/version'
require 'capybara/queries/base_query'
require 'capybara/query'
require 'capybara/queries/text_query'
require 'capybara/queries/title_query'
require 'capybara/queries/current_path_query'
require 'capybara/node/finders'
require 'capybara/node/matchers'
require 'capybara/node/actions'
require 'capybara/node/document_matchers'
require 'capybara/node/simple'
require 'capybara/node/base'
require 'capybara/node/element'
require 'capybara/node/document'
require 'capybara/driver/base'
require 'capybara/driver/node'
require 'capybara/rack_test/driver'
require 'capybara/rack_test/node'
require 'capybara/rack_test/form'
require 'capybara/rack_test/browser'
require 'capybara/rack_test/css_handlers.rb'
require 'capybara/selenium/node'
require 'capybara/selenium/driver'
end
Capybara.configure do |config|
config.always_include_port = false
config.run_server = true
config.server {|app, port| Capybara.run_default_server(app, port)}
config.default_selector = :css
config.default_max_wait_time = 2
config.ignore_hidden_elements = true
config.default_host = "http://www.example.com"
config.automatic_reload = true
config.match = :smart
config.exact = false
config.raise_server_errors = true
config.server_errors = [StandardError]
config.visible_text_only = false
config.wait_on_first_by_default = false
end
Capybara.register_driver :rack_test do |app|
Capybara::RackTest::Driver.new(app)
end
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app)
end
capybara-2.5.0/lib/capybara/ 0000755 0001750 0001750 00000000000 12573712570 014665 5 ustar lunar lunar capybara-2.5.0/lib/capybara/server.rb 0000644 0001750 0001750 00000003615 12573712570 016525 0 ustar lunar lunar require 'uri'
require 'net/http'
require 'rack'
module Capybara
class Server
class Middleware
attr_accessor :error
def initialize(app)
@app = app
end
def call(env)
if env["PATH_INFO"] == "/__identify__"
[200, {}, [@app.object_id.to_s]]
else
begin
@app.call(env)
rescue *Capybara.server_errors => e
@error = e unless @error
raise e
end
end
end
end
class << self
def ports
@ports ||= {}
end
end
attr_reader :app, :port, :host
def initialize(app, port=Capybara.server_port, host=Capybara.server_host)
@app = app
@middleware = Middleware.new(@app)
@server_thread = nil # suppress warnings
@host, @port = host, port
@port ||= Capybara::Server.ports[@app.object_id]
@port ||= find_available_port
end
def reset_error!
@middleware.error = nil
end
def error
@middleware.error
end
def responsive?
return false if @server_thread && @server_thread.join(0)
res = Net::HTTP.start(host, @port) { |http| http.get('/__identify__') }
if res.is_a?(Net::HTTPSuccess) or res.is_a?(Net::HTTPRedirection)
return res.body == @app.object_id.to_s
end
rescue SystemCallError
return false
end
def boot
unless responsive?
Capybara::Server.ports[@app.object_id] = @port
@server_thread = Thread.new do
Capybara.server.call(@middleware, @port)
end
Timeout.timeout(60) { @server_thread.join(0.1) until responsive? }
end
rescue Timeout::Error
raise "Rack application timed out during boot"
else
self
end
private
def find_available_port
server = TCPServer.new('127.0.0.1', 0)
server.addr[1]
ensure
server.close if server
end
end
end
capybara-2.5.0/lib/capybara/query.rb 0000644 0001750 0001750 00000007254 12573712570 016367 0 ustar lunar lunar module Capybara
# @deprecated This class and its methods are not supposed to be used by users of Capybara's public API.
# It may be removed in future versions of Capybara.
class Query < Queries::BaseQuery
attr_accessor :selector, :locator, :options, :expression, :find, :negative
VALID_KEYS = [:text, :visible, :between, :count, :maximum, :minimum, :exact, :match, :wait]
VALID_MATCH = [:first, :smart, :prefer_exact, :one]
def initialize(*args)
@options = if args.last.is_a?(Hash) then args.pop.dup else {} end
if args[0].is_a?(Symbol)
@selector = Selector.all[args[0]]
@locator = args[1]
else
@selector = Selector.all.values.find { |s| s.match?(args[0]) }
@locator = args[0]
end
@selector ||= Selector.all[Capybara.default_selector]
# for compatibility with Capybara 2.0
if Capybara.exact_options and @selector == Selector.all[:option]
@options[:exact] = true
end
@expression = @selector.call(@locator)
assert_valid_keys
end
def name; selector.name; end
def label; selector.label or selector.name; end
def description
@description = "#{label} #{locator.inspect}"
@description << " with text #{options[:text].inspect}" if options[:text]
@description << selector.description(options)
@description
end
def matches_filters?(node)
if options[:text]
regexp = options[:text].is_a?(Regexp) ? options[:text] : Regexp.escape(options[:text].to_s)
return false if not node.text(visible).match(regexp)
end
case visible
when :visible then return false unless node.visible?
when :hidden then return false if node.visible?
end
selector.custom_filters.each do |name, filter|
if options.has_key?(name)
return false unless filter.matches?(node, options[name])
elsif filter.default?
return false unless filter.matches?(node, filter.default)
end
end
end
def visible
if options.has_key?(:visible)
case @options[:visible]
when true then :visible
when false then :all
else @options[:visible]
end
else
if Capybara.ignore_hidden_elements
:visible
else
:all
end
end
end
def exact?
if options.has_key?(:exact)
@options[:exact]
else
Capybara.exact
end
end
def match
if options.has_key?(:match)
@options[:match]
else
Capybara.match
end
end
def xpath(exact=nil)
exact = self.exact? if exact == nil
if @expression.respond_to?(:to_xpath) and exact
@expression.to_xpath(:exact)
else
@expression.to_s
end
end
def css
@expression
end
# @api private
def resolve_for(node, exact = nil)
node.synchronize do
children = if selector.format == :css
node.find_css(self.css)
else
node.find_xpath(self.xpath(exact))
end.map do |child|
if node.is_a?(Capybara::Node::Base)
Capybara::Node::Element.new(node.session, child, node, self)
else
Capybara::Node::Simple.new(child)
end
end
Capybara::Result.new(children, self)
end
end
private
def valid_keys
COUNT_KEYS + [:text, :visible, :exact, :match, :wait] + @selector.custom_filters.keys
end
def assert_valid_keys
super
unless VALID_MATCH.include?(match)
raise ArgumentError, "invalid option #{match.inspect} for :match, should be one of #{VALID_MATCH.map(&:inspect).join(", ")}"
end
end
end
end
capybara-2.5.0/lib/capybara/selector.rb 0000644 0001750 0001750 00000017446 12573712570 017046 0 ustar lunar lunar module Capybara
class Selector
class Filter
def initialize(name, block, options={})
@name = name
@block = block
@options = options
@options[:valid_values] = [true,false] if options[:boolean]
end
def default?
@options.has_key?(:default)
end
def default
@options[:default]
end
def matches?(node, value)
if @options.has_key?(:valid_values) && !Array(@options[:valid_values]).include?(value)
warn "Invalid value #{value.inspect} passed to filter #{@name}"
end
@block.call(node, value)
end
end
attr_reader :name, :custom_filters, :format
class << self
def all
@selectors ||= {}
end
def add(name, &block)
all[name.to_sym] = Capybara::Selector.new(name.to_sym, &block)
end
def remove(name)
all.delete(name.to_sym)
end
end
def initialize(name, &block)
@name = name
@custom_filters = {}
@match = nil
@label = nil
@failure_message = nil
@description = nil
instance_eval(&block)
end
def xpath(&block)
@format = :xpath
@xpath = block if block
@xpath
end
# Same as xpath, but wrap in XPath.css().
def css(&block)
@format = :css
@css = block if block
@css
end
def match(&block)
@match = block if block
@match
end
def label(label=nil)
@label = label if label
@label
end
def description(options={})
(@description && @description.call(options)).to_s
end
def call(locator)
if @format==:css
@css.call(locator)
else
@xpath.call(locator)
end
end
def match?(locator)
@match and @match.call(locator)
end
def filter(name, options={}, &block)
@custom_filters[name] = Filter.new(name, block, options)
end
def describe &block
@description = block
end
end
end
Capybara.add_selector(:xpath) do
xpath { |xpath| xpath }
end
Capybara.add_selector(:css) do
css { |css| css }
end
Capybara.add_selector(:id) do
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
end
Capybara.add_selector(:field) do
xpath { |locator| XPath::HTML.field(locator) }
filter(:checked, boolean: true) { |node, value| not(value ^ node.checked?) }
filter(:unchecked, boolean: true) { |node, value| (value ^ node.checked?) }
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
filter(:readonly, boolean: true) { |node, value| not(value ^ node[:readonly]) }
filter(:with) { |node, with| node.value == with.to_s }
filter(:type) do |node, type|
if ['textarea', 'select'].include?(type)
node.tag_name == type
else
node[:type] == type
end
end
describe do |options|
desc, states = "", []
desc << " of type #{options[:type].inspect}" if options[:type]
desc << " with value #{options[:with].to_s.inspect}" if options.has_key?(:with)
states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
states << 'disabled' if options[:disabled]
desc << " that is #{states.join(' and ')}" unless states.empty?
desc
end
end
Capybara.add_selector(:fieldset) do
xpath { |locator| XPath::HTML.fieldset(locator) }
end
Capybara.add_selector(:link_or_button) do
label "link or button"
xpath { |locator| XPath::HTML.link_or_button(locator) }
filter(:disabled, default: false, boolean: true) { |node, value| node.tag_name == "a" or not(value ^ node.disabled?) }
describe { |options| " that is disabled" if options[:disabled] }
end
Capybara.add_selector(:link) do
xpath { |locator| XPath::HTML.link(locator) }
filter(:href) do |node, href|
if href.is_a? Regexp
node[:href].match href
else
node.first(:xpath, XPath.axis(:self)[XPath.attr(:href).equals(href.to_s)], minimum: 0)
end
end
describe { |options| " with href #{options[:href].inspect}" if options[:href] }
end
Capybara.add_selector(:button) do
xpath { |locator| XPath::HTML.button(locator) }
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
describe { |options| " that is disabled" if options[:disabled] }
end
Capybara.add_selector(:fillable_field) do
label "field"
xpath { |locator| XPath::HTML.fillable_field(locator) }
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
describe { |options| " that is disabled" if options[:disabled] }
end
Capybara.add_selector(:radio_button) do
label "radio button"
xpath { |locator| XPath::HTML.radio_button(locator) }
filter(:checked, boolean: true) { |node, value| not(value ^ node.checked?) }
filter(:unchecked, boolean: true) { |node, value| (value ^ node.checked?) }
filter(:option) { |node, value| node.value == value.to_s }
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
describe do |options|
desc, states = "", []
desc << " with value #{options[:option].inspect}" if options[:option]
states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
states << 'disabled' if options[:disabled]
desc << " that is #{states.join(' and ')}" unless states.empty?
desc
end
end
Capybara.add_selector(:checkbox) do
xpath { |locator| XPath::HTML.checkbox(locator) }
filter(:checked, boolean: true) { |node, value| not(value ^ node.checked?) }
filter(:unchecked, boolean: true) { |node, value| (value ^ node.checked?) }
filter(:option) { |node, value| node.value == value.to_s }
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
describe do |options|
desc, states = "", []
desc << " with value #{options[:option].inspect}" if options[:option]
states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
states << 'disabled' if options[:disabled]
desc << " that is #{states.join(' and ')}" unless states.empty?
desc
end
end
Capybara.add_selector(:select) do
label "select box"
xpath { |locator| XPath::HTML.select(locator) }
filter(:options) do |node, options|
actual = node.all(:xpath, './/option').map { |option| option.text }
options.sort == actual.sort
end
filter(:with_options) { |node, options| options.all? { |option| node.first(:option, option, minimum: 0) } }
filter(:selected) do |node, selected|
actual = node.all(:xpath, './/option').select { |option| option.selected? }.map { |option| option.text }
[selected].flatten.sort == actual.sort
end
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
describe do |options|
desc = ""
desc << " with options #{options[:options].inspect}" if options[:options]
desc << " with at least options #{options[:with_options].inspect}" if options[:with_options]
desc << " with #{options[:selected].inspect} selected" if options[:selected]
desc << " that is disabled" if options[:disabled]
desc
end
end
Capybara.add_selector(:option) do
xpath { |locator| XPath::HTML.option(locator) }
end
Capybara.add_selector(:file_field) do
label "file field"
xpath { |locator| XPath::HTML.file_field(locator) }
filter(:disabled, default: false, boolean: true) { |node, value| not(value ^ node.disabled?) }
describe { |options| " that is disabled" if options[:disabled] }
end
Capybara.add_selector(:table) do
xpath { |locator| XPath::HTML.table(locator) }
end
capybara-2.5.0/lib/capybara/node/ 0000755 0001750 0001750 00000000000 12573712570 015612 5 ustar lunar lunar capybara-2.5.0/lib/capybara/node/simple.rb 0000644 0001750 0001750 00000011124 12573712570 017427 0 ustar lunar lunar module Capybara
module Node
##
#
# A {Capybara::Node::Simple} is a simpler version of {Capybara::Node::Base} which
# includes only {Capybara::Node::Finders} and {Capybara::Node::Matchers} and does
# not include {Capybara::Node::Actions}. This type of node is returned when
# using {Capybara.string}.
#
# It is useful in that it does not require a session, an application or a driver,
# but can still use Capybara's finders and matchers on any string that contains HTML.
#
class Simple
include Capybara::Node::Finders
include Capybara::Node::Matchers
include Capybara::Node::DocumentMatchers
attr_reader :native
def initialize(native)
native = Capybara::HTML(native) if native.is_a?(String)
@native = native
end
##
#
# @return [String] The text of the element
#
def text(type=nil)
native.text
end
##
#
# Retrieve the given attribute
#
# element[:title] # => HTML title attribute
#
# @param [Symbol] name The attribute name to retrieve
# @return [String] The value of the attribute
#
def [](name)
attr_name = name.to_s
if attr_name == 'value'
value
elsif 'input' == tag_name and 'checkbox' == native[:type] and 'checked' == attr_name
native['checked'] == 'checked'
else
native[attr_name]
end
end
##
#
# @return [String] The tag name of the element
#
def tag_name
native.node_name
end
##
#
# An XPath expression describing where on the page the element can be found
#
# @return [String] An XPath expression
#
def path
native.path
end
##
#
# @return [String] The value of the form element
#
def value
if tag_name == 'textarea'
native.content
elsif tag_name == 'select'
if native['multiple'] == 'multiple'
native.xpath(".//option[@selected='selected']").map { |option| option[:value] || option.content }
else
option = native.xpath(".//option[@selected='selected']").first || native.xpath(".//option").first
option[:value] || option.content if option
end
elsif tag_name == 'input' && %w(radio checkbox).include?(native[:type])
native[:value] || 'on'
else
native[:value]
end
end
##
#
# Whether or not the element is visible. Does not support CSS, so
# the result may be inaccurate.
#
# @param [Boolean] check_ancestors Whether to inherit visibility from ancestors
# @return [Boolean] Whether the element is visible
#
def visible?(check_ancestors = true)
if check_ancestors
#check size because oldest supported nokogiri doesnt support xpath boolean() function
native.xpath("./ancestor-or-self::*[contains(@style, 'display:none') or contains(@style, 'display: none') or @hidden or name()='script' or name()='head']").size() == 0
else
#no need for an xpath if only checking the current element
!(native.has_attribute?('hidden') || (native[:style] =~ /display:\s?none/) || %w(script head).include?(tag_name))
end
end
##
#
# Whether or not the element is checked.
#
# @return [Boolean] Whether the element is checked
#
def checked?
native[:checked]
end
##
#
# Whether or not the element is disabled.
#
# @return [Boolean] Whether the element is disabled
def disabled?
native[:disabled]
end
##
#
# Whether or not the element is selected.
#
# @return [Boolean] Whether the element is selected
#
def selected?
native[:selected]
end
def synchronize(seconds=nil)
yield # simple nodes don't need to wait
end
def allow_reload!
# no op
end
def title
if native.respond_to? :title
native.title
else
#old versions of nokogiri don't have #title - remove in 3.0
native.xpath('/html/head/title | /html/title').first.text
end
end
def inspect
%(#)
end
# @api private
def find_css(css)
native.css(css)
end
# @api private
def find_xpath(xpath)
native.xpath(xpath)
end
end
end
end
capybara-2.5.0/lib/capybara/node/actions.rb 0000644 0001750 0001750 00000013275 12573712570 017607 0 ustar lunar lunar module Capybara
module Node
module Actions
##
#
# Finds a button or link by id, text or value and clicks it. Also looks at image
# alt text inside the link.
#
# @param [String] locator Text, id or value of link or button
#
def click_link_or_button(locator, options={})
find(:link_or_button, locator, options).click
end
alias_method :click_on, :click_link_or_button
##
#
# Finds a link by id, text or title and clicks it. Also looks at image
# alt text inside the link.
#
# @param [String] locator text, id, title or nested image's alt attribute
# @param options See {Capybara::Node::Finders#find_link}
#
def click_link(locator, options={})
find(:link, locator, options).click
end
##
#
# Finds a button on the page and clicks it.
# This can be any \ element of type submit, reset, image, button or it can be a
# \