1import { describe, expect, it } from "vite-plus/test";
2
3import {
4 deriveAvailableInstanceId,
5 getProviderIdentityDraft,
6 isConfiguredAcpRegistryAgent,
7 resolveAcpRegistryWizardNavigation,
8 resolveWizardNavigation,
9 updateProviderIdentityDraft,
10} from "./AddProviderInstanceDialog.logic";
11
12describe("resolveWizardNavigation", () => {
13 const invalidId = { instanceIdError: "Instance ID is required." };
14 const validId = { instanceIdError: null };
15
16 it("allows moving from Driver to Identity before the instance id is valid", () => {
17 expect(resolveWizardNavigation(0, 1, 3, invalidId)).toEqual({ kind: "navigate", step: 1 });
18 });
19
20 it("blocks Next from Identity to Config while the instance id is invalid", () => {
21 expect(resolveWizardNavigation(1, 2, 3, invalidId)).toEqual({
22 kind: "blocked",
23 step: 1,
24 error: "Instance ID is required.",
25 });
26 });
27
28 it("stops a direct Driver-to-Config skip at Identity and surfaces its error", () => {
29 expect(resolveWizardNavigation(0, 2, 3, invalidId)).toEqual({
30 kind: "blocked",
31 step: 1,
32 error: "Instance ID is required.",
33 });
34 });
35
36 it("allows advancing and skipping forward once the instance id is valid", () => {
37 expect(resolveWizardNavigation(1, 2, 3, validId)).toEqual({ kind: "navigate", step: 2 });
38 expect(resolveWizardNavigation(0, 2, 3, validId)).toEqual({ kind: "navigate", step: 2 });
39 });
40
41 it("always preserves backward Driver and Identity navigation", () => {
42 expect(resolveWizardNavigation(2, 1, 3, invalidId)).toEqual({ kind: "navigate", step: 1 });
43 expect(resolveWizardNavigation(2, 0, 3, invalidId)).toEqual({ kind: "navigate", step: 0 });
44 expect(resolveWizardNavigation(1, 0, 3, invalidId)).toEqual({ kind: "navigate", step: 0 });
45 });
46
47 it("clamps requested steps to the wizard bounds", () => {
48 expect(resolveWizardNavigation(2, 8, 3, validId)).toEqual({ kind: "navigate", step: 2 });
49 expect(resolveWizardNavigation(0, -1, 3, invalidId)).toEqual({ kind: "navigate", step: 0 });
50 });
51});
52
53describe("ACP Registry wizard", () => {
54 it("requires a prepared result or valid manual configuration before Identity", () => {
55 expect(
56 resolveAcpRegistryWizardNavigation(0, 1, {
57 instanceIdError: null,
58 selectionError: "Select an ACP or configure one manually.",
59 }),
60 ).toEqual({
61 kind: "blocked",
62 step: 0,
63 error: "Select an ACP or configure one manually.",
64 });
65
66 expect(
67 resolveAcpRegistryWizardNavigation(0, 1, {
68 instanceIdError: null,
69 selectionError: null,
70 }),
71 ).toEqual({ kind: "navigate", step: 1 });
72 });
73
74 it("derives a collision-free instance id without exceeding the slug limit", () => {
75 const derive = (label: string) => `acpRegistry_${label}`;
76 const existing = new Set(["acpRegistry_gemini", "acpRegistry_gemini_2"]);
77
78 expect(deriveAvailableInstanceId(derive, "gemini", existing)).toBe("acpRegistry_gemini_3");
79
80 const longBase = `acpRegistry_${"a".repeat(48)}`;
81 expect(deriveAvailableInstanceId(() => longBase, "ignored", new Set([longBase]))).toHaveLength(
82 62,
83 );
84 });
85
86 it("only marks matching ACP Registry instances as already added", () => {
87 const instances = {
88 codex: { driver: "codex", config: { agentId: "gemini" } },
89 registry: { driver: "acpRegistry", config: { agentId: "gemini" } },
90 };
91
92 expect(isConfiguredAcpRegistryAgent(instances, "gemini")).toBe(true);
93 expect(isConfiguredAcpRegistryAgent(instances, "codex")).toBe(false);
94 });
95
96 it("keeps registry-prefilled identity separate from other drivers", () => {
97 const registryDrafts = updateProviderIdentityDraft({}, "acpRegistry", {
98 label: "Gemini CLI",
99 instanceIdOverride: "acpRegistry_gemini_cli",
100 });
101
102 expect(getProviderIdentityDraft(registryDrafts, "codex")).toEqual({
103 label: "",
104 accentColor: "",
105 instanceIdOverride: null,
106 });
107
108 const drafts = updateProviderIdentityDraft(registryDrafts, "codex", {
109 label: "Work",
110 instanceIdOverride: "codex_work",
111 });
112 expect(getProviderIdentityDraft(drafts, "acpRegistry")).toMatchObject({
113 label: "Gemini CLI",
114 instanceIdOverride: "acpRegistry_gemini_cli",
115 });
116 });
117});