Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Django 1-5 Reset Password Form - how to generate the token for the test?

With the following test, the token is not recognised as valid. In my manual test, it's working so I'm missing something in the way the password is generated I guess.

def test_actual_reset_password(self):
    new_password = "myNewPassword012*"
    token_generator = PasswordResetTokenGenerator()
    user = UserFactory.create()
    token = token_generator.make_token(user=user)

    response = self.assert_page_loading(path="/forgot-password/reset/{0}/".format(token))
    print response 
    # That loads the page with the error message mentioning that the token was already used        

    # So I cannot carry on:
    form = response.form
    form['new_password1'] = new_password
    form['new_password2'] = new_password

    response = form.submit()

In the django source code, in the PasswordResetForm, I've found this code; I can't see what the difference is:

def save(self, ..., token_generator=default_token_generator, ...):
    """
    Generates a one-use only link for resetting password and sends to the
    user.
    """
    ...
    for user in self.users_cache:
        ...
        c = {
            ...
            'token': token_generator.make_token(user),
            ...
        }
        ...
        send_mail(subject, email, from_email, [user.email])
like image 636
François Constant Avatar asked Aug 16 '13 02:08

François Constant


People also ask

How can I get Django password reset token?

Registration and forgot password routes We're going to create four URL endpoints: /register that includes the registration form and sends the activation token email . /activate that validates the activation token from the email. /password reset that includes the forgot password form and sends the reset token email .

How do I run a TestCase in Django?

Open /catalog/tests/test_models.py.TestCase , as shown: from django. test import TestCase # Create your tests here. Often you will add a test class for each model/view/form you want to test, with individual methods for testing specific functionality.


1 Answers

Ok, I was just searching for info on how to do this and your question prompted me to figure it out myself. I'm not sure if you're still working on this, but here's how I got it to work:

from django.core import mail
# First we get the initial password reset form.  
# This is not strictly necessary, but I included it for completeness
response = self.c.get(reverse('password_reset'))
self.assertEqual(response.status_code, 200)
self.assertEqual(response.template_name, 'authentication/password_reset_form.html')

# Then we post the response with our "email address"
response = self.c.post(reverse('password_reset'),{'email':'[email protected]'})
self.assertEqual(response.status_code, 302)
# At this point the system will "send" us an email. We can "check" it thusly:
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, 'Password reset on example.com')

# Now, here's the kicker: we get the token and userid from the response
token = response.context[0]['token']
uid = response.context[0]['uid']
# Now we can use the token to get the password change form
response = self.c.get(reverse('password_reset_confirm', kwargs={'token':token,'uidb64':uid}))
self.assertEqual(response.status_code, 200)
self.assertEqual(response.template_name, 'authentication/password_reset_confirm.html')

# Now we post to the same url with our new password:
response = self.c.post(reverse('password_reset_confirm', 
    kwargs={'token':token,'uidb36':uid}), {'new_password1':'pass','new_password2':'pass'})
self.assertEqual(response.status_code, 302)

And that's it! Not so hard after all.

like image 144
Jared Martin Avatar answered Sep 18 '22 18:09

Jared Martin