153 lines · 4.2 KB · TypeScript
RawDownload
import { afterEach, describe, expect, it } from "@effect/vitest";import { EnvironmentId, ProviderInstanceId } from "@t3tools/contracts"; import { appAtomRegistry } from "./atom-registry";import {  clearComposerDraftContentState,  composerDraftsAtom,  decodePersistedComposerDrafts,  type ComposerDraft,  getComposerDraftSnapshot,  removeComposerDraftsForEnvironment,} from "./use-composer-drafts"; const DRAFT: ComposerDraft = {  text: "hello",  attachments: [],}; afterEach(() => {  appAtomRegistry.set(composerDraftsAtom, {});}); describe("mobile composer drafts", () => {  it("hydrates selector state even when the message content is empty", () => {    expect(      decodePersistedComposerDrafts({        schemaVersion: 1,        drafts: {          "new-task:environment-1:project-1": {            text: "",            attachments: [],            modelSelection: {              instanceId: "codex",              model: "gpt-5.4",              options: [{ id: "reasoningEffort", value: "xhigh" }],            },            runtimeMode: "approval-required",            interactionMode: "plan",            workspaceSelection: {              mode: "worktree",              branch: "main",              worktreePath: null,            },          },        },      }),    ).toEqual({      "new-task:environment-1:project-1": {        text: "",        attachments: [],        modelSelection: {          instanceId: "codex",          model: "gpt-5.4",          options: [{ id: "reasoningEffort", value: "xhigh" }],        },        runtimeMode: "approval-required",        interactionMode: "plan",        workspaceSelection: {          mode: "worktree",          branch: "main",          worktreePath: null,        },      },    });  });   it("keeps legacy content-only drafts and rejects invalid selector state", () => {    expect(      decodePersistedComposerDrafts({        schemaVersion: 1,        drafts: {          "environment-1:thread-1": DRAFT,        },      }),    ).toEqual({      "environment-1:thread-1": DRAFT,    });     expect(() =>      decodePersistedComposerDrafts({        schemaVersion: 1,        drafts: {          "environment-1:thread-1": {            ...DRAFT,            runtimeMode: "sometimes-safe",          },        },      }),    ).toThrow();  });   it("clears sent content without clearing the selected model or workspace", () => {    const draftKey = "environment-1:thread-1";    const draft: ComposerDraft = {      text: "send this",      attachments: [],      modelSelection: {        instanceId: ProviderInstanceId.make("codex"),        model: "gpt-5.4",        options: [{ id: "reasoningEffort", value: "xhigh" }],      },      workspaceSelection: {        mode: "worktree",        branch: "main",        worktreePath: null,      },    };     expect(clearComposerDraftContentState({ [draftKey]: draft }, draftKey)).toEqual({      [draftKey]: {        ...draft,        text: "",        attachments: [],      },    });  });   it("reads the latest selector state synchronously for send", () => {    const draftKey = "environment-1:thread-1";    const selectedDraft: ComposerDraft = {      text: "send this",      attachments: [],      modelSelection: {        instanceId: ProviderInstanceId.make("codex"),        model: "gpt-5.4",        options: [{ id: "reasoningEffort", value: "xhigh" }],      },    };    appAtomRegistry.set(composerDraftsAtom, { [draftKey]: selectedDraft });     expect(getComposerDraftSnapshot(draftKey)).toEqual(selectedDraft);  });   it("removes only drafts owned by the selected environment", () => {    const environmentId = EnvironmentId.make("environment-cloud");    const retainedEnvironmentId = EnvironmentId.make("environment-local");     expect(      removeComposerDraftsForEnvironment(        {          [`${environmentId}:thread-cloud`]: DRAFT,          [`new-task:${environmentId}:project-cloud`]: DRAFT,          [`${retainedEnvironmentId}:thread-local`]: DRAFT,          [`new-task:${retainedEnvironmentId}:project-local`]: DRAFT,        },        environmentId,      ),    ).toEqual({      [`${retainedEnvironmentId}:thread-local`]: DRAFT,      [`new-task:${retainedEnvironmentId}:project-local`]: DRAFT,    });  });});