From 9f1b8b42151ff576a2639a60b7de2174dfa38dab Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 12 May 2026 22:00:44 +0200 Subject: [PATCH] =?UTF-8?q?fix(enrichment-block):=20migrate=20$app/stores?= =?UTF-8?q?=20=E2=86=92=20$app/state=20to=20eliminate=20birpc=20race?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The async vi.mock factory in EnrichmentBlock.svelte.spec.ts performed an `await import(...)` in its body — the same mechanism #535/#546 fixed for pdfjs-dist. Issue #553: when Chromium's playwright route handler fetches the mocked module after the worker's birpc channel has closed, the factory's RPC roundtrip raises `[birpc] rpc is closed, cannot call "resolveManualMock"` and the run exits 1. Migrate EnrichmentBlock from the deprecated `$app/stores.navigating` (store) to the modern `$app/state.navigating` (reactive proxy). The spec uses vi.hoisted + a sync vi.mock factory with a getter that defers the read — no dynamic import in the factory body. Delete the now-unused __mocks__/navigatingStore.ts. Fix path applied: $app/state migration (Markus's recommendation / Felix's Path 2). See ADR-012. Refs #553 Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/lib/document/EnrichmentBlock.svelte | 4 +-- .../document/EnrichmentBlock.svelte.spec.ts | 28 +++++++++++-------- .../lib/document/__mocks__/navigatingStore.ts | 3 -- 3 files changed, 18 insertions(+), 17 deletions(-) delete mode 100644 frontend/src/lib/document/__mocks__/navigatingStore.ts diff --git a/frontend/src/lib/document/EnrichmentBlock.svelte b/frontend/src/lib/document/EnrichmentBlock.svelte index a4327cf3..77a9e96a 100644 --- a/frontend/src/lib/document/EnrichmentBlock.svelte +++ b/frontend/src/lib/document/EnrichmentBlock.svelte @@ -1,5 +1,5 @@ diff --git a/frontend/src/lib/document/EnrichmentBlock.svelte.spec.ts b/frontend/src/lib/document/EnrichmentBlock.svelte.spec.ts index ac5167d1..35039cb2 100644 --- a/frontend/src/lib/document/EnrichmentBlock.svelte.spec.ts +++ b/frontend/src/lib/document/EnrichmentBlock.svelte.spec.ts @@ -2,19 +2,23 @@ import { describe, it, expect, afterEach, vi } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; -// The store must live in a separate module because vi.mock factories are -// hoisted and cannot reference top-level variables defined in this file. -import { navigatingStore } from './__mocks__/navigatingStore'; import EnrichmentBlock from './EnrichmentBlock.svelte'; -vi.mock('$app/stores', async () => { - const mod = await import('./__mocks__/navigatingStore'); - return { navigating: mod.navigatingStore }; -}); +// Hoist the mutable navigation reference so vi.mock's factory (also hoisted) +// can read it via a getter. Sync factory, no dynamic import: ADR-012 invariant. +const { mockNavigating } = vi.hoisted(() => ({ + mockNavigating: { type: null as string | null } +})); + +vi.mock('$app/state', () => ({ + get navigating() { + return mockNavigating; + } +})); afterEach(() => { cleanup(); - navigatingStore.set(null); + mockNavigating.type = null; }); type Doc = { id: string; title: string; uploadedAt: string }; @@ -65,8 +69,8 @@ describe('EnrichmentBlock', () => { await expect.element(page.getByTestId('dashboard-needs-metadata')).toBeInTheDocument(); }); - it('renders the skeleton when $navigating is active and topDocs is empty', async () => { - navigatingStore.set({ type: 'link' }); + it('renders the skeleton when navigation is active and topDocs is empty', async () => { + mockNavigating.type = 'link'; render(EnrichmentBlock, { topDocs: [], totalCount: 0, @@ -76,8 +80,8 @@ describe('EnrichmentBlock', () => { await expect.element(page.getByTestId('enrichment-block-skeleton')).toBeInTheDocument(); }); - it('does not render the skeleton when topDocs is non-empty even during $navigating', async () => { - navigatingStore.set({ type: 'link' }); + it('does not render the skeleton when topDocs is non-empty even during navigation', async () => { + mockNavigating.type = 'link'; render(EnrichmentBlock, { topDocs: [doc('d1')], totalCount: 1, diff --git a/frontend/src/lib/document/__mocks__/navigatingStore.ts b/frontend/src/lib/document/__mocks__/navigatingStore.ts deleted file mode 100644 index 932122e4..00000000 --- a/frontend/src/lib/document/__mocks__/navigatingStore.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { writable } from 'svelte/store'; - -export const navigatingStore = writable(null);