Test 10.22 is supposed to be green but it is red. I added create method in users_controller and deleted another create method that was here. Is it possible create error or maybe another reasons for error?
How to fix this?
thanks
errors and files related as below:
ERROR["test_invalid_signup_information", UsersSignupTest, 2016-03-23 16:43:47 +0000]
test_invalid_signup_information#UsersSignupTest (1458751427.59s)
AbstractController::ActionNotFound: AbstractController::ActionNotFound: The action 'create' could not be found for UsersController
test/integration/users_signup_test.rb:8:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/users_signup_test.rb:7:in `block in <class:UsersSignupTest>'
test/integration/users_signup_test.rb:8:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/users_signup_test.rb:7:in `block in <class:UsersSignupTest>'
ERROR["test_valid_signup_information", UsersSignupTest, 2016-03-23 16:43:47 +0000]
test_valid_signup_information#UsersSignupTest (1458751427.61s)
AbstractController::ActionNotFound: AbstractController::ActionNotFound: The action 'create' could not be found for UsersController
test/integration/users_signup_test.rb:21:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/users_signup_test.rb:20:in `block in <class:UsersSignupTest>'
test/integration/users_signup_test.rb:21:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/users_signup_test.rb:20:in `block in <class:UsersSignupTest>'
38/38: [=====================================================] 100% Time: 00:00:05, Time: 00:00:05
Finished in 5.52461s
38 tests, 153 assertions, 0 failures, 2 errors, 0 skips
and my codes
# test/integration/users_signup_test.rb
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, user: {name: "",
email: "user#invalid",
password: "foo",
password_confirmation: "bar"}
end
assert_template 'users/new'
assert_select 'div#error_explanation'
assert_select 'div.field_with_errors'
end
test "valid signup information" do
get signup_path
assert_difference 'User.count', 1 do
post_via_redirect users_path, user: {name: "Example User",
email: "user#example.com",
password: "password",
password_confirmation: "password"}
end
# assert_template 'users/show'
# assert is_logged_in?
end
end
and
# app/controllers/users_corntroller.rb
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def edit
end
def update
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def index
#users = User.paginate(page: params[:page])
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless #user == current_user
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
def create
#user = User.new(user_params)
if #user.save
UserMailer.account_activation(#user).deliver_now
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
end
It looks like you have the create method in the private part of your controller. Move the create method to the public section of the controller. I'm not positive that is the problem but I am not on a development computer to see myself. Btw is this the Mike Hartl tutorial?
Related
I'm plugging away after an extended leave (a year) on the Ruby on Rails Tutorial by Michael Hartl. I'm getting a user_param error in an integration test. I've gone to 4 sources trying to figure out where I'm going wrong on the strong parameters including the documentations.
Since starting up again last week, I have four hours generally getting to know the tutorial project and another twelve hours reading over chapters 7 to 12, then an hour chasing this problem. I keep feeling like I must be scanning too quickly over this stuff & keenly realizing I am not good at tracing errors.
Can anyone shed some light on what I'm missing? I'd also like any tips on trouble shooting this type of thing too! Thanks for your time!
Here's the error message I'm getting from console:
ERROR["test_password_resets", PasswordResetsTest, 2016-10-20 15:24:37 +0000]
test_password_resets#PasswordResetsTest (1476977077.03s)
NoMethodError: NoMethodError: undefined method `[]' for nil:NilClass
app/controllers/password_resets_controller.rb:10:in `create'
test/integration/password_resets_test.rb:14:in `block in <class:PasswordResetsTest>'
app/controllers/password_resets_controller.rb:10:in `create'
test/integration/password_resets_test.rb:14:in `block in <class:PasswordResetsTest>'
ERROR["test_invalid_signup_information", UsersSignupTest, 2016-10-20 15:24:37 +0000]
test_invalid_signup_information#UsersSignupTest (1476977077.04s)
ActionController::ParameterMissing: ActionController::ParameterMissing: param is missing or the value is empty: user
app/controllers/users_controller.rb:52:in `user_params'
app/controllers/users_controller.rb:25:in `create'
test/integration/user_signup_test.rb:12:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/user_signup_test.rb:11:in `block in <class:UsersSignupTest>'
app/controllers/users_controller.rb:52:in `user_params'
app/controllers/users_controller.rb:25:in `create'
test/integration/user_signup_test.rb:12:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/user_signup_test.rb:11:in `block in <class:UsersSignupTest>'
ERROR["test_valid_signup_information_with_account_activation", UsersSignupTest, 2016-10-20 15:24:37 +0000]
test_valid_signup_information_with_account_activation#UsersSignupTest (1476977077.05s)
ActionController::ParameterMissing: ActionController::ParameterMissing: param is missing or the value is empty: user
app/controllers/users_controller.rb:52:in `user_params'
app/controllers/users_controller.rb:25:in `create'
test/integration/user_signup_test.rb:25:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/user_signup_test.rb:24:in `block in <class:UsersSignupTest>'
app/controllers/users_controller.rb:52:in `user_params'
app/controllers/users_controller.rb:25:in `create'
test/integration/user_signup_test.rb:25:in `block (2 levels) in <class:UsersSignupTest>'
test/integration/user_signup_test.rb:24:in `block in <class:UsersSignupTest>'
FAIL["test_should_get_edit", PasswordResetsControllerTest, 2016-10-20 15:24:37 +0000]
test_should_get_edit#PasswordResetsControllerTest (1476977077.05s)
Expected response to be a <success>, but was <302>
test/controllers/password_resets_controller_test.rb:11:in `block in <class:PasswordResetsControllerTest>'
Here's the controller in question (users_controller):
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_url
end
def index
#users = User.paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Please check your email to activate your account."
redirect_to root_url
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
Here's the user_signup_test:
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
def setup
ActionMailer::Base.deliveries.clear
end
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, params: { user: { name: "",
email: "user#invalid",
password: "foo",
password_confirmation: "bar" } }
end
assert_template 'users/new'
assert_select 'div#error_explanation'
assert_select 'div.field_with_errors'
end
test "valid signup information with account activation" do
get signup_path
assert_difference 'User.count', 1 do
post users_path, params: { user: { name: "Example User",
email: "user#example.com",
password: "password",
password_confirmation: "password" } }
end
assert_equal 1, ActionMailer::Base.deliveries.size
user = assigns(:user)
assert_not user.activated?
# Try to log in before activation.
log_in_as(user)
assert_not is_logged_in?
# Invalid activation token
get edit_account_activation_path("invalid token", email: user.email)
assert_not is_logged_in?
# Valid token, wrong email
get edit_account_activation_path(user.activation_token, email: 'wrong')
assert_not is_logged_in?
# Valid activation token
get edit_account_activation_path(user.activation_token, email: user.email)
assert user.reload.activated?
follow_redirect!
assert_template 'users/show'
assert is_logged_in?
end
end
Here is the last controller - missed that one somehow ...
require 'test_helper'
class PasswordResetsTest < ActionDispatch::IntegrationTest
def setup
ActionMailer::Base.deliveries.clear
#user = users(:michael)
end
test "password resets" do
get new_password_reset_path
assert_template 'password_resets/new'
# Invalid email
post password_resets_path, password_reset: { email: "" }
assert_not flash.empty?
assert_template 'password_resets/new'
# Valid email
post password_resets_path,
password_reset: { email: #user.email }
assert_not_equal #user.reset_digest, #user.reload.reset_digest
assert_equal 1, ActionMailer::Base.deliveries.size
assert_not flash.empty?
assert_redirected_to root_url
# Password reset form
user = assigns(:user)
# Wrong email
get edit_password_reset_path(user.reset_token, email: "")
assert_redirected_to root_url
# Inactive user
user.toggle!(:activated)
get edit_password_reset_path(user.reset_token, email: user.email)
assert_redirected_to root_url
user.toggle!(:activated)
# Right email, wrong token
get edit_password_reset_path('wrong token', email: user.email)
assert_redirected_to root_url
# Right email, right token
get edit_password_reset_path(user.reset_token, email: user.email)
assert_template 'password_resets/edit'
assert_select "input[name=email][type=hidden][value=?]", user.email
# Invalid password & confirmation
patch password_reset_path(user.reset_token),
email: user.email,
user: { password: "foobaz",
password_confirmation: "barquux" }
assert_select 'div#error_explanation'
# Empty password
patch password_reset_path(user.reset_token),
email: user.email,
user: { password: "",
password_confirmation: "" }
assert_select 'div#error_explanation'
# Valid password & confirmation
patch password_reset_path(user.reset_token),
email: user.email,
user: { password: "foobaz",
password_confirmation: "foobaz" }
assert is_logged_in?
assert_not flash.empty?
assert_redirected_to user
end
end
PasswordResetController:
class PasswordResetsController < ApplicationController
before_action :get_user, only: [:edit, :update]
before_action :valid_user, only: [:edit, :update]
before_action :check_expiration, only: [:edit, :update] # Case (1)
def new
end
def create
#user = User.find_by(email: params[:password_reset][:email].downcase)
if #user
#user.create_reset_digest
#user.send_password_reset_email
flash[:info] = "Email sent with password reset instructions"
redirect_to root_url
else
flash.now[:danger] = "Email address not found"
render 'new'
end
end
def edit
end
def update
if params[:user][:password].empty? # Case (3)
#user.errors.add(:password, "can't be empty")
render 'edit'
elsif #user.update_attributes(user_params) # Case (4)
log_in #user
flash[:success] = "Password has been reset."
redirect_to #user
else
render 'edit' # Case (2)
end
end
private
def user_params
params.require(:user).permit(:password, :password_confirmation)
end
# Before filters
def get_user
#user = User.find_by(email: params[:email])
end
# Confirms a valid user.
def valid_user
unless (#user && #user.activated? &&
#user.authenticated?(:reset, params[:id]))
redirect_to root_url
end
end
# Checks expiration of reset token.
def check_expiration
if #user.password_reset_expired?
flash[:danger] = "Password reset has expired."
redirect_to new_password_reset_url
end
end
end
I think you should remove params key before user parameters, e.g.:
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, user: { name: "",
email: "user#invalid",
password: "foo",
password_confirmation: "bar" }
end
assert_template 'users/new'
assert_select 'div#error_explanation'
assert_select 'div.field_with_errors'
end
Also you can debug received parameters in controller with pry:
add gem pry to your Gemfile (if there is no one);
run $ bundle install;
add binding.pry in controller before method user_params is called;
check that params contains expected parameters.
Working through Hartl's tutorial, in Chapter 9, Listing 9.56 produces the following error, showing 'admin?' as an undefined method.
I've checked (and rechecked) the 2 sections of code that have been revised since the last green test. Stumped.
ERROR["test_should_redirect_destroy_when_not_logged_in", UsersControllerTest, 2016-02-26 21:29:01 -0500]
test_should_redirect_destroy_when_not_logged_in#UsersControllerTest (1456540141.41s)
NoMethodError: NoMethodError: undefined method `admin?' for nil:NilClass
app/controllers/users_controller.rb:73:in `admin_user'
test/controllers/users_controller_test.rb:48:in `block (2 levels) in <class:UsersControllerTest>'
test/controllers/users_controller_test.rb:47:in `block in <class:UsersControllerTest>'
app/controllers/users_controller.rb:73:in `admin_user'
test/controllers/users_controller_test.rb:48:in `block (2 levels) in <class:UsersControllerTest>'
test/controllers/users_controller_test.rb:47:in `block in <class:UsersControllerTest>'
39/39: [==========================================================] 100% Time: 00:00:00, Time: 00:00:00
Finished in 0.97767s
39 tests, 152 assertions, 0 failures, 1 errors, 0 skips
Note that the admin field was added to the database during a migration, which I understand should automatically produce a boolean admin? method
class AddAdminToUsers < ActiveRecord::Migration
def change
add_column :users, :admin, :boolean, default: false
end
end
users_controller_test.rb is where the problem apparently resides, specifically in the lines:
test "should redirect destroy when not logged in" do
assert_no_difference 'User.count' do
delete :destroy, id: #user
...while the complete file looks like this:
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:michael)
#other_user = users(:archer)
end
test "should redirect index when not logged in" do
get :index
assert_redirected_to login_url
end
test "should get new" do
get :new
assert_response :success
end
test "should redirect edit when not logged in" do
get :edit, id: #user
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect to update when not logged in" do
patch :update, id: #user, user: { name: #user.name, email: #user.email }
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect edit when logged in as wrong user" do
log_in_as(#other_user)
get :edit, id: #user
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect update when logged in as wrong user" do
log_in_as(#other_user)
patch :update, id: #user, user: {name: #user.name, email: #user.email }
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect destroy when not logged in" do
assert_no_difference 'User.count' do
delete :destroy, id: #user
end
assert_redirected_to login_url
end
test "should redirect destroy when logged in as a non-admin" do
log_in_as(#other_user)
assert_no_difference 'User.count' do
delete :destroy, id: #user
end
assert_redirected_to root_url
end
end
and here's the contents of users.yaml
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
michael:
name: Michael Example
email: michael#example.com
password_digest: <%= User.digest('password') %>
admin: true
archer:
name: Sterling Archer
email: duchess#example.gov
password_digest: <%= User.digest('password') %>
lana:
name: Lana Kane
email: hands#example.gov
password_digest: <%= User.digest('password') %>
mallory:
name: Mallory Archer
email: boss#example.gov
password_digest: <%= User.digest('password') %>
<% 30.times do |n| %>
user_<%= n %>:
name: <%= "User #{n}" %>
email: <%= "user-#{n}#example.com" %>
password_digest: <%= User.digest('password') %>
<% end %>
Just to add to this. Whilst bf34's answer does the trick it may not be the correct solution.
Currently doing this tutorial and had the same issue. The reason it was purely current_user.admin? is because it shouldn't even reach this check if not logged in.
After a bit of rereading of my code I discovered that I didn't have the before_action of logged_in_user for the destroy method (see second line).
app/controllers/users_controller.rb:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
#users = User.paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
log_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
# Handle a successful update.
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
# Before filters
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
from the error message it looks like you're calling admin? on current_user but you don't have anyone logged in, so current_user is nil. Try doing current_user.try(:admin?) instead which will return nil if current_user is also nil.
I have run into 4 errors on section 9.2.2.
Errors
ERROR["test_unsuccessful_edit", UsersEditTest, 2015-11-05 04:35:59 -0600]
test_unsuccessful_edit#UsersEditTest (1446719759.23s)
NoMethodError: NoMethodError: undefined method correct_user?' for #<UsersController:0x007fcdf48ad378>
app/controllers/users_controller.rb:58:incorrect_user'
test/integration/users_edit_test.rb:10:in block in <class:UsersEditTest>'
app/controllers/users_controller.rb:58:incorrect_user'
test/integration/users_edit_test.rb:10:in `block in '
ERROR["test_successful_edit", UsersEditTest, 2015-11-05 04:35:59 -0600]
test_successful_edit#UsersEditTest (1446719759.28s)
NoMethodError: NoMethodError: undefined method correct_user?' for #<UsersController:0x007fcdefcea198>
app/controllers/users_controller.rb:58:incorrect_user'
test/integration/users_edit_test.rb:21:in block in <class:UsersEditTest>'
app/controllers/users_controller.rb:58:incorrect_user'
test/integration/users_edit_test.rb:21:in `block in '
ERROR["test_should_redirect_edit_when_logged_in_as_wrong_user", UsersControllerTest, 2015-11-05 04:35:59 -0600]
test_should_redirect_edit_when_logged_in_as_wrong_user#UsersControllerTest (1446719759.42s)
NoMethodError: NoMethodError: undefined method correct_user?' for #<UsersController:0x007fcdf529f778>
app/controllers/users_controller.rb:58:incorrect_user'
test/controllers/users_controller_test.rb:29:in block in <class:UsersControllerTest>'
app/controllers/users_controller.rb:58:incorrect_user'
test/controllers/users_controller_test.rb:29:in `block in '
ERROR["test_should_redirect_update_when_logged_in_as_wrong_user", UsersControllerTest, 2015-11-05 04:35:59 -0600]
test_should_redirect_update_when_logged_in_as_wrong_user#UsersControllerTest (1446719759.44s)
NoMethodError: NoMethodError: undefined method correct_user?' for #<UsersController:0x007fcdf531e118>
app/controllers/users_controller.rb:58:incorrect_user'
test/controllers/users_controller_test.rb:36:in block in <class:UsersControllerTest>'
app/controllers/users_controller.rb:58:incorrect_user'
test/controllers/users_controller_test.rb:36:in `block in '
32/32: [======================] 100% Time: 00:00:01, Time: 00:00:01
Finished in 1.70355s
32 tests, 64 assertions, 0 failures, 4 errors, 0 skips
Users_controller.rb
class UsersController < ApplicationController
before_action :logged_in_user, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
log_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before Filters
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless correct_user?(#user)
end
end
User_controller_test
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:michael)
#other_user = users(:archer)
end
test "should get new" do
get :new
assert_response :success
end
test "should redirect edit when logged in" do
get :edit, id: #user
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect update when not logged in" do
patch :update, id: #user, user: { name: #user.name, email: #user.email }
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect edit when logged in as wrong user" do
log_in_as(#other_user)
get :edit, id: #user
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect update when logged in as wrong user" do
log_in_as(#other_user)
patch :update, id: #user, user: { name: #user.name, email: #user.email }
assert flash.empty?
assert_redirected_to root_url
end
end
users.yml
michael:
name: Michael Example
email: michael#example.com
password_digest: <%= User.digest('password') %>
archer:
name: Sterling Archer
email: duchess#example.gov
password_digest: <%= User.digest('password') %>
users_edit_test
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
#user = users(:michael)
end
test "unsuccessful edit" do
log_in_as(#user)
get edit_user_path(#user)
assert_template 'users/edit'
patch user_path(#user), user: { name: "",
email: "foo#invalid",
password: "foo",
password_confirmation: "bar" }
assert_template 'users/edit'
end
test "successful edit" do
log_in_as(#user)
get edit_user_path(#user)
assert_template 'users/edit'
name = "Foo Bar"
email = "foo#bar.com"
patch user_path(#user), user: { name: name,
email: email,
password: "",
password_confirmation: "" }
assert_not flash.empty?
assert_redirected_to #user
#user.reload
assert_equal name, #user.name
assert_equal email, #user.email
end
end
I think that is all that would be needed to help. I have been struggling for some time now. This is my first post, sorry if it isn't easy to read.
correct_user? isn't defined anywhere.
redirect_to(root_url) unless correct_user?(#user)
Rails's syntactic sugar is going to look for a model flag correct_user or a boolean-returning function #correct_user? getter. I'm assuming that you're trying to validate that an update request from a user actually belongs to the correct user. To do this you must have current_user stored in a session, and then check the request param[:id] == current_user.id
I have this integration test that controls that a logged in user can't edit another user's data.
The code is mostly from Hartl's RoR tutorial.
Those 2 tests fail but when I test myself, the application is behaving as expected (I can't open the edit page of another user)
When I run rake, I get (lines 31 & 38 are assert flash.empty?):
FAIL["test_should_redirect_edit_when_logged_in_as_wrong_user", UsersControllerTest, 2015-07-24 12:15:07 +0800]
test_should_redirect_edit_when_logged_in_as_wrong_user#UsersControllerTest (1437711307.70s)
Failed assertion, no message given.
test/controllers/users_controller_test.rb:31:in `block in <class:UsersControllerTest>'
FAIL["test_should_redirect_update_when_logged_in_as_wrong_user", UsersControllerTest, 2015-07-24 12:15:07 +0800]
test_should_redirect_update_when_logged_in_as_wrong_user#UsersControllerTest (1437711307.71s)
Failed assertion, no message given.
test/controllers/users_controller_test.rb:38:in `block in <class:UsersControllerTest>'
Then, if I comment out assert flash.empty?, I get this (lines 32 & 39 are assert_redirected_to root_url):
FAIL["test_should_redirect_update_when_logged_in_as_wrong_user", UsersControllerTest, 2015-07-24 12:15:08 +0800]
test_should_redirect_update_when_logged_in_as_wrong_user#UsersControllerTest (1437711308.02s)
Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/login>.
Expected "http://test.host/" to be === "http://test.host/login".
test/controllers/users_controller_test.rb:39:in `block in <class:UsersControllerTest>'
FAIL["test_should_redirect_edit_when_logged_in_as_wrong_user", UsersControllerTest, 2015-07-24 12:15:08 +0800]
test_should_redirect_edit_when_logged_in_as_wrong_user#UsersControllerTest (1437711308.03s)
Expected response to be a redirect to <http://test.host/> but was a redirect to <http://test.host/login>.
Expected "http://test.host/" to be === "http://test.host/login".
test/controllers/users_controller_test.rb:32:in `block in <class:UsersControllerTest>'
users_controller_test.rb
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:guillaume)
#other_user = users(:peter)
end
## other tests ##
test "should redirect edit when logged in as wrong user" do
log_in_as(#other_user)
get :edit, id: #user
assert flash.empty?
assert_redirected_to root_url
end
test "should redirect update when logged in as wrong user" do
log_in_as(#other_user)
patch :update, id: #user, user: {name: #user.name, email: #user.email}
assert flash.empty?
assert_redirected_to root_url
end
the lines that fail are the assert and assert_redirect lines
test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'minitest/reporters'
Minitest::Reporters.use!
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Returns true if a test user is logged in
def is_logged_in?
!session[:user_id].nil?
end
# Logs in a test user
def log_in_as(user, options = {})
password = options[:password] || 'password'
if integration_test?
post login_path, session: {email: user.email,
password: password}
else
session[:user] = user.id
end
end
private
# Return true inside an integration test
def integration_test?
defined?(post_via_redirect)
end
end
users_controller.rb
class UsersController < ApplicationController
before_action :logged_in_user, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
## new and create methods here ##
def edit
#user = User.find(params[:id])
end
def update
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name,
:email,
:club_id,
:access_key,
:password,
:password_confirmation)
end
## Before filters ##
# Confirms a logged-in user
def logged_in_user
unless logged_in?
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms a correct user
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
end
users.yml
guillaume:
name: Guillaume
email: guillaume#example.com
password_digest: <%= User.digest('password') %>
peter:
name: Peter
email: peter#example.com
password_digest: <%= User.digest('password') %>
I went though the code several times but I can't find what's missing.
This is also the first app I'm trying to develop on my own, so for this part, I'm working from Hartl's rails tutorial material.
I am going through Aaron Sumner's Everyday Rails Testing with RSpec (3) book, and can't get passed the following step:
I am trying to spec out a users#show action with:
users_controller_spec:
...
describe 'GET #show' do
it "assigns the requested contact to #user" do
user = create(:user)
get :show, id: user.id
expect(assigns(:user)).to eq user
end
it "renders the :show template" do
user = create(:user)
get :show, id: user.id
expect(response).to render_template :show
end
end
...
users_controller:
class UsersController < ApplicationController
before_action :authenticate
before_action :set_user, only: [:show]
### Read:
def show
...
end
private
def set_user
#user = User.find(params[:id])
end
end
application_controller helpers:
def authenticate
redirect_to home_path, alert: 'Please log in first' if current_user.nil?
end
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
Errors:
Failures:
1) UsersController GET #show assigns the requested user to #user
Failure/Error: expect(assigns(:user)).to eq user
expected: #<User id: 1, ...">
got: nil
(compared using ==)
# ./spec/controllers/users_controller_spec.rb:10:in `block (3 levels) in <top (required)>'
2) UsersController GET #show renders the :show template
Failure/Error: expect(response).to render_template :show
expecting <"show"> but rendering with <[]>
# ./spec/controllers/users_controller_spec.rb:17:in `block (3 levels) in <top (required)>'
Your issue comes from before_action :authenticate either you need to set yourself as authenticated in the specs or you need to skip authentication for the show action.
You would normally test like:
context 'when logged in' do
before(:each) do
set_as_logged_in
end
# your specs
end
where the set_as_logged_in method would differ based on the way you are authenticating. Then you could also have a 'when not logged in' context to verify the action behaves as expected when you are not logged in.