Working through the tutorial in Chapter 10, everything was working and testing green with no problems. However, when I add more users as per Listing 10.47, the 'update user with friendly forwarding' test starts failing.
FAIL["test_successful_edit_with_friendly_forwarding", UsersEditTest, 1.8292690003290772]
test_successful_edit_with_friendly_forwarding#UsersEditTest (1.83s)
Expected response to be a redirect to <http://ift.tt/1NpgCsS; but was a redirect to <http://ift.tt/1D1DOKt;.
Expected "http://ift.tt/1NpgCJ6" to be === "http://ift.tt/1D1DOKz".
test/integration/users_edit_test.rb:35:in `block in <class:UsersEditTest>'
I've tested this a fair bit, and when I remove users from users.yml, the test passes again. So I have a bug in my code which is only appearing when there are more than 2 users in the app. This was my test:
users_edit_test.rb
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), params: { user: { name: '',
email: 'foo@invalid',
password: 'foo',
password_confirmation: 'bar' } }
assert_template 'users/edit'
assert_select 'div.alert',
'The form contains 4 errors.'
end
# This is the failing test
test "successful edit with friendly forwarding" do
get edit_user_path(@user)
log_in_as(@user)
assert_redirected_to edit_user_url(@user)
name = "Foo Bar"
email = "foo@bar.com"
patch user_path(@user), params: { user: { name: name,
email: email,
password: "",
password_confirmation: "" } }
assert_not flash.empty?
assert_redirected_to @user #The test is failing on this line
@user.reload
assert_equal name, @user.name
assert_equal email, @user.email
end
end
Looking at the error, it appears that user_path(@user) is returning the wrong user. I've tested and it looks like the patch request is failing, and the user name and email are the original user name and password, not the ones set in the patch request. This may be because it is patching the wrong user, but I can't understand why or how. When I test to figure out the value of @user, it's always resolving to the first user in users.yml, as far as I can tell.
users.yml
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') %>
malory:
name: Malory 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 %>
If I remove the additional users and leave only the first two, the test now passes. Which is the state we were in when I wrote the test. Now, my pagination test fails instead because there aren't enough users for pagination. That is as it should be.
I'm fairly new to Rails (what which doing the tutorial and all), and particularly new to testing. I've tried various techniques in changing the test temporarily to figure out what is going wrong, but I honestly can't trace where the bug is. I've compared all my code to the code provided and can't see any typos or mistakes, but there has to be something wrong.
Strangely, I can't replicate the bug at all in development or in production on Heroku. The application behaves as it should as far as I can tell both as a user and in looking at logs. But the test continues to fail – I must have introduced a bug somewhere. Or my test is wrong but I can't see anything different from the code in the tutorial.
I've seen similar questions such as this one, but the issue there was with the redirect which as far as I have tested is working. In addition, if I change my test to take away the redirect, and test only the user update, the test still fails. So the problem may well be in my user update method.
user_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_by(params[:user_id])
end
def update
@user = User.find_by(params[:user_id])
if @user.update_attributes(user_params)
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
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
Aucun commentaire:
Enregistrer un commentaire