From 8e2839d35b9634f8b02112d0c84309667d0cfe26 Mon Sep 17 00:00:00 2001 From: ehsan shariati Date: Fri, 4 Sep 2026 18:00:33 -0400 Subject: [PATCH] test: stop booting a real libp2p node inside jsdom from the two screen tests that still did CI on main has gone red twice today with every test passing: Vitest caught 2 unhandled errors during the test run. TypeError: Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'. Queue.emitEmpty it-queue/src/index.ts Timeout.later it-queue/src/utils.ts This error originated in "src/screens/InitialSetup/__tests__/ConnectToBlox.test.tsx" ... caught after test environment was torn down. The last ConnectToBlox test navigates on to Set authorizer, which calls `Helper.initFula` on mount to mint the app peer id. That file mocked LAN, BLE and discovery but not `@/utils/helper`, so the call was real: it created an actual libp2p node inside jsdom. The test finished on its assertion, the tree was unmounted, and libp2p's `it-queue` kept ticking -- one of its timers then dispatched a Node-realm Event into a torn-down jsdom EventTarget. Vitest counts that as a failure regardless of the test tally. Timing-dependent, so it hit roughly one full-suite run in three, on CI and on main. guards.test.tsx had the same hole from the other side: landing on /blox mounts the main shell, whose `useEnsureFulaClient` calls `initFula` for the current Blox. Seconds of libp2p boot that routing tests never look at -- and the reason "set up -> / lands on /blox" was the one test that failed under full-suite load while passing alone. Every sibling setup test (SetBloxAuthorizer, SetupComplete, ConnectToExistingBlox, LinkPassword, setupFlow) already stubs `initFula`. These two now do too, the same way. Test-only; no runtime change. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_013BpqXrkEPA9odTyRdK5Mnx --- apps/fxblox-web/src/app/__tests__/guards.test.tsx | 9 +++++++++ .../InitialSetup/__tests__/ConnectToBlox.test.tsx | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/apps/fxblox-web/src/app/__tests__/guards.test.tsx b/apps/fxblox-web/src/app/__tests__/guards.test.tsx index d3f5c78..36d2c8a 100644 --- a/apps/fxblox-web/src/app/__tests__/guards.test.tsx +++ b/apps/fxblox-web/src/app/__tests__/guards.test.tsx @@ -20,6 +20,15 @@ vi.mock('@/app/bootstrap', () => ({ return boot.current!.promise; }, })); +// Landing on /blox mounts the main shell, whose `useEnsureFulaClient` calls `initFula` for the current Blox. +// Left real, that boots an actual libp2p node inside jsdom — seconds of work that these routing tests never +// look at, and whose timers outlive the test (see ConnectToBlox.test.tsx for the unhandled-error shape). It +// is also why "set up → / lands on /blox" was the one test in the suite that failed under full-suite load +// while passing alone: the route waited on a libp2p boot that nothing here needed. +vi.mock('@/utils/helper', async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, initFula: vi.fn(async () => '12D3KooWAppPeer'.padEnd(52, 'A')) }; +}); import { TestProviders } from '@/test/helpers/renderWithProviders'; import { buildAppRoutes } from '@/app/routes/appRoutes'; diff --git a/apps/fxblox-web/src/screens/InitialSetup/__tests__/ConnectToBlox.test.tsx b/apps/fxblox-web/src/screens/InitialSetup/__tests__/ConnectToBlox.test.tsx index 72d9347..3e02df7 100644 --- a/apps/fxblox-web/src/screens/InitialSetup/__tests__/ConnectToBlox.test.tsx +++ b/apps/fxblox-web/src/screens/InitialSetup/__tests__/ConnectToBlox.test.tsx @@ -22,6 +22,15 @@ vi.mock('@/platform/bluetooth', async (importOriginal) => { vi.mock('@/services/setupDiscovery', () => ({ discoverUnownedBloxes: vi.fn(), })); +// The last test here navigates on to Set authorizer, which calls `initFula` on mount to mint the app peer id. +// Left real, that boots an actual libp2p node inside jsdom, and its `it-queue` timers outlive the test: one of +// them then dispatches an Event from Node's realm into a torn-down jsdom EventTarget, which Vitest reports as +// an unhandled error and fails the run — roughly one full-suite run in three, on CI and on `main`. Every +// sibling setup test already stubs this; this file was the one that did not. +vi.mock('@/utils/helper', async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, initFula: vi.fn(async () => '12D3KooWAppPeer'.padEnd(52, 'A')) }; +}); import { API_URL } from '@/api'; import { BleRegistry } from '@/platform/bluetooth';