import { describe, expect, it, vi } from "vitest"; import { createRuntimeAdapters, createRuntimeHttpClient, } from "../../src/bootstrap/runtime-adapters.ts"; import { createBrowserMutationIntentFactory } from "../../src/adapters/platform/browser-mutation-intent-factory.ts"; import { TEST_HTTP_CONTRACT } from "../helpers/http-contract-fixture.ts"; type Runtime = Parameters[0]["runtime"]; type Release = Parameters[0]["release"]; const runtime: Runtime = { config: { APP_ENV: "local", API_BASE_URL: "http://localhost:8080", TELEMETRY_ENABLED: false, AUTH_MODE: "demo", REQUEST_TIMEOUT_MS: 4321, MAX_RETRY_ATTEMPTS: 0, RELEASE_MANIFEST_URL: "/release-manifest.json", CONFIG_SCHEMA_VERSION: "2.0", CAPABILITY_OVERRIDES: { REALTIME: "DEFAULT", WEB_WORKER: "DEFAULT", SERVICE_WORKER: "DEFAULT", OFFLINE_COMMANDS: "DEFAULT", }, }, configSchema: "V2", build: { buildId: "build-a", commitSha: "abc123", routerBasePath: "/", runtimeConfigUrl: "/config.json", }, validationDurationMs: 0, }; const release: Release = { schemaVersion: 2, appVersion: "0.1.0", buildId: "build-a", commitSha: "abc123", configSchemaVersion: "2.0", contractSet: { setAlgorithm: "CA_CONTRACT_SET_V1", setDigest: `sha256:${"0".repeat(64)}`, packages: [], }, assetManifestHash: "hash-a", releaseId: "release-a", builtAt: "2026-07-25T00:00:00Z", routeChunks: { "route-home": "assets/home.js" }, }; describe("runtime adapter composition", () => { it("creates validated intent and idempotency identities with independent UUID calls", () => { const randomUUID = vi .fn<() => string>() .mockReturnValueOnce("intent-uuid") .mockReturnValueOnce("idempotency-uuid"); const factory = createBrowserMutationIntentFactory({ randomUUID, monotonicNow: () => 12.5, }); const intent = factory.create({ operationId: "CREATE_ENTITY", canonicalInputIdentity: "opaque-canonical-input", requiresIdempotencyKey: true, }); expect(intent).toEqual({ intentId: "intent-uuid", operationId: "CREATE_ENTITY", canonicalInputIdentity: "opaque-canonical-input", idempotencyKey: "idempotency-uuid", createdAtMonotonicMs: 12.5, }); expect(Object.isFrozen(intent)).toBe(true); expect(randomUUID).toHaveBeenCalledTimes(2); }); it("rejects invalid or unbounded mutation intent values", () => { const factory = createBrowserMutationIntentFactory({ randomUUID: () => "opaque-runtime-identifier", monotonicNow: () => 1, }); expect(() => factory.create({ operationId: " ", canonicalInputIdentity: "valid-identity", requiresIdempotencyKey: false, }), ).toThrow(TypeError); expect(() => factory.create({ operationId: "CREATE_ENTITY", canonicalInputIdentity: "x".repeat(16_385), requiresIdempotencyKey: false, }), ).toThrow(TypeError); expect(() => createBrowserMutationIntentFactory({ randomUUID: () => "opaque-runtime-identifier", monotonicNow: () => -1, }).create({ operationId: "CREATE_ENTITY", canonicalInputIdentity: "valid-identity", requiresIdempotencyKey: false, }), ).toThrow(TypeError); }); it("constructs the local demo seam and infrastructure adapters", async () => { const adapters = await createRuntimeAdapters({ runtime, release, host: {}, }); expect(adapters.outputPorts.session.getState()).toBe("unauthenticated"); await expect(adapters.outputPorts.releaseInfo.getCurrent()).resolves.toMatchObject({ releaseId: "release-a", }); expect(adapters.infrastructure.queryClient).toBeDefined(); expect(adapters.infrastructure.queryInvalidation).toBeDefined(); expect(adapters.infrastructure.mutationIntentFactory).toBeDefined(); expect( adapters.infrastructure.crossContextInvalidationStatus(), ).toBe("DEGRADED_LOCAL_ONLY"); expect(adapters.outputPorts.diagnostics.record).toEqual(expect.any(Function)); expect(adapters.outputPorts.telemetry.emit).toEqual(expect.any(Function)); expect(adapters.outputPorts.telemetry.pendingCount()).toBe(0); expect(adapters).not.toHaveProperty("http"); expect(adapters).not.toHaveProperty("storage"); adapters.infrastructure.dispose(); }); it("runtime infrastructure disposal disposes telemetry first", async () => { const fetcher = vi.fn(async () => new Response(null, { status: 204 })); const adapters = await createRuntimeAdapters({ runtime: { ...runtime, config: { ...runtime.config, TELEMETRY_ENABLED: true, TELEMETRY_ENDPOINT: "https://telemetry.test/events", }, } as Runtime, release, host: {}, fetcher: fetcher as unknown as typeof fetch, }); adapters.outputPorts.telemetry.emit("api.request.failed", { error_kind: "SERVER_FAILURE", http_status_group: "5xx", attempt_count_bucket: "1", route_id: "TEST_ROUTE", }); expect(adapters.outputPorts.telemetry.pendingCount()).toBe(1); adapters.infrastructure.dispose(); expect(adapters.outputPorts.telemetry.pendingCount()).toBe(0); await Promise.resolve(); await Promise.resolve(); expect(fetcher).not.toHaveBeenCalled(); }); it("replaces the QueryClient and coordinator for each session generation", async () => { const adapters = await createRuntimeAdapters({ runtime, release, host: {} }); const previousClient = adapters.infrastructure.queryClient; const previousCoordinator = adapters.infrastructure.queryInvalidation; const runtimeMutationIntentFactory = adapters.infrastructure.mutationIntentFactory; const clearPrevious = vi.spyOn(previousClient, "clear"); await adapters.outputPorts.session.beginSignIn(); await vi.waitFor(() => expect(adapters.infrastructure.queryClient).not.toBe(previousClient), ); expect(adapters.infrastructure.queryInvalidation).not.toBe( previousCoordinator, ); expect(adapters.infrastructure.mutationIntentFactory).toBe( runtimeMutationIntentFactory, ); const clearCallsAfterReplacement = clearPrevious.mock.calls.length; await previousCoordinator.resetLocal(); expect(clearPrevious).toHaveBeenCalledTimes(clearCallsAfterReplacement); adapters.infrastructure.dispose(); }); it("does not fail boot when Web Storage capability getters throw", async () => { const host: Record = {}; Object.defineProperties(host, { localStorage: { get() { throw new DOMException("denied", "SecurityError"); }, }, sessionStorage: { get() { throw new DOMException("denied", "SecurityError"); }, }, }); const adapters = await createRuntimeAdapters({ runtime, release, host, }); expect(adapters.infrastructure.queryClient).toBeDefined(); expect(adapters.outputPorts.preferences.read("COLOR_SCHEME")).toEqual({ ok: true, value: undefined, }); adapters.infrastructure.dispose(); }); it("fails closed when an external auth owner was not installed", async () => { const adapters = await createRuntimeAdapters({ runtime: { ...runtime, config: { ...runtime.config, AUTH_MODE: "external" }, }, release, host: {}, }); expect(adapters.outputPorts.session.getState()).toBe("integration-failed"); }); it("reports the static selection when no capability override disables it", async () => { const adapters = await createRuntimeAdapters({ runtime, release, host: {} }); const snapshot = adapters.outputPorts.runtimeCapabilities.getSnapshot(); expect(snapshot.map((status) => status.capabilityId)).toEqual([ "REALTIME", "WEB_WORKER", "SERVICE_WORKER", "OFFLINE_COMMANDS", ]); expect(snapshot.every((status) => status.override === "DEFAULT")).toBe(true); }); it("carries a disabling override into the capability snapshot", async () => { const adapters = await createRuntimeAdapters({ runtime: { ...runtime, config: { ...runtime.config, CAPABILITY_OVERRIDES: { ...runtime.config.CAPABILITY_OVERRIDES, SERVICE_WORKER: "DISABLED", }, }, }, release, host: {}, }); const serviceWorker = adapters.outputPorts.runtimeCapabilities .getSnapshot() .find((status) => status.capabilityId === "SERVICE_WORKER"); expect(serviceWorker?.override).toBe("DISABLED"); expect(serviceWorker?.active).toBe(0); }); it("states contract identity as a digest for a V2 release manifest", async () => { const adapters = await createRuntimeAdapters({ runtime, release, host: {} }); const current = await adapters.outputPorts.releaseInfo.getCurrent(); expect(current.contractSetDigest).toBe(release.contractSet?.setDigest); expect(current.apiContractVersion).toBeUndefined(); expect(current).not.toHaveProperty("contractSet"); }); it("states contract identity as the legacy scalar for a V1 release manifest", async () => { const adapters = await createRuntimeAdapters({ runtime, release: { ...release, schemaVersion: 1, contractSet: null, legacyApiContractVersion: "1.4", }, host: {}, }); const current = await adapters.outputPorts.releaseInfo.getCurrent(); expect(current.apiContractVersion).toBe("1.4"); expect(current.contractSetDigest).toBeUndefined(); expect(current).not.toHaveProperty("legacyApiContractVersion"); }); it("refetches the active release manifest with no-store semantics", async () => { const activeRelease = { ...release, buildId: "build-b", releaseId: "release-b", routeChunks: { "route-home": "assets/home-b.js" }, }; const fetcher = vi.fn(async () => new Response(JSON.stringify(activeRelease), { headers: { "content-type": "application/json" }, }), ); const adapters = await createRuntimeAdapters({ runtime, release, fetcher, host: {}, }); await expect(adapters.outputPorts.releaseInfo.refresh()).resolves.toMatchObject({ buildId: "build-b", releaseId: "release-b", }); expect(fetcher).toHaveBeenCalledWith( "/release-manifest.json", expect.objectContaining({ method: "GET", cache: "no-store", credentials: "same-origin", redirect: "error", referrerPolicy: "no-referrer", headers: { Accept: "application/json" }, }), ); }); it("injects runtime timeout and max-attempt policy into HTTP execution", async () => { const scheduled: Array<{ callback: () => void; milliseconds: number }> = []; const scheduler = { setTimeout: vi.fn((callback: () => void, milliseconds: number) => { scheduled.push({ callback, milliseconds }); return scheduled.length; }), clearTimeout: vi.fn(), }; const fetcher = vi.fn(async () => Response.json( { success: false, error: { code: "TEMPORARY" }, meta: { requestId: "request-1", traceId: "trace-1" }, }, { status: 503 }, ), ); const authSession = (await createRuntimeAdapters({ runtime, release, host: {}, })).outputPorts.session; const client = createRuntimeHttpClient( { runtime, authSession, fetcher, clock: { now: () => 0, sleep: async () => {} }, scheduler, }, TEST_HTTP_CONTRACT, ); await client.execute({ operationId: "LIST_ENTITIES", routeId: "TEST_ROUTE", }); expect(fetcher).toHaveBeenCalledOnce(); expect(scheduler.setTimeout).toHaveBeenCalledWith( expect.any(Function), 4321, ); expect(scheduler.clearTimeout).toHaveBeenCalledOnce(); }); });