RailsTutorial Ch. 10: How do I test that only activated users are viewable to others?

844 views Asked by At

Currently, my Rails app only displays activated user accounts in the search results. It also only allows people to navigate to a profile page if that profile has been activated. To do these things, users_controller.rb is configured like this:

def index
  @users = User.where(activated: true).paginate(page: params[:page])
end

def show
  @user = User.find(params[:id])
  redirect_to root_url and return unless @user.activated?
end

I am wondering how to use an integration test to check this behavior. My current test is this:

test "only show profiles of activated users" do
  log_in_as(@admin)
  get users_path
  assert_template 'users/index'
  assert_select 'div.pagination'
  first_page_of_users = User.paginate(page: 1)
  first_page_of_users.each do |user|
    assert_equal true, user.activated?
  end
end

I have also modified /fixtures/users.yml to include a user that has not activated his profile:

non:
  name: Non Activated
  email: [email protected]
  password_digest: <%= User.digest('password') %>
  activated: false

When I run rake test, I get this error:

FAIL["test_only_show_profiles_of_activated_users", UsersIndexTest, 1.271917]
test_only_show_profiles_of_activated_users#UsersIndexTest (1.27s)
    Expected: true
    Actual: false
test/integration/users_index_test.rb:40:in `block (2 levels) in <class:UsersIndexTest>'
test/integration/users_index_test.rb:39:in `block in <class:UsersIndexTest>'

Can anyone help me understand why the test is able to detect profiles of non-activated users?

2

There are 2 answers

2
jjt On BEST ANSWER

Firstly, let me state that my struggle with this same exercise landed me here, so I’m obliged for your post. 6 months late, but perhaps my response might still provide some insight.

After a good deal of effort, this much is clear to me:

  1. User.paginate is semi-redundant to the actual code in users_controller.rb, and furthermore, is actually causing your immediate problem -- namely, in your test, User.paginate doesn’t include the where filter
  2. Instantiating User.paginate directly in the test and using it to evaluate its own members doesn’t make sense - in this case, the test is only testing itself and not the app
  3. In order to actually test the app, one must access the @users instance variable in users_controller.rb, e.g., my_test_users = assigns(:users)
  4. In order to be thorough and test for presence of the non-activated user pre-defined in the users.yml fixture, we should check all pages, which presents the problem of how to determine total number of pages -- will_paginate provides this: my_test_users.total_pages
  5. The final insight that helped with this exercise was to really begin understanding what makes up a REST-ful implementation, namely, how controller-action mapping works with named routes and parameterization, e.g., get users_path, page: 1 -- this obviously calls the users controller, and if we recall that will_paginate takes a :page argument --> User.paginate(page: params[:page]) -- we see that this argument is provided by the named path parameter above

So hopefully this much is enough to put the pieces together for a complete integration test.

(The test to see if non-activated user is redirected to root_url upon attempting to navigate to user profile is much more straightforward)

For what it’s worth, so far, this exercise has proven to be the most challenging and rewarding of the tutorial.

0
Sagar.Patil On

I think for your case the better way of access you can use default scope

default_scope where(:published => true)