1import { ProviderDriverKind, ProviderInstanceId, type ServerProvider } from "@t3tools/contracts";
2import { describe, expect, it } from "vite-plus/test";
3
4import { getProviderSummary, getProviderVersionAdvisoryPresentation } from "./providerStatus";
5
6const provider: ServerProvider = {
7 instanceId: ProviderInstanceId.make("codex"),
8 driver: ProviderDriverKind.make("codex"),
9 enabled: true,
10 installed: true,
11 version: "1.0.0",
12 status: "ready",
13 auth: { status: "authenticated", label: "ChatGPT" },
14 checkedAt: "2026-08-23T00:00:00.000Z",
15 models: [],
16 slashCommands: [],
17 skills: [],
18};
19
20describe("getProviderSummary", () => {
21 it("reports ready providers with unknown authentication as available", () => {
22 expect(getProviderSummary({ ...provider, auth: { status: "unknown" } })).toEqual({
23 headline: "Available",
24 detail: null,
25 });
26 });
27
28 it("does not hide a provider error behind a previous authenticated state", () => {
29 expect(
30 getProviderSummary({
31 ...provider,
32 status: "error",
33 message: "The provider process failed to start.",
34 }),
35 ).toEqual({
36 headline: "Unavailable",
37 detail: "The provider process failed to start.",
38 });
39 });
40
41 it("does not hide a provider warning behind an authenticated state", () => {
42 expect(
43 getProviderSummary({
44 ...provider,
45 status: "warning",
46 message: "The provider version is unsupported.",
47 }),
48 ).toEqual({
49 headline: "Needs attention",
50 detail: "The provider version is unsupported.",
51 });
52 });
53
54 it("keeps authentication failures actionable when their provider status is error", () => {
55 expect(
56 getProviderSummary({
57 ...provider,
58 status: "error",
59 auth: { status: "unauthenticated" },
60 message: "Run codex login.",
61 }),
62 ).toEqual({
63 headline: "Not authenticated",
64 detail: "Run codex login.",
65 });
66 });
67
68 it("treats a disabled provider status as disabled even before its enabled flag updates", () => {
69 expect(getProviderSummary({ ...provider, status: "disabled" }).headline).toBe("Disabled");
70 });
71});
72
73it("does not suggest copying a command that installs an incompatible latest version", () => {
74 const advisory = {
75 status: "behind_latest" as const,
76 currentVersion: "1.0.0",
77 latestVersion: "2.0.0",
78 updateCommand: "npm install -g fixture@latest",
79 canUpdate: true,
80 checkedAt: provider.checkedAt,
81 message: null,
82 };
83 const compatibility = {
84 status: "supported" as const,
85 latestVersionStatus: "broken" as const,
86 message: null,
87 recommendedRange: null,
88 recommendedVersion: null,
89 };
90 expect(getProviderVersionAdvisoryPresentation(advisory, compatibility)).toBeNull();
91 expect(
92 getProviderVersionAdvisoryPresentation(advisory, { ...compatibility, status: "broken" }, false),
93 ).toBeNull();
94 expect(
95 getProviderVersionAdvisoryPresentation(advisory, {
96 ...compatibility,
97 latestVersionStatus: "supported",
98 }),
99 ).not.toBeNull();
100});
101
102it("shows compatibility in the version popover even when the installed version is current", () => {
103 const advisory = {
104 status: "current" as const,
105 currentVersion: "2.0.0",
106 latestVersion: "2.0.0",
107 updateCommand: "npm install -g fixture@latest",
108 canUpdate: true,
109 checkedAt: provider.checkedAt,
110 message: null,
111 };
112 const compatibility = {
113 status: "broken" as const,
114 latestVersionStatus: "broken" as const,
115 message: "This version drops turns. Use 1.9.0.",
116 recommendedRange: null,
117 recommendedVersion: "1.9.0",
118 };
119 expect(getProviderVersionAdvisoryPresentation(advisory, compatibility)).toEqual({
120 title: "Known broken version",
121 detail: compatibility.message,
122 updateCommand: null,
123 emphasis: "strong",
124 targetVersion: "1.9.0",
125 });
126 expect(
127 getProviderVersionAdvisoryPresentation(undefined, {
128 ...compatibility,
129 status: "graceful",
130 recommendedVersion: null,
131 recommendedRange: ">=2.1.0",
132 message: null,
133 }),
134 ).toEqual({
135 title: "Limited support",
136 detail: "Use >=2.1.0 for full support.",
137 updateCommand: null,
138 emphasis: "normal",
139 targetVersion: null,
140 });
141});
142
143describe("provider status copy", () => {
144 it("surfaces an ACP-advertised authentication method", () => {
145 const provider = {
146 enabled: true,
147 installed: true,
148 status: "error",
149 auth: { status: "unauthenticated", type: "agent", label: "Company login" },
150 message: "Complete this authentication method on the server.",
151 } as ServerProvider;
152
153 expect(getProviderSummary(provider)).toEqual({
154 headline: "Not authenticated · Company login",
155 detail: "Complete this authentication method on the server.",
156 });
157 });
158});