Trying to test that page contains
with:
# spec/features/reports_spec.rb
require \'spec_helper\'
feature \"A
I had this problem only when using 'shared_examples_for', maybe because of other changes. I also noticed that when I placed
<title>My Title</title>
in the body of the page (where it doesn't belong and won't render), the test passed. Not a good thing!
This worked:
it{should have_title("My Title")}
(capybara 2.1.0, launchy 2.3.0, nokogiri 1.5.9, rspec 2.13)
Capybara 2.1 changed its support for querying the title element. So using have selector in to query for the title element in the head of the html doc in this fashion will fail "page.should have_selector('title', :text => 'Some text'). From what i understand the preferred method in capybara 2.1 new API is to use "page.should have_title('Some text')" to query the title element should work.
i ran into the same issue when upgrading capybara from version 1.x to > 2.0
The problem is that Capybara ignores invisible text in its matchers. The cleanest way to address this issue is to use the :visible => false
option on finders.
e.g.
it { should have_selector('title', text: 'My Title', visible: false) }
Another (global) option is to set:
Capybara.ignore_hidden_elements = false
I know this has an accepted answer already, but for what it's worth, you can do the following, in less lines of code:
title = first("head title").native.text
expect(title).to == "What you expect it to match"
This allows access to the native driver element; further, since Capybara 2.0 ignores invisible text (title is invisible except to the browser), you would need this (or a similar workaround) to satisfy this case. (See https://github.com/jnicklas/capybara/issues/863)
I had the same issues when I upgraded to Capybara 2.0, and managed to solve them by creating the following custom RSpec matcher using Capybara.string:
spec/support/utilities.rb
RSpec::Matchers::define :have_title do |text|
match do |page|
Capybara.string(page.body).has_selector?('title', text: text)
end
end
Now, in a spec file where subject { page }
, I can use:
it { should have_title("My Title") }
it { should_not have_title("My Title") }
As an aside, the conversation on this question was extremely helpful in getting me to this answer, so thank you!
If you don't want to create a custom RSpec matcher, thanks to this StackOverflow answer by user dimuch I now know that you can call have_selector
directly on page.source (aliased page.body
) to test for non-visible DOM elements:
it "should show the correct title" do
page.source.should have_selector('title', text: 'My Title')
end
or where subject { page }
:
its(:source) { should have_selector('title', text: 'My Title') }
From Capybara 2.1, there are built-in have_title
/has_title?
matchers, negating the need for the custom RSpec matcher in this answer. Furthermore, the its(:source) { ... }
tests described in Update 1 seem to break under Capybara 2.1; I've confirmed the have_title
/has_title?
work as expected, so it's probably best to go with the following syntax if you plan on upgrading:
When subject { page }
:
it { should have_title("My Title") }
it { should_not have_title("My Title") }
When using expect
syntax within an it
/scenario
block:
expect(page).to have_title("My Title")
expect(page).to_not have_title("My Title")
I see two possible issues here:
<title>
tag is present on the page but the text My Title
is somewhere else on the page, not within the tag. That would explain why the other tests pass: there is a <title>
tag on the page so have_selector('title')
passes, and there is the My Title
text on the page so have_text(base_title)
passes.<title>
tag contains the text My Title
as well as something else, which would also explain the results you see: there is a <title>
tag on the page so have_selector('title')
passes, and there is the text My Title
so the have_text(base_title)
also passes, however the text
option in have_selector
is strict, therefore it will fail if it finds a string which does not exactly equal My Title
.You can check the latter of these two possibilities using the xpath selector: should have_xpath("//title[contains(.,'#{base_title}')]")
. If that passes, then you probably have some whitespace or newlines around your title text which are tripping have_selector
up (I thought it ignored those, but I could be wrong).
Hope that helps.