Make a controller test for the user-limericks index controller action

In this part, we will make a controller test for the UserLimericksController#index controller action. As we will see, this index action differs from the one on the previous page (LimericksController#index) in that it displays only the limericks authored by one particular user, and user authentication is required to access the action. These differences change how the controller test must be written.

Inspect the UserLimericksController#index controller action

As on the previous page, we must (1) find the route for this controller action and (2) determine if user authentication is required to access the action.

Open the config/routes.rb file, and locate the route that calls this index action. You should find this route:

  get 'users/:user_id/limericks', to: 'user_limericks#index', as: 'user_limericks'

Note that, as per the as part of this route, the URL helper will be named user_limericks_url, and as per the URI pattern, it will need to be passed an argument for the user_id.

Open the app/controllers/user_limericks_controller.rb file in VS Code, and inspect the UserLimericksController class defined within. It should look like this.

class UserLimericksController < ApplicationController

  before_action :authenticate_user!

  def index
    @user = User.find(params[:user_id])
    @limericks = @user.limericks.reverse_order
    render :index
  end

end

Note that the before_action requires that the user be authenticated in order to access all the actions in this controller, including the index action.

Add a controller test for UserLimericksController#index

Open the controller test file test/controller/user_limericks_controller_test.rb in VS Code. Similar to how we found the previous controller test file, this one should also contain only one commented-out test case, "the truth".

require "test_helper"

class UserLimericksControllerTest < ActionDispatch::IntegrationTest
  # test "the truth" do
  #   assert true
  # end
end

Import a Devise mixin module into the controller test class, so that we can call Devise helpers when writing our test cases.

class UserLimericksControllerTest < ActionDispatch::IntegrationTest
  include Devise::Test::IntegrationHelpers

  # test "the truth" do
  #   assert true
  # end
end

Uncomment this test case, and rename it as "should get index".

  test "should get index" do
    assert true
  end

Note that it is OK that this test case has the same name as the one from the previous page, because the test cases are members of different controller test classes.

As in the previous test case, we will follow the Arrange, Act, and Assert pattern.

Arrange. Make the following changes to the test case to prepare the system running the index action.

  test "should get index" do
    user = users(:one)
    limericks_size = user.limericks.size
    sign_in user
  end

Note that the fixture methods, such as users, can be used to retrieve an individual fixture by passing a symbol with the name of the fixture, such as :one. Note that we must capture the size of this user’s set of limericks (rather than all the limericks stored in the database) as only this user’s limericks will be displayed on the page.

Act. Similar to the previous page, use the get command to simulate an HTTP GET request with the URL for the index page as follows.

  test "should get index" do
    user = users(:one)
    limericks_size = user.limericks.size
    sign_in user
    get user_limericks_url(user)
  end

Assert. Similar to the previous page, replace the assert true call with with a call to assert_response that checks that the HTTP response produced by the app has a success code (a 2xx status code, like 200 OK), and add an additional call to assert_select that checks that the correct number of cards were rendered on the page.

  test "should get index" do
    user = users(:one)
    limericks_size = user.limericks.size
    sign_in user
    get user_limericks_url(user)
    assert_response :success
    assert_select 'div.card', limericks_size
  end

Run the controller test

As before, run the following command to run all test cases defined in the project.

rails test -v

The output of the command should look like the following.

Running 2 tests in a single process (parallelization threshold is 50)
Run options: -v --seed 18500

# Running:

LimericksControllerTest#test_should_get_index = 2.37 s = .
UserLimericksControllerTest#test_should_get_index = 0.02 s = .

Finished in 2.398942s, 0.8337 runs/s, 1.6674 assertions/s.
2 runs, 4 assertions, 0 failures, 0 errors, 0 skips

Note that the UserLimericksControllerTest#test_should_get_index is now included in the list of test cases that ran, that 2 total test cases ran, that 4 assertions were checked (2 from the previous test case and 2 from the latest one), and that 0 test assertions failed and 0 system errors occurred.


⏴ Back More to Come!