bud panels duplicate-add guard: server-side already_present flag + client-side error Brief w. FYI flash highlight on the existing entry — for each of the three #id_bud_btn panels (My Buds / post-share / gatekeeper-invite), the JSON response from add_bud / share_post / invite_gamer now carries {already_present, recipient_display, recipient_user_id}; bud-btn.js branches on already_present → calls new Brief.showDuplicateBanner({display_name, target_selector}) instead of the normal onSuccess append; banner title reads @<username> is already present, NVM dismisses, FYI dismisses AND eases in the .bud-duplicate-flash class (color: var(--terUser); text-shadow: 0 0 .5em var(--ninUser); transition: 600ms) onto the existing element (.bud-entry .bud-name / .post-recipient[data-user-id=…] / .gate-slot.filled[data-user-id=…]); gatekeeper "already present" = recipient is either GateSlot.FILLED + gamer OR has TableSeat OR has a pending RoomInvite (highlight target only set when seated — pending invites have no visible slot); .post-recipient chips + .gate-slot.filled cells gain data-user-id so the FYI selector can find them; my_buds.html now loads note.js via the {% block scripts %} pattern (Brief module is required by the duplicate banner path); bonus: latent test_jasmine.py bug fixed — "0 failures" in result.text matched "10 failures" / "20 failures" / etc, silently passing up to 99 failed specs; replaced w. re.search(r"(?<!\d)0 failures\b", …) (caught my new red specs, would've caught any prior Jasmine regression); 18 new ITs + 10 new Jasmine specs + 3 new FTs (one per panel) — TDD
Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -379,3 +379,49 @@ class PostHtmlAperturePageClassTest(FunctionalTest):
|
||||
"page-billboard" in cls or "page-billpost" in cls,
|
||||
f"my_posts.html body class missing aperture marker: {cls!r}",
|
||||
)
|
||||
|
||||
|
||||
class BudBtnDuplicateShareErrorTest(FunctionalTest):
|
||||
"""Re-sharing a post w. someone already in post.shared_with triggers
|
||||
the error Brief titled `@<username> is already present`. FYI on the
|
||||
Brief dismisses + adds .bud-duplicate-flash to the existing
|
||||
.post-recipient[data-user-id=…] chip."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.sharer = User.objects.create(email="bud@test.io", username="bud")
|
||||
self.alice = User.objects.create(email="alice@test.io", username="alice")
|
||||
self.post = _seed_a_post(self.sharer)
|
||||
self.post.shared_with.add(self.alice)
|
||||
self.create_pre_authenticated_session("bud@test.io")
|
||||
self.browser.get(self.live_server_url + f"/billboard/post/{self.post.id}/")
|
||||
|
||||
def test_duplicate_share_shows_error_brief_and_fyi_flashes_chip(self):
|
||||
btn = self.wait_for(lambda: self.browser.find_element(By.ID, "id_bud_btn"))
|
||||
btn.click()
|
||||
recipient = self.wait_for(lambda: self.browser.find_element(By.ID, "id_recipient"))
|
||||
recipient.send_keys("alice@test.io")
|
||||
self.browser.find_element(By.CSS_SELECTOR, "#id_bud_panel .btn.btn-confirm").click()
|
||||
|
||||
title = self.wait_for(lambda: self.browser.find_element(
|
||||
By.CSS_SELECTOR, ".note-banner--duplicate .note-banner__title"
|
||||
))
|
||||
self.assertEqual(title.text, "@alice is already present")
|
||||
|
||||
# Existing chip carries data-user-id so the FYI highlight can find it
|
||||
chip = self.browser.find_element(
|
||||
By.CSS_SELECTOR, f".post-recipient[data-user-id='{self.alice.id}']"
|
||||
)
|
||||
self.assertNotIn("bud-duplicate-flash", chip.get_attribute("class") or "")
|
||||
|
||||
# FYI dismisses + applies flash class
|
||||
self.browser.find_element(
|
||||
By.CSS_SELECTOR, ".note-banner--duplicate .note-banner__fyi"
|
||||
).click()
|
||||
self.wait_for(lambda: self.assertEqual(
|
||||
self.browser.find_elements(By.CSS_SELECTOR, ".note-banner--duplicate"),
|
||||
[],
|
||||
))
|
||||
self.wait_for(lambda: self.assertIn(
|
||||
"bud-duplicate-flash", chip.get_attribute("class") or ""
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user