From 5e71b1d5daf9fbdc8aeaae316b5e63a56a42ec2e Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Mon, 18 May 2026 21:42:58 -0400 Subject: [PATCH] =?UTF-8?q?Baltimorean:=20post-attribution=20titles=20now?= =?UTF-8?q?=20read=20"Baltimorean"=20not=20"Ard!"=20=E2=80=94=20TDD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User caught a missed surface on iPhone after the May-18b rename pass (1ccb045): the post.html `.post-attribution` spans still rendered "@disco the Ard!" instead of "@disco the Baltimorean" — six callsites across the post header (author / invitee / shared-self / created-by) plus `_my_buds_applet_item.html`'s bud row body. Same shape on display: navbar DON greeting is the only surface that should keep "Ayo, Ard!", per the May-18b architectural decision ; root cause: `User.active_title_display` at lyric/models.py:152 returned `self.active_title.display_title` ("Ard!" for Baltimorean) instead of `self.active_title.display_name` ("Baltimorean"). The Sprint-18b rename pass swapped the inline `attr_combo` + Brief.title to use `display_name`, but missed this property which is the indirection layer for `.post-attribution` callsites. Navbar uses `{{ user.active_title.display_title }}` directly (no helper-property indirection) so it stays at "Ard!" — that's the intended single Ard! surface ; fix: one-line swap in `active_title_display` from `display_title` to `display_name`. For stargazer / schizo / nomad these two are equal (the Note model's `display_name` property at drama/models.py:262 falls through to `display_title` unless the slug has an override in `_NOTE_DISPLAY[slug]["display_name"]`) — Baltimorean is the only current override w. `{"display_name": "Baltimorean"}`. So this is no-op for every non-Baltimorean Note ; TDD trail: +3 UTs in apps.lyric.tests.integrated.test_models.UserModelTest: `test_active_title_display_returns_earthman_when_no_note_donned` (smoke), `test_active_title_display_uses_display_name_not_display_title` (pins the Baltimorean override path — went red 'Ard! != Baltimorean' before the fix), `test_active_title_display_falls_through_to_display_title_for_non_overridden_slugs` (pins the no-op path for stargazer). Red → green confirmed. Surfaces auto-affected: post.html post-attribution × 5 callsites + `_my_buds_applet_item.html` bud row body (all use `{{ user.active_title_display }}`) ; 1008 IT/UT green in 46s (+3 from 1005) Code architected by Disco DeDisco Git commit message Co-Authored-By: Claude Sonnet 4.6 --- src/apps/lyric/models.py | 11 +++++--- .../lyric/tests/integrated/test_models.py | 26 +++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/apps/lyric/models.py b/src/apps/lyric/models.py index 8ab8103..7985ce2 100644 --- a/src/apps/lyric/models.py +++ b/src/apps/lyric/models.py @@ -151,11 +151,14 @@ class User(AbstractBaseUser): @property def active_title_display(self): """Render-ready string for "{username} the {title}" attributions — - returns the donned Note's recognition title, or 'Earthman' when no - Note is donned. The 'Earthman' default mirrors the dashboard greeting - fallback in dashboard/views.home_page.""" + returns the donned Note's `display_name`, or 'Earthman' when no + Note is donned. Uses `display_name` (not `display_title`) so the + Baltimorean rename — `display_title="Ard!"` (navbar DON greeting + flair only) vs. `display_name="Baltimorean"` (everywhere else) — + propagates to inline attributions like `.post-attribution`. For + non-overridden slugs the two are equal so this is a no-op.""" if self.active_title_id: - return self.active_title.display_title + return self.active_title.display_name return "Earthman" @property diff --git a/src/apps/lyric/tests/integrated/test_models.py b/src/apps/lyric/tests/integrated/test_models.py index 0378d11..05794e2 100644 --- a/src/apps/lyric/tests/integrated/test_models.py +++ b/src/apps/lyric/tests/integrated/test_models.py @@ -51,6 +51,32 @@ class UserModelTest(TestCase): user.refresh_from_db() self.assertIsNone(user.active_title) + def test_active_title_display_returns_earthman_when_no_note_donned(self): + user = User.objects.create(email="a@b.cde") + self.assertEqual(user.active_title_display, "Earthman") + + def test_active_title_display_uses_display_name_not_display_title(self): + """Inline attributions like `.post-attribution` should render the + Note's `display_name`, not its `display_title` — the only divergence + today is Baltimorean (display_title="Ard!" navbar-flair, display_name + ="Baltimorean" everywhere else). Pinning here so future Notes that + override one field but not the other don't surprise the post page.""" + user = User.objects.create(email="ard@b.cde") + note = Note.objects.create(user=user, slug="baltimorean", earned_at=timezone.now()) + user.active_title = note + user.save(update_fields=["active_title"]) + self.assertEqual(user.active_title_display, "Baltimorean") + + def test_active_title_display_falls_through_to_display_title_for_non_overridden_slugs(self): + """Stargazer / Schizo / Nomad don't override display_name, so + active_title_display returns the same string display_title would — + the rename pattern is no-op for these surfaces.""" + user = User.objects.create(email="star@b.cde") + note = Note.objects.create(user=user, slug="stargazer", earned_at=timezone.now()) + user.active_title = note + user.save(update_fields=["active_title"]) + self.assertEqual(user.active_title_display, note.display_title) + class LoginTokenModelTest(TestCase): def test_links_user_with_autogen_uid(self): login_token1 = LoginToken.objects.create(email="a@b.cde")