diff --git a/desktop/src/testing/e2eBridge.ts b/desktop/src/testing/e2eBridge.ts index 6c0bc1b94..b7f699916 100644 --- a/desktop/src/testing/e2eBridge.ts +++ b/desktop/src/testing/e2eBridge.ts @@ -1254,9 +1254,9 @@ declare global { __BUZZ_E2E_RELEASE_OBSERVER_ARCHIVE_POLICY__?: () => number; /** Number of observer archive policy commands currently held by the seam. */ __BUZZ_E2E_OBSERVER_ARCHIVE_POLICY_PENDING__?: number; - /** Hold channel reads until released. */ + /** Hold the next channel read until released. */ __BUZZ_E2E_DEFER_NEXT_CHANNELS_READ__?: () => void; - /** Release every channel read held by the explicit E2E seam. */ + /** Disarm the latch and release the held channel read, if any. */ __BUZZ_E2E_RELEASE_CHANNELS_READ__?: () => number; /** Number of channel reads currently held by the seam. */ __BUZZ_E2E_CHANNELS_READ_PENDING__?: number; @@ -9798,6 +9798,7 @@ export function maybeInstallE2eTauriMocks() { deferNextChannelsRead = true; }; window.__BUZZ_E2E_RELEASE_CHANNELS_READ__ = () => { + deferNextChannelsRead = false; const queued = deferredChannelsReadQueue.splice(0); window.__BUZZ_E2E_CHANNELS_READ_PENDING__ = 0; for (const resolve of queued) resolve(); diff --git a/desktop/tests/e2e/community-rail.spec.ts b/desktop/tests/e2e/community-rail.spec.ts index ef71957ad..a58f8ddd6 100644 --- a/desktop/tests/e2e/community-rail.spec.ts +++ b/desktop/tests/e2e/community-rail.spec.ts @@ -467,6 +467,31 @@ test.describe("community rail", () => { ), ) .not.toBeNull(); + expect( + await page.evaluate(async () => { + const testWindow = window as Window & { + __BUZZ_E2E_DEFER_NEXT_CHANNELS_READ__?: () => void; + __BUZZ_E2E_RELEASE_CHANNELS_READ__?: () => number; + __BUZZ_E2E_CHANNELS_READ_PENDING__?: number; + __BUZZ_E2E_INVOKE_MOCK_COMMAND__?: ( + command: string, + ) => Promise; + }; + const deferNext = testWindow.__BUZZ_E2E_DEFER_NEXT_CHANNELS_READ__; + const release = testWindow.__BUZZ_E2E_RELEASE_CHANNELS_READ__; + const invoke = testWindow.__BUZZ_E2E_INVOKE_MOCK_COMMAND__; + if (!deferNext || !release || !invoke) { + throw new Error("missing channel-read latch seam"); + } + deferNext(); + const released = release(); + await invoke("get_channels"); + return { + released, + pending: testWindow.__BUZZ_E2E_CHANNELS_READ_PENDING__, + }; + }), + ).toEqual({ released: 0, pending: 0 }); await page.evaluate(() => { const source = window.localStorage.getItem( "buzz-channels.v1:ws://localhost:3000", @@ -567,6 +592,15 @@ test.describe("community rail", () => { ), ) .toBe(1); + await page.evaluate(() => { + const deferNext = ( + window as Window & { + __BUZZ_E2E_DEFER_NEXT_CHANNELS_READ__?: () => void; + } + ).__BUZZ_E2E_DEFER_NEXT_CHANNELS_READ__; + if (!deferNext) throw new Error("missing channel-read defer seam"); + deferNext(); + }); const released = await page.evaluate( () => ( @@ -576,6 +610,20 @@ test.describe("community rail", () => { ).__BUZZ_E2E_RELEASE_CHANNELS_READ__?.() ?? 0, ); expect(released).toBe(1); + await page.evaluate(async () => { + const testWindow = window as Window & { + __BUZZ_E2E_INVOKE_MOCK_COMMAND__?: ( + command: string, + ) => Promise; + __BUZZ_E2E_CHANNELS_READ_PENDING__?: number; + }; + const invoke = testWindow.__BUZZ_E2E_INVOKE_MOCK_COMMAND__; + if (!invoke) throw new Error("missing mock command seam"); + await invoke("get_channels"); + if (testWindow.__BUZZ_E2E_CHANNELS_READ_PENDING__ !== 0) { + throw new Error("release left the channel-read latch armed"); + } + }); await expect .poll(() => page.evaluate(