144 lines · 5.4 KB · TypeScript
RawDownload
import {  EnvironmentId,  ProjectId,  ThreadId,  type OrchestrationV2ShellSnapshot,} 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 { PrimaryConnectionTarget } from "../connection/model.ts";import { v2ShellSnapshot, v2ThreadShell } from "./orchestrationV2TestFixtures.ts";import { createEnvironmentThreadShellAtoms } from "./threadShell.ts"; const environmentId = EnvironmentId.make("environment-v2");const remoteEnvironmentId = EnvironmentId.make("remote-environment-v2");const otherProjectId = ProjectId.make("other-project"); function makeHarness(environmentIds: ReadonlyArray<EnvironmentId> = [environmentId]) {  const snapshotAtom = Atom.family((_environmentId: EnvironmentId) =>    Atom.make<OrchestrationV2ShellSnapshot | null>(v2ShellSnapshot),  );  const catalogValueAtom = Atom.make({    isReady: true,    entries: new Map(      environmentIds.map((id) => [        id,        {          target: new PrimaryConnectionTarget({            environmentId: id,            label: "Environment",            httpBaseUrl: "https://example.test",            wsBaseUrl: "wss://example.test",          }),          profile: Option.none(),        },      ]),    ),  });  return {    registry: AtomRegistry.make(),    snapshotAtom,    catalogValueAtom,    threads: createEnvironmentThreadShellAtoms({ catalogValueAtom, snapshotAtom }),  };} describe("v2 thread shell lists", () => {  it("shares point and list values without retaining an atom for every listed thread", () => {    const harness = makeHarness();    const snapshot = {      ...v2ShellSnapshot,      threads: Array.from({ length: 200 }, (_, index) => ({        ...v2ThreadShell,        id: ThreadId.make(`thread-${index}`),      })),    };    harness.registry.set(harness.snapshotAtom(environmentId), snapshot);    const listAtom = harness.threads.threadShellsAtom;    const projectListAtom = harness.threads.threadShellsForProjectRefsAtom([      { environmentId, projectId: v2ThreadShell.projectId },    ]);    const disposeList = harness.registry.mount(listAtom);    const disposeProjectList = harness.registry.mount(projectListAtom);    try {      const before = harness.registry.get(listAtom);      expect(before).toHaveLength(200);      expect(harness.registry.get(projectListAtom)).toEqual(before);      expect(harness.registry.getNodes().size).toBeLessThan(20);      const firstAtom = harness.threads.threadShellAtom({        environmentId,        threadId: snapshot.threads[0]!.id,      });      expect(harness.registry.get(firstAtom)).toBe(before[0]);       harness.registry.set(harness.snapshotAtom(environmentId), {        ...snapshot,        snapshotSequence: 1,        threads: snapshot.threads.map((thread, index) =>          index === 199 ? { ...thread, title: "Updated last thread" } : thread,        ),      });      const after = harness.registry.get(listAtom);      expect(after[0]).toBe(before[0]);      expect(after.at(-1)).not.toBe(before.at(-1));      expect(after.at(-1)?.title).toBe("Updated last thread");      expect(harness.registry.get(projectListAtom).at(-1)).toBe(after.at(-1));      expect(harness.registry.get(firstAtom)).toBe(after[0]);      expect(harness.registry.getNodes().size).toBeLessThan(20);    } finally {      disposeProjectList();      disposeList();      harness.registry.dispose();    }  });   it("preserves project memberships on updates and keeps the same thread separate per environment", () => {    const harness = makeHarness([environmentId, remoteEnvironmentId]);    const otherThread = {      ...v2ThreadShell,      id: ThreadId.make("other-thread"),      projectId: otherProjectId,    };    const snapshot = { ...v2ShellSnapshot, threads: [v2ThreadShell, otherThread] };    harness.registry.set(harness.snapshotAtom(environmentId), snapshot);    const membershipAtom = harness.threads.environmentThreadRefsByProjectAtom(environmentId);    const listAtom = harness.threads.threadShellsForProjectRefsAtom([      { environmentId: remoteEnvironmentId, projectId: v2ThreadShell.projectId },      { environmentId, projectId: v2ThreadShell.projectId },    ]);    const disposeList = harness.registry.mount(listAtom);    try {      const membership = harness.registry.get(membershipAtom);      const before = harness.registry.get(listAtom);      expect(before).toHaveLength(2);      expect(before[0]).not.toBe(before[1]);      expect(before.map((thread) => thread.environmentId)).toEqual([        remoteEnvironmentId,        environmentId,      ]);       harness.registry.set(harness.snapshotAtom(environmentId), {        ...snapshot,        threads: [v2ThreadShell, { ...otherThread, title: "Changed elsewhere" }],      });      expect(harness.registry.get(membershipAtom)).toBe(membership);      expect(harness.registry.get(listAtom)).toBe(before);       harness.registry.set(harness.snapshotAtom(environmentId), {        ...snapshot,        threads: [{ ...v2ThreadShell, projectId: otherProjectId }, otherThread],      });      expect(harness.registry.get(listAtom)).toEqual([before[0]]);      harness.registry.set(harness.snapshotAtom(remoteEnvironmentId), {        ...v2ShellSnapshot,        threads: [],      });      expect(harness.registry.get(listAtom)).toEqual([]);    } finally {      disposeList();      harness.registry.dispose();    }  });});