diff --git a/src/apps/billboard/views.py b/src/apps/billboard/views.py index cee7604..d627e43 100644 --- a/src/apps/billboard/views.py +++ b/src/apps/billboard/views.py @@ -216,7 +216,7 @@ def my_notes(request): { "obj": n, "title": _NOTE_META.get(n.slug, {}).get("title", n.slug), - "recognition_title": n.display_title, + "recognition_title": n.card_title, "description": _NOTE_META.get(n.slug, {}).get("description", ""), "palette_options": _NOTE_META.get(n.slug, {}).get("palette_options", []), "swatch_label": _NOTE_META.get(n.slug, {}).get("swatch_label"), diff --git a/src/apps/dashboard/tests/integrated/test_views.py b/src/apps/dashboard/tests/integrated/test_views.py index 95f6ce9..ed4fe80 100644 --- a/src/apps/dashboard/tests/integrated/test_views.py +++ b/src/apps/dashboard/tests/integrated/test_views.py @@ -768,7 +768,7 @@ class SetPronounsBawlmoreseUnlockTest(TestCase): def test_brief_payload_carries_baltimorean_title(self): response = self.client.post(self.url, data={"pronouns": "bawlmorese"}) brief = response.json()["brief"] - self.assertEqual(brief["title"], "Ard!") + self.assertEqual(brief["title"], "Baltimorean") def test_brief_payload_square_url_jumps_to_my_notes(self): """NOTE_UNLOCK Briefs carry a `square_url` pointing at /billboard/my-notes/ diff --git a/src/apps/drama/models.py b/src/apps/drama/models.py index e129572..0ae9cea 100644 --- a/src/apps/drama/models.py +++ b/src/apps/drama/models.py @@ -212,7 +212,7 @@ _NOTE_DISPLAY = { "nomad": {"greeting": "Welcome,", "title": "Nomad"}, "super-schizo": {"greeting": "21st Century", "title": "Schizoid Man"}, "super-nomad": {"greeting": "Howdy,", "title": "Stranger"}, - "baltimorean": {"greeting": "Ayo,", "title": "Ard!"}, + "baltimorean": {"greeting": "Ayo,", "title": "Ard!", "card_title": "Baltimorean"}, } # Note slugs whose grant prose uses the long admin format ("The administration @@ -249,6 +249,15 @@ class Note(models.Model): def display_greeting(self): return _NOTE_DISPLAY.get(self.slug, {}).get("greeting", "Welcome,") + @property + def card_title(self): + """The string shown in the my-notes card's "Title:" row. Defaults to + `display_title` (the don-able title — most slugs render the title you + DON here, e.g. "Schizoid Man" for super-schizo). Baltimorean overrides + so the card reads "Baltimorean" instead of the navbar-only "Ard!" + flair.""" + return _NOTE_DISPLAY.get(self.slug, {}).get("card_title", self.display_title) + @property def display_name(self): """The Note's *name* (e.g., "Stargazer", "Super-Schizo") — the heading @@ -316,9 +325,13 @@ class Note(models.Model): "This does not entail any additional corporate benefits." ) else: + # Inline attribution reads "{handle} the {Note name}", not the + # don-able title. For most slugs the two coincide ("the Stargazer") + # but Baltimorean's title is the navbar flair "Ard!" — "the Ard!" + # reads oddly inline; "the Baltimorean" matches the Note name. attr_combo = ( f'{handle} ' - f'the {note.display_title}' + f'the {note.display_name}' ) line_text = ( f"Look!—new Note unlocked. {note_anchor} " @@ -339,6 +352,6 @@ class Note(models.Model): post=post, line=line, kind=Brief.KIND_NOTE_UNLOCK, - title=note.display_title, + title=note.display_name, ) return note, created, brief diff --git a/src/apps/drama/tests/integrated/test_note_brief.py b/src/apps/drama/tests/integrated/test_note_brief.py index bd80e87..fd8b940 100644 --- a/src/apps/drama/tests/integrated/test_note_brief.py +++ b/src/apps/drama/tests/integrated/test_note_brief.py @@ -30,8 +30,9 @@ class GrantIfNewSpawnsBriefTest(TestCase): self.assertEqual(brief.owner, self.user) # The Brief's line is one of the Post's lines self.assertIn(brief.line, list(post.lines.all())) - # Brief title matches Note display title - self.assertEqual(brief.title, note.display_title) + # Brief title matches Note display name (the Note's name — used in the + # banner's title slot and inline "the {name}" attribution). + self.assertEqual(brief.title, note.display_name) def test_second_grant_same_slug_returns_no_brief(self): Note.grant_if_new(self.user, "stargazer") diff --git a/src/apps/drama/tests/unit/test_models.py b/src/apps/drama/tests/unit/test_models.py index a947ce5..7c823db 100644 --- a/src/apps/drama/tests/unit/test_models.py +++ b/src/apps/drama/tests/unit/test_models.py @@ -27,6 +27,12 @@ class NoteDisplayBaltimoreanTest(SimpleTestCase): through to `slug.title()` → 'Baltimorean'.""" self.assertEqual(_note("baltimorean").display_name, "Baltimorean") + def test_baltimorean_card_title_is_baltimorean(self): + """The my-notes card's "Title:" row uses `card_title`, which Baltimorean + explicitly overrides to "Baltimorean" so the navbar-only "Ard!" flair + doesn't leak onto the card.""" + self.assertEqual(_note("baltimorean").card_title, "Baltimorean") + class NoteDisplayStargazerTest(SimpleTestCase): """Smoke tests for the existing stargazer entry — pins the contract that @@ -37,3 +43,8 @@ class NoteDisplayStargazerTest(SimpleTestCase): def test_stargazer_display_greeting_is_welcome(self): self.assertEqual(_note("stargazer").display_greeting, "Welcome,") + + def test_stargazer_card_title_falls_back_to_display_title(self): + """Slugs without a `card_title` override fall through to display_title — + for stargazer that's "Stargazer" (don-able title == Note name).""" + self.assertEqual(_note("stargazer").card_title, "Stargazer") diff --git a/src/functional_tests/test_bill_baltimorean.py b/src/functional_tests/test_bill_baltimorean.py index fcf73fa..ad1a402 100644 --- a/src/functional_tests/test_bill_baltimorean.py +++ b/src/functional_tests/test_bill_baltimorean.py @@ -7,7 +7,7 @@ Baltimorean Note and fires the slide-down Brief banner. End-to-end loop captured here: 1. Game Kit → pronouns applet → click `bawlmorese` card → guard portal "OK" - 2. Brief banner slides in with title "Ard!" + Look! prose + FYI/NVM/?-square + 2. Brief banner slides in with title "Baltimorean" + Look! prose + FYI/NVM/?-square 3. Navigate to /billboard/my-notes/ → Baltimorean item w. the Aaron quote 4. DON the Baltimorean Note → navbar greeting flips "Welcome, Earthman" → "Ayo, Ard!" @@ -106,10 +106,10 @@ class BaltimoreanNoteFromGameKitTest(FunctionalTest): banner = self.wait_for_slow(lambda: self.browser.find_element( By.CSS_SELECTOR, ".note-banner" )) - # The title slot carries the recognition title — for baltimorean - # that's "Ard!" (vs stargazer's "Stargazer"). + # The title slot carries the Note name — "Baltimorean". The don-able + # title "Ard!" only surfaces in the navbar greeting after DON. self.assertIn( - "Ard!", + "Baltimorean", banner.find_element(By.CSS_SELECTOR, ".note-banner__title").text, ) # Look! prose lands in the description. diff --git a/src/functional_tests/test_game_kit.py b/src/functional_tests/test_game_kit.py index 2a24479..2c432a2 100644 --- a/src/functional_tests/test_game_kit.py +++ b/src/functional_tests/test_game_kit.py @@ -198,12 +198,13 @@ class PronounsAppletFlowTest(FunctionalTest): self.assertIn("Set pronoun preference?", portal.text) self.assertIn("yo/yo/yos", portal.text) - # 4. Click OK — the page reloads, .active class moves to bawlmorese. + # 4. Click OK — first-time bawlmorese unlocks the Baltimorean Note, so + # the server returns 200 w. a Brief payload (no reload — the banner + # would be lost). Wait for the banner to confirm the commit landed + # before navigating away. portal.find_element(By.CSS_SELECTOR, ".guard-yes").click() self.wait_for( - lambda: self.browser.find_element( - By.CSS_SELECTOR, ".gk-pronoun-card.active[data-pronoun='bawlmorese']" - ) + lambda: self.browser.find_element(By.CSS_SELECTOR, ".note-banner") ) # 5. Navigate to the Billboard — Most Recent Scroll applet must now