Best practice for testing capybara visit page - ruby-on-rails

So I was wondering what the best way is to go about testing that a page was actually visited using capybara
describe "Pages" do
subject { page }
describe "Home page" do
it "should have the title 'My Home Page'" do
visit root_path
expect(page).to have_title('My Home Page')
end
end
end
Now it seems like the standard way to test this is to compare the title of the page (as above). This doesn't seem super robust though, as if the page title changes, it will break any tests that reference this.
Is this the standard practice? or is there another way to test it.
Thanks,
Matt

I don't think that the example you gave is the standard way to test that a page is visited. It is the standard way to see if the page's title match what you expect =P
If you want to make an assertion about the path in capybara, a much more reliable way to do it is using current_path. So, you can rewrite your example as follows:
describe "Pages" do
describe "Home page" do
it "will visit root_path" do
visit root_path
expect(current_path).to eql root_path
end
end
end
Notice that this is not a much valuable test though. We all know that capybara is well tested and that it will visit root_path if we tell it to do so. Anyways, if you want to make a sanity check or something, this is the right way to go.
I hope it helps !

Related

Capybara testing with RSpec in Ruby

on my index page I have this div:
<div class="banner">
<h1 class="glow-header">Galaxy Far, Far Away? Quick Trip to Mars?<br>
Pianeta has you covered.</h1>
<div>
In my testfile this works:
RSpec.describe 'home features' do
it 'displays the name of the app and links to the index-all planets page' do
visit root_path
expect(page).to have_content('Space is full of surprises.')
click_link('Go Beyond')
expect(current_path).to eq('/planets')
expect(page).to have_content('Galaxy Far, Far Away?')
end
end
But I would like it to be working with the h1 included.
I did this:
expect(page).to have_content('<h1 class="glow-header">Galaxy Far, Far Away? Quick Trip to Mars?<br>
Pianeta has you covered.</h1>')
end
But the test failed. What did I do wrong ?
The #has_content?/#has_text? method only checks the text content of the page. It does not look at the HTML tags.
If you want to check for content within a specific HTML element there is a #within method that takes a block and will scope the Capybara lookups within it to be within the matched element. The element referenced by #within must exist or Capybara will raise an exception.
page.within('h1.glow-header') do
expect(page).to have_content('Galaxy Far, Far Away?')
end
If you don't want to deal with scoping using within for a single expectation you could do
expect(page).to have_css('h1.glow-header', text: 'Galaxy Far, Far Away?')
If you've already got a reference to the header you could also do something like
header = find('h1.glow-header')
...
expect(header).to have_text('Galaxy Far, Far Away?')
Additionally you should not be doing expect(current_path).to eq('/planets'). Using RSpecs eq matcher with Capybara will lead to flaky tests as soon as you move to using an asynchronous (JS supporting) driver, because it prevents Capybaras auto waiting/retrying behaviors. Instead you should use the Capybara provided matcher
expect(page).to have_current_path('/planets')

Testing ruby with rails, Element not found

I get the error:
Capybara::ElementNotFound:
Unable to find field "user_email"
And this is the test code:
feature 'User' do
given!(:user) { User.new(email: 'testuserid#example.com', encrypted_password: 'test') }
scenario 'opens sign_up page' do
visit new_user_session_path
expect(page).to have_content 'unique text on the page'
end
scenario 'signs in with invalid email' do
visit new_user_session_path
fill_in('user_email',with: 'ssd')
expect(page).to have_content 'unique text on the page'
end
end
My HTML file consists of this code literally:
unique text on the page
<br>
<input type="text" id="user_email">
So this proves that the path is correct because my first scenario runs correctly. It is visiting the right page. But still I get this error for second scenario in fill_in.
I have also tried element = page.find("user_email"), it gives same error.
What am I possibly doing wrong?
I have been scratching my head like hell.
Usually the reason for this is that the input isn't actually visible on the page. You can verify this by doing
fill_in('user_email', with: 'ssd', visible: false)
If that succeeds in finding the element, then you need to change your test to first perform whatever actions make the field visible before attempting to fill it in.
Your code seems right. Maybe you are visiting wrong url or you have used user_email id once more. But you can give a try with alternative syntax like following :
find("input[id$='user_email']").set "ssd"

Capybara can't click link, response contains shows the link

I'm trying to write a test that clicks a link but when I run the test, Capybara returns the following error:
"no link with title, id or text 'New Mwod post' found
so I put a 'debugger' and printed the response. The body contained the following:
New Mwod post
the test has the following code:
describe "GET /mwod_posts/new" do
it "creates a new mwod post" do
FactoryGirl.create(:mwod_tag)
get mwod_posts_path
debugger
response.status.should be(200)
click_link "New Mwod post"
end
end
Any ideas why capybara can't click the link?
The problem is that you're using get when you should be using visit.
Switch:
get mwod_posts_path
to:
visit mwod_posts_path
That will let you click links with click_link etc. To parse the response, you'll need to change:
response.status.should be(200)
to:
page.response_code.should be(200)
I haven't actually confirmed that this works, but discussion elsewhere would seem to indicate you can check response codes this way from page. Although, as noted in that discussion, this is not something you should really be doing in integration tests.
For more see on the difference between get and visit see this answer and this post. (This is a common point of confusion.).

Testing a view renders translated content when content is html_safe?

Been trying to find out how to write a test that tests that a view renders correct content when the content is translation keys with html. To explain a bit more in detail I have this rspec test:
require 'spec_helper'
describe "application/error_404.html.erb" do
I18n.available_locales.each do |locale|
it "should have 'not found text' in #{locale}" do
I18n.locale = locale
render
rendered.should have_content I18n.t(:not_found_html)
end
end
end
to test that it renders :not_found_html for each locale I have available. But the test fails due to that it looks for a string without the html:
Failure/Error: rendered.should have_content I18n.t(:not_found_html)
expected there to be content "Could not find the page or item you tried to view.
Please try again and if the problem persists please <a href=\"%{contact_link} \">let us
know</a> so we can fix this."
in
"\n\t\n\t\t\tNot found\n\t\t\n\t\n\t\t\t\n\t\t\t\tCould not find the page or item you tried
to view. Please try again and if the problem persists please let us know so we can fix
this.\n\t\t\t\t\n\t\t\n\t"
I do not know enough of rails to know how to make this work. I would need some way I guess to render just the I18n string? Any help on this would be much appreciated.
I18n.t(:not_found_html) renders just the string.
You could do:
I18n.available_locales.each do |l|
I18n.locale = l
I18n.translate! :not_found_html
end
It'd raise an I18n::MissingTranslationData if not found.

How to test css property in rspec?

I'm using tabnav plugin for Rails and I want to use rpsec to make sure it highlights properly.
describe 'account navigation links' do
it 'should have account settings link' do
get '/account/settings'
response.should have_tag("li", :text => "Account Settings")
end
it 'should be highlighted' do
get '/account/settings'
response.should have_tag("li", :color => "Account Settings")
end
end
However the above code doesn't seem to work. I'm using webrat with rspec btw. Any help? Thanks.
The only real thing to be testing here is whether or not a particular class name is applied, if highlighting comes from a class name. If so, you could do have_tag("li.highlighted", :text => "Account Settings").
Otherwise, you probably should not be automating your testing for whether or not the CSS selectors themselves are applied correctly. This is a purely presentational detail, and it isn't really what a test suite is designed to test. I suspect that Webrat doesn't bother to go through and apply your stylesheet for you, so testing that detail isn't feasible, not to mention that you could check with just one page load whether or not it's working - after all, you are arguably testing your stylesheet as you design it.
Anyway. Your question doesn't really make clear what you're really trying to test for, but you shouldn't be testing presentation, anyway. Testing the structure of the HTML document is good, but confirming how the client program interprets the document is the role of a designer, not a programmer. (If you wear both hats, so be it, but don't go mixing your foods.)
describe 'highlighting' do
it 'should highlight account/settings' do
get '/account/settings'
response.should have_tag("a.active[href=?]", account_settings_path, /Account Settings/i)
end
it 'should highlight account/profile' do
get '/account/profile'
response.should have_tag("a.active[href=?]", account_profile_path, /Profile Information/i)
end
it 'should highlight account/picture' do
get '/account/picture'
response.should have_tag("a.active[href=?]", account_picture_path, /Profile Picture/i)
end
it 'should highlight account/notifications' do
get '/account/notifications'
response.should have_tag("a.active[href=?]", account_notifications_path, /Notifications/i)
end
it 'should not highlight Profile' do
get '/account/profile'
response.should_not have_tag("a.active[href=?]", account_settings_path, /Account Settings/i)
end
it 'should not highlight Notifications' do
get '/account/profile'
response.should_not have_tag("a.active[href=?]", account_notifications_path, /Notifications/i)
end
it 'should not highlight Picture' do
get '/account/profile'
response.should_not have_tag("a.active[href=?]", account_picture_path, /Profile Picture/i)
end
end
You could write more test, especially for "doesn't highlight on wrong action" scenarios, but I think this is good enough.
If you're using Sass you can parse it with the Sass parser:
root = Sass::SCSS::Parser.new('.error { color: red; }', 'example.scss').parse
It returns a parse tree you could test by diving into it. For example:
prop = root.children.select {|child| child.rule.flatten.include?('.error')}.first
prop_strings = prop.children.map {|p| [p.name.flatten.first, p.value].join(':')}
prop_strings.should include?('color:red')

Resources