vendredi 12 août 2016

Rails test for auto-generating password

My app allows teachers to start accounts for their students. To avoid the burden of asking teachers to think of passwords for their students, I've written a method to automatically generate passwords. The feature is working correctly in development and production. I' trying to write a test to ensure that this feature continues to work, but the results are not what I expect.

My hunch is that my mistake is in the test:

students_controller_test.rb

test "Auto Password" do
    post students_path, params: { student: { first_name:  "Ren",
                                         last_name: "Stimpy",
                                        studentNum: 13},
                                 aula: { seminar_id: @seminar.id } }
    student = assigns(:student)
    assert_equal "rs13", student.username
    assert_equal Student.digest('rs13'), student.password_digest
end

And the results:

 FAIL["test_Auto_Password", StudentsControllerTest, 2.0619301088154316]
 test_Auto_Password#StudentsControllerTest (2.06s)
        --- expected
        +++ actual
        @@ -1,2 +1 @@
        -# encoding: ASCII-8BIT
        -"$2a$04$1FfqltU9B7yawIs7Z4GWLe9eaaVhFxdPvF9Vg2UWUbYxwqQ5j/9Dm"
        +"$2a$04$CuN1BLKhI/Fx9ueB4QAskOl9Ik.og26TJeeDDF5tdur1erILzjj7W"
        test/controllers/students_controller_test.rb:91:in `block in <class:StudentsControllerTest>'

I'm probably misunderstanding something about the way password digestion works. The student's password should be "rs13". So I expected that Student.digest('rs13') should be equal to student.password_digest. Apparently, they're not.

I don't think the following method is important, but I'll post it in case. It occurs in the students_controller upon creating or updating a student. It creates the student number, username, and password if the teacher leaves any of them blank. The student number will be equal to that student's id from the Database. The username is composed of the student's initials, plus student number. The password will be equal to the username. (The student should change this later).

def autoInfo(student)   # Auto-generate missing info for students
  if student.studentNum.blank? || student.username.blank? || student.password_digest.blank?
    student.studentNum = student.id if student.studentNum.blank?
    student.username = makeUsername(student) if student.username.blank?
    student.password = student.username if student.password.blank?
    student.save!
  end
end

Finally, in case you need to see the digest method, it's cut-and-paste from Michael Hartl's Tutorial,

class << self
    # Returns the hash digest of the given string.
    def digest(string)
        cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                      BCrypt::Engine.cost
        BCrypt::Password.create(string, cost: cost)
    end

    # Returns a random token
    def new_token
        SecureRandom.urlsafe_base64
    end
end

Thank you in advance for any insight!

Aucun commentaire:

Enregistrer un commentaire