Testing Django 1-5 Reset Password Form - how to generate the token for the test?
authentication, django, django-webtest
Solution
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':'fred@home.com'})
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.
Problem
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]) ```