From 4edbb8912f4f0381ae954d111f34d139709e4aa8 Mon Sep 17 00:00:00 2001 From: malibio Date: Sat, 26 Sep 2026 14:57:37 +0200 Subject: [PATCH 1/2] Wait for the second persisted write in the Kanban drag-move browser test (closes #3080) The second move's updateTaskNode call is dispatched after the card re-renders in its new column, so asserting versionsSent right after the UI waitFor saw only the first write. Wait for both writes instead. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../tests/browser/kanban-consecutive-status-moves.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/desktop-app/src/tests/browser/kanban-consecutive-status-moves.test.ts b/packages/desktop-app/src/tests/browser/kanban-consecutive-status-moves.test.ts index f4f8e4b59..7b418995d 100644 --- a/packages/desktop-app/src/tests/browser/kanban-consecutive-status-moves.test.ts +++ b/packages/desktop-app/src/tests/browser/kanban-consecutive-status-moves.test.ts @@ -228,7 +228,11 @@ describe('KanbanView — consecutive status moves on a task node (browser mode)' }); expect(cardsIn(columnFor(container, 'In Progress'))).toEqual([]); - expect(versionsSent).toEqual([1, 2]); + // The second move's write goes out after the card re-renders in its new + // column, so wait for it instead of asserting on the render's timing. + await waitFor(() => { + expect(versionsSent).toEqual([1, 2]); + }); expect(conflictNotifications.notifications).toEqual([]); }); From 6addae78130ecf6285481979babac4654d7a48f8 Mon Sep 17 00:00:00 2001 From: malibio Date: Sat, 26 Sep 2026 15:45:34 +0200 Subject: [PATCH 2/2] Address review: wait for the second write in the sibling Kanban test too - The select-driven consecutive-move test goes through the same optimistic updateTypedNode path, so its versionsSent assertion now waits as well. - Comments name the mechanism: the store applies the move before sending. Skipped: making the mock reject on a version mismatch so the conflictNotifications assertion has teeth - a pre-existing coverage gap, out of scope for a timing fix. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../browser/kanban-consecutive-status-moves.test.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/desktop-app/src/tests/browser/kanban-consecutive-status-moves.test.ts b/packages/desktop-app/src/tests/browser/kanban-consecutive-status-moves.test.ts index 7b418995d..93c2c46b1 100644 --- a/packages/desktop-app/src/tests/browser/kanban-consecutive-status-moves.test.ts +++ b/packages/desktop-app/src/tests/browser/kanban-consecutive-status-moves.test.ts @@ -169,7 +169,11 @@ describe('KanbanView — consecutive status moves on a task node (browser mode)' // The critical assertion: each write sent the version RETURNED by the // previous write, not a stale/repeated one — this is exactly the OCC // mismatch the issue describes ("every subsequent status change fails"). - expect(versionsSent).toEqual([1, 2]); + // The store applies each move before sending its write, so wait for the + // second write rather than asserting on the render's timing. + await waitFor(() => { + expect(versionsSent).toEqual([1, 2]); + }); expect(conflictNotifications.notifications).toEqual([]); }); @@ -228,8 +232,9 @@ describe('KanbanView — consecutive status moves on a task node (browser mode)' }); expect(cardsIn(columnFor(container, 'In Progress'))).toEqual([]); - // The second move's write goes out after the card re-renders in its new - // column, so wait for it instead of asserting on the render's timing. + // The store applies the move before sending its write, so the card lands + // in its new column first — wait for the second write rather than + // asserting on the render's timing. await waitFor(() => { expect(versionsSent).toEqual([1, 2]); });