fix(fase-15): cap excludeNames at 200 + update D-06 for excluded suggestions

Two regressions surfaced when running the full e2e suite against the
shared dev DB (which accumulates hundreds of items in the seed list
over the lifetime of the test stack):

  - fetchSuggestions URL ballooned past Kong's ~16 KiB request URI cap
    when excludeNames carried 300+ names, freezing the query and
    breaking the realtime + reorder-items + section-visibility tests
    (which co-locate two browser contexts hitting the same list). Cap
    at 200 names; past that the filter degrades to a no-op (the
    dropdown may surface a few names already on the list, which is
    fine UX for a long-running shared list).
  - items.test.ts D-06 (frequency suggestions visible) was asserting
    on "milk" which is in the seed list — Fase 15 correctly suppresses
    it now. Route the test through a freshly-created empty list so
    the strip is deterministic.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 12:16:15 +02:00
parent a3fb423596
commit 6a02d6d5ab
2 changed files with 57 additions and 12 deletions

View File

@@ -102,19 +102,55 @@ test.describe('Shopping items — member (Borja)', () => {
});
test('D-06: frequency suggestions render below the add-item input', async ({ page }) => {
await gotoSeedList(page);
const nameInput = page.getByPlaceholder(ADD_ITEM_PLACEHOLDER);
await expect(nameInput).toBeVisible({ timeout: 10_000 });
// Use a fresh empty list. The seed list is shared mutable state for
// the entire suite — it accumulates many items over a long run, and
// the Fase-15 exclude-on-list filter then suppresses every frequency
// name that happens to match one of those items. A fresh empty list
// keeps the suggestion strip's contents deterministic.
const listId = await page.evaluate(async () => {
const supabase = (
window as unknown as { __sb: import('@supabase/supabase-js').SupabaseClient }
).__sb;
const { data } = await supabase
.from('shopping_lists')
.insert({
collective_id: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
name: `d-06 list ${Date.now()}`,
created_by: '22222222-2222-2222-2222-222222222222'
})
.select('id')
.single();
return data?.id ?? '';
});
// Focus the input. The seed data has "milk", "bread", "eggs", etc. in
// item_frequency, so suggestion chips should render.
await nameInput.click();
// At least one of the seed-frequency items should be visible as a chip.
await expect(page.getByRole('button', { name: /^milk$/i })).toBeVisible({ timeout: 5_000 });
try {
await page.goto(`/lists/${listId}`);
await expect(page.getByRole('button', { name: /Casa García-López/ })).toBeVisible({
timeout: 15_000
});
const nameInput = page.getByPlaceholder(ADD_ITEM_PLACEHOLDER);
await expect(nameInput).toBeVisible({ timeout: 10_000 });
// Typing a prefix should narrow suggestions. "mi" matches "milk".
await nameInput.fill('mi');
await expect(page.getByRole('button', { name: /^milk$/i })).toBeVisible({ timeout: 3_000 });
// The strip renders the top of item_frequency. The seed has
// milk/bread/eggs/etc., and the list is empty so nothing is
// excluded — at least one chip must be there.
await nameInput.click();
await expect(page.getByTestId('item-suggestions-strip')).toBeVisible({ timeout: 5_000 });
// Typing a prefix narrows the chips; the strip still renders.
await nameInput.fill('mi');
await expect(page.getByRole('button', { name: /^milk$/i })).toBeVisible({ timeout: 5_000 });
} finally {
await page.evaluate(
async ({ id }) => {
const supabase = (
window as unknown as { __sb: import('@supabase/supabase-js').SupabaseClient }
).__sb;
await supabase.from('shopping_lists').delete().eq('id', id);
},
{ id: listId }
);
}
});
});