import { BearerConnectionTarget, PrimaryConnectionTarget, } from "@t3tools/client-runtime/connection"; import type { EnvironmentCatalogState } from "@t3tools/client-runtime/state/connections"; import type { EnvironmentShellState } from "@t3tools/client-runtime/state/shell"; import { EnvironmentId } from "@t3tools/contracts"; import * as Option from "effect/Option"; import { Atom, AtomRegistry } from "effect/unstable/reactivity"; import { describe, expect, it } from "vite-plus/test"; import { createAllEnvironmentProjectSnapshotsReadyAtom } from "./shell"; const LOCAL = EnvironmentId.make("local"); const REMOTE = EnvironmentId.make("remote"); function shellState(status: EnvironmentShellState["status"]): EnvironmentShellState { return { status, snapshot: status === "empty" ? Option.none() : Option.some({ snapshotSequence: 1, updatedAt: "2026-09-04T00:00:00.000Z", projects: [], threads: [], }), error: Option.none(), }; } function catalogState(environmentIds: readonly EnvironmentId[]): EnvironmentCatalogState { return { isReady: true, entries: new Map( environmentIds.map((environmentId) => [ environmentId, { target: environmentId === LOCAL ? new PrimaryConnectionTarget({ environmentId, label: environmentId, httpBaseUrl: `https://${environmentId}.example.test`, wsBaseUrl: `wss://${environmentId}.example.test`, }) : new BearerConnectionTarget({ environmentId, connectionId: environmentId, label: environmentId, }), profile: Option.none(), }, ]), ), }; } function makeHarness(requiresPrimaryEnvironment = true) { const catalog = Atom.make({ isReady: false, entries: new Map() }); const shells = Atom.family((_environmentId: EnvironmentId) => Atom.make(shellState("empty")), ); const ready = createAllEnvironmentProjectSnapshotsReadyAtom({ catalogValueAtom: catalog, shellStateValueAtom: shells, requiresPrimaryEnvironment, }); const registry = AtomRegistry.make(); return { catalog, shells, ready, registry }; } describe("project snapshot readiness", () => { it("does not clear a saved scope while the ready catalog is still empty", () => { const { catalog, ready, registry } = makeHarness(); expect(registry.get(ready)).toBe(false); registry.set(catalog, catalogState([])); expect(registry.get(ready)).toBe(false); registry.dispose(); }); it("waits for primary discovery even if a persisted remote is already live", () => { const { catalog, shells, ready, registry } = makeHarness(); registry.set(catalog, catalogState([REMOTE])); registry.set(shells(REMOTE), shellState("live")); expect(registry.get(ready)).toBe(false); registry.set(catalog, catalogState([LOCAL, REMOTE])); expect(registry.get(ready)).toBe(false); registry.set(shells(LOCAL), shellState("live")); expect(registry.get(ready)).toBe(true); registry.dispose(); }); it("allows a hosted client to load projects without a primary environment", () => { const { catalog, shells, ready, registry } = makeHarness(false); registry.set(catalog, catalogState([REMOTE])); expect(registry.get(ready)).toBe(false); registry.set(shells(REMOTE), shellState("live")); expect(registry.get(ready)).toBe(true); registry.dispose(); }); it("waits for live snapshots through offline startup and reconnect", () => { const { catalog, shells, ready, registry } = makeHarness(); registry.set(catalog, catalogState([LOCAL, REMOTE])); registry.set(shells(LOCAL), shellState("live")); expect(registry.get(ready)).toBe(false); // An old cache and a reconnect in progress can both omit a real project. registry.set(shells(REMOTE), shellState("cached")); expect(registry.get(ready)).toBe(false); registry.set(shells(REMOTE), shellState("synchronizing")); expect(registry.get(ready)).toBe(false); registry.set(shells(REMOTE), shellState("live")); expect(registry.get(ready)).toBe(true); registry.set(shells(REMOTE), shellState("cached")); expect(registry.get(ready)).toBe(false); registry.set(shells(REMOTE), shellState("live")); expect(registry.get(ready)).toBe(true); registry.dispose(); }); it("stops waiting for an environment only when it leaves the catalog", () => { const { catalog, shells, ready, registry } = makeHarness(); registry.set(catalog, catalogState([LOCAL, REMOTE])); registry.set(shells(LOCAL), shellState("live")); expect(registry.get(ready)).toBe(false); registry.set(catalog, catalogState([LOCAL])); expect(registry.get(ready)).toBe(true); registry.dispose(); }); });