feat(fase-11): realtime re-sort on sort_order UPDATE + drag-reorder e2e (11.4)
The drag handle + dndzone + reorderItems batch UPDATE were already wired
on the list detail view (Fase 5.10). One observable contract was missing:
when another client reorders an item, the local realtime UPDATE feed
shallow-merges the new payload onto the existing row but does NOT
re-position the row in the array — so the new order is invisible until
a reload. Fix: sort the `items` array by sort_order after every realtime
UPDATE / INSERT merge. Cheap (n is small per list) and matches the cold-
load order.
E2E (reorder-items.test.ts):
* RO-01: create 3 items, write a new sort_order via the same PATCH the
in-page reorderItems() helper does, reload, assert the reorder
persisted.
* RO-02: dual-context, Ana reorders, Borja sees the new order via
realtime within the suite's 10s window — without this commit's
sort fix the test failed because Borja's DOM order stayed at the
old order.
Drag emulation in headless Chromium is unreliable for svelte-dnd-action
(native HTML5 DnD). Both tests drive the same write path the page uses
(reorderItems = batch PATCH on sort_order) via fetch from inside the
browser context, using the session token the SDK has already stored.
The realtime + reload paths are unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -338,10 +338,16 @@
|
||||
// UPDATE payload. INSERTs of brand-new rows arrive without tags
|
||||
// (they're attached separately); seed an empty array.
|
||||
const next = applyItemEvent(items as unknown as ShoppingItem[], evt);
|
||||
items = next.map((row) => {
|
||||
const existing = items.find((i) => i.id === row.id);
|
||||
return { ...row, tags: existing?.tags ?? [] };
|
||||
});
|
||||
// Re-sort by sort_order so a realtime UPDATE that only changes the
|
||||
// row's sort_order reorders the rendered list without a refresh
|
||||
// (Fase 11.4.3). Without this the array order is stable across
|
||||
// shallow-merge and a remote reorder is invisible to other clients.
|
||||
items = next
|
||||
.map((row) => {
|
||||
const existing = items.find((i) => i.id === row.id);
|
||||
return { ...row, tags: existing?.tags ?? [] };
|
||||
})
|
||||
.sort((a, b) => a.sort_order - b.sort_order);
|
||||
});
|
||||
|
||||
// Listen for shopping_item_tags changes so attach/detach in another tab
|
||||
|
||||
Reference in New Issue
Block a user