my-buds async add: render full row (anchor + the <Title> + data-tt-* attrs) so the appended entry's tooltip isn't empty — TDD
Adding a bud appended a stripped `@handle`-only <li> — no `applet-list-entry` class, no bud-page anchor, no ` the <Title>` span, no data-tt-* attrs — so the new row rendered without its title and its tooltip came up empty next to the server-rendered rows above it. - add_bud (billboard/views.py) — bud payload now carries `at_handle` (server- computed; the client can't replicate at_handle's truncate_email fallback for username-less buds) + `title` (active_title_display). IT asserts both. - _bud_add_panel.html `_appendBudEntry` — rebuilt to mirror _my_buds_item.html exactly: both classes, data-tt-title/description/email/shoptalk, the bud-name anchor into /billboard/buds/<id>/, and the trailing ` the <Title>`. New FT pins the regression: appended row carries the attrs + anchor + title and its portal populates non-empty on row-lock. AddBudViewTest + append FT green. Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -142,6 +142,19 @@ class AddBudViewTest(TestCase):
|
||||
response = self.client.get(reverse("billboard:add_bud"))
|
||||
self.assertEqual(response.status_code, 405)
|
||||
|
||||
def test_add_returns_at_handle_and_title_for_tooltip_row(self):
|
||||
"""The async-appended My Buds row mirrors _my_buds_item.html, so the
|
||||
payload must carry the bud's at_handle + active_title_display to fill
|
||||
the data-tt-* attrs — without them the new row's tooltip renders empty
|
||||
(the entries above it, server-rendered, have them). Regression
|
||||
2026-05-29."""
|
||||
alice = User.objects.create(email="alice@test.io", username="alice")
|
||||
body = self.client.post(
|
||||
reverse("billboard:add_bud"), data={"recipient": "alice"},
|
||||
).json()
|
||||
self.assertEqual(body["bud"]["at_handle"], "@alice")
|
||||
self.assertEqual(body["bud"]["title"], alice.active_title_display)
|
||||
|
||||
def test_add_resolves_username_too_not_just_email(self):
|
||||
"""Phase 2: recipient field accepts usernames as well as emails."""
|
||||
alice = User.objects.create(email="alice@test.io", username="alice")
|
||||
|
||||
@@ -700,11 +700,16 @@ def add_bud(request):
|
||||
already_present = candidate in request.user.buds.all()
|
||||
if not already_present:
|
||||
request.user.buds.add(candidate)
|
||||
from apps.lyric.templatetags.lyric_extras import at_handle
|
||||
display = candidate.username or candidate.email
|
||||
bud = {
|
||||
"id": str(candidate.id),
|
||||
"username": display,
|
||||
"email": candidate.email,
|
||||
"id": str(candidate.id),
|
||||
"username": display,
|
||||
"email": candidate.email,
|
||||
# at_handle + title feed the async row's data-tt-* attrs so its
|
||||
# tooltip matches the server-rendered rows (regression 2026-05-29).
|
||||
"at_handle": at_handle(candidate),
|
||||
"title": candidate.active_title_display,
|
||||
}
|
||||
recipient_display = display
|
||||
recipient_user_id = str(candidate.id)
|
||||
|
||||
Reference in New Issue
Block a user