capybara-3.12.0/ 0000755 0001750 0001750 00000000000 13411315075 014115 5 ustar utkarsh2102 utkarsh2102 capybara-3.12.0/README.md 0000644 0001750 0001750 00000113642 13411315075 015403 0 ustar utkarsh2102 utkarsh2102 # Capybara
[](https://travis-ci.org/teamcapybara/capybara)
[](https://ci.appveyor.com/api/projects/github/teamcapybara/capybara)
[](https://codeclimate.com/github/teamcapybara/capybara)
[](https://gitter.im/jnicklas/capybara?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[](https://dependabot.com/compatibility-score.html?dependency-name=capybara&package-manager=bundler&version-scheme=semver)
**Note** You are viewing the README for the 3.12.x version of 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.
## Support Capybara
If you and/or your company find value in Capybara and would like to contribute financially to its ongoing maintenance and development, please visit
Patreon
**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](#using-capybara-with-minitest)
- [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 sessions](#using-sessions)
- [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)
- ["Threadsafe" mode](#threadsafe)
- [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 2.3.0 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'
```
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). If using Rails 5.0+, but not using the Rails system tests from 5.1, you'll probably also
want to swap the "server" used to launch your app to Puma in order to match Rails defaults.
```ruby
Capybara.server = :puma # Until your setup is working
Capybara.server = :puma, { Silent: true } # To clean up your test output
```
## 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 tags for each registered driver set up for you (`@selenium`, `@rack_test`, etc).
## Using Capybara with RSpec
Load RSpec 3.5+ 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` or `spec/system` (only works
if [you have it configured in
RSpec](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#file-type-inference-disabled))
and if you have your Capybara specs in a different directory, then tag the
example groups with `type: :feature` or `type: :system` depending on which type of test you're writing.
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 also 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
```
**Note: When you require 'capybara/rspec' proxy methods are installed to work around name collisions between Capybara::DSL methods
`all`/`within` and the identically named built-in RSpec matchers. If you opt not to require 'capybara/rspec' you can install the proxy methods by requiring 'capybara/rspec/matcher_proxies' after requiring RSpec and 'capybara/dsl'**
## Using Capybara with Test::Unit
* If you are using `Test::Unit`, define a base class for your Capybara tests
like so:
```ruby
require 'capybara/dsl'
class CapybaraTestCase < Test::Unit::TestCase
include Capybara::DSL
def teardown
Capybara.reset_sessions!
Capybara.use_default_driver
end
end
```
## Using Capybara with Minitest
* 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
require 'capybara/rails'
require 'capybara/minitest'
class ActionDispatch::IntegrationTest
# Make the Capybara DSL available in all integration tests
include Capybara::DSL
# Make `assert_*` methods behave like Minitest assertions
include Capybara::Minitest::Assertions
# Reset sessions and driver between tests
# Use super wherever this method is redefined in your individual test classes
def teardown
Capybara.reset_sessions!
Capybara.use_default_driver
end
end
```
* If you are not using Rails, define a base class for your Capybara tests like
so:
```ruby
require 'capybara/minitest'
class CapybaraTestCase < Minitest::Test
include Capybara::DSL
include Capybara::Minitest::Assertions
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
Follow the above instructions for Minitest and additionally require capybara/minitest/spec
```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 # :selenium_chrome and :selenium_chrome_headless are also registered
```
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
Capybara supports [Selenium 3.5+
(Webdriver)](https://www.seleniumhq.org/projects/webdriver/).
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.
Capybara pre-registers a number of named drives that use Selenium - they are:
* :selenium => Selenium driving Firefox
* :selenium_headless => Selenium driving Firefox in a headless configuration
* :selenium_chrome => Selenium driving Chrome
* :selenium_chrome_headless => Selenium driving Chrome in a headless configuration
These should work (with relevant software installation) in a local desktop configuration but you may
need to customize them if using in a CI environment where additional options may need to be passed
to the browsers. See the section on adding and configuring drivers.
**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](#transactions-and-database-setup) below.
### Capybara-webkit
Note: `capybara-webkit` depends on QtWebkit which went EOL quite some time ago. There has been an attempt to revive the project but `capybara-webkit` is not yet (AFAIK) compatible with the revived version of QtWebKit (could be a good OSS project for someone) and as such is still limited to an old version of QtWebKit. This means its support for modern JS and CSS is severely limited.
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
Note: `poltergeist` depends on PhantomJS for which active development ended quite some time ago (2.1.1). As such it is roughly equivalent to a 6-7 year old version of Safari, meaning lack of support for modern JS And CSS. If any effort to update PhantomJS succeeds in the future this situation could change.
[Poltergeist](https://github.com/teampoltergeist/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/teamcapybara/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/teamcapybara/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/teamcapybara/capybara/master/Capybara/Session#current_path-instance_method)
of the browsing session, and test it using the [`have_current_path`](http://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/RSpecMatchers#have_current_path-instance_method) matcher:
```ruby
expect(page).to have_current_path(post_comments_path(post))
```
**Note**: You can also assert the current path by testing the value of
`current_path` directly. However, using the `have_current_path` matcher is
safer since it uses Capybara's [waiting behaviour](#asynchronous-javascript-ajax-and-friends)
to ensure that preceding actions (such as a `click_link`) have completed.
### Clicking links and buttons
*Full reference: [Capybara::Node::Actions](http://rubydoc.info/github/teamcapybara/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/teamcapybara/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/teamcapybara/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/teamcapybara/capybara/master/Capybara/Node/Finders)_
You can also find specific elements, in order to manipulate them:
```ruby
find_field('First Name').value
find_field(id: 'my_field').value
find_link('Hello', :visible => :all).visible?
find_link(class: ['some_class', 'some_other_class'], :visible => :all).visible?
find_button('Send').click
find_button(value: '1234').click
find(:xpath, ".//table/tr").click
find("#overlay").find("h1").click
all('a').each { |a| a[:href] }
```
If you need to find elements by additional attributes/properties you can also pass a filter block, which will be checked inside the normal waiting behavior.
If you find yourself needing to use this a lot you may be better off adding a [custom selector](http://www.rubydoc.info/github/teamcapybara/capybara/Capybara#add_selector-class_method) or [adding a filter to an existing selector](http://www.rubydoc.info/github/teamcapybara/capybara/Capybara#modify_selector-class_method).
```ruby
find_field('First Name'){ |el| el['data-xyz'] == '123' }
find("#img_loading"){ |img| img['complete'] == true }
```
**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/teamcapybara/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/teamcapybara/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
```
Screenshots are saved to `Capybara.save_path`, relative to the app directory.
If you have required `capybara/rails`, `Capybara.save_path` will default to
`tmp/capybara`.
## 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
**Note:** Rails 5.1+ "safely" shares the database connection between the app and test threads. Therefore,
if using Rails 5.1+ you SHOULD be able to ignore this section.
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/DatabaseCleaner/database_cleaner).
## 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/dsl'
Capybara.default_driver = :webkit
module MyModule
include Capybara::DSL
def login!
within(:xpath, ".//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 sessions
Capybara manages named sessions (:default if not specified) allowing multiple sessions using the same driver and test app instance to be interacted with.
A new session will be created using the current driver if a session with the given name using the current driver and test app instance is not found.
### Named sessions
To perform operations in a different session and then revert to the previous session
```ruby
Capybara.using_session("Bob's session") do
#do something in Bob's browser session
end
#reverts to previous session
```
To permanently switch the current session to a different session
```ruby
Capybara.session_name = "some other session"
```
### Using sessions manually
For ultimate control, you can instantiate and use a
[Session](http://rubydoc.info/github/teamcapybara/capybara/master/Capybara/Session)
manually.
```ruby
require 'capybara'
session = Capybara::Session.new(:webkit, my_rack_app)
session.within("form#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
# Note: Capybara registers this by default
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](https://github.com/SeleniumHQ/selenium/wiki/Ruby-Bindings) 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](https://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)
## "Threadsafe" mode
In normal mode most of Capybara's configuration options are global settings which can cause issues
if using multiple sessions and wanting to change a setting for only one of the sessions. To provide
support for this type of usage Capybara now provides a "threadsafe" mode which can be enabled by setting
```ruby
Capybara.threadsafe = true
```
This setting can only be changed before any sessions have been created. In "threadsafe" mode the following
behaviors of Capybara change
* Most options can now be set on a session. These can either be set at session creation time or after, and
default to the global options at the time of session creation. Options which are NOT session specific are
`app`, `reuse_server`, `default_driver`, `javascript_driver`, and (obviously) `threadsafe`. Any drivers and servers
registered through `register_driver` and `register_server` are also global.
```ruby
my_session = Capybara::Session.new(:driver, some_app) do |config|
config.automatic_label_click = true # only set for my_session
end
my_session.config.default_max_wait_time = 10 # only set for my_session
Capybara.default_max_wait_time = 2 # will not change the default_max_wait in my_session
```
* `current_driver` and `session_name` are thread specific. This means that `using_session` and
`using_driver` also only affect the current thread.
## Development
To set up a development environment, simply do:
```bash
bundle install
bundle exec rake # run the test suite with Firefox - requires `geckodriver` to be installed
bundle exec rake spec_chrome # run the test suite with Chrome - require `chromedriver` to be installed
```
See
[CONTRIBUTING.md](https://github.com/teamcapybara/capybara/blob/master/CONTRIBUTING.md)
for how to send issues and pull requests.
capybara-3.12.0/spec/ 0000755 0001750 0001750 00000000000 13411315075 015047 5 ustar utkarsh2102 utkarsh2102 capybara-3.12.0/spec/minitest_spec_spec.rb 0000644 0001750 0001750 00000011033 13411315075 021252 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'capybara/minitest'
require 'capybara/minitest/spec'
class MinitestSpecTest < Minitest::Spec
include ::Capybara::DSL
include ::Capybara::Minitest::Assertions
before do
visit('/form')
end
after do
Capybara.reset_sessions!
end
it 'supports text expectations' do
page.must_have_text('Form', minimum: 1)
page.wont_have_text('Not a form')
form = find(:css, 'form', text: 'Title')
form.must_have_text('Customer Email')
form.wont_have_text('Some other email')
end
it 'supports current_path expectations' do
page.must_have_current_path('/form')
page.wont_have_current_path('/form2')
end
it 'supports title expectations' do
visit('/with_title')
page.must_have_title('Test Title')
page.wont_have_title('Not the title')
end
it 'supports xpath expectations' do
page.must_have_xpath('.//input[@id="customer_email"]')
page.wont_have_xpath('.//select[@id="not_form_title"]')
page.wont_have_xpath('.//input[@id="customer_email"]') { |el| el[:id] == 'not_customer_email' }
select = find(:select, 'form_title')
select.must_have_xpath('.//option[@class="title"]')
select.must_have_xpath('.//option', count: 1) { |option| option[:class] != 'title' && !option.disabled? }
select.wont_have_xpath('.//input[@id="customer_email"]')
end
it 'support css expectations' do
page.must_have_css('input#customer_email')
page.wont_have_css('select#not_form_title')
el = find(:select, 'form_title')
el.must_have_css('option.title')
el.wont_have_css('input#customer_email')
end
it 'supports link expectations' do
visit('/with_html')
page.must_have_link('A link')
page.wont_have_link('Not on page')
end
it 'supports button expectations' do
page.must_have_button('fresh_btn')
page.wont_have_button('not_btn')
end
it 'supports field expectations' do
page.must_have_field('customer_email')
page.wont_have_field('not_on_the_form')
end
it 'supports select expectations' do
page.must_have_select('form_title')
page.wont_have_select('not_form_title')
end
it 'supports checked_field expectations' do
page.must_have_checked_field('form_pets_dog')
page.wont_have_checked_field('form_pets_cat')
end
it 'supports unchecked_field expectations' do
page.must_have_unchecked_field('form_pets_cat')
page.wont_have_unchecked_field('form_pets_dog')
end
it 'supports table expectations' do
visit('/tables')
page.must_have_table('agent_table')
page.wont_have_table('not_on_form')
end
it 'supports all_of_selectors expectations' do
page.must_have_all_of_selectors(:css, 'select#form_other_title', 'input#form_last_name')
end
it 'supports none_of_selectors expectations' do
page.must_have_none_of_selectors(:css, 'input#not_on_page', 'input#also_not_on_page')
end
it 'supports any_of_selectors expectations' do
page.must_have_any_of_selectors(:css, 'select#form_other_title', 'input#not_on_page')
end
it 'supports match_selector expectations' do
find(:field, 'customer_email').must_match_selector(:field, 'customer_email')
find(:select, 'form_title').wont_match_selector(:field, 'customer_email')
end
it 'supports match_css expectations' do
find(:select, 'form_title').must_match_css('select#form_title')
find(:select, 'form_title').wont_match_css('select#form_other_title')
end
it 'supports match_xpath expectations' do
find(:select, 'form_title').must_match_xpath('.//select[@id="form_title"]')
find(:select, 'form_title').wont_match_xpath('.//select[@id="not_on_page"]')
end
it 'handles failures' do
page.must_have_select('non_existing_form_title')
end
it 'supports style expectations' do
skip "Rack test doesn't support style" if Capybara.current_driver == :rack_test
visit('/with_html')
find(:css, '#second').must_have_style('display' => 'inline')
end
end
RSpec.describe 'capybara/minitest/spec' do
before do
Capybara.current_driver = :rack_test
Capybara.app = TestApp
end
after do
Capybara.use_default_driver
end
it 'should support minitest spec' do
output = StringIO.new
reporter = Minitest::SummaryReporter.new(output)
reporter.start
MinitestSpecTest.run reporter, {}
reporter.report
expect(output.string).to include('20 runs, 42 assertions, 1 failures, 0 errors, 1 skips')
# Make sure error messages are displayed
expect(output.string).to include('expected to find select box "non_existing_form_title" but there were no matches')
end
end
capybara-3.12.0/spec/fixtures/ 0000755 0001750 0001750 00000000000 13411315075 016720 5 ustar utkarsh2102 utkarsh2102 capybara-3.12.0/spec/fixtures/selenium_driver_rspec_failure.rb 0000644 0001750 0001750 00000000657 13411315075 025354 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'selenium-webdriver'
RSpec.describe Capybara::Selenium::Driver do
it 'should exit with a non-zero exit status' do
options = { browser: (ENV['SELENIUM_BROWSER'] || :firefox).to_sym }
browser = Capybara::Selenium::Driver.new(TestApp, options).browser
expect(browser).to be_truthy
expect(true).to eq(false) # rubocop:disable RSpec/ExpectActual
end
end
capybara-3.12.0/spec/fixtures/certificate.pem 0000644 0001750 0001750 00000002725 13411315075 021713 0 ustar utkarsh2102 utkarsh2102 -----BEGIN CERTIFICATE-----
MIIEITCCAwmgAwIBAgIJALROkwd1gZHQMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV
BAYTAlVTMQswCQYDVQQIEwJDQTERMA8GA1UEChMIQ2FweWJhcmExFjAUBgNVBAMT
DWNhcHliYXJhLnRlc3QxITAfBgkqhkiG9w0BCQEWEnR3YWxwb2xlQGdtYWlsLmNv
bTAeFw0xODA1MDEyMDI5NDVaFw0yODA0MjgyMDI5NDVaMGgxCzAJBgNVBAYTAlVT
MQswCQYDVQQIEwJDQTERMA8GA1UEChMIQ2FweWJhcmExFjAUBgNVBAMTDWNhcHli
YXJhLnRlc3QxITAfBgkqhkiG9w0BCQEWEnR3YWxwb2xlQGdtYWlsLmNvbTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL7icqMv9uApxRXlcIQ3hSEfmULk
7CLT1aUAjEmTiqy8TkFqOeSuA3elnbVBhOW+emrb1uUyje20LvEOHbqYYw90ezlV
jqNWUapawqjxb+q7KVNpA5uDCtOHIC/1Z1kxQ+yZP/8St4SvnLGUMsUhu0h+ywJa
iGZ2xy8wdfjABUiUImRESdNkT7Xs0wxQGY0/FZ4K5Sec4kroOuvdxKKhyf5Js5xS
NRv2tXSMWlKHbYEvYzsVtFgv/4GjqN4wVvbfJmsS8thcyrSYSMN7eE0R6dcbJaLM
P/GTiw669zPJP164K84QoabLClgwyG+7mqjm7jutq9qXipwyrGsf/WR5fkUCAwEA
AaOBzTCByjAdBgNVHQ4EFgQU4ut9c0oB2OGMlN/nvn0Y7twBzJowgZoGA1UdIwSB
kjCBj4AU4ut9c0oB2OGMlN/nvn0Y7twBzJqhbKRqMGgxCzAJBgNVBAYTAlVTMQsw
CQYDVQQIEwJDQTERMA8GA1UEChMIQ2FweWJhcmExFjAUBgNVBAMTDWNhcHliYXJh
LnRlc3QxITAfBgkqhkiG9w0BCQEWEnR3YWxwb2xlQGdtYWlsLmNvbYIJALROkwd1
gZHQMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAANtqdDrdehBt20s
IVOsVzOp+tJI8pn6G62WJcZWGsvLLfx6Y6eJSP24r5NW4v39cqCgE76J2znzKxeo
VIShAJ1SLodR0GwzFGsl3TVKVoce6gBWZNXgkZyJTNqKGWeme8CH1EG3TqYlcybt
EXWLQ6wKndD+uHJIfqUy7HfaUv+TghJGLkv8QYqcAWILQko4xqZ1NULDQ2uhjxei
oaQlK9teHlVaH87dONesAg3f5rh9j6nvzGiC/T8ycdEhn/DxJMxRS2+mVZqKkk7U
60+e9Foc6qTW8UaMShIFYMspoRnr9baBxzxh9V9LZznwqVTf3vuEIck2l2j2KL/R
SOBenCM=
-----END CERTIFICATE-----
capybara-3.12.0/spec/fixtures/key.pem 0000644 0001750 0001750 00000003213 13411315075 020212 0 ustar utkarsh2102 utkarsh2102 -----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAvuJyoy/24CnFFeVwhDeFIR+ZQuTsItPVpQCMSZOKrLxOQWo5
5K4Dd6WdtUGE5b56atvW5TKN7bQu8Q4duphjD3R7OVWOo1ZRqlrCqPFv6rspU2kD
m4MK04cgL/VnWTFD7Jk//xK3hK+csZQyxSG7SH7LAlqIZnbHLzB1+MAFSJQiZERJ
02RPtezTDFAZjT8VngrlJ5ziSug6693EoqHJ/kmznFI1G/a1dIxaUodtgS9jOxW0
WC//gaOo3jBW9t8maxLy2FzKtJhIw3t4TRHp1xslosw/8ZOLDrr3M8k/XrgrzhCh
pssKWDDIb7uaqObuO62r2peKnDKsax/9ZHl+RQIDAQABAoIBABhZepYmgC+IJIPu
iLPVAT6AcWR/H0AyFYa+0yZvk7kFLFZb3pa1O+v/TGbavMEx0xvef0Mtd71ixrop
OtGarshB65Ycu91KHZDFkx9J7STcSyFAvB0SUkc5bXmwrEZMaoW75tX65T4fyLU+
WlubOfC9e9gJBG1NqYrze5kHpaTkR8pBaSxECns5y2HLaMvs1t1kK7snqtGHFRAb
deAUl0ONENaO6PF797yM3bsIEgnljdKvaVP3kYq/eAzH4jyw+qG/xq0bZ+nalJzM
IL7xRSR/Yak7WZ3QUh99t3dng/z3De4yvhBLq/mc2mIVvt7aERPo/aDG4SrmQ9Jw
f1GUT+ECgYEA+i96w2zPHkq0djuuhNaa/R0vybD9hVCdB7enQ8skBzQAQyhp9X9W
by38VAbFRVIMrzdfbvwSFrE3Nd9BvyLWl16G+MVu+hq0jhM9p44a62vXvfgQmfFh
iXyGkzCTufeLEzOFnP8S+ezacodK1hbQTjllUndn6NUhXcbfozTPfx8CgYEAw1Il
xqfU7NkVX6UP/FvTx9aBKqwrD8YOPn9nj26Q45zVbmHJZZIvywlsMDCiJ6JJawEa
GSkiZTDpypEvS/2UtLEY0zfbSbQGkBTnagHIFAuVh0AD1EP+kCcnrxA5Vjr8v0WE
B0HBfMgoZxa8rmHMpPhrlCCo1ectRgu+dgzEKhsCgYAQ17lwBpc69tSHUSVClCAD
AkABWAT5QKARsO91xOs8AOgznTjk6hmrinD+RyZosEliUlv+YMHm/S82VT1b3MCN
mDOF8+SwubOGDQ2NhieRycTQaS7U7kcetl9o8VBAqMWYGVPZaeKhKKzcIPeMyiRj
38FOd/Nq3U5NveG4XwnJCQKBgGrzmnfTAsbGf+uliMFYzviIPqZNLC8w9i/Gt8BU
fMYF5ODSbuNNTxpQiItCtigZtzX+nnnUil76j6o6IbnsmvbuWneeCFetWkKfD7B+
VT6UsUYkCXS73rK0nghATAUpu6hIumj22qonN+hrDNo390UGOnIcCBdIxQOr/pjJ
mMitAoGAB3tFzlzZHpCE38IqdHL7CKIML9cYJSOm07nFIEUAKN2bUHGsvMH/tMS1
I3hyeHxMmYCrOLn7xLqiOVgRjbYS9JiQVdDojqeSvvnLCtY9/lHWi50pqbPfwyfK
Og6QoFyxjBEsoSilc6dai58VTO6ufhoJXbXX9PcIl7le4dVPnzE=
-----END RSA PRIVATE KEY-----
capybara-3.12.0/spec/fixtures/selenium_driver_rspec_success.rb 0000644 0001750 0001750 00000000652 13411315075 025370 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'selenium-webdriver'
RSpec.describe Capybara::Selenium::Driver do
it 'should exit with a zero exit status' do
options = { browser: (ENV['SELENIUM_BROWSER'] || :firefox).to_sym }
browser = Capybara::Selenium::Driver.new(TestApp, options).browser
expect(browser).to be_truthy
expect(true).to eq(true) # rubocop:disable RSpec/ExpectActual
end
end
capybara-3.12.0/spec/fixtures/capybara.csv 0000644 0001750 0001750 00000000026 13411315075 021215 0 ustar utkarsh2102 utkarsh2102 test, mime-type, file
capybara-3.12.0/spec/result_spec.rb 0000644 0001750 0001750 00000014267 13411315075 017736 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
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', minimum: 0 # pass minimum: 0 so lazy evaluation doesn't get triggered yet
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
it 'supports all modes of []' do
expect(result[1].text).to eq 'Beta'
expect(result[0, 2].map(&:text)).to eq %w[Alpha Beta]
expect(result[1..3].map(&:text)).to eq %w[Beta Gamma Delta]
expect(result[-1].text).to eq 'Delta'
expect(result[-2, 3].map(&:text)).to eq %w[Gamma Delta]
expect(result[1..7].map(&:text)).to eq %w[Beta Gamma Delta]
expect(result[1...3].map(&:text)).to eq %w[Beta Gamma]
expect(result[2..-1].map(&:text)).to eq %w[Gamma Delta]
expect(result[2...-1].map(&:text)).to eq %w[Gamma]
eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.5
expect(result[2..].map(&:text)).to eq %w[Gamma Delta]
TEST
end
it 'works with filter blocks' do
result = string.all('//li') { |node| node.text == 'Alpha' }
expect(result.size).to eq 1
end
it 'should catch invalid element errors during filtering' do
allow_any_instance_of(Capybara::Node::Simple).to receive(:text).and_raise(StandardError)
allow_any_instance_of(Capybara::Node::Simple).to receive(:session).and_return(
instance_double('Capybara::Session', driver: instance_double('Capybara::Driver::Base', invalid_element_errors: [StandardError]))
)
result = string.all('//li', text: 'Alpha')
expect(result.size).to eq 0
end
it 'should return non-invalid element errors during filtering' do
allow_any_instance_of(Capybara::Node::Simple).to receive(:text).and_raise(StandardError)
allow_any_instance_of(Capybara::Node::Simple).to receive(:session).and_return(
instance_double('Capybara::Session', driver: instance_double('Capybara::Driver::Base', invalid_element_errors: [ArgumentError]))
)
expect do
string.all('//li', text: 'Alpha').to_a
end.to raise_error(StandardError)
end
# Not a great test but it indirectly tests what is needed
it 'should evaluate filters lazily for idx' do
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
# Not processed until accessed
expect(result.instance_variable_get('@result_cache').size).to be 0
# Only one retrieved when needed
result.first
expect(result.instance_variable_get('@result_cache').size).to be 1
# works for indexed access
result[0]
expect(result.instance_variable_get('@result_cache').size).to be 1
result[2]
expect(result.instance_variable_get('@result_cache').size).to be 3
# All cached when converted to array
result.to_a
expect(result.instance_variable_get('@result_cache').size).to eq 4
end
it 'should evaluate filters lazily for range' do
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
result[0..1]
expect(result.instance_variable_get('@result_cache').size).to be 2
expect(result[0..7].size).to eq 4
expect(result.instance_variable_get('@result_cache').size).to be 4
end
it 'should evaluate filters lazily for idx and length' do
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
result[1, 2]
expect(result.instance_variable_get('@result_cache').size).to be 3
expect(result[2, 5].size).to eq 2
expect(result.instance_variable_get('@result_cache').size).to be 4
end
it 'should only need to evaluate one result for any?' do
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
result.any?
expect(result.instance_variable_get('@result_cache').size).to be 1
end
it 'should evaluate all elements when #to_a called' do
# All cached when converted to array
result.to_a
expect(result.instance_variable_get('@result_cache').size).to eq 4
end
context '#each' do
it 'lazily evaluates' do
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
results = []
result.each do |el|
results << el
expect(result.instance_variable_get('@result_cache').size).to eq results.size
end
expect(results.size).to eq 4
end
context 'without a block' do
it 'returns an iterator' do
expect(result.each).to be_a(Enumerator)
end
it 'lazily evaluates' do
skip 'JRuby has an issue with lazy enumerator evaluation' if RUBY_PLATFORM == 'java'
result.each.with_index do |_el, idx|
expect(result.instance_variable_get('@result_cache').size).to eq(idx + 1) # 0 indexing
end
end
end
end
context 'lazy select' do
it 'is compatible' do
# This test will let us know when JRuby fixes lazy select so we can re-enable it in Result
pending 'JRuby has an issue with lazy enumberator evaluation' if RUBY_PLATFORM == 'java'
eval_count = 0
enum = %w[Text1 Text2 Text3].lazy.select do
eval_count += 1
true
end
expect(eval_count).to eq 0
enum.next
sleep 1
expect(eval_count).to eq 1
end
end
end
capybara-3.12.0/spec/rspec_spec.rb 0000644 0001750 0001750 00000011012 13411315075 017515 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'capybara/rspec' do
context 'Feature', type: :feature do
it 'should include Capybara in rspec' do
visit('/foo')
expect(page.body).to include('Another World')
end
it 'should include RSpec matcher proxies' do
expect(self.class.ancestors).to include Capybara::RSpecMatcherProxies
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
context '#all' do
it 'allows access to the Capybara finder' do
visit('/with_html')
found = all(:css, 'h2') { |element| element[:class] == 'head' }
expect(found.size).to eq(5)
end
it 'allows access to the RSpec matcher' do
visit('/with_html')
strings = %w[test1 test2]
expect(strings).to all(be_a(String))
end
end
context '#within' do
it 'allows access to the Capybara scoper' do
visit('/with_html')
expect do
within(:css, '#does_not_exist') { click_link 'Go to simple' }
end.to raise_error(Capybara::ElementNotFound)
end
it 'allows access to the RSpec matcher' do
visit('/with_html')
# This reads terribly, but must call #within
expect(find(:css, 'span.number').text.to_i).to within(1).of(41)
end
end
end
context 'Type: Other', type: :other do
context 'when RSpec::Matchers is included after Capybara::DSL' do
before do
class DSLMatchersTest
include Capybara::DSL
include RSpec::Matchers
end
@test_class_instance = DSLMatchersTest.new
end
context '#all' do
it 'allows access to the Capybara finder' do
@test_class_instance.visit('/with_html')
expect(@test_class_instance.all(:css, 'h2.head').size).to eq(5)
end
it 'allows access to the RSpec matcher' do
@test_class_instance.visit('/with_html')
strings = %w[test1 test2]
expect(strings).to @test_class_instance.all(be_a(String))
end
end
context '#within' do
it 'allows access to the Capybara scoper' do
@test_class_instance.visit('/with_html')
expect do
@test_class_instance.within(:css, '#does_not_exist') { @test_class_instance.click_link 'Go to simple' }
end.to raise_error(Capybara::ElementNotFound)
end
it 'allows access to the RSpec matcher' do
@test_class_instance.visit('/with_html')
# This reads terribly, but must call #within
expect(@test_class_instance.find(:css, 'span.number').text.to_i).to @test_class_instance.within(1).of(41)
end
end
context 'when `match_when_negated` is not defined in a matcher' do
before do
RSpec::Matchers.define :only_match_matcher do |expected|
match do |actual|
!(actual ^ expected)
end
end
end
it 'can be called with `not_to`' do
# This test is for a bug in jruby where `super` isn't defined correctly - https://github.com/jruby/jruby/issues/4678
# Reported in https://github.com/teamcapybara/capybara/issues/2115
@test_class_instance.instance_eval do
expect do
expect(true).not_to only_match_matcher(false) # rubocop:disable RSpec/ExpectActual
end.not_to raise_error
end
end
end
end
it 'should not include Capybara' do
expect { visit('/') }.to raise_error(NoMethodError)
end
end
end
feature 'Feature DSL' do
scenario 'is pulled in' do
visit('/foo')
expect(page.body).to include('Another World')
end
end
capybara-3.12.0/spec/selector_spec.rb 0000644 0001750 0001750 00000045104 13411315075 020232 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe Capybara do
describe 'Selectors' do
let :string do
Capybara.string <<-STRING
selectors
STRING
end
before do
Capybara.add_selector :custom_selector do
css { |css_class| "div.#{css_class}" }
node_filter(:not_empty, boolean: true, default: true, skip_if: :all) { |node, value| value ^ (node.text == '') }
end
Capybara.add_selector :custom_css_selector do
css(:name, :other_name) do |selector, name: nil, **|
selector ||= ''
selector += "[name='#{name}']" if name
selector
end
expression_filter(:placeholder) do |expr, val|
expr + "[placeholder='#{val}']"
end
expression_filter(:value) do |expr, val|
expr + "[value='#{val}']"
end
expression_filter(:title) do |expr, val|
expr + "[title='#{val}']"
end
end
Capybara.add_selector :custom_xpath_selector do
xpath(:valid1, :valid2) { |selector| selector }
match { |value| value == 'match_me' }
end
end
it 'supports `filter` as an alias for `node_filter`' do
expect do
Capybara.add_selector :filter_alias_selector do
css { |_unused| 'div' }
filter(:something) { |_node, _value| true }
end
end.not_to raise_error
end
describe 'adding a selector' do
it 'can set default visiblity' do
Capybara.add_selector :hidden_field do
visible :hidden
css { |_sel| 'input[type="hidden"]' }
end
expect(string).to have_no_css('input[type="hidden"]')
expect(string).to have_selector(:hidden_field)
end
end
describe 'modify_selector' do
it 'allows modifying a selector' do
el = string.find(:custom_selector, 'aa')
expect(el.tag_name).to eq 'div'
Capybara.modify_selector :custom_selector do
css { |css_class| "h1.#{css_class}" }
end
el = string.find(:custom_selector, 'aa')
expect(el.tag_name).to eq 'h1'
end
it "doesn't change existing filters" do
Capybara.modify_selector :custom_selector do
css { |css_class| "p.#{css_class}" }
end
expect(string).to have_selector(:custom_selector, 'bb', count: 1)
expect(string).to have_selector(:custom_selector, 'bb', not_empty: false, count: 1)
expect(string).to have_selector(:custom_selector, 'bb', not_empty: :all, count: 2)
end
end
describe '::[]' do
it 'can find a selector' do
expect(Capybara::Selector[:field]).not_to be_nil
end
it 'raises if no selector found' do
expect { Capybara::Selector[:no_exist] }.to raise_error(ArgumentError, /Unknown selector type/)
end
end
describe '::for' do
it 'finds selector that matches the locator' do
expect(Capybara::Selector.for('match_me').name).to eq :custom_xpath_selector
end
it 'returns nil if no match' do
expect(Capybara::Selector.for('nothing')).to be nil
end
end
describe 'xpath' do
it 'uses filter names passed in' do
selector = Capybara::Selector.new :test do
xpath(:something, :other) { |_locator| XPath.descendant }
end
expect(selector.expression_filters.keys).to include(:something, :other)
end
it 'gets filter names from block if none passed to xpath method' do
selector = Capybara::Selector.new :test do
xpath { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
end
expect(selector.expression_filters.keys).to include(:valid3, :valid4)
end
it 'ignores block parameters if names passed in' do
selector = Capybara::Selector.new :test do
xpath(:valid1) { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
end
expect(selector.expression_filters.keys).to include(:valid1)
expect(selector.expression_filters.keys).not_to include(:valid3, :valid4)
end
end
describe 'css' do
it "supports filters specified in 'css' definition" do
expect(string).to have_selector(:custom_css_selector, 'input', name: 'form[my_text_input]')
expect(string).to have_no_selector(:custom_css_selector, 'input', name: 'form[not_my_text_input]')
end
it 'supports explicitly defined expression filters' do
expect(string).to have_selector(:custom_css_selector, placeholder: 'my text')
expect(string).to have_no_selector(:custom_css_selector, placeholder: 'not my text')
expect(string).to have_selector(:custom_css_selector, value: 'click me', title: 'submit button')
end
it 'uses filter names passed in' do
selector = Capybara::Selector.new :text do
css(:name, :other_name) { |_locator| '' }
end
expect(selector.expression_filters.keys).to include(:name, :other_name)
end
it 'gets filter names from block if none passed to css method' do
selector = Capybara::Selector.new :test do
css { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
end
expect(selector.expression_filters.keys).to include(:valid3, :valid4)
end
it 'ignores block parameters if names passed in' do
selector = Capybara::Selector.new :test do
css(:valid1) { |_locator, valid3:, valid4: nil| "#{valid3} #{valid4}" }
end
expect(selector.expression_filters.keys).to include(:valid1)
expect(selector.expression_filters.keys).not_to include(:valid3, :valid4)
end
end
describe 'builtin selectors' do
context 'when locator is nil' do
it 'devolves to just finding element types' do
selectors = {
field: ".//*[self::input | self::textarea | self::select][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'hidden')]",
fieldset: './/fieldset',
link: './/a[./@href]',
link_or_button: ".//a[./@href] | .//input[./@type = 'submit' or ./@type = 'reset' or ./@type = 'image' or ./@type = 'button'] | .//button",
fillable_field: ".//*[self::input | self::textarea][not(./@type = 'submit' or ./@type = 'image' or ./@type = 'radio' or ./@type = 'checkbox' or ./@type = 'hidden' or ./@type = 'file')]",
radio_button: ".//input[./@type = 'radio']",
checkbox: ".//input[./@type = 'checkbox']",
select: './/select',
option: './/option',
file_field: ".//input[./@type = 'file']",
table: './/table'
}
selectors.each do |selector, xpath|
results = string.all(selector, nil).to_a.map(&:native)
expect(results.size).to be > 0
expect(results).to eq string.all(:xpath, xpath).to_a.map(&:native)
end
end
end
context 'with :id option' do
it 'works with compound css selectors' do
expect(string.all(:custom_css_selector, 'div, h1', id: 'page').size).to eq 1
expect(string.all(:custom_css_selector, 'h1, div', id: 'page').size).to eq 1
end
it "works with 'special' characters" do
expect(string.find(:custom_css_selector, 'div', id: '#special')[:id]).to eq '#special'
expect(string.find(:custom_css_selector, 'input', id: '2checkbox')[:id]).to eq '2checkbox'
end
it 'accepts XPath expression for xpath based selectors' do
expect(string.find(:custom_xpath_selector, './/div', id: XPath.contains('peci'))[:id]).to eq '#special'
expect(string.find(:custom_xpath_selector, './/input', id: XPath.ends_with('box'))[:id]).to eq '2checkbox'
end
it 'errors XPath expression for CSS based selectors' do
expect { string.find(:custom_css_selector, 'div', id: XPath.contains('peci')) }
.to raise_error(ArgumentError, /not supported/)
end
it 'accepts Regexp for xpath based selectors' do
expect(string.find(:custom_xpath_selector, './/div', id: /peci/)[:id]).to eq '#special'
expect(string.find(:custom_xpath_selector, './/div', id: /pEcI/i)[:id]).to eq '#special'
end
it 'accepts Regexp for css based selectors' do
expect(string.find(:custom_css_selector, 'div', id: /sp.*al/)[:id]).to eq '#special'
end
end
context 'with :class option' do
it 'works with compound css selectors' do
expect(string.all(:custom_css_selector, 'div, h1', class: 'aa').size).to eq 2
expect(string.all(:custom_css_selector, 'h1, div', class: 'aa').size).to eq 2
end
it 'handles negated classes' do
expect(string.all(:custom_css_selector, 'div, p', class: ['bb', '!cc']).size).to eq 2
expect(string.all(:custom_css_selector, 'div, p', class: ['!cc', '!dd', 'bb']).size).to eq 1
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['bb', '!cc']).size).to eq 2
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!cc', '!dd', 'bb']).size).to eq 1
end
it 'handles classes starting with ! by requiring negated negated first' do
expect(string.all(:custom_css_selector, 'div, p', class: ['!!!mine']).size).to eq 1
expect(string.all(:custom_xpath_selector, XPath.descendant(:div, :p), class: ['!!!mine']).size).to eq 1
end
it "works with 'special' characters" do
expect(string.find(:custom_css_selector, 'input', class: '.special')[:id]).to eq 'file'
expect(string.find(:custom_css_selector, 'input', class: '2checkbox')[:id]).to eq '2checkbox'
end
it 'accepts XPath expression for xpath based selectors' do
expect(string.find(:custom_xpath_selector, './/div', class: XPath.contains('dom wor'))[:id]).to eq 'random_words'
expect(string.find(:custom_xpath_selector, './/div', class: XPath.ends_with('words'))[:id]).to eq 'random_words'
end
it 'errors XPath expression for CSS based selectors' do
expect { string.find(:custom_css_selector, 'div', class: XPath.contains('random')) }
.to raise_error(ArgumentError, /not supported/)
end
it 'accepts Regexp for XPath based selectors' do
expect(string.find(:custom_xpath_selector, './/div', class: /dom wor/)[:id]).to eq 'random_words'
expect(string.find(:custom_xpath_selector, './/div', class: /dOm WoR/i)[:id]).to eq 'random_words'
end
it 'accepts Regexp for CSS base selectors' do
expect(string.find(:custom_css_selector, 'div', class: /random/)[:id]).to eq 'random_words'
end
end
# :css, :xpath, :id, :field, :fieldset, :link, :button, :link_or_button, :fillable_field, :radio_button, :checkbox, :select,
# :option, :file_field, :label, :table, :frame
describe ':css selector' do
it 'finds by CSS locator' do
expect(string.find(:css, 'input#my_text_input')[:name]).to eq 'form[my_text_input]'
end
end
describe ':xpath selector' do
it 'finds by XPath locator' do
expect(string.find(:xpath, './/input[@id="my_text_input"]')[:name]).to eq 'form[my_text_input]'
end
end
describe ':id selector' do
it 'finds by locator' do
expect(string.find(:id, 'my_text_input')[:name]).to eq 'form[my_text_input]'
expect(string.find(:id, /my_text_input/)[:name]).to eq 'form[my_text_input]'
expect(string.find(:id, /_text_/)[:name]).to eq 'form[my_text_input]'
expect(string.find(:id, /i[nmo]/)[:name]).to eq 'form[my_text_input]'
end
end
describe ':field selector' do
it 'finds by locator' do
expect(string.find(:field, 'My Text Input')[:id]).to eq 'my_text_input'
expect(string.find(:field, 'my_text_input')[:id]).to eq 'my_text_input'
expect(string.find(:field, 'form[my_text_input]')[:id]).to eq 'my_text_input'
end
it 'finds by id string' do
expect(string.find(:field, id: 'my_text_input')[:name]).to eq 'form[my_text_input]'
end
it 'finds by id regexp' do
expect(string.find(:field, id: /my_text_inp/)[:name]).to eq 'form[my_text_input]'
end
it 'finds by name' do
expect(string.find(:field, name: 'form[my_text_input]')[:id]).to eq 'my_text_input'
end
it 'finds by placeholder' do
expect(string.find(:field, placeholder: 'my text')[:id]).to eq 'my_text_input'
end
it 'finds by type' do
expect(string.find(:field, type: 'file')[:id]).to eq 'file'
expect(string.find(:field, type: 'select')[:id]).to eq 'select'
end
end
describe ':option selector' do
it 'finds disabled options' do
expect(string.find(:option, disabled: true).value).to eq 'b'
end
it 'finds selected options' do
expect(string.find(:option, selected: true).value).to eq 'c'
end
it 'finds not selected and not disabled options' do
expect(string.find(:option, disabled: false, selected: false).value).to eq 'a'
end
end
describe ':button selector' do
it 'finds by value' do
expect(string.find(:button, 'click me').value).to eq 'click me'
end
it 'finds by title' do
expect(string.find(:button, 'submit button').value).to eq 'click me'
end
it 'includes non-matching parameters in failure message' do
expect { string.find(:button, 'click me', title: 'click me') }.to raise_error(/with title click me/)
end
end
describe ':element selector' do
it 'finds by any attributes' do
expect(string.find(:element, 'input', type: 'submit').value).to eq 'click me'
end
it 'supports regexp matching' do
expect(string.find(:element, 'input', type: /sub/).value).to eq 'click me'
expect(string.find(:element, 'input', title: /sub\w.*button/).value).to eq 'click me'
expect(string.find(:element, 'input', title: /sub.* b.*ton/).value).to eq 'click me'
expect(string.find(:element, 'input', title: /sub.*mit.*/).value).to eq 'click me'
expect(string.find(:element, 'input', title: /^submit button$/).value).to eq 'click me'
expect(string.find(:element, 'input', title: /^(?:submit|other) button$/).value).to eq 'click me'
expect(string.find(:element, 'input', title: /SuB.*mIt/i).value).to eq 'click me'
expect(string.find(:element, 'input', title: /^Su.*Bm.*It/i).value).to eq 'click me'
expect(string.find(:element, 'input', title: /^Ot.*he.*r b.*\d/i).value).to eq "don't click me"
end
it 'still works with system keys' do
expect { string.all(:element, 'input', type: 'submit', count: 1) }.not_to raise_error
end
it 'works without element type' do
expect(string.find(:element, type: 'submit').value).to eq 'click me'
end
it 'validates attribute presence when true' do
expect(string.find(:element, name: true)[:id]).to eq 'my_text_input'
end
it 'validates attribute absence when false' do
expect(string.find(:element, 'option', disabled: false, selected: false).value).to eq 'a'
end
it 'includes wildcarded keys in description' do
expect { string.find(:element, 'input', not_there: 'bad', presence: true, absence: false, count: 1) }
.to(raise_error do |e|
expect(e).to be_a(Capybara::ElementNotFound)
expect(e.message).to include 'not_there => bad'
expect(e.message).to include 'with presence attribute'
expect(e.message).to include 'without absence attribute'
expect(e.message).not_to include 'count 1'
end)
end
it 'accepts XPath::Expression' do
expect(string.find(:element, 'input', type: XPath.starts_with('subm')).value).to eq 'click me'
expect(string.find(:element, 'input', type: XPath.ends_with('ext'))[:type]).to eq 'text'
expect(string.find(:element, 'input', type: XPath.contains('ckb'))[:type]).to eq 'checkbox'
expect(string.find(:element, 'input', title: XPath.contains_word('submit'))[:type]).to eq 'submit'
expect(string.find(:element, 'input', title: XPath.contains_word('button 1'))[:type]).to eq 'button'
end
end
describe ':link_or_button selector' do
around(:all) do |example|
Capybara.modify_selector(:link_or_button) do
expression_filter(:random) { |xpath, _| xpath } # do nothing filter
end
example.run
Capybara::Selector[:link_or_button].expression_filters.delete(:random)
end
context 'when modified' do
it 'should still work' do
filter = Capybara::Selector[:link_or_button].expression_filters[:random]
allow(filter).to receive(:apply_filter).and_call_original
expect(string.find(:link_or_button, 'click me', random: 'blah').value).to eq 'click me'
expect(filter).to have_received(:apply_filter).with(anything, :random, 'blah', anything)
end
end
end
end
end
end
capybara-3.12.0/spec/selenium_spec_firefox_remote.rb 0000644 0001750 0001750 00000006774 13411315075 023342 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'selenium-webdriver'
require 'shared_selenium_session'
require 'rspec/shared_spec_matchers'
def selenium_host
ENV.fetch('SELENIUM_HOST', '0.0.0.0')
end
def selenium_port
ENV.fetch('SELENIUM_PORT', 4445)
end
def ensure_selenium_running!
timer = Capybara::Helpers.timer(expire_in: 20)
begin
TCPSocket.open(selenium_host, selenium_port)
rescue StandardError
if timer.expired?
raise 'Selenium is not running. ' \
"You can run a selenium server easily with: \n" \
' $ docker-compose up -d selenium_firefox'
else
puts 'Waiting for Selenium docker instance...'
sleep 1
retry
end
end
end
Capybara.register_driver :selenium_firefox_remote do |app|
ensure_selenium_running!
url = "http://#{selenium_host}:#{selenium_port}/wd/hub"
browser_options = ::Selenium::WebDriver::Firefox::Options.new
Capybara::Selenium::Driver.new app,
browser: :remote,
desired_capabilities: :firefox,
options: browser_options,
url: url
end
FIREFOX_REMOTE_DRIVER = :selenium_firefox_remote
module TestSessions
RemoteFirefox = Capybara::Session.new(FIREFOX_REMOTE_DRIVER, TestApp)
end
TestSessions::RemoteFirefox.driver.browser.file_detector = lambda do |args|
# args => ["/path/to/file"]
str = args.first.to_s
str if File.exist?(str)
end
skipped_tests = %i[response_headers status_code trigger download]
Capybara::SpecHelper.run_specs TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|
case example.metadata[:full_description]
when 'Capybara::Session selenium_firefox_remote node #click should allow multiple modifiers'
skip "Firefox doesn't generate an event for shift+control+click" if firefox_gte?(62, @session)
when 'Capybara::Session selenium_firefox_remote #accept_prompt should accept the prompt with a blank response when there is a default'
pending "Geckodriver doesn't set a blank response in FF < 63 - https://bugzilla.mozilla.org/show_bug.cgi?id=1486485" if firefox_lt?(63, @session)
when 'Capybara::Session selenium_firefox_remote #attach_file with multipart form should fire change once for each set of files uploaded'
pending 'Gekcodriver appends files so we have to first call clear for multiple files which creates an extra change ' \
'if files are already set'
when 'Capybara::Session selenium_firefox_remote #attach_file with multipart form should fire change once when uploading multiple files from empty'
pending "FF < 62 doesn't support setting all files at once" if firefox_lt?(62, @session)
when 'Capybara::Session selenium_firefox_remote #reset_session! removes ALL cookies'
pending "Geckodriver doesn't provide a way to remove cookies outside the current domain"
when /#accept_confirm should work with nested modals$/
# skip because this is timing based and hence flaky when set to pending
skip 'Broken in FF 63 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if firefox_gte?(63, @session)
end
end
RSpec.describe 'Capybara::Session with remote firefox' do
include Capybara::SpecHelper
include_examples 'Capybara::Session', TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVER
include_examples Capybara::RSpecMatchers, TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVER
it 'is considered to be firefox' do
expect(session.driver.browser.browser).to eq :firefox
end
end
capybara-3.12.0/spec/server_spec.rb 0000644 0001750 0001750 00000017115 13411315075 017721 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
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
# TODO: travis with jruby in container mode has an issue with this test
skip 'This platform has an issue with this test' if (ENV['TRAVIS'] && (RUBY_ENGINE == 'jruby')) || Gem.win_platform?
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, port: 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 support SSL' do
begin
key = File.join(Dir.pwd, 'spec', 'fixtures', 'key.pem')
cert = File.join(Dir.pwd, 'spec', 'fixtures', 'certificate.pem')
Capybara.server = :puma, { Host: "ssl://#{Capybara.server_host}?key=#{key}&cert=#{cert}" }
app = proc { |_env| [200, {}, ['Hello SSL Server!']] }
server = Capybara::Server.new(app).boot
expect do
Net::HTTP.start(server.host, server.port) { |http| http.get('/__idntify__') }
end.to raise_error(EOFError)
res = Net::HTTP.start(server.host, server.port, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |https|
https.get('/')
end
expect(res.body).to include('Hello SSL Server!')
ensure
Capybara.server = :default
end
end
context 'When Capybara.reuse_server is true' do
before do
@old_reuse_server = Capybara.reuse_server
Capybara.reuse_server = true
end
after do
Capybara.reuse_server = @old_reuse_server
end
it 'should use the existing server if it already running' do
@app = proc { |_env| [200, {}, ['Hello Server!']] }
@server1 = Capybara::Server.new(@app).boot
@server2 = Capybara::Server.new(@app).boot
res = Net::HTTP.start(@server1.host, @server1.port) { |http| http.get('/') }
expect(res.body).to include('Hello Server')
res = Net::HTTP.start(@server2.host, @server2.port) { |http| http.get('/') }
expect(res.body).to include('Hello Server')
expect(@server1.port).to eq(@server2.port)
end
it 'detects and waits for all reused server sessions pending requests' do
done = 0
app = proc do |env|
request = Rack::Request.new(env)
sleep request.params['wait_time'].to_f
done += 1
[200, {}, ['Hello Server!']]
end
server1 = Capybara::Server.new(app).boot
server2 = Capybara::Server.new(app).boot
expect do
start_request(server1, 1.0)
start_request(server2, 3.0)
server1.wait_for_pending_requests
end.to change { done }.from(0).to(2)
expect(server2.send(:pending_requests?)).to eq(false)
end
end
context 'When Capybara.reuse_server is false' do
before do
@old_reuse_server = Capybara.reuse_server
Capybara.reuse_server = false
end
after do
Capybara.reuse_server = @old_reuse_server
end
it 'should not reuse an already running server' do
@app = proc { |_env| [200, {}, ['Hello Server!']] }
@server1 = Capybara::Server.new(@app).boot
@server2 = Capybara::Server.new(@app).boot
res = Net::HTTP.start(@server1.host, @server1.port) { |http| http.get('/') }
expect(res.body).to include('Hello Server')
res = Net::HTTP.start(@server2.host, @server2.port) { |http| http.get('/') }
expect(res.body).to include('Hello Server')
expect(@server1.port).not_to eq(@server2.port)
end
it 'detects and waits for only one sessions pending requests' do
done = 0
app = proc do |env|
request = Rack::Request.new(env)
sleep request.params['wait_time'].to_f
done += 1
[200, {}, ['Hello Server!']]
end
server1 = Capybara::Server.new(app).boot
server2 = Capybara::Server.new(app).boot
expect do
start_request(server1, 1.0)
start_request(server2, 3.0)
server1.wait_for_pending_requests
end.to change { done }.from(0).to(1)
expect(server2.send(:pending_requests?)).to eq(true)
expect do
server2.wait_for_pending_requests
end.to change { done }.from(1).to(2)
end
end
it 'should raise server errors when the server errors before the timeout' do
begin
Capybara.register_server :kaboom do
sleep 0.1
raise 'kaboom'
end
Capybara.server = :kaboom
expect do
Capybara::Server.new(proc { |e| }).boot
end.to raise_error(RuntimeError, 'kaboom')
ensure
Capybara.server = :default
end
end
it 'is not #responsive? when Net::HTTP raises a SystemCallError' do
app = -> { [200, {}, ['Hello, world']] }
server = Capybara::Server.new(app)
allow(Net::HTTP).to receive(:start).and_raise(SystemCallError.allocate)
expect(server.responsive?).to eq false
end
[EOFError, Net::ReadTimeout].each do |err|
it "should attempt an HTTPS connection if HTTP connection returns #{err}" do
app = -> { [200, {}, ['Hello, world']] }
ordered_errors = [Errno::ECONNREFUSED, err]
allow(Net::HTTP).to receive(:start).with(anything, anything, hash_excluding(:use_ssl)) do
raise ordered_errors.shift
end
response = Net::HTTPSuccess.allocate
allow(response).to receive(:body).and_return app.object_id.to_s
allow(Net::HTTP).to receive(:start).with(anything, anything, hash_including(use_ssl: true)).and_return(response).once
Capybara::Server.new(app).boot
expect(Net::HTTP).to have_received(:start).exactly(3).times
end
end
def start_request(server, wait_time)
# Start request, but don't wait for it to finish
socket = TCPSocket.new(server.host, server.port)
socket.write "GET /?wait_time=#{wait_time} HTTP/1.0\r\n\r\n"
sleep 0.1
socket.close
sleep 0.1
end
end
capybara-3.12.0/spec/basic_node_spec.rb 0000644 0001750 0001750 00000011040 13411315075 020470 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
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 value' 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-3.12.0/spec/rspec/ 0000755 0001750 0001750 00000000000 13411315075 016163 5 ustar utkarsh2102 utkarsh2102 capybara-3.12.0/spec/rspec/shared_spec_matchers.rb 0000644 0001750 0001750 00000077117 13411315075 022673 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'capybara/dsl'
require 'capybara/rspec/matchers'
require 'benchmark'
# rubocop:disable RSpec/ExpectActual
RSpec.shared_examples Capybara::RSpecMatchers do |session, _mode|
include Capybara::DSL
include Capybara::RSpecMatchers
describe 'have_css matcher' do
it 'gives proper description' do
expect(have_css('h1').description).to eq('have visible 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 visible 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 visible 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 visible 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 visible 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 visible css "h1"/)
end
end
it 'supports compounding' do
expect('
').to have_no_css('h2').or have_css('h1')
end
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 visible css "h1"/)
end
end
end
end
describe 'have_xpath matcher' do
it 'gives proper description' do
expect(have_xpath('//h1').description).to eq("have visible 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 visible xpath "//h1"})
end
end
it 'supports compounding' do
expect('
').to have_no_xpath('//h4').or have_xpath('//h4')
end
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 visible 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 visible 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(/expected not to find visible 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 visible 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(/expected not to find visible css "h1" with text "test"/)
end
end
end
it 'supports compounding' do
expect('
').to have_no_selector('//h3').and have_selector('//h1')
end
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 }
after { Capybara.default_selector = :xpath }
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
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_no_content('XYZ').and have_content('Or')
end
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 Integer 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 }
after { Capybara.default_selector = :xpath }
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
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
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 visible link "Just a link"')
end
it 'passes if there is such a link' do
expect(html).to have_link('Just a link')
end
it 'fails if there is no such link' 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')
expect(html).to have_no_link('Not a link').and have_link('Another link')
end
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 do
@session = session
@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: 2)
end
end
it "doesn't wait if wait time is less than timeout" do
@session.click_link('Change title')
using_wait_time 3 do
expect(@session).not_to have_title('changed title', wait: 0)
end
end
end
end
it 'supports compounding' do
expect('I compound').to have_title('I dont compound').or have_title('I compound')
end
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 do
@session = session
@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: 2)
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
end
describe 'have_button matcher' do
let(:html) { '' }
it 'gives proper description' do
expect(have_button('A button').description).to eq('have visible 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
end
describe 'have_field matcher' do
let(:html) { '' }
it 'gives proper description' do
expect(have_field('Text field').description).to eq('have visible field "Text field" that is not disabled')
end
it 'gives proper description for a given value' do
expect(have_field('Text field', with: 'some value').description).to eq('have visible field "Text field" that is not disabled 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 visible 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
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 visible field "it is checked" that is checked and not disabled')
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 visible 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 visible 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
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 visible field "unchecked field" that is not checked and not disabled')
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 visible 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 visible 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
end
describe 'have_select matcher' do
let(:html) { '' }
it 'gives proper description' do
expect(have_select('Select Box').description).to eq('have visible select box "Select Box" that is not disabled')
end
it 'gives proper description for a given selected value' do
expect(have_select('Select Box', selected: 'some value').description).to eq('have visible select box "Select Box" that is not disabled 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
end
describe 'have_table matcher' do
let(:html) { '
Lovely table
' }
it 'gives proper description' do
expect(have_table('Lovely table').description).to eq('have visible table "Lovely table"')
expect(have_table('Lovely table', caption: 'my caption').description).to eq('have visible table "Lovely table" with caption "my caption"')
end
it 'gives proper description when :visible option passed' do
expect(have_table('Lovely table', visible: true).description).to eq('have visible table "Lovely table"')
expect(have_table('Lovely table', visible: :hidden).description).to eq('have non-visible table "Lovely table"')
expect(have_table('Lovely table', visible: :all).description).to eq('have table "Lovely table"')
expect(have_table('Lovely table', visible: false).description).to eq('have table "Lovely table"')
end
it 'passes if there is such a table' do
expect(html).to have_table('Lovely table')
end
it 'fails if there is no such table' 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
end
context 'compounding timing' do
before do
@session = session
@session.visit('/with_js')
@el = @session.find(:css, '#reload-me')
end
context '#and' do
it "should run 'concurrently'" do
Capybara.using_wait_time(2) do
matcher = have_text('this is not there').and have_text('neither is this')
expect(Benchmark.realtime do
expect do
expect(@el).to matcher
end.to raise_error RSpec::Expectations::ExpectationNotMetError
end).to be_between(2, 3)
end
end
it "should run 'concurrently' and retry" do
@session.click_link('reload-link')
@session.using_wait_time(2) do
expect(Benchmark.realtime do
expect do
expect(@el).to have_text('waiting to be reloaded').and(have_text('has been reloaded'))
end.to raise_error RSpec::Expectations::ExpectationNotMetError, /expected to find text "waiting to be reloaded" in "has been reloaded"/
end).to be_between(2, 3)
end
end
it 'should ignore :wait options' do
@session.using_wait_time(2) do
matcher = have_text('this is not there', wait: 5).and have_text('neither is this', wait: 6)
expect(Benchmark.realtime do
expect do
expect(@el).to matcher
end.to raise_error RSpec::Expectations::ExpectationNotMetError
end).to be_between(2, 3)
end
end
it 'should work on the session' do
@session.using_wait_time(2) do
@session.click_link('reload-link')
expect(@session).to have_selector(:css, 'h1', text: 'FooBar').and have_text('has been reloaded')
end
end
end
context '#and_then' do
it 'should run sequentially' do
@session.click_link('reload-link')
expect(@el).to have_text('waiting to be reloaded').and_then have_text('has been reloaded')
end
end
context '#or' do
it "should run 'concurrently'" do
@session.using_wait_time(3) do
expect(Benchmark.realtime do
expect(@el).to have_text('has been reloaded').or have_text('waiting to be reloaded')
end).to be < 1
end
end
it 'should retry' do
@session.using_wait_time(3) do
expect(Benchmark.realtime do
expect do
expect(@el).to have_text('has been reloaded').or have_text('random stuff')
end.to raise_error RSpec::Expectations::ExpectationNotMetError
end).to be > 3
end
end
it 'should ignore :wait options' do
@session.using_wait_time(2) do
expect(Benchmark.realtime do
expect do
expect(@el).to have_text('this is not there', wait: 10).or have_text('neither is this', wait: 15)
end.to raise_error RSpec::Expectations::ExpectationNotMetError
end).to be_between(2, 3)
end
end
it 'should work on the session' do
@session.using_wait_time(2) do
@session.click_link('reload-link')
expect(@session).to have_selector(:css, 'h1', text: 'Not on the page').or have_text('has been reloaded')
end
end
end
end
end
# rubocop:enable RSpec/ExpectActual
capybara-3.12.0/spec/rspec/scenarios_spec.rb 0000644 0001750 0001750 00000001025 13411315075 021506 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'capybara/rspec'
RSpec.configuration.before(:each, file_path: './spec/rspec/scenarios_spec.rb') do
@in_filtered_hook = true
end
feature 'if fscenario aliases focused tag then' do
fscenario 'scenario should have focused meta tag' do |example| # rubocop:disable RSpec/Focus
expect(example.metadata[:focus]).to eq true
end
end
feature 'if xscenario aliases to pending then' do
xscenario "this test should be 'temporarily disabled with xscenario'" do
end
end
capybara-3.12.0/spec/rspec/views_spec.rb 0000644 0001750 0001750 00000000577 13411315075 020670 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'capybara/rspec', type: :view do
it 'allows matchers to be used on strings' do
html = %(
Test header
)
expect(html).to have_css('h1', text: 'Test header')
end
it "doesn't include RSpecMatcherProxies" do
expect(self.class.ancestors).not_to include(Capybara::RSpecMatcherProxies)
end
end
capybara-3.12.0/spec/rspec/features_spec.rb 0000644 0001750 0001750 00000004707 13411315075 021350 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
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
scenario 'includes Capybara' do
visit('/')
expect(page).to have_content('Hello world!')
end
scenario 'preserves description' do |ex|
expect(ex.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).not_to respond_to(:feature)
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 |ex|
expect(ex.metadata[:capybara_feature]).to be_truthy
end
scenario 'have a type of :feature' do |ex|
expect(ex.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 "Capybara's feature DSL with driver", driver: :culerity do
scenario 'switches driver' do
expect(Capybara.current_driver).to eq(:culerity)
end
end
# rubocop:disable RSpec/RepeatedExample
xfeature 'if xfeature aliases to pending then' do
scenario "this should be 'temporarily disabled with xfeature'" do
# dummy
end
scenario "this also should be 'temporarily disabled with xfeature'" do
# dummy
end
end
ffeature 'if ffeature aliases focused tag then' do # rubocop:disable RSpec/Focus
scenario 'scenario inside this feature has metatag focus tag' do |example|
expect(example.metadata[:focus]).to eq true
end
scenario 'other scenarios also has metatag focus tag ' do |example|
expect(example.metadata[:focus]).to eq true
end
end
# rubocop:enable RSpec/RepeatedExample
capybara-3.12.0/spec/regexp_dissassembler_spec.rb 0000644 0001750 0001750 00000014413 13411315075 022623 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe Capybara::Selector::RegexpDisassembler do
it 'handles strings' do
verify_strings(
/abcdef/ => %w[abcdef],
/abc def/ => ['abc def']
)
end
it 'handles escaped characters' do
verify_strings(
/abc\\def/ => %w[abc\def],
/abc\.def/ => %w[abc.def],
/\nabc/ => ["\nabc"],
%r{abc/} => %w[abc/],
/ab\++cd/ => %w[ab+ cd]
)
end
it 'handles wildcards' do
verify_strings(
/abc.*def/ => %w[abc def],
/.*def/ => %w[def],
/abc./ => %w[abc],
/abc.*/ => %w[abc],
/abc.def/ => %w[abc def],
/abc.def.ghi/ => %w[abc def ghi],
/abc.abcd.abcde/ => %w[abcde],
/.*/ => []
)
end
it 'ignores optional characters for substrings' do
{
/abc*def/ => %w[ab def],
/abc*/ => %w[ab],
/c*/ => [],
/abc?def/ => %w[ab def],
/abc?/ => %w[ab],
/abc?def?/ => %w[ab de],
/abc?def?g/ => %w[ab de g],
/d?/ => []
}.each do |regexp, expected|
expect(Capybara::Selector::RegexpDisassembler.new(regexp).substrings).to eq expected
end
end
it 'handles optional characters for #alternated_substrings' do
verify_alternated_strings(
/abc*def/ => [%w[ab def]],
/abc*/ => [%w[ab]],
/c*/ => [],
/abc?def/ => [%w[abdef], %w[abcdef]],
/abc?/ => [%w[ab]],
/abc?def?/ => [%w[abde], %w[abcde]],
/abc?def?g/ => [%w[abdeg], %w[abdefg], %w[abcdeg], %w[abcdefg]],
/d?/ => []
)
end
it 'handles character classes' do
verify_strings(
/abc[a-z]/ => %w[abc],
/abc[a-z]def[0-9]g/ => %w[abc def g],
/[0-9]abc/ => %w[abc],
/[0-9]+/ => [],
/abc[0-9&&[^7]]/ => %w[abc]
)
end
it 'handles posix bracket expressions' do
verify_strings(
/abc[[:alpha:]]/ => %w[abc],
/[[:digit:]]abc/ => %w[abc],
/abc[[:print:]]def/ => %w[abc def]
)
end
it 'handles repitition' do
verify_strings(
/abc{3}/ => %w[abccc],
/abc{3}d/ => %w[abcccd],
/abc{0}/ => %w[ab],
/abc{,2}/ => %w[ab],
/abc{2,}/ => %w[abcc],
/def{1,5}/ => %w[def],
/abc+def/ => %w[abc def],
/ab(cde){,4}/ => %w[ab],
/(ab){,2}cd/ => %w[cd],
/(abc){2,3}/ => %w[abcabc],
/(abc){3}/ => %w[abcabcabc],
/ab{2,3}cd/ => %w[abb cd],
/(ab){2,3}cd/ => %w[abab cd]
)
end
it 'handles non-greedy repetition' do
verify_strings(
/abc.*?/ => %w[abc],
/abc+?/ => %w[abc],
/abc*?cde/ => %w[ab cde],
/(abc)+?def/ => %w[abc def],
/ab(cde)*?fg/ => %w[ab fg]
)
end
it 'ignores alternation for #substrings' do
{
/abc|def/ => [],
/ab(?:c|d)/ => %w[ab],
/ab(c|d|e)fg/ => %w[ab fg],
/ab?(c|d)fg/ => %w[a fg],
/ab(c|d)ef/ => %w[ab ef],
/ab(cd?|ef)g/ => %w[ab g],
/ab(cd|ef*)g/ => %w[ab g],
/ab|cd*/ => [],
/cd(?:ef|gh)|xyz/ => [],
/(cd(?:ef|gh)|xyz)/ => [],
/cd(ef|gh)+/ => %w[cd],
/cd(ef|gh)?/ => %w[cd],
/cd(ef|gh)?ij/ => %w[cd ij],
/cd(ef|gh)+ij/ => %w[cd ij],
/cd(ef|gh){2}ij/ => %w[cd ij],
/(cd(ef|g*))/ => %w[cd],
/ab(cd){0,2}ef/ => %w[ab ef],
/ab(cd){0,1}ef/ => %w[ab ef],
/ab(cd|cd)ef/ => %w[ab ef],
/ab(cd|cd)?ef/ => %w[ab ef],
/ab\\?cd/ => %w[ab cd]
}.each do |regexp, expected|
expect(Capybara::Selector::RegexpDisassembler.new(regexp).substrings).to eq expected
end
end
it 'handles alternation for #alternated_substrings' do
verify_alternated_strings(
/abc|def/ => [%w[abc], %w[def]],
/ab(?:c|d)/ => [%w[abc], %w[abd]],
/ab(c|d|e)fg/ => [%w[abcfg], %w[abdfg], %w[abefg]],
/ab?(c|d)fg/ => [%w[acfg], %w[adfg], %w[abcfg], %w[abdfg]],
/ab(c|d)ef/ => [%w[abcef], %w[abdef]],
/ab(cd?|ef)g/ => [%w[abcg], %w[abcdg], %w[abefg]],
/ab(cd|ef*)g/ => [%w[abcdg], %w[abe g]],
/ab|cd*/ => [%w[ab], %w[c]],
/cd(?:ef|gh)|xyz/ => [%w[cdef], %w[cdgh], %w[xyz]],
/(cd(?:ef|gh)|xyz)/ => [%w[cdef], %w[cdgh], %w[xyz]],
/cd(ef|gh)+/ => [%w[cdef], %w[cdgh]],
/cd(ef|gh)?/ => [%w[cd]],
/cd(ef|gh)?ij/ => [%w[cdij], %w[cdefij], %w[cdghij]],
/cd(ef|gh)+ij/ => [%w[cdef ij], %w[cdgh ij]],
/cd(ef|gh){2}ij/ => [%w[cdefefij], %w[cdefghij], %w[cdghefij], %w[cdghghij]],
/(cd(ef|g*))/ => [%w[cd]],
/a|b*/ => [],
/ab(?:c|d?)/ => [%w[ab]],
/ab(c|d)|a*/ => [],
/(abc)?(d|e)/ => [%w[d], %w[e]],
/(abc*de)?(d|e)/ => [%w[d], %w[e]],
/(abc*de)?(d|e?)/ => [],
/(abc)?(d|e?)/ => [],
/ab(cd){0,2}ef/ => [%w[ab ef]],
/ab(cd){0,1}ef/ => [%w[abef], %w[abcdef]],
/ab(cd|cd)ef/ => [%w[abcdef]],
/ab(cd|cd)?ef/ => [%w[abef], %w[abcdef]],
/ab\\?cd/ => [%w[abcd], %w[ab\cd]]
)
end
it 'handles grouping' do
verify_strings(
/(abc)/ => %w[abc],
/(abc)?/ => [],
/ab(cde)/ => %w[abcde],
/(abc)de/ => %w[abcde],
/ab(cde)fg/ => %w[abcdefg],
/ab(?cd)ef/ => %w[abcdef],
/gh(?>ij)kl/ => %w[ghijkl],
/m(n.*p)q/ => %w[mn pq],
/(?:ab(cd)*){2,3}/ => %w[ab],
/(ab(cd){3})?/ => [],
/(ab(cd)+){2}/ => %w[abcd]
)
end
it 'handles meta characters' do
verify_strings(
/abc\d/ => %w[abc],
/abc\wdef/ => %w[abc def],
/\habc/ => %w[abc]
)
end
it 'handles character properties' do
verify_strings(
/ab\p{Alpha}cd/ => %w[ab cd],
/ab\p{Blank}/ => %w[ab],
/\p{Digit}cd/ => %w[cd]
)
end
it 'handles backreferences' do
verify_strings(
/a(?abc).\k.+/ => %w[aabc]
)
end
it 'handles subexpressions' do
verify_strings(
/\A(?a\g*b)+\z/ => %w[a b]
)
end
it 'handles anchors' do
verify_strings(
/^abc/ => %w[abc],
/def$/ => %w[def],
/^abc$/ => %w[abc]
)
end
def verify_strings(hsh)
hsh.each do |regexp, expected|
expect(Capybara::Selector::RegexpDisassembler.new(regexp).substrings).to eq expected
end
verify_alternated_strings(hsh, wrap: true)
end
def verify_alternated_strings(hsh, wrap: false)
hsh.each do |regexp, expected|
expected = [expected] if wrap && (expected != [])
expect(Capybara::Selector::RegexpDisassembler.new(regexp).alternated_substrings).to eq expected
end
end
end
capybara-3.12.0/spec/rspec_matchers_spec.rb 0000644 0001750 0001750 00000004041 13411315075 021407 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Capybara RSpec Matchers', type: :feature do
context 'after called on session' do
it 'HaveSelector should allow getting a description of the matcher' do
visit('/with_html')
matcher = have_selector(:css, 'h2.head', minimum: 3)
expect(page).to matcher
expect { matcher.description }.not_to raise_error
end
it 'HaveText should allow getting a description' do
visit('/with_html')
matcher = have_text('Lorem')
expect(page).to matcher
expect { matcher.description }.not_to raise_error
end
it 'should produce the same error for .to have_no_xxx and .not_to have_xxx' do
visit('/with_html')
not_to_msg = error_msg_for { expect(page).not_to have_selector(:css, '#referrer') }
have_no_msg = error_msg_for { expect(page).to have_no_selector(:css, '#referrer') }
expect(not_to_msg).to eq have_no_msg
not_to_msg = error_msg_for { expect(page).not_to have_text('This is a test') }
have_no_msg = error_msg_for { expect(page).to have_no_text('This is a test') }
expect(not_to_msg).to eq have_no_msg
end
end
context 'after called on element' do
it 'HaveSelector should allow getting a description' do
visit('/with_html')
el = find(:css, '#first')
matcher = have_selector(:css, 'a#foo')
expect(el).to matcher
expect { matcher.description }.not_to raise_error
end
it 'MatchSelector should allow getting a description' do
visit('/with_html')
el = find(:css, '#first')
matcher = match_selector(:css, '#first')
expect(el).to matcher
expect { matcher.description }.not_to raise_error
end
it 'HaveText should allow getting a description' do
visit('/with_html')
el = find(:css, '#first')
matcher = have_text('Lorem')
expect(el).to matcher
expect { matcher.description }.not_to raise_error
end
end
def error_msg_for(&block)
expect(&block).to(raise_error { |e| return e.message })
end
end
capybara-3.12.0/spec/selenium_spec_edge.rb 0000644 0001750 0001750 00000002107 13411315075 021213 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'selenium-webdriver'
require 'shared_selenium_session'
require 'rspec/shared_spec_matchers'
Capybara.register_driver :selenium_edge do |app|
# ::Selenium::WebDriver.logger.level = "debug"
Capybara::Selenium::Driver.new(app, browser: :edge)
end
module TestSessions
SeleniumEdge = Capybara::Session.new(:selenium_edge, TestApp)
end
skipped_tests = %i[response_headers status_code trigger modals]
$stdout.puts `#{Selenium::WebDriver::Edge.driver_path} --version` if ENV['CI']
Capybara::SpecHelper.run_specs TestSessions::SeleniumEdge, 'selenium', capybara_skip: skipped_tests do |example|
case example.metadata[:description]
when /#refresh it reposts$/
skip 'Edge insists on prompting without providing a way to suppress'
end
end
RSpec.describe 'Capybara::Session with Edge', capybara_skip: skipped_tests do
include Capybara::SpecHelper
include_examples 'Capybara::Session', TestSessions::SeleniumEdge, :selenium_edge
include_examples Capybara::RSpecMatchers, TestSessions::SeleniumEdge, :selenium_edge
end
capybara-3.12.0/spec/per_session_config_spec.rb 0000644 0001750 0001750 00000005247 13411315075 022274 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'capybara/dsl'
RSpec.describe Capybara::SessionConfig do
describe 'threadsafe' do
it 'defaults to global session options' do
Capybara.threadsafe = true
session = Capybara::Session.new(:rack_test, TestApp)
%i[default_host app_host always_include_port run_server
default_selector default_max_wait_time ignore_hidden_elements
automatic_reload match exact raise_server_errors visible_text_only
automatic_label_click enable_aria_label save_path
asset_host].each do |m|
expect(session.config.public_send(m)).to eq Capybara.public_send(m)
end
end
it "doesn't change global session when changed" do
Capybara.threadsafe = true
host = 'http://my.example.com'
session = Capybara::Session.new(:rack_test, TestApp) do |config|
config.default_host = host
config.automatic_label_click = !config.automatic_label_click
config.server_errors << ArgumentError
end
expect(Capybara.default_host).not_to eq host
expect(session.config.default_host).to eq host
expect(Capybara.automatic_label_click).not_to eq session.config.automatic_label_click
expect(Capybara.server_errors).not_to eq session.config.server_errors
end
it "doesn't allow session configuration block when false" do
Capybara.threadsafe = false
expect do
Capybara::Session.new(:rack_test, TestApp) { |config| }
end.to raise_error 'A configuration block is only accepted when Capybara.threadsafe == true'
end
it "doesn't allow session config when false" do
Capybara.threadsafe = false
session = Capybara::Session.new(:rack_test, TestApp)
expect { session.config.default_selector = :title }.to raise_error(/Per session settings are only supported when Capybara.threadsafe == true/)
expect do
session.configure do |config|
config.exact = true
end
end.to raise_error(/Session configuration is only supported when Capybara.threadsafe == true/)
end
it 'uses the config from the session' do
Capybara.threadsafe = true
session = Capybara::Session.new(:rack_test, TestApp) do |config|
config.default_selector = :link
end
session.visit('/with_html')
expect(session.find('foo').tag_name).to eq 'a'
end
it "won't change threadsafe once a session is created" do
Capybara.threadsafe = true
Capybara.threadsafe = false
Capybara::Session.new(:rack_test, TestApp)
expect { Capybara.threadsafe = true }.to raise_error(/Threadsafe setting cannot be changed once a session is created/)
end
end
end
capybara-3.12.0/spec/css_splitter_spec.rb 0000644 0001750 0001750 00000002117 13411315075 021125 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe Capybara::Selector::CSS::Splitter do
let :splitter do
::Capybara::Selector::CSS::Splitter.new
end
context 'split not needed' do
it 'normal CSS selector' do
css = 'div[id="abc"]'
expect(splitter.split(css)).to eq [css]
end
it 'comma in strings' do
css = 'div[id="a,bc"]'
expect(splitter.split(css)).to eq [css]
end
it 'comma in pseudo-selector' do
css = 'div.class1:not(.class1, .class2)'
expect(splitter.split(css)).to eq [css]
end
end
context 'split needed' do
it 'root level comma' do
css = 'div.class1, span, p.class2'
expect(splitter.split(css)).to eq ['div.class1', 'span', 'p.class2']
end
it 'root level comma when quotes and pseudo selectors' do
css = 'div.class1[id="abc\\"def,ghi"]:not(.class3, .class4), span[id=\'a"c\\\'de\'], section, #abc\\,def'
expect(splitter.split(css)).to eq ['div.class1[id="abc\\"def,ghi"]:not(.class3, .class4)', 'span[id=\'a"c\\\'de\']', 'section', '#abc\\,def']
end
end
end
capybara-3.12.0/spec/selenium_spec_chrome_remote.rb 0000644 0001750 0001750 00000005312 13411315075 023140 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'selenium-webdriver'
require 'shared_selenium_session'
require 'rspec/shared_spec_matchers'
def selenium_host
ENV.fetch('SELENIUM_HOST', '0.0.0.0')
end
def selenium_port
ENV.fetch('SELENIUM_PORT', 4444)
end
def ensure_selenium_running!
timer = Capybara::Helpers.timer(expire_in: 20)
begin
TCPSocket.open(selenium_host, selenium_port)
rescue StandardError
if timer.expired?
raise 'Selenium is not running. ' \
"You can run a selenium server easily with: \n" \
' $ docker-compose up -d selenium_chrome'
else
puts 'Waiting for Selenium docker instance...'
sleep 1
retry
end
end
end
def selenium_gte?(version)
defined?(Selenium::WebDriver::VERSION) && (Selenium::WebDriver::VERSION.to_f >= version)
end
Capybara.register_driver :selenium_chrome_remote do |app|
ensure_selenium_running!
url = "http://#{selenium_host}:#{selenium_port}/wd/hub"
browser_options = ::Selenium::WebDriver::Chrome::Options.new
Capybara::Selenium::Driver.new app,
browser: :remote,
desired_capabilities: :chrome,
options: browser_options,
url: url
end
CHROME_REMOTE_DRIVER = :selenium_chrome_remote
module TestSessions
Chrome = Capybara::Session.new(CHROME_REMOTE_DRIVER, TestApp)
end
TestSessions::Chrome.driver.browser.file_detector = lambda do |args|
# args => ["/path/to/file"]
str = args.first.to_s
str if File.exist?(str)
end
skipped_tests = %i[response_headers status_code trigger download]
Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|
case example.metadata[:full_description]
when 'Capybara::Session selenium_chrome_remote #attach_file with multipart form should not break when using HTML5 multiple file input uploading multiple files',
'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once for each set of files uploaded',
'Capybara::Session selenium_chrome_remote #attach_file with multipart form should fire change once when uploading multiple files from empty'
pending "Selenium with Remote Chrome doesn't support multiple file upload" unless selenium_gte?(3.14)
end
end
RSpec.describe 'Capybara::Session with remote Chrome' do
include Capybara::SpecHelper
include_examples 'Capybara::Session', TestSessions::Chrome, CHROME_REMOTE_DRIVER
include_examples Capybara::RSpecMatchers, TestSessions::Chrome, CHROME_REMOTE_DRIVER
it 'is considered to be chrome' do
expect(session.driver.browser.browser).to eq :chrome
end
end
capybara-3.12.0/spec/css_builder_spec.rb 0000644 0001750 0001750 00000007065 13411315075 020714 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe Capybara::Selector::CSSBuilder do
let :builder do
::Capybara::Selector::CSSBuilder.new(@css)
end
context 'add_attribute_conditions' do
it 'adds a single string condition to a single selector' do
@css = 'div'
selector = builder.add_attribute_conditions(random: 'abc')
expect(selector).to eq %(div[random='abc'])
end
it 'adds multiple string conditions to a single selector' do
@css = 'div'
selector = builder.add_attribute_conditions(random: 'abc', other: 'def')
expect(selector).to eq %(div[random='abc'][other='def'])
end
it 'adds a single string condition to a multiple selector' do
@css = 'div, ul'
selector = builder.add_attribute_conditions(random: 'abc')
expect(selector).to eq %(div[random='abc'], ul[random='abc'])
end
it 'adds multiple string conditions to a multiple selector' do
@css = 'div, ul'
selector = builder.add_attribute_conditions(random: 'abc', other: 'def')
expect(selector).to eq %(div[random='abc'][other='def'], ul[random='abc'][other='def'])
end
it 'adds simple regexp conditions to a single selector' do
@css = 'div'
selector = builder.add_attribute_conditions(random: /abc/, other: /def/)
expect(selector).to eq %(div[random*='abc'][other*='def'])
end
it 'adds wildcard regexp conditions to a single selector' do
@css = 'div'
selector = builder.add_attribute_conditions(random: /abc.*def/, other: /def.*ghi/)
expect(selector).to eq %(div[random*='abc'][random*='def'][other*='def'][other*='ghi'])
end
it 'adds alternated regexp conditions to a single selector' do
@css = 'div'
selector = builder.add_attribute_conditions(random: /abc|def/, other: /def|ghi/)
expect(selector).to eq %(div[random*='abc'][other*='def'], div[random*='abc'][other*='ghi'], div[random*='def'][other*='def'], div[random*='def'][other*='ghi'])
end
it 'adds alternated regexp conditions to a multiple selector' do
@css = 'div,ul'
selector = builder.add_attribute_conditions(other: /def.*ghi|jkl/)
expect(selector).to eq %(div[other*='def'][other*='ghi'], div[other*='jkl'], ul[other*='def'][other*='ghi'], ul[other*='jkl'])
end
it "returns original selector when regexp can't be substringed" do
@css = 'div'
selector = builder.add_attribute_conditions(other: /.+/)
expect(selector).to eq 'div'
end
context ':class' do
it 'handles string with CSS .' do
@css = 'a'
selector = builder.add_attribute_conditions(class: 'my_class')
expect(selector).to eq 'a.my_class'
end
it 'handles negated string with CSS .' do
@css = 'a'
selector = builder.add_attribute_conditions(class: '!my_class')
expect(selector).to eq 'a:not(.my_class)'
end
it 'handles array of string with CSS .' do
@css = 'a'
selector = builder.add_attribute_conditions(class: %w[my_class my_other_class])
expect(selector).to eq 'a.my_class.my_other_class'
end
it 'handles array of string with CSS . when negated included' do
@css = 'a'
selector = builder.add_attribute_conditions(class: %w[my_class !my_other_class])
expect(selector).to eq 'a.my_class:not(.my_other_class)'
end
end
context ':id' do
it 'handles string with CSS #' do
@css = 'ul'
selector = builder.add_attribute_conditions(id: 'my_id')
expect(selector).to eq 'ul#my_id'
end
end
end
end
capybara-3.12.0/spec/shared_selenium_session.rb 0000644 0001750 0001750 00000046206 13411315075 022316 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'selenium-webdriver'
RSpec.shared_examples 'Capybara::Session' do |session, mode|
let(:session) { session }
context 'with selenium driver' do
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(mode)
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__), '..'))
@env = { 'SELENIUM_BROWSER' => session.driver.options[:browser].to_s }
end
after do
Dir.chdir(@current_dir)
end
it 'should have return code 1 when running selenium_driver_rspec_failure.rb' do
skip 'only setup for local non-headless' if headless_or_remote?
system(@env, 'rspec spec/fixtures/selenium_driver_rspec_failure.rb', out: File::NULL, err: File::NULL)
expect($CHILD_STATUS.exitstatus).to eq(1)
end
it 'should have return code 0 when running selenium_driver_rspec_success.rb' do
skip 'only setup for local non-headless' if headless_or_remote?
system(@env, 'rspec spec/fixtures/selenium_driver_rspec_success.rb', out: File::NULL, err: File::NULL)
expect($CHILD_STATUS.exitstatus).to eq(0)
end
end
describe '#accept_alert', requires: [:modals] 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(session.driver.send(:modal_error))
end
it 'can be called before visiting' do
session.accept_alert 'Initial alert' do
session.visit('/initial_alert')
end
expect(session).to have_text('Initial alert page')
end
end
context '#fill_in_with empty string and no options' do
it 'should trigger change when clearing a field' do
session.visit('/with_js')
session.fill_in('with_change_event', with: '')
# 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
context '#fill_in with { :clear => :backspace } fill_option', requires: [:js] do
before do
# Firefox has an issue with change events if the main window doesn't think it's focused
session.execute_script('window.focus()')
end
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 fill in a field, replacing an existing value, even with caret position' do
session.visit('/form')
session.find(:css, '#form_first_name').execute_script <<-JS
this.focus();
this.setSelectionRange(0, 0);
JS
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 fill in if the option is set via global option' do
Capybara.default_set_options = { clear: :backspace }
session.visit('/form')
session.fill_in('form_first_name', with: 'Thomas')
expect(session.find(:fillable_field, 'form_first_name').value).to eq('Thomas')
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, '#with_focus_event').click
expect(session.find(:css, '.change_event_triggered', match: :one, wait: 5)).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, '#with_focus_event').click
expect(session).to have_selector(:css, '.change_event_triggered', match: :one, wait: 5)
end
it 'should trigger input event field_value.length times' 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_xpath('//p[@class="input_event_triggered"]', count: 13)
end
end
context '#fill_in with { clear: :none } fill_options' do
it 'should append to content in a field' do
session.visit('/form')
session.fill_in('form_first_name',
with: 'Harry',
fill_options: { clear: :none })
expect(session.find(:fillable_field, 'form_first_name').value).to eq('JohnHarry')
end
end
context '#fill_in with Date' do
before do
session.visit('/form')
session.find(:css, '#form_date').execute_script <<-JS
window.capybara_formDateFiredEvents = [];
var fd = this;
['focus', 'input', 'change'].forEach(function(eventType) {
fd.addEventListener(eventType, function() { window.capybara_formDateFiredEvents.push(eventType); });
});
JS
# work around weird FF issue where it would create an extra focus issue in some cases
session.find(:css, 'body').click
end
it 'should generate standard events on changing value' do
pending "IE 11 doesn't support date input type" if ie?(session)
session.fill_in('form_date', with: Date.today)
expect(session.evaluate_script('window.capybara_formDateFiredEvents')).to eq %w[focus input change]
end
it 'should not generate input and change events if the value is not changed' do
pending "IE 11 doesn't support date input type" if ie?(session)
session.fill_in('form_date', with: Date.today)
session.fill_in('form_date', with: Date.today)
# Chrome adds an extra focus for some reason - ok for now
expect(session.evaluate_script('window.capybara_formDateFiredEvents')).to eq(%w[focus input change])
end
end
context '#fill_in with { clear: Array } fill_options' do
it 'should pass the array through to the element' do
# this is mainly for use with [[:control, 'a'], :backspace] - however since that is platform dependant I'm testing with something less useful
session.visit('/form')
session.fill_in('form_first_name',
with: 'Harry',
fill_options: { clear: [[:shift, 'abc'], :backspace] })
expect(session.find(:fillable_field, 'form_first_name').value).to eq('JohnABHarry')
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
it 'handles namespaces in xhtml' do
pending "IE 11 doesn't handle all XPath querys (namespace-uri, etc)" if ie?(session)
session.visit '/with_namespace'
rect = session.find(:css, 'div svg rect:first-of-type')
expect(rect.path).to eq("/HTML/BODY/DIV/./*[((local-name(.) = 'svg') and (namespace-uri(.) = 'http://www.w3.org/2000/svg'))]/./*[((local-name(.) = 'rect') and (namespace-uri(.) = 'http://www.w3.org/2000/svg'))][1]")
expect(session.find(:xpath, rect.path)).to eq rect
end
it 'handles default namespaces in html5' do
pending "IE 11 doesn't handle all XPath querys (namespace-uri, etc)" if ie?(session)
session.visit '/with_html5_svg'
rect = session.find(:css, 'div svg rect:first-of-type')
expect(rect.path).to eq("/HTML/BODY/DIV/./*[((local-name(.) = 'svg') and (namespace-uri(.) = 'http://www.w3.org/2000/svg'))]/./*[((local-name(.) = 'rect') and (namespace-uri(.) = 'http://www.w3.org/2000/svg'))][1]")
expect(session.find(:xpath, rect.path)).to eq rect
end
it 'handles case sensitive element names' do
pending "IE 11 doesn't handle all XPath querys (namespace-uri, etc)" if ie?(session)
session.visit '/with_namespace'
els = session.all(:css, 'div *', visible: :all)
expect { els.map(&:path) }.not_to raise_error
lg = session.find(:css, 'div linearGradient', visible: :all)
expect(session.find(:xpath, lg.path, visible: :all)).to eq lg
end
end
describe 'all with disappearing elements' do
it 'ignores stale elements in results' do
session.visit('/path')
elements = session.all(:link) { |_node| raise Selenium::WebDriver::Error::StaleElementReferenceError }
expect(elements.size).to eq 0
end
end
describe '#evaluate_script' do
it 'can return an element' do
session.visit('/form')
element = session.evaluate_script("document.getElementById('form_title')")
expect(element).to eq session.find(:id, 'form_title')
end
it 'can return arrays of nested elements' do
session.visit('/form')
elements = session.evaluate_script('document.querySelectorAll("#form_city option")')
expect(elements).to all(be_instance_of Capybara::Node::Element)
expect(elements).to eq session.find(:css, '#form_city').all(:css, 'option').to_a
end
it 'can return hashes with elements' do
session.visit('/form')
result = session.evaluate_script("{ a: document.getElementById('form_title'), b: {c: document.querySelectorAll('#form_city option')}}")
expect(result).to eq(
'a' => session.find(:id, 'form_title'),
'b' => {
'c' => session.find(:css, '#form_city').all(:css, 'option').to_a
}
)
end
describe '#evaluate_async_script' do
it 'will timeout if the script takes too long' do
session.visit('/with_js')
expect do
session.using_wait_time(1) do
session.evaluate_async_script('var cb = arguments[0]; setTimeout(function(){ cb(null) }, 3000)')
end
end.to raise_error Selenium::WebDriver::Error::ScriptTimeoutError
end
end
end
describe 'Element#inspect' do
it 'outputs obsolete elements' do
session.visit('/form')
el = session.find(:button, 'Click me!').click
expect(session).to have_no_button('Click me!')
allow(el).to receive(:synchronize)
expect(el.inspect).to eq 'Obsolete #'
expect(el).not_to have_received(:synchronize)
end
end
describe 'Element#click' do
it 'should handle fixed headers/footers' do
session.visit('/with_fixed_header_footer')
# session.click_link('Go to root')
session.find(:link, 'Go to root').click
expect(session).to have_current_path('/')
end
end
describe 'Element#drag_to' do
before do
skip "Firefox < 62 doesn't support a DataTransfer constuctor" if firefox_lt?(62.0, session)
skip "IE doesn't support a DataTransfer constuctor" if ie?(session)
end
it 'should HTML5 drag and drop an object' do
session.visit('/with_js')
element = session.find('//div[@id="drag_html5"]')
target = session.find('//div[@id="drop_html5"]')
element.drag_to(target)
expect(session).to have_xpath('//div[contains(., "HTML5 Dropped drag_html5")]')
end
it 'should not HTML5 drag and drop on a non HTML5 drop element' do
session.visit('/with_js')
element = session.find('//div[@id="drag_html5"]')
target = session.find('//div[@id="drop_html5"]')
target.execute_script("$(this).removeClass('drop');")
element.drag_to(target)
sleep 1
expect(session).not_to have_xpath('//div[contains(., "HTML5 Dropped drag_html5")]')
end
it 'should HTML5 drag and drop when scrolling needed' do
session.visit('/with_js')
element = session.find('//div[@id="drag_html5_scroll"]')
target = session.find('//div[@id="drop_html5_scroll"]')
element.drag_to(target)
expect(session).to have_xpath('//div[contains(., "HTML5 Dropped drag_html5_scroll")]')
end
it 'should drag HTML5 default draggable elements' do
session.visit('/with_js')
link = session.find_link('drag_link_html5')
target = session.find(:id, 'drop_html5')
link.drag_to target
expect(session).to have_xpath('//div[contains(., "HTML5 Dropped")]')
end
end
describe 'Capybara#Node#attach_file' do
it 'can attach a directory' do
pending "Geckodriver doesn't support uploading a directory" if firefox?(session)
pending "Selenium remote doesn't support transferring a directory" if remote?(session)
pending "Headless Chrome doesn't support directory upload - https://bugs.chromium.org/p/chromedriver/issues/detail?id=2521&q=directory%20upload&colspec=ID%20Status%20Pri%20Owner%20Summary" if chrome?(session) && ENV['HEADLESS']
session.visit('/form')
@test_file_dir = File.expand_path('./fixtures', File.dirname(__FILE__))
session.attach_file('Directory Upload', @test_file_dir)
session.click_button('Upload Multiple')
expect(session.body).to include('5 | ') # number of files
end
end
context 'Windows' do
it "can't close the primary window" do
expect do
session.current_window.close
end.to raise_error(ArgumentError, 'Not allowed to close the primary window')
end
end
describe 'Capybara#disable_animation' do
context 'when set to `true`' do
before(:context) do # rubocop:disable RSpec/BeforeAfterAll
# NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
# it doesn't affect any of these tests because the settings are applied per-session
Capybara.disable_animation = true
@animation_session = Capybara::Session.new(session.mode, TestApp.new)
end
after(:context) do # rubocop:disable RSpec/BeforeAfterAll
@animation_session = nil
end
it 'should disable CSS transitions' do
@animation_session.visit('with_animation')
@animation_session.click_link('transition me away')
expect(@animation_session).to have_no_link('transition me away', wait: 0.5)
end
it 'should disable CSS animations' do
@animation_session.visit('with_animation')
@animation_session.click_link('animate me away')
expect(@animation_session).to have_no_link('animate me away', wait: 0.5)
end
end
context 'if we pass in css that matches elements' do
before(:context) do # rubocop:disable RSpec/BeforeAfterAll
# NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
# it doesn't affect any of these tests because the settings are applied per-session
Capybara.disable_animation = '#with_animation a'
@animation_session_with_matching_css = Capybara::Session.new(session.mode, TestApp.new)
end
after(:context) do # rubocop:disable RSpec/BeforeAfterAll
@animation_session_with_matching_css = nil
end
it 'should disable CSS transitions' do
@animation_session_with_matching_css.visit('with_animation')
@animation_session_with_matching_css.click_link('transition me away')
expect(@animation_session_with_matching_css).to have_no_link('transition me away', wait: 0.5)
end
it 'should disable CSS animations' do
@animation_session_with_matching_css.visit('with_animation')
@animation_session_with_matching_css.click_link('animate me away')
expect(@animation_session_with_matching_css).to have_no_link('animate me away', wait: 0.5)
end
end
context 'if we pass in css that does not match elements' do
before(:context) do # rubocop:disable RSpec/BeforeAfterAll
# NOTE: Although Capybara.SpecHelper.reset! sets Capybara.disable_animation to false,
# it doesn't affect any of these tests because the settings are applied per-session
Capybara.disable_animation = '.this-class-matches-nothing'
@animation_session_without_matching_css = Capybara::Session.new(session.mode, TestApp.new)
end
after(:context) do # rubocop:disable RSpec/BeforeAfterAll
@animation_session_without_matching_css = nil
end
it 'should not disable CSS transitions' do
@animation_session_without_matching_css.visit('with_animation')
@animation_session_without_matching_css.click_link('transition me away')
sleep 0.5 # Wait long enough for click to have been processed
expect(@animation_session_without_matching_css).to have_link('transition me away', wait: false)
expect(@animation_session_without_matching_css).to have_no_link('transition me away', wait: 5)
end
it 'should not disable CSS animations' do
@animation_session_without_matching_css.visit('with_animation')
@animation_session_without_matching_css.click_link('animate me away')
sleep 0.5 # Wait long enough for click to have been processed
expect(@animation_session_without_matching_css).to have_link('animate me away', wait: false)
expect(@animation_session_without_matching_css).to have_no_link('animate me away', wait: 5)
end
end
end
describe ':element selector' do
it 'can find html5 svg elements' do
session.visit('with_html5_svg')
expect(session).to have_selector(:element, :svg)
expect(session).to have_selector(:element, :rect, visible: true)
expect(session).to have_selector(:element, :circle)
expect(session).to have_selector(:element, :linearGradient, visible: :all)
end
it 'can query attributes with strange characters' do
session.visit('/form')
expect(session).to have_selector(:element, "{custom}": true)
expect(session).to have_selector(:element, "{custom}": 'abcdef')
end
end
end
def headless_or_remote?
!ENV['HEADLESS'].nil? || session.driver.options[:browser] == :remote
end
end
capybara-3.12.0/spec/session_spec.rb 0000644 0001750 0001750 00000003730 13411315075 020074 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe Capybara::Session do
context '#new' do
it 'should raise an error if passed non-existent driver' do
expect do
Capybara::Session.new(:quox, TestApp).driver
end.to raise_error(Capybara::DriverNotFoundError)
end
it 'verifies a passed app is a rack app' do
expect do
Capybara::Session.new(:unknown, random: 'hash')
end.to raise_error TypeError, 'The second parameter to Session::new should be a rack app if passed.'
end
end
context 'current_driver' do
around do |example|
orig_driver = Capybara.current_driver
example.run
Capybara.current_driver = orig_driver
end
it 'is global when threadsafe false' do
Capybara.threadsafe = false
Capybara.current_driver = :selenium
thread = Thread.new do
Capybara.current_driver = :random
end
thread.join
expect(Capybara.current_driver).to eq :random
end
it 'is thread specific threadsafe true' do
Capybara.threadsafe = true
Capybara.current_driver = :selenium
thread = Thread.new do
Capybara.current_driver = :random
end
thread.join
expect(Capybara.current_driver).to eq :selenium
end
end
context 'session_name' do
around do |example|
orig_name = Capybara.session_name
example.run
Capybara.session_name = orig_name
end
it 'is global when threadsafe false' do
Capybara.threadsafe = false
Capybara.session_name = 'sess1'
thread = Thread.new do
Capybara.session_name = 'sess2'
end
thread.join
expect(Capybara.session_name).to eq 'sess2'
end
it 'is thread specific when threadsafe true' do
Capybara.threadsafe = true
Capybara.session_name = 'sess1'
thread = Thread.new do
Capybara.session_name = 'sess2'
end
thread.join
expect(Capybara.session_name).to eq 'sess1'
end
end
end
capybara-3.12.0/spec/rack_test_spec.rb 0000644 0001750 0001750 00000020641 13411315075 020370 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
nokogumbo_required = begin
require 'nokogumbo'
true
rescue LoadError
false
end
module TestSessions
RackTest = Capybara::Session.new(:rack_test, TestApp)
end
skipped_tests = %i[
js
modals
screenshot
frames
windows
send_keys
server
hover
about_scheme
download
css
]
Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip: skipped_tests do |example|
case example.metadata[:full_description]
when /has_css\? should support case insensitive :class and :id options/
pending "Nokogiri doesn't support case insensitive CSS attribute matchers"
end
end
RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
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
after do
@session.driver.options[:respect_data_method] = false
end
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
end
describe '#fill_in' do
it 'should warn that :fill_options are not supported' do
allow_any_instance_of(Capybara::RackTest::Node).to receive(:warn)
@session.visit '/with_html'
field = @session.fill_in 'test_field', with: 'not_monkey', fill_options: { random: true }
expect(@session).to have_field('test_field', with: 'not_monkey')
expect(field.base).to have_received(:warn).with("Options passed to Node#set but the RackTest driver doesn't support any - ignoring")
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
it 'should not submit an obsolete mime type' do
@test_jpg_file_path = File.expand_path('fixtures/capybara.csv', File.dirname(__FILE__))
@session.visit('/form')
@session.attach_file 'form_document', @test_jpg_file_path
@session.click_button('Upload Single')
expect(@session).to have_content('Content-type: text/csv')
end
end
describe '#click' do
context 'on a label' do
it 'should toggle the associated checkbox' do
@session.visit('/form')
expect(@session).to have_unchecked_field('form_pets_cat')
@session.find(:label, 'Cat').click
expect(@session).to have_checked_field('form_pets_cat')
@session.find(:label, 'Cat').click
expect(@session).to have_unchecked_field('form_pets_cat')
@session.find(:label, 'McLaren').click
expect(@session).to have_checked_field('form_cars_mclaren', visible: :hidden)
end
it 'should toggle the associated radio' do
@session.visit('/form')
expect(@session).to have_unchecked_field('gender_male')
@session.find(:label, 'Male').click
expect(@session).to have_checked_field('gender_male')
@session.find(:label, 'Female').click
expect(@session).to have_unchecked_field('gender_male')
end
end
end
describe '#text' do
it 'should return original text content for textareas' do
@session.visit('/with_html')
@session.find_field('normal', type: 'textarea', with: 'banana').set('hello')
normal = @session.find(:css, '#normal')
expect(normal.value).to eq 'hello'
expect(normal.text).to eq 'banana'
end
end
describe '#style' do
it 'should raise an error' do
@session.visit('/with_html')
el = @session.find(:css, '#first')
expect { el.style('display') }.to raise_error NotImplementedError, /not process CSS/
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
RSpec.describe 'Capybara::String' do
it 'should use gumbo' do
skip 'Only valid if gumbo is included' unless nokogumbo_required
allow(Nokogiri).to receive(:HTML5).and_call_original
Capybara.string('')
expect(Nokogiri).to have_received(:HTML5)
end
end
module CSSHandlerIncludeTester
def dont_extend_css_handler
raise 'should never be called'
end
end
RSpec.describe Capybara::RackTest::CSSHandlers do
include CSSHandlerIncludeTester
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-3.12.0/spec/dsl_spec.rb 0000644 0001750 0001750 00000021132 13411315075 017167 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'capybara/dsl'
class TestClass
include Capybara::DSL
end
Capybara::SpecHelper.run_specs TestClass.new, 'DSL', capybara_skip: %i[
js modals screenshot frames windows send_keys server hover about_scheme psc download css driver
] do |example|
case example.metadata[:full_description]
when /has_css\? should support case insensitive :class and :id options/
pending "Nokogiri doesn't support case insensitive CSS attribute matchers"
end
end
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) # rubocop:disable RSpec/ExpectInHook
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 # rubocop:disable Lint/RescueException,Lint/HandleExceptions
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 # rubocop:disable Lint/RescueException,Lint/HandleExceptions
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
it 'should allow a session object' do
original_session = Capybara.current_session
new_session = Capybara::Session.new(:rack_test, proc {})
Capybara.using_session(new_session) do
expect(Capybara.current_session).to eq(new_session)
end
expect(Capybara.current_session).to eq(original_session)
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
allow(Capybara).to receive(:using_session)
@session.using_session(:name)
expect(Capybara).to have_received(:using_session).with(:name)
end
it "should provide a 'using_wait_time' shortcut" do
allow(Capybara).to receive(:using_wait_time)
@session.using_wait_time(6)
expect(Capybara).to have_received(:using_wait_time).with(6)
end
end
end
capybara-3.12.0/spec/xpath_builder_spec.rb 0000644 0001750 0001750 00000007721 13411315075 021247 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe Capybara::Selector::XPathBuilder do
let :builder do
::Capybara::Selector::XPathBuilder.new(@xpath)
end
context 'add_attribute_conditions' do
it 'adds a single string condition to a single selector' do
@xpath = './/div'
selector = builder.add_attribute_conditions(random: 'abc')
expect(selector).to eq %((.//div)[(./@random = 'abc')])
end
it 'adds multiple string conditions to a single selector' do
@xpath = './/div'
selector = builder.add_attribute_conditions(random: 'abc', other: 'def')
expect(selector).to eq %(((.//div)[(./@random = 'abc')])[(./@other = 'def')])
end
it 'adds a single string condition to a multiple selector' do
@xpath = XPath.descendant(:div, :ul)
selector = builder.add_attribute_conditions(random: 'abc')
expect(selector.to_s).to eq @xpath[XPath.attr(:random) == 'abc'].to_s
end
it 'adds multiple string conditions to a multiple selector' do
@xpath = XPath.descendant(:div, :ul)
selector = builder.add_attribute_conditions(random: 'abc', other: 'def')
expect(selector.to_s).to eq %(.//*[self::div | self::ul][(./@random = 'abc')][(./@other = 'def')])
end
it 'adds simple regexp conditions to a single selector' do
@xpath = XPath.descendant(:div)
selector = builder.add_attribute_conditions(random: /abc/, other: /def/)
expect(selector.to_s).to eq %(.//div[./@random[contains(., 'abc')]][./@other[contains(., 'def')]])
end
it 'adds wildcard regexp conditions to a single selector' do
@xpath = './/div'
selector = builder.add_attribute_conditions(random: /abc.*def/, other: /def.*ghi/)
expect(selector).to eq %(((.//div)[./@random[(contains(., 'abc') and contains(., 'def'))]])[./@other[(contains(., 'def') and contains(., 'ghi'))]])
end
it 'adds alternated regexp conditions to a single selector' do
@xpath = XPath.descendant(:div)
selector = builder.add_attribute_conditions(random: /abc|def/, other: /def|ghi/)
expect(selector.to_s).to eq %(.//div[./@random[(contains(., 'abc') or contains(., 'def'))]][./@other[(contains(., 'def') or contains(., 'ghi'))]])
end
it 'adds alternated regexp conditions to a multiple selector' do
@xpath = XPath.descendant(:div, :ul)
selector = builder.add_attribute_conditions(other: /def.*ghi|jkl/)
expect(selector.to_s).to eq %(.//*[self::div | self::ul][./@other[((contains(., 'def') and contains(., 'ghi')) or contains(., 'jkl'))]])
end
it "returns original selector when regexp can't be substringed" do
@xpath = './/div'
selector = builder.add_attribute_conditions(other: /.+/)
expect(selector).to eq '(.//div)[./@other]'
end
context ':class' do
it 'handles string' do
@xpath = './/a'
selector = builder.add_attribute_conditions(class: 'my_class')
expect(selector).to eq %((.//a)[contains(concat(' ', normalize-space(./@class), ' '), ' my_class ')])
end
it 'handles negated strings' do
@xpath = XPath.descendant(:a)
selector = builder.add_attribute_conditions(class: '!my_class')
expect(selector.to_s).to eq @xpath[!XPath.attr(:class).contains_word('my_class')].to_s
end
it 'handles array of strings' do
@xpath = './/a'
selector = builder.add_attribute_conditions(class: %w[my_class my_other_class])
expect(selector).to eq %((.//a)[(contains(concat(' ', normalize-space(./@class), ' '), ' my_class ') and contains(concat(' ', normalize-space(./@class), ' '), ' my_other_class '))])
end
it 'handles array of string when negated included' do
@xpath = XPath.descendant(:a)
selector = builder.add_attribute_conditions(class: %w[my_class !my_other_class])
expect(selector.to_s).to eq @xpath[XPath.attr(:class).contains_word('my_class') & !XPath.attr(:class).contains_word('my_other_class')].to_s
end
end
end
end
capybara-3.12.0/spec/capybara_spec.rb 0000644 0001750 0001750 00000005657 13411315075 020205 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
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
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 '.register_server' do
it 'should add a new server' do
Capybara.register_server :blob do |_app, _port, _host|
# do nothing
end
expect(Capybara.servers).to have_key(:blob)
end
end
describe '.server' do
after do
Capybara.server = :default
end
it 'should default to a proc that calls run_default_server' do
mock_app = Object.new
allow(Capybara).to receive(:run_default_server).and_return(true)
Capybara.server.call(mock_app, 8000)
expect(Capybara).to have_received(:run_default_server).with(mock_app, 8000)
end
it 'should return a custom server proc' do
server = ->(_app, _port) {}
Capybara.register_server :custom, &server
Capybara.server = :custom
expect(Capybara.server).to eq(server)
end
it 'should have :webrick registered' do
expect(Capybara.servers[:webrick]).not_to be_nil
end
it 'should have :puma registered' do
expect(Capybara.servers[:puma]).not_to be_nil
end
end
describe 'server=' do
after do
Capybara.server = :default
end
it 'accepts a proc' do
server = ->(_app, _port) {}
Capybara.server = server
expect(Capybara.server).to eq server
end
end
describe 'app_host' do
after do
Capybara.app_host = nil
end
it 'should warn if not a valid URL' do
expect { Capybara.app_host = 'www.example.com' }.to raise_error(ArgumentError, /Capybara\.app_host should be set to a url/)
end
it 'should not warn if a valid URL' do
expect { Capybara.app_host = 'http://www.example.com' }.not_to raise_error
end
it 'should not warn if nil' do
expect { Capybara.app_host = nil }.not_to raise_error
end
end
describe 'default_host' do
around do |test|
old_default = Capybara.default_host
test.run
Capybara.default_host = old_default
end
it 'should raise if not a valid URL' do
expect { Capybara.default_host = 'www.example.com' }.to raise_error(ArgumentError, /Capybara\.default_host should be set to a url/)
end
it 'should not warn if a valid URL' do
expect { Capybara.default_host = 'http://www.example.com' }.not_to raise_error
end
end
end
capybara-3.12.0/spec/minitest_spec.rb 0000644 0001750 0001750 00000010213 13411315075 020237 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'capybara/minitest'
class MinitestTest < Minitest::Test
include Capybara::DSL
include Capybara::Minitest::Assertions
def setup
visit('/form')
end
def teardown
Capybara.reset_sessions!
end
def test_assert_text
assert_text('Form')
assert_no_text('Not on the page')
refute_text('Also Not on the page')
end
def test_assert_title
visit('/with_title')
assert_title('Test Title')
assert_no_title('Not the title')
refute_title('Not the title')
end
def test_assert_current_path
assert_current_path('/form')
assert_no_current_path('/not_form')
refute_current_path('/not_form')
end
def test_assert_xpath
assert_xpath('.//select[@id="form_title"]')
assert_xpath('.//select', count: 1) { |el| el[:id] == 'form_title' }
assert_no_xpath('.//select[@id="not_form_title"]')
assert_no_xpath('.//select') { |el| el[:id] == 'not_form_title' }
refute_xpath('.//select[@id="not_form_title"]')
end
def test_assert_css
assert_css('select#form_title')
assert_no_css('select#not_form_title')
end
def test_assert_selector
assert_selector(:css, 'select#form_title')
assert_selector(:xpath, './/select[@id="form_title"]')
assert_no_selector(:css, 'select#not_form_title')
assert_no_selector(:xpath, './/select[@id="not_form_title"]')
refute_selector(:css, 'select#not_form_title')
end
def test_assert_link
visit('/with_html')
assert_link('A link')
assert_link(count: 1) { |el| el.text == 'A link' }
assert_no_link('Not on page')
end
def test_assert_button
assert_button('fresh_btn')
assert_button(count: 1) { |el| el[:id] == 'fresh_btn' }
assert_no_button('not_btn')
end
def test_assert_field
assert_field('customer_email')
assert_no_field('not_on_the_form')
end
def test_assert_select
assert_select('form_title')
assert_no_select('not_form_title')
end
def test_assert_checked_field
assert_checked_field('form_pets_dog')
assert_no_checked_field('form_pets_cat')
refute_checked_field('form_pets_snake')
end
def test_assert_unchecked_field
assert_unchecked_field('form_pets_cat')
assert_no_unchecked_field('form_pets_dog')
refute_unchecked_field('form_pets_snake')
end
def test_assert_table
visit('/tables')
assert_table('agent_table')
assert_no_table('not_on_form')
refute_table('not_on_form')
end
def test_assert_all_of_selectors
assert_all_of_selectors(:css, 'select#form_other_title', 'input#form_last_name')
end
def test_assert_none_of_selectors
assert_none_of_selectors(:css, 'input#not_on_page', 'input#also_not_on_page')
end
def test_assert_any_of_selectors
assert_any_of_selectors(:css, 'input#not_on_page', 'select#form_other_title')
end
def test_assert_matches_selector
assert_matches_selector(find(:field, 'customer_email'), :field, 'customer_email')
assert_not_matches_selector(find(:select, 'form_title'), :field, 'customer_email')
refute_matches_selector(find(:select, 'form_title'), :field, 'customer_email')
end
def test_assert_matches_css
assert_matches_css(find(:select, 'form_title'), 'select#form_title')
refute_matches_css(find(:select, 'form_title'), 'select#form_other_title')
end
def test_assert_matches_xpath
assert_matches_xpath(find(:select, 'form_title'), './/select[@id="form_title"]')
refute_matches_xpath(find(:select, 'form_title'), './/select[@id="form_other_title"]')
end
def test_assert_style
skip "Rack test doesn't support style" if Capybara.current_driver == :rack_test
visit('/with_html')
assert_style(find(:css, '#second'), display: 'inline')
end
end
RSpec.describe 'capybara/minitest' do
before do
Capybara.current_driver = :rack_test
Capybara.app = TestApp
end
after do
Capybara.use_default_driver
end
it 'should support minitest' do
output = StringIO.new
reporter = Minitest::SummaryReporter.new(output)
reporter.start
MinitestTest.run reporter, {}
reporter.report
expect(output.string).to include('20 runs, 50 assertions, 0 failures, 0 errors, 1 skips')
end
end
capybara-3.12.0/spec/selenium_spec_ie.rb 0000644 0001750 0001750 00000006362 13411315075 020713 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'selenium-webdriver'
require 'shared_selenium_session'
require 'rspec/shared_spec_matchers'
Capybara.register_driver :selenium_ie do |app|
# ::Selenium::WebDriver.logger.level = "debug"
options = ::Selenium::WebDriver::IE::Options.new
options.require_window_focus = true
Capybara::Selenium::Driver.new(
app,
browser: :ie,
desired_capabilities: ::Selenium::WebDriver::Remote::Capabilities.ie,
options: options
)
end
module TestSessions
SeleniumIE = Capybara::Session.new(:selenium_ie, TestApp)
end
TestSessions::SeleniumIE.current_window.resize_to(800, 500)
skipped_tests = %i[response_headers status_code trigger modals hover form_attribute windows]
$stdout.puts `#{Selenium::WebDriver::IE.driver_path} --version` if ENV['CI']
TestSessions::SeleniumIE.current_window.resize_to(1600, 1200)
Capybara::SpecHelper.run_specs TestSessions::SeleniumIE, 'selenium', capybara_skip: skipped_tests do |example|
case example.metadata[:full_description]
when /#refresh it reposts$/
skip 'IE insists on prompting without providing a way to suppress'
when /#click_link can download a file$/
skip 'Not sure how to configure IE for automatic downloading'
when /#fill_in with Date /
pending "IE 11 doesn't support date input types"
when /#click_link_or_button with :disabled option happily clicks on links which incorrectly have the disabled attribute$/
skip 'IE 11 obeys non-standard disabled attribute on anchor tag'
when /#right_click should allow modifiers$/
skip "Windows can't :meta click because :meta triggers start menu"
when /#click should allow multiple modifiers$/
skip "Windows can't :meta click because :meta triggers start menu"
when /#double_click should allow multiple modifiers$/
skip "Windows can't :alt double click due to being properties shortcut"
when /via clicking the wrapping label if possible$/
pending 'IEDriver has an issue with the click location of elements with multiple children if the first child is a text node and the page is scrolled'
end
end
RSpec.describe 'Capybara::Session with Internet Explorer', capybara_skip: skipped_tests do # rubocop:disable RSpec/MultipleDescribes
include Capybara::SpecHelper
include_examples 'Capybara::Session', TestSessions::SeleniumIE, :selenium_ie
include_examples Capybara::RSpecMatchers, TestSessions::SeleniumIE, :selenium_ie
end
RSpec.describe Capybara::Selenium::Node do
it '#right_click should allow modifiers' do
session = TestSessions::SeleniumIE
session.visit('/with_js')
session.find(:css, '#click-test').right_click(:control)
expect(session).to have_link('Has been control right clicked')
end
it '#click should allow multiple modifiers' do
session = TestSessions::SeleniumIE
session.visit('with_js')
# IE triggers system behavior with :meta so can't use those here
session.find(:css, '#click-test').click(:ctrl, :shift, :alt)
expect(session).to have_link('Has been alt control shift clicked')
end
it '#double_click should allow modifiers' do
session = TestSessions::SeleniumIE
session.visit('/with_js')
session.find(:css, '#click-test').double_click(:shift)
expect(session).to have_link('Has been shift double clicked')
end
end
capybara-3.12.0/spec/selenium_spec_firefox.rb 0000644 0001750 0001750 00000016575 13411315075 021767 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'selenium-webdriver'
require 'shared_selenium_session'
require 'rspec/shared_spec_matchers'
browser_options = ::Selenium::WebDriver::Firefox::Options.new
browser_options.headless! if ENV['HEADLESS']
# browser_options.add_option("log", {"level": "trace"})
browser_options.profile = Selenium::WebDriver::Firefox::Profile.new.tap do |profile|
profile['browser.download.dir'] = Capybara.save_path
profile['browser.download.folderList'] = 2
profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/csv'
end
Capybara.register_driver :selenium_firefox do |app|
# ::Selenium::WebDriver.logger.level = "debug"
Capybara::Selenium::Driver.new(
app,
browser: :firefox,
options: browser_options,
timeout: 31,
# Get a trace level log from geckodriver
# :driver_opts => { args: ['-vv'] }
)
end
Capybara.register_driver :selenium_firefox_not_clear_storage do |app|
Capybara::Selenium::Driver.new(
app,
browser: :firefox,
clear_local_storage: false,
clear_session_storage: false,
options: browser_options
)
end
module TestSessions
SeleniumFirefox = Capybara::Session.new(:selenium_firefox, TestApp)
end
skipped_tests = %i[response_headers status_code trigger]
$stdout.puts `#{Selenium::WebDriver::Firefox.driver_path} --version` if ENV['CI']
Capybara::SpecHelper.run_specs TestSessions::SeleniumFirefox, 'selenium', capybara_skip: skipped_tests do |example|
case example.metadata[:full_description]
when 'Capybara::Session selenium node #click should allow multiple modifiers'
pending "Firefox doesn't generate an event for shift+control+click" if firefox_gte?(62, @session) && !Gem.win_platform?
when /^Capybara::Session selenium node #double_click/
pending "selenium-webdriver/geckodriver doesn't generate double click event" if firefox_lt?(59, @session)
when 'Capybara::Session selenium #accept_prompt should accept the prompt with a blank response when there is a default'
pending "Geckodriver doesn't set a blank response in FF < 63 - https://bugzilla.mozilla.org/show_bug.cgi?id=1486485" if firefox_lt?(63, @session)
when 'Capybara::Session selenium #attach_file with multipart form should fire change once for each set of files uploaded'
pending 'Gekcodriver appends files so we have to first call clear for multiple files which creates an extra change ' \
'if files are already set'
when 'Capybara::Session selenium #attach_file with multipart form should fire change once when uploading multiple files from empty'
pending "FF < 62 doesn't support setting all files at once" if firefox_lt?(62, @session)
when 'Capybara::Session selenium #accept_confirm should work with nested modals'
skip 'Broken in FF 63 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if firefox_gte?(63, @session)
when 'Capybara::Session selenium #click_link can download a file'
skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
when 'Capybara::Session selenium #reset_session! removes ALL cookies'
pending "Geckodriver doesn't provide a way to remove cookies outside the current domain"
end
end
RSpec.describe 'Capybara::Session with firefox' do # rubocop:disable RSpec/MultipleDescribes
include Capybara::SpecHelper
include_examples 'Capybara::Session', TestSessions::SeleniumFirefox, :selenium_firefox
include_examples Capybara::RSpecMatchers, TestSessions::SeleniumFirefox, :selenium_firefox
end
RSpec.describe Capybara::Selenium::Driver do
before do
@driver = Capybara::Selenium::Driver.new(TestApp, browser: :firefox, options: browser_options)
end
describe '#quit' do
it 'should reset browser when quit' do
expect(@driver.browser).to be_truthy
@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
context 'with errors' do
before do
@original_browser = @driver.browser
end
after do
# Ensure browser is actually quit so we don't leave hanging processe
RSpec::Mocks.space.proxy_for(@original_browser).reset
@original_browser.quit
end
it 'warns UnknownError returned during quit because the browser is probably already gone' do
allow(@driver).to receive(:warn)
allow(@driver.browser).to(
receive(:quit)
.and_raise(Selenium::WebDriver::Error::UnknownError, 'random message')
)
expect { @driver.quit }.not_to raise_error
expect(@driver.instance_variable_get(:@browser)).to be_nil
expect(@driver).to have_received(:warn).with(/random message/)
end
it 'ignores silenced UnknownError returned during quit because the browser is almost definitely already gone' do
allow(@driver).to receive(:warn)
allow(@driver.browser).to(
receive(:quit)
.and_raise(Selenium::WebDriver::Error::UnknownError, 'Error communicating with the remote browser')
)
expect { @driver.quit }.not_to raise_error
expect(@driver.instance_variable_get(:@browser)).to be_nil
expect(@driver).not_to have_received(:warn)
end
end
end
context 'storage' do
describe '#reset!' do
it 'clears storage by default' do
@session = TestSessions::SeleniumFirefox
@session.visit('/with_js')
@session.find(:css, '#set-storage').click
@session.reset!
@session.visit('/with_js')
expect(@session.driver.browser.local_storage.keys).to be_empty
expect(@session.driver.browser.session_storage.keys).to be_empty
end
it 'does not clear storage when false' do
@session = Capybara::Session.new(:selenium_firefox_not_clear_storage, TestApp)
@session.visit('/with_js')
@session.find(:css, '#set-storage').click
@session.reset!
@session.visit('/with_js')
expect(@session.driver.browser.local_storage.keys).not_to be_empty
expect(@session.driver.browser.session_storage.keys).not_to be_empty
end
end
end
context 'timeout' do
it 'sets the http client read timeout' do
expect(TestSessions::SeleniumFirefox.driver.browser.send(:bridge).http.read_timeout).to eq 31
end
end
end
RSpec.describe Capybara::Selenium::Node do
context '#click' do
it 'warns when attempting on a table row' do
session = TestSessions::SeleniumFirefox
session.visit('/tables')
tr = session.find(:css, '#agent_table tr:first-child')
allow(tr.base).to receive(:warn)
tr.click
expect(tr.base).to have_received(:warn).with(/Clicking the first cell in the row instead/)
end
it 'should allow multiple modifiers', requires: [:js] do
session = TestSessions::SeleniumFirefox
session.visit('with_js')
# Firefox v62+ doesn't generate an event for control+shift+click
session.find(:css, '#click-test').click(:alt, :ctrl, :meta)
# it also triggers a contextmenu event when control is held so don't check click type
expect(session).to have_link('Has been alt control meta')
end
end
context '#send_keys' do
it 'should process space' do
session = TestSessions::SeleniumFirefox
session.visit('/form')
session.find(:css, '#address1_city').send_keys('ocean', [:shift, :space, 'side'])
expect(session.find(:css, '#address1_city').value).to eq 'ocean SIDE'
end
end
end
capybara-3.12.0/spec/selenium_spec_chrome.rb 0000644 0001750 0001750 00000007430 13411315075 021570 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
require 'selenium-webdriver'
require 'shared_selenium_session'
require 'rspec/shared_spec_matchers'
CHROME_DRIVER = :selenium_chrome
browser_options = ::Selenium::WebDriver::Chrome::Options.new
browser_options.headless! if ENV['HEADLESS']
browser_options.add_option(:w3c, !!ENV['W3C'])
Capybara.register_driver :selenium_chrome do |app|
Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options, timeout: 30).tap do |driver|
driver.browser.download_path = Capybara.save_path
end
end
Capybara.register_driver :selenium_chrome_not_clear_storage do |app|
chrome_options = {
browser: :chrome,
options: browser_options
}
Capybara::Selenium::Driver.new(app, chrome_options.merge(clear_local_storage: false, clear_session_storage: false))
end
module TestSessions
Chrome = Capybara::Session.new(CHROME_DRIVER, TestApp)
end
skipped_tests = %i[response_headers status_code trigger]
$stdout.puts `#{Selenium::WebDriver::Chrome.driver_path} --version` if ENV['CI']
Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybara_skip: skipped_tests do |example|
case example.metadata[:full_description]
when /#click_link can download a file$/
skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
when /Capybara::Session selenium_chrome Capybara::Window#maximize/
pending "Chrome headless doesn't support maximize" if ENV['HEADLESS']
end
end
RSpec.describe 'Capybara::Session with chrome' do
include Capybara::SpecHelper
include_examples 'Capybara::Session', TestSessions::Chrome, CHROME_DRIVER
include_examples Capybara::RSpecMatchers, TestSessions::Chrome, CHROME_DRIVER
context 'storage' do
describe '#reset!' do
it 'clears storage by default' do
@session = TestSessions::Chrome
@session.visit('/with_js')
@session.find(:css, '#set-storage').click
@session.reset!
@session.visit('/with_js')
expect(@session.evaluate_script('Object.keys(localStorage)')).to be_empty
expect(@session.evaluate_script('Object.keys(sessionStorage)')).to be_empty
end
it 'does not clear storage when false' do
@session = Capybara::Session.new(:selenium_chrome_not_clear_storage, TestApp)
@session.visit('/with_js')
@session.find(:css, '#set-storage').click
@session.reset!
@session.visit('/with_js')
expect(@session.evaluate_script('Object.keys(localStorage)')).not_to be_empty
expect(@session.evaluate_script('Object.keys(sessionStorage)')).not_to be_empty
end
end
end
context 'timeout' do
it 'sets the http client read timeout' do
expect(TestSessions::Chrome.driver.browser.send(:bridge).http.read_timeout).to eq 30
end
end
describe 'filling in Chrome-specific date and time fields with keystrokes' do
let(:datetime) { Time.new(1983, 6, 19, 6, 30) }
before do
@session = TestSessions::Chrome
@session.visit('/form')
end
it 'should fill in a date input with a String' do
@session.fill_in('form_date', with: '06/19/1983')
@session.click_button('awesome')
expect(Date.parse(extract_results(@session)['date'])).to eq datetime.to_date
end
it 'should fill in a time input with a String' do
@session.fill_in('form_time', with: '06:30A')
@session.click_button('awesome')
results = extract_results(@session)['time']
expect(Time.parse(results).strftime('%r')).to eq datetime.strftime('%r')
end
it 'should fill in a datetime input with a String' do
@session.fill_in('form_datetime', with: "06/19/1983\t06:30A")
@session.click_button('awesome')
expect(Time.parse(extract_results(@session)['datetime'])).to eq datetime
end
end
end
capybara-3.12.0/spec/filter_set_spec.rb 0000644 0001750 0001750 00000002726 13411315075 020555 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'spec_helper'
RSpec.describe Capybara::Selector::FilterSet do
after do
Capybara::Selector::FilterSet.remove(:test)
end
it 'allows node filters' do
fs = Capybara::Selector::FilterSet.add(:test) do
node_filter(:node_test, :boolean) { |_node, _value| true }
expression_filter(:expression_test, :boolean) { |_expr, _value| true }
end
expect(fs.node_filters.keys).to include(:node_test)
expect(fs.node_filters.keys).not_to include(:expression_test)
end
it 'allows expression filters' do
fs = Capybara::Selector::FilterSet.add(:test) do
node_filter(:node_test, :boolean) { |_node, _value| true }
expression_filter(:expression_test, :boolean) { |_expr, _value| true }
end
expect(fs.expression_filters.keys).to include(:expression_test)
expect(fs.expression_filters.keys).not_to include(:node_test)
end
it 'allows node filter and expression filter with the same name' do
fs = Capybara::Selector::FilterSet.add(:test) do
node_filter(:test, :boolean) { |_node, _value| true }
expression_filter(:test, :boolean) { |_expr, _value| true }
end
expect(fs.expression_filters[:test]).not_to eq fs.node_filters[:test]
end
it 'allows `filter` as an alias of `node_filter`' do
fs = Capybara::Selector::FilterSet.add(:test) do
filter(:node_test, :boolean) { |_node, _value| true }
end
expect(fs.node_filters.keys).to include(:node_test)
end
end
capybara-3.12.0/spec/spec_helper.rb 0000644 0001750 0001750 00000003017 13411315075 017666 0 ustar utkarsh2102 utkarsh2102 # frozen_string_literal: true
require 'rspec/expectations'
require 'capybara/spec/spec_helper'
require 'webdrivers' if ENV['CI']
module Capybara
module SpecHelper
def firefox?(session)
browser_name(session) == :firefox &&
session.driver.browser.capabilities.is_a?(::Selenium::WebDriver::Remote::W3C::Capabilities)
end
def firefox_lt?(version, session)
firefox?(session) && (session.driver.browser.capabilities[:browser_version].to_f < version)
end
def firefox_gte?(version, session)
firefox?(session) && (session.driver.browser.capabilities[:browser_version].to_f >= version)
end
def chrome?(session)
browser_name(session) == :chrome
end
def chrome_lt?(version, session)
chrome?(session) && (session.driver.browser.capabilities[:version].to_f < version)
end
def chrome_gte?(version, session)
chrome?(session) && (session.driver.browser.capabilities[:version].to_f >= version)
end
def edge?(session)
browser_name(session) == :edge
end
def ie?(session)
%i[internet_explorer ie].include?(browser_name(session))
end
def browser_name(session)
session.driver.browser.browser if session.respond_to?(:driver)
end
def remote?(session)
session.driver.browser.is_a? ::Selenium::WebDriver::Remote::Driver
end
end
end
RSpec.configure do |config|
Capybara::SpecHelper.configure(config)
config.filter_run_including focus_: true unless ENV['CI']
config.run_all_when_everything_filtered = true
end
capybara-3.12.0/License.txt 0000644 0001750 0001750 00000002111 13411315075 016233 0 ustar utkarsh2102 utkarsh2102 (The MIT License)
Copyright (c) 2009-2018 Thomas Walpole, Jonas Nicklas
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
capybara-3.12.0/capybara.gemspec 0000644 0001750 0001750 00000041271 13411315075 017251 0 ustar utkarsh2102 utkarsh2102 #########################################################
# This file has been automatically generated by gem2tgz #
#########################################################
# -*- encoding: utf-8 -*-
# stub: capybara 3.12.0 ruby lib
Gem::Specification.new do |s|
s.name = "capybara".freeze
s.version = "3.12.0"
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.metadata = { "changelog_uri" => "https://github.com/teamcapybara/capybara/blob/master/History.md", "source_code_uri" => "https://github.com/teamcapybara/capybara" } if s.respond_to? :metadata=
s.require_paths = ["lib".freeze]
s.authors = ["Thomas Walpole".freeze, "Jonas Nicklas".freeze]
s.cert_chain = ["gem-public_cert.pem".freeze]
s.date = "2018-11-28"
s.description = "Capybara is an integration testing tool for rack based web applications. It simulates how a user would interact with a website".freeze
s.email = ["twalpole@gmail.com".freeze, "jonas.nicklas@gmail.com".freeze]
s.files = ["History.md".freeze, "License.txt".freeze, "README.md".freeze, "lib/capybara.rb".freeze, "lib/capybara/config.rb".freeze, "lib/capybara/cucumber.rb".freeze, "lib/capybara/driver/base.rb".freeze, "lib/capybara/driver/node.rb".freeze, "lib/capybara/dsl.rb".freeze, "lib/capybara/helpers.rb".freeze, "lib/capybara/minitest.rb".freeze, "lib/capybara/minitest/spec.rb".freeze, "lib/capybara/node/actions.rb".freeze, "lib/capybara/node/base.rb".freeze, "lib/capybara/node/document.rb".freeze, "lib/capybara/node/document_matchers.rb".freeze, "lib/capybara/node/element.rb".freeze, "lib/capybara/node/finders.rb".freeze, "lib/capybara/node/matchers.rb".freeze, "lib/capybara/node/simple.rb".freeze, "lib/capybara/queries/ancestor_query.rb".freeze, "lib/capybara/queries/base_query.rb".freeze, "lib/capybara/queries/current_path_query.rb".freeze, "lib/capybara/queries/match_query.rb".freeze, "lib/capybara/queries/selector_query.rb".freeze, "lib/capybara/queries/sibling_query.rb".freeze, "lib/capybara/queries/style_query.rb".freeze, "lib/capybara/queries/text_query.rb".freeze, "lib/capybara/queries/title_query.rb".freeze, "lib/capybara/rack_test/browser.rb".freeze, "lib/capybara/rack_test/css_handlers.rb".freeze, "lib/capybara/rack_test/driver.rb".freeze, "lib/capybara/rack_test/form.rb".freeze, "lib/capybara/rack_test/node.rb".freeze, "lib/capybara/rails.rb".freeze, "lib/capybara/result.rb".freeze, "lib/capybara/rspec.rb".freeze, "lib/capybara/rspec/features.rb".freeze, "lib/capybara/rspec/matcher_proxies.rb".freeze, "lib/capybara/rspec/matchers.rb".freeze, "lib/capybara/rspec/matchers/base.rb".freeze, "lib/capybara/rspec/matchers/become_closed.rb".freeze, "lib/capybara/rspec/matchers/compound.rb".freeze, "lib/capybara/rspec/matchers/have_current_path.rb".freeze, "lib/capybara/rspec/matchers/have_selector.rb".freeze, "lib/capybara/rspec/matchers/have_style.rb".freeze, "lib/capybara/rspec/matchers/have_text.rb".freeze, "lib/capybara/rspec/matchers/have_title.rb".freeze, "lib/capybara/rspec/matchers/match_selector.rb".freeze, "lib/capybara/selector.rb".freeze, "lib/capybara/selector/builders/css_builder.rb".freeze, "lib/capybara/selector/builders/xpath_builder.rb".freeze, "lib/capybara/selector/css.rb".freeze, "lib/capybara/selector/filter.rb".freeze, "lib/capybara/selector/filter_set.rb".freeze, "lib/capybara/selector/filters/base.rb".freeze, "lib/capybara/selector/filters/expression_filter.rb".freeze, "lib/capybara/selector/filters/locator_filter.rb".freeze, "lib/capybara/selector/filters/node_filter.rb".freeze, "lib/capybara/selector/regexp_disassembler.rb".freeze, "lib/capybara/selector/selector.rb".freeze, "lib/capybara/selenium/driver.rb".freeze, "lib/capybara/selenium/driver_specializations/chrome_driver.rb".freeze, "lib/capybara/selenium/driver_specializations/firefox_driver.rb".freeze, "lib/capybara/selenium/extensions/html5_drag.rb".freeze, "lib/capybara/selenium/node.rb".freeze, "lib/capybara/selenium/nodes/chrome_node.rb".freeze, "lib/capybara/selenium/nodes/firefox_node.rb".freeze, "lib/capybara/selenium/patches/pause_duration_fix.rb".freeze, "lib/capybara/server.rb".freeze, "lib/capybara/server/animation_disabler.rb".freeze, "lib/capybara/server/checker.rb".freeze, "lib/capybara/server/middleware.rb".freeze, "lib/capybara/session.rb".freeze, "lib/capybara/session/config.rb".freeze, "lib/capybara/session/matchers.rb".freeze, "lib/capybara/spec/fixtures/another_test_file.txt".freeze, "lib/capybara/spec/fixtures/capybara.jpg".freeze, "lib/capybara/spec/fixtures/no_extension".freeze, "lib/capybara/spec/fixtures/test_file.txt".freeze, "lib/capybara/spec/public/jquery-ui.js".freeze, "lib/capybara/spec/public/jquery.js".freeze, "lib/capybara/spec/public/test.js".freeze, "lib/capybara/spec/session/accept_alert_spec.rb".freeze, "lib/capybara/spec/session/accept_confirm_spec.rb".freeze, "lib/capybara/spec/session/accept_prompt_spec.rb".freeze, "lib/capybara/spec/session/all_spec.rb".freeze, "lib/capybara/spec/session/ancestor_spec.rb".freeze, "lib/capybara/spec/session/assert_all_of_selectors_spec.rb".freeze, "lib/capybara/spec/session/assert_current_path_spec.rb".freeze, "lib/capybara/spec/session/assert_selector_spec.rb".freeze, "lib/capybara/spec/session/assert_style_spec.rb".freeze, "lib/capybara/spec/session/assert_text_spec.rb".freeze, "lib/capybara/spec/session/assert_title_spec.rb".freeze, "lib/capybara/spec/session/attach_file_spec.rb".freeze, "lib/capybara/spec/session/body_spec.rb".freeze, "lib/capybara/spec/session/check_spec.rb".freeze, "lib/capybara/spec/session/choose_spec.rb".freeze, "lib/capybara/spec/session/click_button_spec.rb".freeze, "lib/capybara/spec/session/click_link_or_button_spec.rb".freeze, "lib/capybara/spec/session/click_link_spec.rb".freeze, "lib/capybara/spec/session/current_scope_spec.rb".freeze, "lib/capybara/spec/session/current_url_spec.rb".freeze, "lib/capybara/spec/session/dismiss_confirm_spec.rb".freeze, "lib/capybara/spec/session/dismiss_prompt_spec.rb".freeze, "lib/capybara/spec/session/element/assert_match_selector_spec.rb".freeze, "lib/capybara/spec/session/element/match_css_spec.rb".freeze, "lib/capybara/spec/session/element/match_xpath_spec.rb".freeze, "lib/capybara/spec/session/element/matches_selector_spec.rb".freeze, "lib/capybara/spec/session/evaluate_async_script_spec.rb".freeze, "lib/capybara/spec/session/evaluate_script_spec.rb".freeze, "lib/capybara/spec/session/execute_script_spec.rb".freeze, "lib/capybara/spec/session/fill_in_spec.rb".freeze, "lib/capybara/spec/session/find_button_spec.rb".freeze, "lib/capybara/spec/session/find_by_id_spec.rb".freeze, "lib/capybara/spec/session/find_field_spec.rb".freeze, "lib/capybara/spec/session/find_link_spec.rb".freeze, "lib/capybara/spec/session/find_spec.rb".freeze, "lib/capybara/spec/session/first_spec.rb".freeze, "lib/capybara/spec/session/frame/frame_title_spec.rb".freeze, "lib/capybara/spec/session/frame/frame_url_spec.rb".freeze, "lib/capybara/spec/session/frame/switch_to_frame_spec.rb".freeze, "lib/capybara/spec/session/frame/within_frame_spec.rb".freeze, "lib/capybara/spec/session/go_back_spec.rb".freeze, "lib/capybara/spec/session/go_forward_spec.rb".freeze, "lib/capybara/spec/session/has_all_selectors_spec.rb".freeze, "lib/capybara/spec/session/has_any_selectors_spec.rb".freeze, "lib/capybara/spec/session/has_button_spec.rb".freeze, "lib/capybara/spec/session/has_css_spec.rb".freeze, "lib/capybara/spec/session/has_current_path_spec.rb".freeze, "lib/capybara/spec/session/has_field_spec.rb".freeze, "lib/capybara/spec/session/has_link_spec.rb".freeze, "lib/capybara/spec/session/has_none_selectors_spec.rb".freeze, "lib/capybara/spec/session/has_select_spec.rb".freeze, "lib/capybara/spec/session/has_selector_spec.rb".freeze, "lib/capybara/spec/session/has_style_spec.rb".freeze, "lib/capybara/spec/session/has_table_spec.rb".freeze, "lib/capybara/spec/session/has_text_spec.rb".freeze, "lib/capybara/spec/session/has_title_spec.rb".freeze, "lib/capybara/spec/session/has_xpath_spec.rb".freeze, "lib/capybara/spec/session/headers_spec.rb".freeze, "lib/capybara/spec/session/html_spec.rb".freeze, "lib/capybara/spec/session/node_spec.rb".freeze, "lib/capybara/spec/session/node_wrapper_spec.rb".freeze, "lib/capybara/spec/session/refresh_spec.rb".freeze, "lib/capybara/spec/session/reset_session_spec.rb".freeze, "lib/capybara/spec/session/response_code_spec.rb".freeze, "lib/capybara/spec/session/save_and_open_page_spec.rb".freeze, "lib/capybara/spec/session/save_and_open_screenshot_spec.rb".freeze, "lib/capybara/spec/session/save_page_spec.rb".freeze, "lib/capybara/spec/session/save_screenshot_spec.rb".freeze, "lib/capybara/spec/session/screenshot_spec.rb".freeze, "lib/capybara/spec/session/select_spec.rb".freeze, "lib/capybara/spec/session/selectors_spec.rb".freeze, "lib/capybara/spec/session/sibling_spec.rb".freeze, "lib/capybara/spec/session/source_spec.rb".freeze, "lib/capybara/spec/session/text_spec.rb".freeze, "lib/capybara/spec/session/title_spec.rb".freeze, "lib/capybara/spec/session/uncheck_spec.rb".freeze, "lib/capybara/spec/session/unselect_spec.rb".freeze, "lib/capybara/spec/session/visit_spec.rb".freeze, "lib/capybara/spec/session/window/become_closed_spec.rb".freeze, "lib/capybara/spec/session/window/current_window_spec.rb".freeze, "lib/capybara/spec/session/window/open_new_window_spec.rb".freeze, "lib/capybara/spec/session/window/switch_to_window_spec.rb".freeze, "lib/capybara/spec/session/window/window_opened_by_spec.rb".freeze, "lib/capybara/spec/session/window/window_spec.rb".freeze, "lib/capybara/spec/session/window/windows_spec.rb".freeze, "lib/capybara/spec/session/window/within_window_spec.rb".freeze, "lib/capybara/spec/session/within_spec.rb".freeze, "lib/capybara/spec/spec_helper.rb".freeze, "lib/capybara/spec/test_app.rb".freeze, "lib/capybara/spec/views/buttons.erb".freeze, "lib/capybara/spec/views/fieldsets.erb".freeze, "lib/capybara/spec/views/form.erb".freeze, "lib/capybara/spec/views/frame_child.erb".freeze, "lib/capybara/spec/views/frame_one.erb".freeze, "lib/capybara/spec/views/frame_parent.erb".freeze, "lib/capybara/spec/views/frame_two.erb".freeze, "lib/capybara/spec/views/header_links.erb".freeze, "lib/capybara/spec/views/host_links.erb".freeze, "lib/capybara/spec/views/initial_alert.erb".freeze, "lib/capybara/spec/views/obscured.erb".freeze, "lib/capybara/spec/views/path.erb".freeze, "lib/capybara/spec/views/popup_one.erb".freeze, "lib/capybara/spec/views/popup_two.erb".freeze, "lib/capybara/spec/views/postback.erb".freeze, "lib/capybara/spec/views/tables.erb".freeze, "lib/capybara/spec/views/with_animation.erb".freeze, "lib/capybara/spec/views/with_base_tag.erb".freeze, "lib/capybara/spec/views/with_count.erb".freeze, "lib/capybara/spec/views/with_fixed_header_footer.erb".freeze, "lib/capybara/spec/views/with_hover.erb".freeze, "lib/capybara/spec/views/with_html.erb".freeze, "lib/capybara/spec/views/with_html5_svg.erb".freeze, "lib/capybara/spec/views/with_html_entities.erb".freeze, "lib/capybara/spec/views/with_js.erb".freeze, "lib/capybara/spec/views/with_namespace.erb".freeze, "lib/capybara/spec/views/with_scope.erb".freeze, "lib/capybara/spec/views/with_simple_html.erb".freeze, "lib/capybara/spec/views/with_slow_unload.erb".freeze, "lib/capybara/spec/views/with_title.erb".freeze, "lib/capybara/spec/views/with_unload_alert.erb".freeze, "lib/capybara/spec/views/with_windows.erb".freeze, "lib/capybara/spec/views/within_frames.erb".freeze, "lib/capybara/version.rb".freeze, "lib/capybara/window.rb".freeze, "spec/basic_node_spec.rb".freeze, "spec/capybara_spec.rb".freeze, "spec/css_builder_spec.rb".freeze, "spec/css_splitter_spec.rb".freeze, "spec/dsl_spec.rb".freeze, "spec/filter_set_spec.rb".freeze, "spec/fixtures/capybara.csv".freeze, "spec/fixtures/certificate.pem".freeze, "spec/fixtures/key.pem".freeze, "spec/fixtures/selenium_driver_rspec_failure.rb".freeze, "spec/fixtures/selenium_driver_rspec_success.rb".freeze, "spec/minitest_spec.rb".freeze, "spec/minitest_spec_spec.rb".freeze, "spec/per_session_config_spec.rb".freeze, "spec/rack_test_spec.rb".freeze, "spec/regexp_dissassembler_spec.rb".freeze, "spec/result_spec.rb".freeze, "spec/rspec/features_spec.rb".freeze, "spec/rspec/scenarios_spec.rb".freeze, "spec/rspec/shared_spec_matchers.rb".freeze, "spec/rspec/views_spec.rb".freeze, "spec/rspec_matchers_spec.rb".freeze, "spec/rspec_spec.rb".freeze, "spec/selector_spec.rb".freeze, "spec/selenium_spec_chrome.rb".freeze, "spec/selenium_spec_chrome_remote.rb".freeze, "spec/selenium_spec_edge.rb".freeze, "spec/selenium_spec_firefox.rb".freeze, "spec/selenium_spec_firefox_remote.rb".freeze, "spec/selenium_spec_ie.rb".freeze, "spec/server_spec.rb".freeze, "spec/session_spec.rb".freeze, "spec/shared_selenium_session.rb".freeze, "spec/spec_helper.rb".freeze, "spec/xpath_builder_spec.rb".freeze]
s.homepage = "https://github.com/teamcapybara/capybara".freeze
s.licenses = ["MIT".freeze]
s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze)
s.rubygems_version = "2.5.2.1".freeze
s.summary = "Capybara aims to simplify the process of integration testing Rack applications, such as Rails, Sinatra or Merb".freeze
if s.respond_to? :specification_version then
s.specification_version = 4
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q.freeze, [">= 0"])
s.add_development_dependency(%q.freeze, [">= 0"])
s.add_development_dependency(%q.freeze, [">= 2.3.0"])
s.add_development_dependency(%q.freeze, [">= 0"])
s.add_development_dependency(%q.freeze, [">= 1.0.0"])
s.add_development_dependency(%q.freeze, [">= 2.0.4"])
s.add_runtime_dependency(%q.freeze, [">= 0.1.3"])
s.add_development_dependency(%q.freeze, [">= 0"])
s.add_runtime_dependency(%q.freeze, ["~> 1.8"])
s.add_development_dependency(%q.freeze, [">= 0"])
s.add_runtime_dependency(%q.freeze, [">= 1.6.0"])
s.add_runtime_dependency(%q.freeze, [">= 0.6.3"])
s.add_development_dependency(%q.freeze, [">= 0"])
s.add_runtime_dependency(%q.freeze, ["~> 1.2"])
s.add_development_dependency(%q.freeze, [">= 3.5.0"])
s.add_development_dependency(%q.freeze, [">= 0"])
s.add_development_dependency(%q.freeze, [">= 0"])
s.add_development_dependency(%q.freeze, ["~> 3.5"])
s.add_development_dependency(%q.freeze, [">= 1.4.0"])
s.add_runtime_dependency(%q.freeze, ["~> 3.2"])
s.add_development_dependency(%q.freeze, [">= 0.9.0"])
else
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, [">= 2.3.0"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, [">= 1.0.0"])
s.add_dependency(%q.freeze, [">= 2.0.4"])
s.add_dependency(%q.freeze, [">= 0.1.3"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, ["~> 1.8"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, [">= 1.6.0"])
s.add_dependency(%q.freeze, [">= 0.6.3"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, ["~> 1.2"])
s.add_dependency(%q.freeze, [">= 3.5.0"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, ["~> 3.5"])
s.add_dependency(%q.freeze, [">= 1.4.0"])
s.add_dependency(%q.freeze, ["~> 3.2"])
s.add_dependency(%q.freeze, [">= 0.9.0"])
end
else
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, [">= 2.3.0"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, [">= 1.0.0"])
s.add_dependency(%q.freeze, [">= 2.0.4"])
s.add_dependency(%q.freeze, [">= 0.1.3"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, ["~> 1.8"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, [">= 1.6.0"])
s.add_dependency(%q.freeze, [">= 0.6.3"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, ["~> 1.2"])
s.add_dependency(%q.freeze, [">= 3.5.0"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, [">= 0"])
s.add_dependency(%q.freeze, ["~> 3.5"])
s.add_dependency(%q.freeze, [">= 1.4.0"])
s.add_dependency(%q.freeze, ["~> 3.2"])
s.add_dependency(%q.freeze, [">= 0.9.0"])
end
end
capybara-3.12.0/History.md 0000644 0001750 0001750 00000163452 13411315075 016113 0 ustar utkarsh2102 utkarsh2102 # Version 3.12.0
Release date: 2018-11-28
### Added
* Support Ruby 2.6 endless range in Result#[] and query `:between` option
* Pre-registered headless firefox driver :selenium_headless [Andrew Havens]
* Selenium driver now defaults to clearing `sessionStorage` and `localStorage`. To disable pass `clear_local_storage: false` and/or `clear_session_storage: false` when creating Capybara::Selenium::Driver instance in your driver registration
### Fixed
* Raise error if only :x or :y are passed as an offset to click methods
### Removed
* Support for RSpec < 3.5
# Version 3.11.1
Release date: 2018-11-16
### Fixed
* Fixed :link_or_button XPath generation when it has had an expression filter added
# Version 3.11.0
Release date: 2018-11-14
### Added
* Ability for node filters to set detailed error messages
* `Capybara::HTML` Will use `nokogumbo` for HTML parsing if installed
* `Selector#locator_filter` added to allow for dynamic locator in selectors
### Fixed
* Node filters are evaluated in the context of the Selector they are used in to ensure the correct options are used
# Version 3.10.1
Release date: 2018-11-03
### Fixed
* Fix `aria-label` and `test_id` matching for `link_or_button` selector type - Issue #2125
* Fixed crash in element path creation for matcher failure messages - Issue #2120
# Version 3.10.0
Release date: 2018-10-23
### Added
* :class filter can now check for class names starting with !
* Selector `xpath`/`css` expression definitions will get filter names from block parameters if not explicitly provided
* `any_of_selectors` assertions and matchers to complement `all_of_selectors` and `none_of_selectors`
### Fixed
* Selector `css` expression definiton declared filters now work again
* Cleaned up warnings [Yuji Yaginuma]
* Workaround installation of rspec matcher proxies under jruby by reverting to the old solution not using prepend, so jruby bugs are not hit - Issue #2115
# Version 3.9.0
Release date: 2018-10-03
### Added
* Selenium with Chrome removes all cookies at session reset instead of just cookies from current domain if possible
* Support for Regexp for system :id and :class filters where possible
* `using_session` now accepts a session object as well as the name of the session for users who manually manage sessions
* The `:field` selector will now find `type = "hidden"` fields if the `type: "hidden"` filter option is provided
# Version 3.8.2
Release date: 2018-09-26
### Fixed
* Fixed negated class selector option - Issue #2103
# Version 3.8.1
Release date: 2018-09-22
### Fixed
* Filling in of date fields with a string when using selenium chrome regression [Micah Geisel]
# Version 3.8.0
Release date: 2018-09-20
### Added
* Workaround geckodriver 0.22 issue with undefined pause durations
* :element selector ignores XML namespaces
### Fixed
* Added Errno::ECONNRESET to the errors which will allows https server detection
# Version 3.7.2
Release date: 2018-09-12
### Fixed
* Fix MatchQuery based matchers when used on a root element found using any type of parent/ancestor query - Issue #2097
* Fix Chrome/FF HTML5 drag simulation for elements (a, img) which default to draggable - Issue #2098
# Version 3.7.1
Release date: 2018-09-05
### Fixed
* Restored ability to pass symbol as the CSS selector when calling `has_css?`/`have_css`/etc - Issue #2093
# Version 3.7.0
Release date: 2018-09-02
### Added
* `Capybara.disable_animation` can be set to a CSS selector to identify which elements will have animation disabled [Michael Glass]
* `Capybara.default_normalize_ws` option which sets whether or not text predicates and matchers (`has_text?`, `has_content?`, `assert_text`, etc) use `normalize_ws` option by default. Defaults to false. [Stegalin Ivan]
* Selector based predicates, matchers, and finders now support the `:normalize_ws` option for the `:text`/`:exact_text` filters. Defaults to the `Capybara.default_normalize_ws`setting above.
* Element `choose`/`check`/`uncheck`/`attach_file`/`fill_in` can now operate on the element they're called on or a descendant if no locator is passed.
### Fixed
* All CSS styles applied by the `Element#attach_file` `:make_visible` option will now have `!important` priority set to ensure they override any other specified style.
* Firefox file inputs are only manually cleared when necessary.
# Version 3.6.0
Release date: 2018-08-14
### Added
* Workaround geckodriver/firefox send_keys issues as much as possible using the Selenium actions API
* Workaround lack of HTML5 native drag and drop events when using Selenium driver with Chrome and FF >= 62
* `Capybara.predicates_wait` option which sets whether or not Capybaras matcher predicate methods (`has_css?`, `has_selector?`, `has_text?`, etc.) default to using waiting/retrying behavior (defaults to true)
# Version 3.5.1
Release date: 2018-08-03
### Fixed
* Fixed misspelled method name `refute_matches_elector` => `refute_matches_selector`
# Version 3.5.0
Release date: 2018-08-01
### Added
* text predicates and matchers (`has_text?`, `has_content?`, `assert_text`, etc) now support a `normalize_ws` option
### Fixed
* `attach_file` with Selenium and local Firefox 62+ now correctly generates only one change event when attaching multiple files
# Version 3.4.2
Release date: 2018-07-24
### Fixed
* `match_xxx` selectors and `matches_xxx?` predicates work correctly with elements found using a sibling selector - Issue #2073
# Version 3.4.1
Release date: 2018-07-20
### Fixed
* `Session#evaluate_script` now strips the script in `Session` rather than only in the Selenium driver
# Version 3.4.0
Release date: 2018-07-19
### Fixed
* Make selenium driver :backspace clear stategy work even if caret location is in middle of field content [Champier Cyril]
* Selenium issue with fieldset nested in disabled fieldset not being considered disabled
* `Session#evaluate_script` and `Element#evaluate_script` now strip leading/trailing whitespace from scripts [Ian Lesperance]
### Added
* Work around Selenium lack of support for `file_detector` with remote geckodriver
* `#within_frame` locator is optional when only one frame exists
* `Capybara.test_id` option that allows for matching the Capybara provided selector types on an arbitrary attribute
(defaults to nil), set to your test id attribute ('data-test-id, etc) if using test id attributes in your project
# Version 3.3.1
Release date: 2018-06-27
### Fixed
* `selenium-webdriver` version check [ahorek]
* Selenium driver correctly responds to `disabled?` for fieldset elements - Issue #2059 [Thomas Walpole]
# Version 3.3.0
Release date: 2018-06-25
### Added
* RackTest driver now handles 307/308 redirects
* `execute_async_script` can now be called on elements to run the JS in the context of the element
* `:download` filter option on `:link' selector
* `Window#fullscreen`
* `Element#style` and associated matchers
### Changed
* Minimum "supported" `selenium-webdriver` is raised to 3.5.0 (but you really should be using newer than that)
### Fixes
* Selenium driver with Firefox workaround for clicking on table row - https://github.com/mozilla/geckodriver/issues/1228
* :class and :id filters applied to CSS based selectors now correctly handle the CSS comma
* Selenium driver handles namespaces when generating an elements `#path` - Issue #2048
# Version 3.2.1
Release date: 2018-06-04
### Fixes
* Only split CSS selectors when :class or :id options are given. Restores 3.1.1 functionality for now but the underlying issue
will require a larger fix, hopefully coming soon. - Issue #2044 [Thomas Walpole]
# Version 3.2.0
Release date: 2018-06-01
### Changed
* Ruby 2.3.0+ is now required
* `ElementNotFound` errors raised in selector filters are interpreted as non-matches
### Added
* New global configuration `default_set_options` used in `Capybara::Node::Element#set` as default `options` hash [Champier Cyril]
* `execute_script` and `evaluate_script` can now be called on elements to run the JS in the context of the element [Thomas Walpole]
* Filters in custom selectors now support a `matcher` Regexp to handle multiple filter options [Thomas Walpole]
* `:element` selector type which will match on any attribute (other than the reserved names) passed as a filter option [Thomas Walpole]
* `:class` filter option now supports preceding class names with `!` to indicate not having that class [Thomas Walpole]
* `:class` and `:id` filter options now accept `XPath::Expression` objects to allow for more flexibility in matching [Thomas Walpole]
* `Capybara.disable_animation` setting which triggers loading of a middleware that attempts to disable animations in pages.
This is very much a beta feature and may change/disappear in the future. [Thomas Walpole]
# Version 3.1.1
Release date: 2018-05-25
### Fixes
* Ensure keystrokes are sent when setting time/date fields to a string with the Selenium driver [Thomas Walpole]
# Version 3.1.0
Release date: 2018-05-10
### Added
* Support for using `select` with text inputs associated with a datalist element
* `type` filter on `:button` selector
* Support for server operating in https mode
* Selenium driver now uses JS to fill_in/set date and time fields when passed date or time objects [Aleksei Gusev, Thomas Walpole]
# Version 3.0.3
Release date: 2018-04-30
### Fixes
* Issue in `check` where the locator string could not be omitted
* Selenium browser type detection when using remote [Ian Ker-Seymer]
* Potential hang when waiting for requests to complete [Chris Zetter]
# Version 3.0.2
Release date: 2018-04-13
### Fixes
* Fix expression filter descriptions in some selector failure messages
* Fix compounding of negated matechers - Issue #2010
# Version 3.0.1
Release date: 2018-04-06
### Changed
* Restored ability for `Capybara.server=` to accept a proc which was accidentally removed in 3.0.0
# Version 3.0.0
Release date: 2018-04-05
### Changed
* Selenium driver only closes extra windows for browsers where that is known to work (Firefox, Chrome)
* "threadsafe" mode is no longer considered beta
### Fixes
* Multiple file attach_file with Firefox
* Use Puma::Server directly rather than Rack::Handler::Puma so signal handlers don't prevent test quitting
# Version 3.0.0.rc2
Release date: 2018-03-23
### Changed
* Visibile text whitespace is no longer fully normalized in favor of being more in line with the WebDriver spec for visible text
* Drivers are expected to close extra windows when resetting the session
* Selenium driver supports Date/Time when filling in date/time/datetime-local inputs
* `current_url` returns the url for the top level browsing context
* `title` returns the title for the top level browsing context
### Added
* `Driver#frame_url` returns the url for the current frame
* `Driver#frame_title` returns the title for the current frame
# Version 3.0.0.rc1
Release date: 2018-03-02
### Added
* Support for libraries wrapping Capybara elements and providing a `#to_capybara_node` method
### Changed
* `first` now raises ElementNotFound, by default, instead of returning nil when no matches are found - Issue #1507
* 'all' now waits for at least one matching element by default. Pass `wait: false` if you want the previous
behavior where an empty result would be returned immediately if no matching elements exist yet.
* ArgumentError raised if extra parameters passed to selector queries
### Removed
* Ruby < 2.2.2 support
* `Capybara.exact_options` no longer exists. Just use `exact: true` on relevant actions/finders if necessary.
* All previously deprecated methods removed
* RSpec 2.x support
* selenium-webdriver 2.x support
* Nokogiri < 1.8 support
* `field_labeled` alias for `find_field`
# Version 2.18.0
Release date: 2018-02-12
### Fixed
* Firefox/geckodriver setting of contenteditable childs contents
* Ignore Selenium::WebDriver::Error::SessionNotCreatedError when quitting driver [Tim Connor]
### Removed
* Headless chrome modal JS injection that is no longer needed for Chrome 64+/chromedriver 2.35+
# Version 2.17.0
Release date: 2018-01-02
### Added
* `have_all_of_selectors`, `have_none_of_selectors` RSpec matchers for parity with minitest assertions [Thomas Walpole]
### Fixed
* Allow xpath 3.x gem [Thomas Walpole]
* Issue when drivers returned nil for `current_path` and a matcher was used with a Regexp [Thomas Walpole]
* Error message when visible element not found, but non-visible was [Andy Klimczak]
# Version 2.16.1
Release date: 2017-11-20
### Fixed
* Fix rack_test driver for rack_test 0.7.1/0.8.0 [Thomas Walpole]
* `accept_prompt` response text can contain quotes when using selenium with headless chrome [Thomas Walpole]
# Version 2.16.0
Release date: 2017-11-13
### Added
* Attempt to move element into view when selenium doesn't correctly do it - See PR #1917 [Thomas Walpole]
* `current_path` matchers will now autodetect path vs url based on string to be matched. Deprecates
`:only_path` in favor of `:ignore_query` option [Thomas Walpole]
* Session#evaluate_async_script [Thomas Walpole]
### Fixed
* Default prompt value when using headless Chrome works correctly [Thomas Walpole]
* Support new modal error returned by selenium-webdriver 3.7 for W3C drivers [Thomas Walpole]
* Calling `respond_to?` on the object passed to `Capybara.configure` block - Issue #1935
# Version 2.15.4
Release date: 2017-10-07
### Fixed
* Visiting an absolute URL shouldn't overwrite the port when no server or always_include_port=false - Issue #1921
# Version 2.15.3
Release date: 2017-10-03
### Fixed
* Visiting '/' when Capybara.app_host has a trailing '/' - Issue #1918 [Thomas Walpole]
# Version 2.15.2
Release date: 2017-10-02
### Fixed
* Include within scope description in element not found/ambiguous errors [Thomas Walpole]
* Raise error when no activation block is passed to modal methods if using headless chrome [Thomas Walpole]
* Don't retry element access when inspecting [Ivan Neverov]
* Don't override a specified port (even if it is default port) in visited url [Thomas Walpole]
# Version 2.15.1
Release date: 2017-08-04
### Fixed
* `attach_file` with no extension/MIME type when using the `:rack_test` driver [Thomas Walpole]
# Version 2.15.0
Release date: 2017-08-04
### Added
* `sibling` and `ancestor` finders added [Thomas Walpole]
* Added ability to pass options to registered servers when setting
* Added basic built-in driver registrations `:selenium_chrome` and `:selenium_chrome_headless` [Thomas Walpole]
* Add `and_then` to Capybara RSpec matchers which behaves like the previous `and` compounder. [Thomas Walpole]
* Compound RSpec expectations with Capybara matchers now run both matchers inside a retry loop rather
than waiting for one to pass/fail before checking the second. Will make `#or` more performant and confirm
both conditions are true "simultaneously" for `and`. [Thomas Walpole]
If you still want the
* Default filter values are now included in error descriptions [Thomas Walpole]
* Add `Session#refresh` [Thomas Walpole]
* Loosened restrictions on where `Session#within_window` can be called from [Thomas Walpole]
* Switched from `mime-types` dependency to `mini_mime` [Jason Frey]
# Version 2.14.4
Release date: 2017-06-27
### Fixed
* Fix retrieval of session_options for HaveSelector matcher descriptions - Issue #1883
# Version 2.14.3
Release date: 2017-06-15
### Fixed
* Minitest assertions now raise the correct error type - Issue #1879 [Thomas Walpole]
* Improve flexibility of detecting Chrome headless mode [Thomas Walpole]
# Version 2.14.2
Release date: 2017-06-09
### Fixed
* Workaround for system modals when using headless Chrome now works if the page changes
# Version 2.14.1
Release date: 2017-06-07
### Fixed
* Catch correct error when unexpected system modals are discovered in latest selenium [Thomas Walpole]
* Update default `puma` server registration to encourage it to run in single mode [Thomas Walpole]
* Suppress invalid element errors raised while lazily evaluating the results of `all` [Thomas Walpole]
* Added missing `with_selected` option to the :select selector to match `options`/`with_options` options - Issue #1865 [Bartosz Nowak]
* Workaround broken system modals when using selenium with headless Chrome
# Version 2.14.0
Release date: 2017-05-01
### Added
* "threadsafe" mode that allows per-session configuration
* `:type` filter added to the `:fillable_field` selector
* Proxy methods when using RSpec for `all`/`within` that call either the Capybara::DSL or RSpec matchers
depending on arguments passed
* Support for the new errors in selenium-webdriver 3.4
### Fixed
* Element#inspect doesn't raise an error on obsolete elements
* Setting a contenteditable element with Selenium and Chrome 59
* Workaround a hang while setting the window size when using geckodriver 0.16 and Firefox 53
* Clicking on url with a blank href goes to the current url when using the RackTest driver
# Version 2.13.0
Release date: 2017-03-16
### Added
* Selenium driver supports returning element(s) from evaluate_script [Thomas Walpole]
* rack_test driver supports click on checkboxes and radio buttons to change their states [Thomas Walpole]
* Support RSpec equivalent assertions and expectations for MiniTest [Thomas Walpole]
### Fixed
* Editing of content editable children with selenium
# Version 2.12.1
Release date: 2017-02-16
### Fixed
* Disable lazy Capybara::Results evaluation for JRuby due to ongoing issues
# Version 2.12.0
Release date: 2017-01-22
### Added
* Session#switch_to_frame for manually handling frame switching - Issue #1365 [Thomas Walpole]
* Session#within_frame now accepts a selector type (defaults to :frame) and locator [Thomas Walpole]
* Session#execute_script and Session#evaluate_script now accept optional arguments that will be passed to the JS function. This may not be supported
by all drivers, and the types of arguments that may be passed is limited. If drivers opt to support this feature they should support passing page elements. [Thomas Walpole]
* :exact option for text and title matchers - Issue #1256 [Thomas Walpole]
* :exact_text option for selector finders/minders - Issue #1256 [Thomas Walpole]
* Capybara.exact_text setting that affects the text matchers and :text options passed to selector finders/matchers. Issue #1256 [Thomas Walpole]
* :make_visible option for #attach_file that allows for convenient changing of the CSS style of a file input element before attaching the file to it. Requires driver
support for passing page elements to Session#execute_script [Thomas Walpole]
* assert_all_selectors/assert_none_of_selectors assertions added
* :link selector (used by find_link/click_link) now supports finding hyperlink placeholders (no href attribute) when href: nil option is specified [Thomas Walpole]
* `within_element` as an alias of `within` due to RSpec collision
### Fixed
* Fields inside a disabled fieldset are now correctly considered disabled - Issue #1816 [Thomas Walpole]
* Lazy Capybara::Results evaluation enabled for JRuby 9.1.6.0+
* A driver returning nil for #current_url won't raise an exception when calling #current_path [Dylan Reichstadt]
* Support Ruby 2.4.0 unified Integer [Koichi ITO]
* RackTest driver no longer modifies the text content of textarea elements in order to behave more like a real browser [Thomas Walpole]
* TextQuery (assert_text/have_text/etc) now ignores errors when trying to generate more helpful errors messages so the original error isn't hidden [Thomas Walpole]
# Version 2.11.0
Release date: 2016-12-05
### Added
* Options for clearing session/local storage on reset added to the Selenium driver
* Window size changes wait for the size to stabilize
* Defined return value for most actions
* Ignore specific error when qutting selenium driver instance - Issue #1773 [Dylan Reichstadt, Thomas Walpole]
* Warn on selenium unknown errors rather than raising when quitting driver [Adam Pohorecki, Thomas Walpole]
* Capybara::Result#each now returns an `Enumerator` when called without a block - Issue #1777 [Thomas Walpole]
### Fixed
* Selenium driver with Chrome should support multiple file upload [Thomas Walpole]
* Fix visible: :hidden with :text option behavior [Thomas Walpole]
# Version 2.10.2
Release date: 2016-11-30
### Fixed
* App exceptions with multiple parameter initializers now re-raised correctly - Issue #1785 [Michael Lutsiuk]
* Use Addressable::URI when parsing current_path since it's more lenient of technically invalid URLs - Issue #1801 [Marcos Duque, Thomas Walpole]
# Version 2.10.1
Release date: 2016-10-08
### Fixed
* App errors are now correctly raised with the explanatory cause in JRuby [Thomas Walpole]
* Capybara::Result optimization disabled in JRuby due to issue with lazy enumerator evaluation [Thomas Walpole]
See: https://github.com/jruby/jruby/issues/4212
# Version 2.10.0
Release date: 2016-10-05
### Added
* Select `