1import {
2 DEFAULT_SERVER_SETTINGS,
3 ProviderDriverKind,
4 ProviderInstanceId,
5 type ServerProvider,
6} from "@t3tools/contracts";
7import { describe, expect, it } from "vite-plus/test";
8
9import {
10 getOnboardingProviderState,
11 resolveOnboardingProviderLoginCommand,
12} from "./providerReadiness.logic";
13
14const readyCodex: ServerProvider = {
15 instanceId: ProviderInstanceId.make("codex"),
16 driver: ProviderDriverKind.make("codex"),
17 enabled: true,
18 installed: true,
19 version: "1.0.0",
20 status: "ready",
21 auth: { status: "unknown" },
22 checkedAt: "2026-08-23T00:00:00.000Z",
23 models: [],
24 slashCommands: [],
25 skills: [],
26};
27
28describe("getOnboardingProviderState", () => {
29 it("treats authenticated providers as ready only when their provider status is ready", () => {
30 expect(getOnboardingProviderState({ ...readyCodex, auth: { status: "authenticated" } })).toBe(
31 "ready",
32 );
33 expect(
34 getOnboardingProviderState({
35 ...readyCodex,
36 auth: { status: "authenticated" },
37 status: "error",
38 }),
39 ).toBe("attention");
40 expect(
41 getOnboardingProviderState({
42 ...readyCodex,
43 auth: { status: "authenticated" },
44 status: "warning",
45 }),
46 ).toBe("attention");
47 });
48
49 it("offers sign-in only when the server reports an authentication failure", () => {
50 expect(
51 getOnboardingProviderState({
52 ...readyCodex,
53 status: "error",
54 auth: { status: "unauthenticated" },
55 }),
56 ).toBe("signIn");
57 expect(getOnboardingProviderState({ ...readyCodex, status: "error" })).toBe("attention");
58 expect(getOnboardingProviderState({ ...readyCodex, status: "warning" })).toBe("attention");
59 });
60
61 it("does not offer installation or sign-in for disabled providers", () => {
62 expect(getOnboardingProviderState({ ...readyCodex, enabled: false, installed: false })).toBe(
63 "disabled",
64 );
65 expect(getOnboardingProviderState({ ...readyCodex, status: "disabled" })).toBe("disabled");
66 });
67
68 it("offers installation only when an enabled provider is missing", () => {
69 expect(getOnboardingProviderState({ ...readyCodex, installed: false, status: "error" })).toBe(
70 "install",
71 );
72 });
73});
74
75describe("resolveOnboardingProviderLoginCommand", () => {
76 it("uses the selected Codex account binary", () => {
77 const provider = { ...readyCodex, instanceId: ProviderInstanceId.make("codex_work") };
78
79 expect(
80 resolveOnboardingProviderLoginCommand(
81 provider,
82 {
83 ...DEFAULT_SERVER_SETTINGS,
84 providerInstances: {
85 [provider.instanceId]: {
86 driver: provider.driver,
87 config: { binaryPath: "/opt/codex-work/bin/codex" },
88 },
89 },
90 },
91 "linux",
92 ),
93 ).toBe("/opt/codex-work/bin/codex login");
94 });
95
96 it("quotes a Codex path with spaces for PowerShell", () => {
97 expect(
98 resolveOnboardingProviderLoginCommand(
99 readyCodex,
100 {
101 ...DEFAULT_SERVER_SETTINGS,
102 providerInstances: {
103 [ProviderInstanceId.make("codex")]: {
104 driver: ProviderDriverKind.make("codex"),
105 config: {
106 binaryPath: "C:\\Program Files\\Codex & Tools\\codex.exe",
107 },
108 },
109 },
110 },
111 "windows",
112 ),
113 ).toBe("& 'C:\\Program Files\\Codex & Tools\\codex.exe' login");
114 });
115
116 it("quotes a Claude path with shell metacharacters on POSIX", () => {
117 const provider: ServerProvider = {
118 ...readyCodex,
119 driver: ProviderDriverKind.make("claudeAgent"),
120 instanceId: ProviderInstanceId.make("claude"),
121 };
122
123 expect(
124 resolveOnboardingProviderLoginCommand(
125 provider,
126 {
127 ...DEFAULT_SERVER_SETTINGS,
128 providerInstances: {
129 [ProviderInstanceId.make("claude")]: {
130 driver: ProviderDriverKind.make("claudeAgent"),
131 config: {
132 binaryPath: "/opt/Claude Tools/$current/claude",
133 },
134 },
135 },
136 },
137 "linux",
138 ),
139 ).toBe("'/opt/Claude Tools/$current/claude' auth login");
140 });
141
142 it.each([
143 ["~/my tools/codex", "~/'my tools/codex' login"],
144 ["~\\my tools/codex", "~/'my tools/codex' login"],
145 ["~/tools/codex's build", `~/'tools/codex'"'"'s build' login`],
146 ["~\\tools\\codex's build", `~/'tools\\codex'"'"'s build' login`],
147 ["~/tools/codex; echo unsafe", "~/'tools/codex; echo unsafe' login"],
148 ])("keeps the home prefix expandable while quoting %s", (binaryPath, expectedCommand) => {
149 expect(
150 resolveOnboardingProviderLoginCommand(
151 readyCodex,
152 {
153 ...DEFAULT_SERVER_SETTINGS,
154 providerInstances: {
155 [ProviderInstanceId.make("codex")]: {
156 driver: ProviderDriverKind.make("codex"),
157 config: {
158 binaryPath,
159 },
160 },
161 },
162 },
163 "linux",
164 ),
165 ).toBe(expectedCommand);
166 });
167
168 it("uses the default command when an old server reports an unknown shell", () => {
169 expect(
170 resolveOnboardingProviderLoginCommand(
171 readyCodex,
172 {
173 ...DEFAULT_SERVER_SETTINGS,
174 providerInstances: {
175 [ProviderInstanceId.make("codex")]: {
176 driver: ProviderDriverKind.make("codex"),
177 config: {
178 binaryPath: "/opt/Codex Tools/codex",
179 },
180 },
181 },
182 },
183 "unknown",
184 ),
185 ).toBe("codex login");
186 });
187});