NZisKool
NZisKool

Reputation: 239

How to test a 301 redirection with Minitest on Rails 6

Using Rails 6, I'm redirecting from native ids (/users/id) to friendly_ids (/users/username) (following the answer brought here) which handles the redirect as such:

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base

  def redirect_resource_if_not_latest_friendly_id(resource)
    if resource.friendly_id != params[:id]
      redirect_to resource, status: 301
    end
  end
end

In my controller, I call the method as such:

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  before_action :set_user, only: [:show]

  def show
    redirect_resource_if_not_latest_friendly_id(set_user)
  end

  protected

  def set_user
    @user = User.friendly.find(params[:id])
  end
end

It's working fine and I want to include the redirection in my test suite. I found answer and topics about how to do that with Rspec but I'm using Minitest and couldn't figure it out.

I tried a bunch of different ways (with params[:id], etc.) but to keep it simple let's say it's the following fixture, test and result.

Here is the fixture:

# test/fixtures/users.yml
one:
  username: username
  email: [email protected]
  slug: username

Here is the test:

# test/controllers/users_controller_test.rb  
class UsersControllerTest < ActionDispatch::IntegrationTest

  test "should 301 redirect to the friendly_id" do
    @user = users(:one)
    get user_path(@user)
    assert_redirected_to "/users/#{@user.slug}"
  end
end

Here is the result of the test:

FAIL["test_should_301_redirect_to_the_friendly_id", #<Minitest::Reporters::Suite:0x00007fe716c66600 @name="UsersControllerTest">, 0.7785789999979897]
 test_should_301_redirect_to_the_friendly_id#UsersControllerTest (0.78s)
        Expected response to be a <3XX: redirect>, but was a <200: OK>
        test/controllers/users_controller_test.rb:8:in `block in <class:UsersControllerTest>'

What am I doing wrong?

Upvotes: 2

Views: 1096

Answers (2)

Sebasti&#225;n Palma
Sebasti&#225;n Palma

Reputation: 33420

The problem is you're using the "whole" user record to make the request, so when you do

user_path(@user)

The route extracts the friendly_id from the resource and then your condition is evaluated to false, because the resource.friendly_id is always going to be the same as the id coming from the params.

Try instead:

get user_path(id: @user.id)

That way you can explicitly pass the @user.id through the params.

Upvotes: 1

bigidigi89
bigidigi89

Reputation: 73

possible the problem resource.friendly_id != params[:id] as I understood they are the same

Upvotes: 0

Related Questions