I'm following this tutorial here, and everything has worked out very well so far.
But now that I've progressed to sessions, some simple rspec tests are failing:
describe SessionsController do
#[...]
describe "GET 'new'" do
it "should have the right title" do
get :new
response.should have_selector( "title", :content => "Sign in" )
end
end
#[...]
describe "POST 'create'" do
#[...]
it "should have the right title" do
post :create, :session => #attr
response.should have_selector("title", :content => "Sign in")
end
#[...]
end
end
When I run rspec, I always get:
1) SessionsController GET 'new' should
have the right title
Failure/Error: response.should have_selector( "title", :content =>
"Sign in
)
expected following output to contain a Sign in tag:
w3.org/TR/REC-html40/loose.dtd">
# ./spec/controllers/sessions_controller_spec.rb:14:in
`block (3 levels) in '
When I access the sessions/new page, the page contains a title tag like the following:
<title>Ruby on Rails Tutorial Sample App | Sign in</title>
Why do those tests fail, while all other similar (= tests for the title tag) tests work fine?
Here's the SessionController:
class SessionsController < ApplicationController
def new
#title = 'Sign in'
end
def create
user = User.authenticate( params[:session][:email], params[:session][:password] )
if user.nil?
flash.now[:error] = "Invalid email/password combination."
#title = 'Sign in'
render 'new'
else
sign_in user
redirect_to user
end
end
def destroy
sign_out
redirect_to root_path
end
end
What am I doing wrong here?
thx for your help
You need to add render_views to the top of the class. Without it, the actual html will not be generated and your have_selector tests will fail.
Related
I have a test I'm trying to pass but I can't get it to pass, I am new to this.
Here's a link to my git repository https://github.com/FrankWiebe/nameofapp
The failure message comes up like so:
1) UsersController GET #show No user is logged in redirects to login
Failure/Error: expect(response).to redirect_to(root_path)
Expected response to be a <redirect>, but was <200>
# ./spec/controllers/users_controller_spec.rb:24:in `block (4 levels) in <top (required)>'
This is the code:
require 'rails_helper'
describe UsersController, :type => :controller do
before do
#user = User.create(email: "doe#example.com", password: "1234567890")
end
describe "GET #show" do
context "User is logged in" do
before do
sign_in #user
end
it "loads correct user details" do
get :show, id: #user.id
expect(response).to have_http_status(200)
expect(assigns(:user)).to eq #user
end
end
context "No user is logged in" do
it "redirects to login" do
get :show, id: #user.id
expect(response).to redirect_to(root_path)
end
end
end
end
Perhaps #user is carried on as being logged in from one test to the next, so the 2nd show succeeds. Try to sign off the user whithin the first test.
As this is not the case, check your config/routes.rb.
Resources requiring login should be wrapped within a do...end
authenticate(:user) do
resources :user
...other stuff
end
I am trying to write tests and application code to redirect users who are already signed-in to the root_path if they try to CREATE a user or visit the NEW user path.
Here are the tests I have written in user_pages_spec.rb:
describe "for signed in users" do
let(:user) { FactoryGirl.create(:user) }
before { sign_in user }
describe "using a 'new' action" do
before { get new_user_path }
specify { response.should redirect_to(root_path) }
end
describe "using a 'create' action" do
before { post users_path }
specify { response.should redirect_to(root_path) }
end
end
UsersController:
class UsersController < ApplicationController
before_action :unsigned_in_user, only: [:create, :new]
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
private
# Before filters
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
def unsigned_in_user
puts signed_in?
redirect_to root_url, notice: "You are already signed in." unless !signed_in?
end
end
The puts signed_in? returns false. I am assuming this is the problem because I would expect it to return true. Here are the errors after running the tests using rspec. Any help is appreciated.
Failures:
1) User pages for signed in users using a 'create' action
Failure/Error: before { post users_path }
ActionController::ParameterMissing:
param not found: user
# ./app/controllers/users_controller.rb:52:in `user_params'
# ./app/controllers/users_controller.rb:20:in `create'
# ./spec/requests/user_pages_spec.rb:162:in `block (4 levels) in <top (required)>'
2) User pages for signed in users using a 'new' action
Failure/Error: specify { response.should redirect_to(root_path) }
Expected response to be a <redirect>, but was <200>
# ./spec/requests/user_pages_spec.rb:158:in `block (4 levels) in <top (required)>'
Within the sessions_helper.rb file:
def signed_in?
!current_user.nil?
end
In spec/support/utilities.rb:
def sign_in(user, options={})
if options[:no_capybara]
# Sign in when not using Capybara.
remember_token = User.new_remember_token
cookies[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
else
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
end
Were you able to get your tests to pass?
In case you weren't, I had the same problem as you today, and was able to get the tests to pass by making two changes to the tests - passing a user hash when POSTing, and using the no_capybara option on the sign_in method, since get and post are not capybara methods and I think RSpec doesn't behave as we might expect if we switch from capybara to non-capybara methods within the same test.
describe "for signed-in users" do
let(:user) { FactoryGirl.create(:user) }
before { sign_in user, no_capybara: true }
describe "using a 'new' action" do
before { get new_user_path }
specify { response.should redirect_to(root_path) }
end
describe "using a 'create' action" do
before do
#user_new = {name: "Example User",
email: "user#example.com",
password: "foobar",
password_confirmation: "foobar"}
post users_path, user: #user_new
end
specify { response.should redirect_to(root_path) }
end
end
Same answer as najwa, but I used the FactoryGirl user with the Rails attributes method to avoid duplication:
describe "using a 'create' action" do
before { post users_path, user: user.attributes }
specify { response.should redirect_to(root_path) }
end
Helps to keep the data decoupled from the test code.
I'm newbie on ruby on rails and I'm trying to test my controller with respect on ruby on rails.
It worked before, but now I don't know what happened, but when I do the test, I got the next error message:
/Library/Ruby/Gems/1.8/gems/rspec-core-2.10.1/lib/rspec/core/configuration.rb:746:in `load': no such file to load -- /Users/armandodejesussantoyareales/Documents/project_newbie/Estaciones/estaciones/spec/controllers/user_controller_spec.rb (LoadError)
this is my spec file:
require 'spec_helper'
describe UserController do
it "create new user" do
get :create, :user => { :email => 'foo#example.com', :name => 'userexample' }
flash[:notice] = 'new user was successfully created.'
end
describe "signup" do
before { visit signup_path }
let(:submit) { "Create my account" }
describe "with invalid information" do
it "should not create a user" do
expect { click_button submit }.not_to change(User, :count)
end
end
describe "with valid information" do
before do
fill_in "Name", with: "Example User"
fill_in "Email", with: "user#example.com"
fill_in "Password", with: "foobar"
fill_in "Confirmation", with: "foobar"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
end
and this is my Usercontroller
class UserController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to user_session_path
else
redirect_to new_user_session_path
end
def show
#user = User.find(params[:id])
#redirect_to #user
end
end
/Users/armandodejesussantoyareales/Documents/project_newbie/Estaciones/estaciones/spec/controllers/user_controller_spec.rb
Are you sure that's the right path? In a terminal, what happens when you do type in:
ls /Users/armandodejesussantoyareales/Documents/project_newbie/Estaciones/estaciones/spec/controllers/user_controller_spec.rb
If you get an error saying No such file or directory, then that path doesn't exist. If it just echoes back the path, then it's fine.
Alternatively, you can just manually look for this file and verify the path. But either way, my guess is you are just entering the path to your spec file incorrectly.
Here is my current users_controller_spec.rb file
require 'spec_helper'
describe UsersController do
render_views
.
.
.
describe "success" do
before(:each) do
#attr = { :name => "New User", :email => "user#example.com",
:password => "foobar", :password_confirmation => "foobar" }
end
it "should create a user" do
lambda do
post :create, :user => #attr
end.should change(User, :count).by(1)
end
it "should redirect to the user show page" do
post :create, :user => #attr
response.should redirect_to(user_path(assigns(:user)))
end
end
end
end
When I run this I get the following:
Failures:
1) UsersController POST 'create' success should redirect to the user show page
Failure/Error: response.should redirect_to(user_path(user))
ActionController::RoutingError:
No route matches {:action=>"show", :controller=>"users"}
# ./spec/controllers/users_controller_spec.rb:95:in `block (4 levels) in <top (required)>'
Which leads me to believe that :user isn't an actual object. How can I test this and how can I change :user into an object that user_path understands.
Thanks in advance for any help.
UPDATED:
def create
#title = "Sign up"
#user = User.new(params[:user])
if #user.save
redirect_to #user, :notice => "Signed Up!"
else
#title = "Sign up"
render "new"
end
end
When I run the following:
it "should redirect to the user show page" do
post :create, :user => #attr
user = assigns(:user)
user.should_not be_blank
puts "user errors are: #{user.errors.full_messages.inspect}" unless user.is_valid?
user.should be_valid
response.should redirect_to(user_path(user))
end
I get:
1) UsersController POST 'create' success should redirect to the user show page
Failure/Error: user.should_not be_blank
expected blank? to return false, got true
# ./spec/controllers/users_controller_spec.rb:94:in `block (4 levels) in <top (required)>'
Try using assigns with brackets instead of parenthesis.
assigns[:user]
(RSpec docs)
EDIT
One pattern I always use when testing controller actions is to ensure that a variable required by the associated view(s) is assigned. For example,
it "should assign an #user variable" do
post :create, :user => #attr
assigns[:user].should_not be_nil
assigns[:user].should be_kind_of(User)
end
You've got a typo
response.should redirect_to(user_path(:user))
should be
response.should redirect_to(user_path(user))
Edit:
Try checking that the user is valid with:
it "should redirect to the user show page" do
post :create, :user => #attr
user = assigns(:user)
user.should_not be_blank
puts "user errors are: #{user.errors.full_messages.inspect}" unless user.is_valid?
user.should be_valid
response.should redirect_to(user_path(user))
end
I know it works on the previous test case... but still worth checking extensively at least once here. You can remove all that guff when you're certain.
In your test:
it "should redirect to the user show page" do
#user = Factory(:user)
post :create, :user => #attr
user = assigns(:user)
response.should redirect_to(user_path(#user))
end
Your #attr hash is different from #user. You are creating user with attributes of #attr, and asserting that it should redirect to #user show (which is different from one created). Change to:
it "should redirect to the user show page" do
post :create, :user => #attr
user = assigns(:user)
response.should redirect_to(user_path(user))
end
I'm running rails 3.0.9 and ruby 1.9.2 and working from the Hartl ruby on rails tutorial. I'm also running spork. Using factory_girl_rails v. 1.1.0
Failures:
1) UsersController GET 'show' should be successful
Failure/Error: #user = Factory(:user)
ActiveRecord::RecordInvalid:
Validation failed: Name can't be blank
# ./spec/controllers/users_controller_spec.rb:9:in `block (3 levels) in <top (required)>'
Finished in 0.38122 seconds
3 examples, 1 failure
Failed examples:
rspec ./spec/controllers/users_controller_spec.rb:12 # UsersController GET 'show' should be successful
Mr factories.rb file
Factory.define :user do |user|
user.name "Michael Hartl"
user.email "mhartl#example.com"
user.password "foobar"
user.password_confirmation "foobar"
end
User_controller_spec.rb file
require 'spec_helper'
describe UsersController do
render_views
describe "GET 'show'" do
before(:each) do
#user = Factory(:user)
end
it "should be successful" do
get :show, :id => #user
response.should be_success
end
# it "show the right user" do
# get :show, :id => #user
# assigns(:user).should == #user
# end
end
describe "GET 'new'" do
it "should be successful" do
get 'new'
response.should be_success
end
it "should have the right title" do
get :new
response.should have_selector('title', :content => "Sign up")
end
end
end
show.html.rb file
<%= #user.name %>, <%= #user.email %>
Just a thought, but did you restart the Spork server? This is sometimes necessary, see Spork: how to refresh validations and other code? for more info.