import { describe, it } from "@std/testing/bdd"; import { expect } from "@std/expect"; import type { DID } from "@commonfabric/identity"; import { EventEmitter } from "../../runtime-client/client/emitter.ts"; const env = globalThis as typeof globalThis & { $API_URL?: string; $ENVIRONMENT?: string; }; env.$API_URL ??= "http://shell.test/"; env.$ENVIRONMENT ??= "development"; type MockRuntimeClientEvents = { console: [unknown]; navigaterequest: [{ cell: { id(): string; space(): DID } }]; error: [unknown]; telemetry: [unknown]; }; class MockRuntimeClient extends EventEmitter { idleCalls = 0; syncedCalls = 0; slugByPageId = new Map(); idle(): Promise { this.idleCalls += 1; return Promise.resolve(); } synced(): Promise { this.syncedCalls += 1; return Promise.resolve(); } getPageSlug(pageId: string): Promise { return Promise.resolve(this.slugByPageId.get(pageId)); } dispose(): Promise { return Promise.resolve(); } } type Deferred = { promise: Promise; resolve: (value: T | PromiseLike) => void; reject: (reason?: unknown) => void; }; function deferred(): Deferred { let resolve!: (value: T | PromiseLike) => void; let reject!: (reason?: unknown) => void; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); return { promise, resolve, reject }; } type NavigationDetail = { spaceDid: DID; pieceId: string; }; describe("RuntimeInternals navigation", () => { it("exposes page slug metadata", async () => { const { RuntimeInternals } = await import("../src/lib/runtime.ts"); const spaceDid = "did:key:z6Mk-shell-runtime-did-nav" as DID; const client = new MockRuntimeClient(); client.slugByPageId.set("piece-789", "demo"); const runtime = new (RuntimeInternals as any)(client); try { await expect(runtime.getSlug(spaceDid, "piece-789")).resolves.toBe( "demo", ); } finally { await runtime.dispose(); } }); it("does not block same-space navigation on piece registration", async () => { const env = globalThis as typeof globalThis & { $API_URL?: string; $ENVIRONMENT?: string; $COMMIT_SHA?: string; $MEMORY_VERSION?: string; $EXPERIMENTAL_MODERN_CELL_REP?: string; }; const originalEnv = { $API_URL: env.$API_URL, $ENVIRONMENT: env.$ENVIRONMENT, $COMMIT_SHA: env.$COMMIT_SHA, $MEMORY_VERSION: env.$MEMORY_VERSION, $EXPERIMENTAL_MODERN_CELL_REP: env.$EXPERIMENTAL_MODERN_CELL_REP, }; env.$API_URL = "http://shell.test/"; env.$ENVIRONMENT = "development"; env.$COMMIT_SHA = undefined; env.$MEMORY_VERSION = undefined; env.$EXPERIMENTAL_MODERN_CELL_REP = undefined; const { RuntimeInternals } = await import("../src/lib/runtime.ts"); const spaceDid = "did:key:z6Mk-shell-runtime-did-nav" as DID; const client = new MockRuntimeClient(); const runtime = new (RuntimeInternals as any)(client); let registrations = 0; const registrationStarted = deferred(); const registrationReleased = deferred(); runtime.registerNavigatedPiece = async () => { registrations += 1; registrationStarted.resolve(); await registrationReleased.promise; }; let navigation: NavigationDetail | undefined; const navigationReceived = deferred(); const onNavigate = (event: Event) => { navigation = (event as CustomEvent).detail; navigationReceived.resolve(navigation!); }; globalThis.addEventListener("cf-navigate", onNavigate); try { client.emit("navigaterequest", { cell: { id: () => "piece-123", space: () => spaceDid, }, }); await registrationStarted.promise; expect(registrations).toBe(1); await navigationReceived.promise; expect(client.idleCalls).toBe(1); expect(client.syncedCalls).toBe(1); expect(navigation).toEqual({ spaceDid, pieceId: "piece-123", }); registrationReleased.resolve(); } finally { globalThis.removeEventListener("cf-navigate", onNavigate); env.$API_URL = originalEnv.$API_URL; env.$ENVIRONMENT = originalEnv.$ENVIRONMENT; env.$COMMIT_SHA = originalEnv.$COMMIT_SHA; env.$MEMORY_VERSION = originalEnv.$MEMORY_VERSION; env.$EXPERIMENTAL_MODERN_CELL_REP = originalEnv.$EXPERIMENTAL_MODERN_CELL_REP; await runtime.dispose(); } }); it("waits for the current runtime to settle before cross-space navigation", async () => { const env = globalThis as typeof globalThis & { $API_URL?: string; $ENVIRONMENT?: string; $COMMIT_SHA?: string; $MEMORY_VERSION?: string; $EXPERIMENTAL_MODERN_CELL_REP?: string; }; const originalEnv = { $API_URL: env.$API_URL, $ENVIRONMENT: env.$ENVIRONMENT, $COMMIT_SHA: env.$COMMIT_SHA, $MEMORY_VERSION: env.$MEMORY_VERSION, $EXPERIMENTAL_MODERN_CELL_REP: env.$EXPERIMENTAL_MODERN_CELL_REP, }; env.$API_URL = "http://shell.test/"; env.$ENVIRONMENT = "development"; env.$COMMIT_SHA = undefined; env.$MEMORY_VERSION = undefined; env.$EXPERIMENTAL_MODERN_CELL_REP = undefined; const { RuntimeInternals } = await import("../src/lib/runtime.ts"); const nextSpace = "did:key:z6Mk-shell-runtime-did-nav-next" as DID; const client = new MockRuntimeClient(); const runtime = new (RuntimeInternals as any)(client); let navigation: NavigationDetail | undefined; const navigationReceived = deferred(); const onNavigate = (event: Event) => { navigation = (event as CustomEvent).detail; navigationReceived.resolve(navigation!); }; globalThis.addEventListener("cf-navigate", onNavigate); try { client.emit("navigaterequest", { cell: { id: () => "piece-456", space: () => nextSpace, }, }); await navigationReceived.promise; expect(client.idleCalls).toBe(1); expect(client.syncedCalls).toBe(1); expect(navigation).toEqual({ spaceDid: nextSpace, pieceId: "piece-456", }); } finally { globalThis.removeEventListener("cf-navigate", onNavigate); env.$API_URL = originalEnv.$API_URL; env.$ENVIRONMENT = originalEnv.$ENVIRONMENT; env.$COMMIT_SHA = originalEnv.$COMMIT_SHA; env.$MEMORY_VERSION = originalEnv.$MEMORY_VERSION; env.$EXPERIMENTAL_MODERN_CELL_REP = originalEnv.$EXPERIMENTAL_MODERN_CELL_REP; await runtime.dispose(); } }); it("creates worker runtime options with explicit CFC enforcement and principal trust", async () => { const { createRuntimeClientOptions } = await import( "../src/lib/runtime.ts" ); const { createSession, Identity } = await import( "@commonfabric/identity" ); const identity = await Identity.generate({ implementation: "noble" }); const session = await createSession({ identity, spaceName: "shell-cfc-runtime-options", }); const options = createRuntimeClientOptions({ session, apiUrl: new URL("http://shell.test/"), }); expect(options.cfcEnforcementMode).toBe("enforce-explicit"); expect(options.trustSnapshot).toEqual({ id: `principal:${session.as.did()}`, actingPrincipal: session.as.did(), }); expect(options.spaceDid).toBe(session.space); expect(options.spaceName).toBe(session.spaceName); }); });