Using cucumber to check page titles - ruby-on-rails

Feature
Scenario: As a user that has not signed in I want to be able to sign up for provisioner
Given I am not logged in
When I go to the home page
And click on the "Sign Up" button
Then I should be on the page with the title: "Sign Up"
When I provide valid information
And click the "Submit" button
Then I should see "Account is being created and verified, you will receive an email with instructions once account has been approved"
And the application should send the administrator an email
And I should be redirected to the home page as an anonymous user
Steps
When /^I go to the home page$/ do
visit root_path
end
When /^click on the "([^"]*)" button$/ do |page_name|
click_link page_name
end
Then /^I should be on the page with the title: "([^"]*)"$/ do |page_title|
response.should have_selector('title', :content => "#{page_title}")
end
Error
expected css "title" to return something (RSpec::Expectations::ExpectationNotMetError)
It fails at the Then step, however the page does render with the title: "Sign Up" when I manually go to it. I want it to make sure it's going to the right place in the test. How do I have it check?
Thanks for all the help in advance.

try this:
page.should have_css('head title', :text => title)

Since 2.1 you can do that:
expect(page).to have_title "my_title"

It might happen because by default capybara selector is set to CSS try change it to
response.should have_xpath('//title', :text => "#{page_title}")

If you are using cucumber-rails gem, try using
assert page.has_title?(page_title), "page has title of '#{page.title}'"

Related

Capybara::ElementNotFound: Unable to find visible link

I'm having trouble with my test for a method which lets an admin user promote other users to admin by the click of "Promote to Admin". It lies in my controller, I'm writing a feature test for it. I'm using Rails 5.1.4.
def promote
#user = User.find(params[:user_id])
if #user.toggle!(:admin)
flash[:success] = "User is promoted to admin."
redirect_to root_path
else
flash[:notice] = "Can't promote."
redirect_to root_path
end
end
This is the test:
describe "Promotion" do
before do
login_as(User.create!(name: "lala", email: Faker::Internet.email,
password: "lalala", admin: true))
visit users_path
end
context "to admin" do
it "promotes user to admin" do
click_link("Promote to Admin", :match => :first)
expect(current_path).to eq user_promote_path
end
end
end
It gives me the error: Capybara::ElementNotFound:
Unable to find visible link "Promote to Admin"
which I think is because I'm not accessing the right page, trying to log in as admin is perhaps not working.
Any suggestion would be very appreciated!
The most likely reason for your test failing is that you don't appear to have created any other users beyond the one you're logging in as. If you haven't then there wouldn't be any users to show "Promote to Admin" links for. You can always save the page or just do puts page.html to make sure what you think is on the page actually is.
A second issue with your test is that you should never use the eq matcher with current_path. You should be using the Capybara provided path matcher of you want stable tests
expect(page).to have_current_path(user_promote_path)
If you want to be sure that you're on the right page, you can do some debugging with:
save_and_open_page (opens your browser)
save_and_open_screenshot (takes a screenshot and opens it)
If it's all good, maybe Capybara can't find the link : Is it a screen size/responsive issue ? If yes, you can configure the window size that Capybara uses (see this link)
If the test still does not pass, maybe the link is not visible by default ?
You can add to option visible: false in click_link to precise that.

How to check page content after button click correctly?

I want to check if there loads correct page after clicking 'sign in' button.
users_spec.rb
before :each do
user = User.create(:email => 'admin#cm.com', :password => '123')
end
it "signs me in" do
visit '/users/sign_in'
within("#new_user") do
fill_in 'Email', :with => 'admin#cm.com'
fill_in 'Password', :with => '123'
click_button 'Sign in'
end
expect(page).to have_content '#{user.name}'
end
expect(page).to have_content 'Dashboard' checks is there user.name word on the same page, where the form is located. So, what's the sense in click_button then? How to make it check content on the page that should load AFTER click_button? By the way, how to correctly name such tests?
Sorry, if it's a silly question, I'm a newbie in rspec :c
Thank you!
You have to pick some content that appears on the page after the user logs in. Does your app display a message saying something like "You are now logged in", if so you can do
expect(page).to have_content("You are now logged in")
If not, does it display the users name in a header bar? Then you can do something like
expect(page).to have_css("header", text: user.name)
etc... The key is that whatever you're searching for needs to appear on the next page but not on the page with the form. In both of those cases Capybara will wait up to Capybara.default_max_wait_time seconds while retrying to find the text (assuming you're using a driver other than rack-test) which should give the next page time to load. If you're using the rack-test driver then there is no JS or asynchronous support, the click_button should have submitted a form and the expect won't execute until the next page has loaded.
As for test naming -- name it something that makes sense to you so you know what its doing a year from now.

What is the difference between visit and current_path and use of .should in rails?

Then /^I should be on the free signup page$/ do
*current_path.should == free_signup_path*
end
Then /^I should be on the free signup page$/ do
*visit free_signup_path*
end
What is the difference between these two ?
#visit tells the browser to go to a new url and will initiate a get request to the app being tested. #current_path lets you read the current location the browser is at.
Note: you should stop using current_path.should == some_path, when verifying the current path, and instead use page.should have_current_path(some_path). The have_current_path matcher includes waiting behavior and will help make tests less flaky with JS capable drivers
You use visit to tell rspec to go to that path to validate if something works or is present. For example:
it 'contains the new sessions form' do
visit 'sessions/new'
current_path.should have_content("Sign In")
end
Granted that my sign in form has a button or whatever with the text 'sign in' this test will pass.
You generally have to declare what path the test hould go to in order to detect content.
Hope this helps!

RSpec / Capybara - Failing to log in

I am trying to learn TDD, and can't get this integration test with Capybara and Rspec to work. The user visits the home page, clicks "Login", fills out the form with an "Email" and "Password", clicks "Log in", and then I expect the page to have the content "Signed in Successfully".
home_page_spec.rb
require 'spec_helper'
feature 'Login' do
scenario 'user logs in to the site' do
visit root_path
click_link 'Login'
expect(page).to have_content "Sign in to your account."
fill_in('Email', with: "test1#joijjoi.eud")
fill_in 'Password', with: "password"
click_button 'Log in'
expect(page).to have_content('Signed in Successfully')
end
end
I am getting "Failure/Error: expect(page).to have_content('Signed in Successfully'). Expected to find text "Signed in Successfully" in . . . . " The text that it finds is the sign in page. It is as if the test is finding the Log in button, but either not clicking it, or the button is not forwarding the page, but it works if I do this by hand in the browser. Any suggestions? Thanks.
you can use the gem capybara-screenshot that save the page html and screen shot when a test fails. That way you can debug the issues. Or you can temporarily switch to selenium webdriver for capybara which opens the default browser and executes your tests.

Capybara/Cucumber not finding flash message

I'm having trouble getting Cucumber / Capybara to find a 'success' flash message on a page after a user is logged in. I'm able to see the message if I do it manually in the browser, so I'm thinking I'm doing something wrong in my steps.
user_login.feature
Feature: User login
Scenario: A user successfully logs in from the homepage
Given A user is on the homepage
When the user clicks "Login"
And they fill out the form
Then they should see a success message
step_definition
Given /^A user is on the homepage$/ do
#user = Factory.create(:user)
visit root_path
end
When /^the user clicks "(.*?)"$/ do |arg1|
click_link arg1
end
When /^they fill out the form$/ do
fill_in "email", with: #user.email
fill_in "password", with: "blahblah1"
click_button "Sign in"
end
Then /^they should see a success message$/ do
page.should have_selector ".alert", text: "Logged in!"
end
output
expected css ".alert" with text "Logged in!" to return something (RSpec::Expectations::ExpectationNotMetError)
Basically, I made a DERP. The credentials I was using (password) to fill in the form weren't the same as the user I was creating via FactoryGirl. This was causing an 'invalid email / password' message to appear when I was testing for a 'success' message.
To debug what the page was outputting, I added a page.should have_content "asdfsdfas" in my spec. When the test fails, Cucumber outputs the content it got on the page compared to what you expected it to receive.

Resources