- Settings -> Account: change your own password (current + new), session
preserved via update_session_auth_hash.
- Custom labels: per-user palette in Settings -> Labels; apply/remove from a
message's ... menu (menu stays open, checkmark = applied). Labels are unified
with tags; chip colours sync to the global TagColor. New Label model +
migration 0017; POST /a/{id}/label (session, owner-scoped, palette-validated).
- Sidebar Keep/Deleted folders are now always shown; count badge only when
non-empty. Updates the stale 'hide when empty' note in CLAUDE.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
54 lines
2.3 KiB
Python
54 lines
2.3 KiB
Python
from django.contrib.auth import get_user_model
|
|
from django.test import TestCase
|
|
from django.urls import reverse
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class ChangePasswordViewTestCase(TestCase):
|
|
def setUp(self):
|
|
self.user = User.objects.create_user(username="alice", password="oldpassword")
|
|
self.client.force_login(self.user)
|
|
|
|
def _post(self, old, new1, new2):
|
|
return self.client.post(
|
|
reverse("settings-account"),
|
|
{"old_password": old, "new_password1": new1, "new_password2": new2},
|
|
)
|
|
|
|
def test_get_renders_form(self):
|
|
response = self.client.get(reverse("settings-account"))
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, "Change password")
|
|
self.assertContains(response, "old_password")
|
|
|
|
def test_requires_login(self):
|
|
self.client.logout()
|
|
response = self.client.get(reverse("settings-account"))
|
|
self.assertEqual(response.status_code, 302)
|
|
|
|
def test_valid_change_updates_password(self):
|
|
response = self._post("oldpassword", "brandnewpass", "brandnewpass")
|
|
self.assertRedirects(response, reverse("settings-account"))
|
|
self.user.refresh_from_db()
|
|
self.assertTrue(self.user.check_password("brandnewpass"))
|
|
self.assertFalse(self.user.check_password("oldpassword"))
|
|
|
|
def test_valid_change_keeps_session(self):
|
|
self._post("oldpassword", "brandnewpass", "brandnewpass")
|
|
# Session must survive the password change (update_session_auth_hash),
|
|
# so a follow-up authenticated request still succeeds.
|
|
response = self.client.get(reverse("settings-account"))
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_wrong_current_password_rejected(self):
|
|
response = self._post("WRONG", "brandnewpass", "brandnewpass")
|
|
self.assertEqual(response.status_code, 200) # re-render with errors, no redirect
|
|
self.user.refresh_from_db()
|
|
self.assertTrue(self.user.check_password("oldpassword"))
|
|
|
|
def test_mismatched_new_password_rejected(self):
|
|
response = self._post("oldpassword", "brandnewpass", "different")
|
|
self.assertEqual(response.status_code, 200)
|
|
self.user.refresh_from_db()
|
|
self.assertTrue(self.user.check_password("oldpassword"))
|