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.
Related
I'm running an acceptance test that includes logging in via /users/sign_in.
How do I set up the test so I can "click" the submit button within a Rspec Capybara test?
Seems that Devise disables the Login submit button and runs javascript to make things work.
<%= f.submit "Log in" %>
produces:
<input type="submit" name="commit" value="Log In" tabindex="4" data-disable-with="Log In" />
The data-disable-with, which devise needs, seems to be breaking capybara testing. I would just like to click the button as per my acceptance test below.
it "logs in and shows success message" do
visit '/users/sign_in'
login_as(user, :scope => :user)
within(".login-details") do
fill_in 'Email', with: user.email
fill_in 'Password', with: 'fakepassword'
end
click_button 'Log in'
expect(page).to have_content 'Success'
end
Is producing:
Capybara::ElementNotFound: Unable to find button "Log in" that is not disabled
Note: I have multiple pages that logging in can send a user to, this example is the simplest test that reveals this bug. So no my goal is not to 'make sure devise works', incase you were wondering 'why do they need this?'
The data-disable-with attribute is used by Rails UJS to change the buttons text after it's been clicked so wouldn't be affecting this test. Looking at the HTML element you posted the value of the button is 'Log In' so, since case matters, you'd need to do
click_button 'Log In'
rather than 'Log in'
I do wonder why you have login_as(user, :scope => :user) in the same code where you're filling in the username and password though, you'd normally only use login_as when you wanted to bypass actually filling in the form and logging in.
My spec:
let(:user) { FactoryGirl.create(:user) }
context 'When user is logged in' do
scenario 'Log in' do
visit login_path
within '.new_user_session' do
fill_in 'username', with: user.email
fill_in 'password', with: user.password
click_on 'Log in'
end
visit new_search_path
expect(page).to have_text "Welcome #{user.name}!"
end
end
The issue is that when visiting new_search_path, even though the login in successful, the page behaves as if there is no user logged in. If I add a sleep(1) call right before visit new_search_path, everything works fine.
Anyone know why this is happening?
I'm using authlogic, capybara, and selenium.
The action triggered.by click_on can occur asynchronously. Therefore, if you do a visit immediately after it can cause the login request to abort and the session cookies never get set. To solve that you need to check for page text/content that indicates the login has succeeded. Something like
expect(page).to have_text 'You are now logged in'
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.
I am testing my rails app with rspec, capybara. Tests are working fine for login.
After login am trying to visit some link, and I could go to the link also but after that it is coming back again to the login page. I am not sure whats wrong with my code. Please help me to figure out the issue.
My test spec file.
require 'spec_helper'
describe "User Login",:js => true do
let(:user) { FactoryGirl.create(:user)}
before(:each) do
visit login_path
fill_in "email", with: user.email
fill_in "password", with: user.password
click_button "Sign in"
end
describe "after login" do
it "should show the left navigation on the dashboard" do
visit "/todos"
visit employees_dashboard_path
page.should have_link('Todo', href: todos_path)
click_link "Todo"
end
end
end
describe "Display the todos list" do
let(:todo) { FactoryGirl.create(:todo)}
it "should disply no todos if the todos are nil" do
expect(Todo.count).to eq(0)
visit "/todos" # I could come till here.
expect(page).to have_content("Todos")
end
end
After vising "/todos" I should see "Todos" as the content on the page but instead am seeling the login page again.
My test trace error:
Display the todos list should disply no todos if the todos are nil
Failure/Error: expect(page).to have_content("Todos")
expected to find text "Todos" in "Please login to access the page Log In
Sign in Forgot Password Close Forgot Password Close"
So am coming back again to the login page. Please tell me why this unexpected behaviour is happening in my code.
Thank you.
In the "Display the todos list" block you are not logging in: you need to either have a similar before(:each) as in the "User login" block or move the entire "display todos" block inside the "User login" block.
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.