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

@@ -287,6 +287,13 @@ export async function reorderItems(items: Pick<ShoppingItem, 'id'>[]) {
* `(...)` list as a SQL error, and the cost of adding the filter for zero
* effect would be wasted bytes on the URL anyway.
*
* Long-list caveat: PostgREST encodes `not.in.(a,b,…)` literally in the
* query string, and supabase-js sends it as a single GET. Some upstream
* proxies / Kong configs cap request URI length around 16 KiB. We hard-cap
* the exclude list at EXCLUDE_NAMES_HARD_CAP names — past that point the
* filter degrades to a no-op (the dropdown may show a few names that are
* already on the list; acceptable UX) instead of failing the whole query.
*
* `limit` overrides the default (5 without prefix, 10 with). The /collective
* manage view does not call this — it has its own unbounded list query in
* commonItems.ts — but UI experimentation may want a smaller bar.
@@ -296,6 +303,8 @@ export interface FetchSuggestionsOptions {
limit?: number;
}
const EXCLUDE_NAMES_HARD_CAP = 200;
export async function fetchSuggestions(
collectiveId: string,
prefix: string,
@@ -317,7 +326,7 @@ export async function fetchSuggestions(
.map((n) => n.toLowerCase().trim())
.filter((n) => n.length > 0);
if (exclude.length > 0) {
if (exclude.length > 0 && exclude.length <= EXCLUDE_NAMES_HARD_CAP) {
// PostgREST in() takes a comma-separated list wrapped in parens. We
// double-quote each entry to be safe against names containing commas
// or parens (e.g. "rice (white)"); the inner double quotes are escaped