Coverage for modules\authentication\tests\test_password_reset.py: 100%

26 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-10-17 16:50 +0800

1import re 

2 

3from django.core import mail 

4from django.test import TestCase, override_settings 

5 

6from modules.authentication.models import AuthAuditEvent, PasswordResetToken, User 

7from modules.authentication.services import AuthService 

8 

9 

10@override_settings( 

11 EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend', 

12 FRONTEND_URL='http://testserver', 

13 PASSWORD_RESET_REQUEST_LIMIT=2, 

14) 

15class PasswordResetServiceTests(TestCase): 

16 def setUp(self): 

17 self.user = User.objects.create_user(email='member@example.com', password='Before123!') 

18 

19 def test_reset_token_is_emailed_hashed_and_single_use(self): 

20 AuthService.request_password_reset(self.user.email) 

21 

22 self.assertEqual(len(mail.outbox), 1) 

23 self.assertNotIn('Before123!', mail.outbox[0].body) 

24 token = re.search(r'token=([^\s]+)', mail.outbox[0].body).group(1) 

25 stored = PasswordResetToken.objects.get(user=self.user) 

26 self.assertNotEqual(stored.token_hash, token) 

27 

28 AuthService.confirm_password_reset(token, 'After123!') 

29 self.user.refresh_from_db() 

30 self.assertTrue(self.user.check_password('After123!')) 

31 self.assertIsNotNone(stored.__class__.objects.get(id=stored.id).used_at) 

32 

33 with self.assertRaisesMessage(Exception, 'invalid or has expired'): 

34 AuthService.confirm_password_reset(token, 'Another123!') 

35 

36 def test_unknown_email_does_not_send_mail_or_reveal_account_status(self): 

37 AuthService.request_password_reset('nobody@example.com') 

38 self.assertEqual(len(mail.outbox), 0) 

39 self.assertTrue(AuthAuditEvent.objects.filter(event_type='PASSWORD_RESET_REQUESTED', email='nobody@example.com').exists())