Les Paul
Les Paul

Reputation: 1278

Ruby on Rails Tutorial 3rd edition, Chapter 9: Failed test on users_edit_test.rb

I am consistently receiving three errors and I have no idea why. I'm following the tutorial to the best of my ability, and I have scoured through Chapter 9 for mistakes and I haven't seen any. Running bundle exec rake test. I get the three following errors:

FAIL["test_unsuccessful_edit", UsersEditTest, 2015-08-22 09:09:06 +0900]
 test_unsuccessful_edit#UsersEditTest (1440202146.96s)
        expecting <"users/edit"> but rendering with <[]>
        test/integration/users_edit_test.rb:12:in `block in <class:UsersEditTest>'

 FAIL["test_successful_edit", UsersEditTest, 2015-08-22 09:09:06 +0900]
 test_successful_edit#UsersEditTest (1440202146.97s)
        expecting <"users/edit"> but rendering with <[]>
        test/integration/users_edit_test.rb:25:in `block in <class:UsersEditTest>'

 FAIL["test_successful_edit_with_friendly_forwarding", UsersEditTest, 2015-08-22 09:09:07 +0900]
 test_successful_edit_with_friendly_forwarding#UsersEditTest (1440202147.07s)
        Expected response to be a redirect to <http://www.example.com/users/762146111/edit> but was a redirect to <http://www.example.com/>.
        Expected "http://www.example.com/users/762146111/edit" to be === "http://www.example.com/".
        test/integration/users_edit_test.rb:43:in `block in <class:UsersEditTest>'

As you can see, all of my errors can be found in test/integration/users_edit_test. Two of my tests fail in the same way, with this message: expecting <"users/edit"> but rendering with <[]>. Line 12 and 25 has the same code:

assert_template 'users/edit'

Line 43 has the following code:

assert_redirected_to edit_user_path(@user)

I have a _header.html.erb file with a link that is supposed to go to the user's edit page but it just redirects to the index. I have a file app/views/users/edit.html.erb so I don't know why it isn't showing up. Here is the code for the settings link:

<li><%= link_to "Settings", edit_user_path(current_user) %></li>

Here is my code for my users_controller.rb file. I suspect the problem is my correct_user method not firing like it is supposed to. (By the way, I have tried commenting out the code inside the "edit" method, but the problem still persists.)

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])
    # debugger
  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
    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

    def logged_in_user
      unless logged_in?
        store_location
        flash[:danger] = "Please log in."
        redirect_to login_url
      end
    end

    def correct_user
      @user = User.find(params[:id])
    #  redirect_to(root_url) unless @user == current_user
      redirect_to(root_url) unless @user == current_user?(@user)  
    end

    def admin_user
      redirect_to(root_url) unless current_user.admin?
    end
end

In app/helpers/sesions_helper.rb I have two methods, current_user and current_user?

def current_user?(user)
  user == current_user
end

def current_user
    if(user_id = session[:user_id])
        @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
        user = User.find_by(id: user_id)
        if user && user.authenticated?(cookies[:remember_token])
            log_in user
            @current_user = user
        end
    end
end

Here is the config/routes file:

root 'static_pages#home'
  get 'help' => 'static_pages#help'
  get 'about' => 'static_pages#about'
  get 'contact' => 'static_pages#contact'
  get 'signup' => 'users#new'
  get 'login' => 'sessions#new'
  post 'login' => 'sessions#create'
  delete 'logout' => 'sessions#destroy'
  resources :users

I suspect the answer to my issue is super easy, but I've no idea what is wrong. Here is the users_edit_test.rb file

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)
    log_in_as(@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)
    log_in_as(@user)
    assert_template 'users/edit'
    name = "Foo Bar"
    email = "[email protected]"
    patch user_path(@user), user: { name: name,
                                    email: email,
                                    password: '',
                                    password_confirmation: '' }
    assert_not flash.empty?
    assert_redirected_to @user
    @user.reload
    assert_equal @user.name, name
    assert_equal @user.email, email
  end

  test "successful edit with friendly forwarding" do
    log_in_as(@user)
    get edit_user_path(@user)
#    log_in_as(@user)
    assert_redirected_to edit_user_path(@user)
    name = "Foo Bar"
    email = "[email protected]"
    patch user_path(@user), user: { name: name,
                    email: email,
                    password: 'foobar',
                    password_confirmation: 'foobar' }
    assert_not flash.empty?
    assert_redirected_to @user
    @user.reload
    assert_equal @user.name, name
    assert_equal @user.email, email
  end
end

Upvotes: 1

Views: 1631

Answers (7)

Endi Caushi
Endi Caushi

Reputation: 1

If anybody is still having this error i was able to get through it by changing the user in the def setup to another user from the users.yml.

Upvotes: 0

davideghz
davideghz

Reputation: 3685

I'm following same tutorial and I got the same error:

  expecting <"users/edit"> but rendering with <[]>

I've solved it just with a switch of position of this block:

  test "unsuccesful edit" do
    log_in_as(@user)
    get edit_user_path(@user)
    assert_template 'users/edit'
    patch user_path(@user), user: { name: "", 
                                    email: "invalid@invalid",
                                    password: "foo",
                                    password_confirmation: "bar" }
    assert_template 'users/edit'
  end

and this one:

  test "successful edit" do
    log_in_as(@user)
    get edit_user_path(@user)
    assert_template 'users/edit'
    name = "Name"
    email = "[email protected]"
    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

Actually now it works in any order I put the two blocks.. I know it doesn't have any sense but maybe it's linked with some strange behaviour of cut&paste on Cloud9 (the cloud-based IDE which the author suggest to use).

Upvotes: 1

Make your users.yml is well defined and there's not a typo over it. I had a typo, and was getting the same error.

Error (notice the upper E in the email)

michael:
  name: michael Example
  email: [email protected]
  password_digest: <%= User.digest('password') %>

Well defined

michael:
  name: michael Example
  email: [email protected]
  password_digest: <%= User.digest('password') %>

Upvotes: 1

sbos61
sbos61

Reputation: 564

Actually I went into the same problem. In my case it turned out that I changed the password for the user in the fixture user.yml.

After several hours, I found that there MUST be STRONG alignement between:

  1. user.yml
  2. test_helper.rb2.
  3. the database (where the digest is stored)

Upvotes: 0

mjhoffmann
mjhoffmann

Reputation: 374

I am working through the tutorial, too. I had some similar issues.

If I understand correctly <[]> indicates a redirect that the test browser hasn't yet followed. I would put a debugger right before the failing assertion and inspect the situation from there. In my case a forgotten follow_redirect! or an assert_template instead of an assert_redirected_to was the reason.

Upvotes: 0

M. Layton
M. Layton

Reputation: 613

I'm working through this tutorial now as well, and I got the tests to pass just fine, so I'm comparing my tests to yours and you need to make the following changes:

  1. In successful test and unsuccessful test, put log_in_as(@user) before get edit_user_path(@user).
  2. In successful test with friendly forwarding, do just the opposite: put log_in_as(@user) after get edit_user_path(@user).
  3. In your users_controller.rb file, check your private correct_user method:

    redirect_to(root_url) unless @user == current_user?(@user)
    

    should be

    redirect_to(root_url) unless current_user?(@user)
    

Making those changes and re-running the test suite should make your tests pass.

Upvotes: 1

K M Rakibul Islam
K M Rakibul Islam

Reputation: 34318

Although, you did not upload your users_edit_test.rb file here, I actually read the chapter 9 from the book you mentioned and then also got the source code from its github repo.

So, I was running the same test as yours (bundle exec rake test test/integration/users_edit_test.rb) locally and it's passing fine. There is no test failure. But, I figured out that, if the log_in_as(@user) is missing from the test "unsuccessful edit" test, then it fails with the exact same error message that you posted here. And, that makes sense, because, if you don't have log_in_as(@user) i.e. logged_in user, then it can't render the edit page for that user and hence gets this error:

expecting <"users/edit"> but rendering with <[]>

So, I am pretty sure that you have missed that part while typing it from the tutorial.

Here is the full working version (all tests are passing) of the users_edit_test.rbfile:

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: "user@invalid",
                                    password:              "foo",
                                    password_confirmation: "bar" }
    assert_template 'users/edit'
  end

  test "successful edit with friendly forwarding" do
    get edit_user_path(@user)
    log_in_as(@user)
    assert_redirected_to edit_user_path(@user)
    name  = "Foo Bar"
    email = "[email protected]"
    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

Just copy this and replace your current file's content with this. Then, all tests will pass.

Upvotes: 4

Related Questions