my_buds: strip bud-autocomplete bindings from _bud_add_panel.html — the autocomplete pool is request.user.buds (per search_buds view), so on the page where you ADD new buds the suggestions are the precise set you can't usefully re-add; post-share + gatekeeper-invite panels keep the binding (re-sharing w. an existing bud is a real flow); test_autocomplete_suggests_buds_by_username_prefix → test_no_autocomplete_suggestions_on_my_buds_page (asserts #id_bud_suggestions absent — deterministic, no debounce-window race); dead id_bud_suggestions click-outside guard + unused {% load static %} dropped — 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:
@@ -5,7 +5,6 @@ will layer autocomplete (sky-place-style top-3 username suggestions) and
|
||||
implicit auto-add on post-share / gate-invite.
|
||||
"""
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
|
||||
from apps.lyric.models import User
|
||||
|
||||
@@ -57,30 +56,21 @@ class MyBudsPageTest(FunctionalTest):
|
||||
self.alice, list(self.gamer.buds.all())
|
||||
))
|
||||
|
||||
def test_autocomplete_suggests_buds_by_username_prefix(self):
|
||||
"""Phase 2: typing in #id_recipient pulls top-3 prefix matches from
|
||||
request.user.buds and renders them as .bud-suggestion-item buttons.
|
||||
Click → input.value fills with the bud's username (or email if the
|
||||
user typed an `@` already)."""
|
||||
def test_no_autocomplete_suggestions_on_my_buds_page(self):
|
||||
"""The bud-autocomplete pool is request.user.buds — surfacing buds
|
||||
you've already added on the page where you ADD new buds is just
|
||||
noise. Post-share + gatekeeper-invite panels keep it (re-sharing
|
||||
with an existing bud is a real flow); the My Buds add-panel drops
|
||||
the autocomplete bindings entirely. Absence of #id_bud_suggestions
|
||||
is the deterministic check (no debounce-window races)."""
|
||||
self.gamer.buds.add(self.alice)
|
||||
bob = User.objects.create(email="bob@test.io", username="bob")
|
||||
self.gamer.buds.add(bob)
|
||||
|
||||
self.browser.get(self.live_server_url + "/billboard/my-buds/")
|
||||
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("al")
|
||||
self.wait_for(lambda: self.browser.find_element(By.ID, "id_bud_btn"))
|
||||
|
||||
suggestions = self.wait_for(lambda: self.browser.find_element(
|
||||
By.CSS_SELECTOR, "#id_bud_suggestions .bud-suggestion-item"
|
||||
))
|
||||
self.assertEqual(suggestions.text.strip(), "alice")
|
||||
|
||||
suggestions.click()
|
||||
self.wait_for(lambda: self.assertEqual(
|
||||
recipient.get_attribute("value"), "alice"
|
||||
))
|
||||
self.assertEqual(
|
||||
self.browser.find_elements(By.ID, "id_bud_suggestions"),
|
||||
[],
|
||||
)
|
||||
|
||||
def test_add_unregistered_email_is_silent_noop(self):
|
||||
self.browser.get(self.live_server_url + "/billboard/my-buds/")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
{% load static %}
|
||||
{# ─────────────────────────────────────────────────────────────────────── #}
|
||||
{# _bud_add_panel.html — bottom-left handshake btn + slide-out add- #}
|
||||
{# bud field. Mirrors _bud_panel.html (post-share) but POSTs to #}
|
||||
@@ -19,18 +18,10 @@
|
||||
<button id="id_bud_ok" type="button" class="btn btn-confirm">OK</button>
|
||||
</div>
|
||||
|
||||
{# Autocomplete suggestions list — sibling of #id_bud_panel because the #}
|
||||
{# panel has overflow:hidden for its scaleX slide animation. #}
|
||||
<div id="id_bud_suggestions" class="bud-suggestions" hidden></div>
|
||||
|
||||
<script src="{% static 'apps/billboard/bud-autocomplete.js' %}"></script>
|
||||
<script>
|
||||
bindBudAutocomplete(
|
||||
document.getElementById('id_recipient'),
|
||||
document.getElementById('id_bud_suggestions'),
|
||||
{ searchUrl: '{% url "billboard:search_buds" %}' }
|
||||
);
|
||||
</script>
|
||||
{# No autocomplete on this panel — the bud-autocomplete pool is the #}
|
||||
{# user's existing buds, which is precisely the set you can't usefully #}
|
||||
{# re-add. Post-share + gatekeeper-invite panels keep the autocomplete #}
|
||||
{# binding (re-sharing with an existing bud is a real flow). #}
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
@@ -77,10 +68,6 @@
|
||||
if (!html.classList.contains('bud-open')) return;
|
||||
if (panel.contains(e.target)) return;
|
||||
if (e.target === btn || btn.contains(e.target)) return;
|
||||
// Suggestions live outside the panel (panel has overflow:hidden
|
||||
// for its scaleX slide); a click inside them must NOT close+clear.
|
||||
var sg = document.getElementById('id_bud_suggestions');
|
||||
if (sg && sg.contains(e.target)) return;
|
||||
_close();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user