1
votes

Description of the Exercise: Railstutorial Exercise 10.4.1.2

The exercise: 'FILL_IN' has to be replaced with the proper code, so that the test is working

test "should not allow the admin attribute to be edited via the web" do
  log_in_as(@other_user)
  assert_not @other_user.admin?
  patch user_path(@other_user), params: {
                                  user: { password:              FILL_IN,
                                          password_confirmation: FILL_IN,
                                          admin: FILL_IN} }
  assert_not @other_user.FILL_IN.admin?
end

My solution:

test "should not allow the admin attribute to be edited via the web" do
  log_in_as(@other_user)
  assert_not @other_user.admin?
  patch user_path(@other_user), params: {
                                  user: { password:              'password',
                                          password_confirmation: 'password',
                                          admin: true } }
  assert_not @other_user.reload.admin?
end

My Question(s):

If you have set the ':admin' attribute to the list of permitted parameters in user_params (in the UsersController class) the test turns 'Red' as it is supposed to. What I don't understand though, is that you can set random passwords and the test is still working properly, like so:

test "should not allow the admin attribute to be edited via the web" do
  log_in_as(@other_user)
  assert_not @other_user.admin?
  patch user_path(@other_user), params: {
                                  user: { password:              'foobar',
                                          password_confirmation: 'foobar',
                                          admin: true } }
  assert_not @other_user.reload.admin?
end

Shouldn't the only valid option be 'password' (and not 'foobar' or even '' (i.e. blank)), since the instance variable @other_user contains the values of the User 'archer' from the fixtures file 'users.yml', who has 'password' as a password_digest? Wouldn't it result in a mismatch between the two attributes password_digest(='password') and password(='foobar')? Or is the 'password_digest' attribute from 'archer' somehow updated as well? If so, how does it work?

And why does the test turn 'Green', if you type in an invalid password, like:

test "should not allow the admin attribute to be edited via the web" do
  log_in_as(@other_user)
  assert_not @other_user.admin?
  patch user_path(@other_user), params: {
                                  user: { password:              'foo',
                                          password_confirmation: 'bar',
                                          admin: true } }
  assert_not @other_user.reload.admin?
end

Could it be that the 'patch' request aborts due to the incorrect password input and thus also fails to update the admin status? Is that the reason why the test is 'Green' (since admin is still 'nil')?

I already looked up the reference implementation of the sample application by Michael Hartl (https://bitbucket.org/railstutorial/sample_app_4th_ed), but unfortunately he does not provide any code relating to the exercises.

Thanks for help!

1
The password parameters in the examples are not there for authentication, but to update the values. :) The reason why the second one fails (or in this case turns the test green) is, because has_secure_password will check if password == password_confirmation before updating the model.Ninigi

1 Answers

0
votes

In Chapter 10.1, for the update tests, we allowed empty password for tests on the User Controller :

class User < ApplicationRecord
.
.
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true 
.
.
end

As mentionned in the same chapter, the password is secured with the has_secure_password helper for the online use. Hope I helped