How can I test the page title with Capybara 2.0?
capybara, rspec, ruby-on-rails
Solution
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!
Update 1:
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') }
Update 2:
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")
Problem
Trying to test that page contains `<title>My Title</title>` with: ``` # spec/features/reports_spec.rb require 'spec_helper' feature "Archive Management" do subject { page } describe "Index Page" do before(:all) { 10.times { FactoryGirl.create(:randomreport) } } after(:all) { Report.delete_all } describe "when no search terms present" do before { visit reports_path } it { should have_selector('title', text: 'My Title') } # <= Fails w/Capybara 2.0 it { should have_selector('title') } # <= passes it { should have_text('My Title') } # <= passes it { should have_selector('h2', text: "Welcome") } # <= passes end end end ``` Error message: ``` Failure/Error: it { should have_selector('title', text: base_title) } Capybara::ExpectationNotMet: expected to find css "title" with text "My Title" but there were no matches. Also found "", which matched the selector but not all filters. ``` I know I'm overlooking the painfully obvious but can't figure out what it is? Are `<title>` tags no longer considered 'selectors'?!? Or...?!? Edit (debugger info): If I drop down into the debugger as cleverly suggested by @shioyama it is clear that the page.body contains `<title>My Title</title>`. The same page.body that contains `<h2>Welcome to My Title Project</h2>` and passes! It appears to find the `<title>`...`</title>` tag but not `My Title` within it. But it does find `My Title` later in the page within `<a href=\"/\" class=\"brand\">My Title</a>` and/or in `<h2>Welcome to The My Title Project</h2>`: ``` (rdb:1) p page #<Capybara::Session> (rdb:1) p page.body "<!DOCTYPE html>\n<html>\n<head>\n<title>My Title</title>\n <meta content='research, report, technology' name='keywords'>\n<meta content='Some Project' name='description'>\n<link href=\"/assets/application.css\" ... </head>\n<body>\n<header class='navbar navbar-fixed-top navbar-inverse'>\n<div class='navbar-inner'>\n<div class='container'>\n <a href=\"/\" class=\"brand\">My Title</a>\n<div class='pull-right'>\n <ul class='nav'>\n<li><a href=\"/about\">About</a></li>\n<li><a href=\"/help\">Help</a> </li>\n</ul>\n<form accept-charset=\"UTF-8\" action=\"/reports\" class=\"navbar-search\" method=\"get\"><div style=\"margin:0;padding:0;display:inline\"> <input name=\"utf8\" type=\"hidden\" value=\"✓\" /></div>\n <input class=\"search-query\" id=\"query\" name=\"query\" placeholder=\"Search\" type=\"text\" />\n</form>\n\n</div>\n</div>\n</div>\n</header>\n\n <div class='container'>\n<div class='hero-unit center'>\n<h1>My Title</h1>\n <h2>Welcome to The My Title Project</h2>\n<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ... ``` What else could I try in the debugger to figure out why have_selector?('title', text: ...) is failing? So, what is the proper way to test for a title in Capybara 2.0?