Open History to see the last commit
1import { describe, expect, it } from "vite-plus/test";
2import {
3 makeProviderSettingsSchema,
4 ProviderDriverKind,
5 SettingsSecretValue,
6 TrimmedString,
7} from "@t3tools/contracts";
8import * as Schema from "effect/Schema";
9
10import { providerClients } from "./providerDriverMeta";
11import {
12 deriveProviderSettingsFields,
13 nextProviderConfigWithFieldValue,
14 reconcileRowsDraft,
15 seedRowsDraft,
16} from "./ProviderSettingsForm";
17
18describe("ProviderSettingsForm helpers", () => {
19 it("keeps every masked field as a stored secret and offers a reference only where typed so", () => {
20 const settingsSchema = makeProviderSettingsSchema({
21 token: TrimmedString.pipe(
22 Schema.annotateKey({ providerSettingsForm: { control: "password" } }),
23 ),
24 apiKey: SettingsSecretValue,
25 });
26
27 expect(
28 deriveProviderSettingsFields({ settingsSchema }).map(
29 ({ key, secret, acceptsSecretReference }) => ({ key, secret, acceptsSecretReference }),
30 ),
31 ).toEqual([
32 { key: "token", secret: true, acceptsSecretReference: undefined },
33 { key: "apiKey", secret: true, acceptsSecretReference: true },
34 ]);
35 });
36
37 it("preserves unknown config keys while omitting empty configurable fields", () => {
38 const opencode = providerClients.get(ProviderDriverKind.make("opencode"));
39 expect(opencode).toBeDefined();
40
41 const serverUrl = deriveProviderSettingsFields(opencode!).find(
42 (field) => field.key === "serverUrl",
43 );
44 expect(serverUrl).toBeDefined();
45
46 const next = nextProviderConfigWithFieldValue(
47 { forkOwned: 1, serverUrl: "http://127.0.0.1:4096" },
48 serverUrl!,
49 "",
50 );
51
52 expect(next).toEqual({ forkOwned: 1 });
53 });
54
55 it("does not store a text value its field's schema rejects", () => {
56 const claude = providerClients.get(ProviderDriverKind.make("claudeAgent"));
57 expect(claude).toBeDefined();
58 const autoCompactWindow = deriveProviderSettingsFields(claude!).find(
59 (field) => field.key === "autoCompactWindow",
60 );
61 expect(autoCompactWindow).toBeDefined();
62
63 for (const invalid of ["300k", "50000"]) {
64 expect(
65 nextProviderConfigWithFieldValue({ launchArgs: "--x" }, autoCompactWindow!, invalid),
66 ).toEqual({ launchArgs: "--x" });
67 }
68 expect(
69 nextProviderConfigWithFieldValue({ launchArgs: "--x" }, autoCompactWindow!, "300000"),
70 ).toEqual({ launchArgs: "--x", autoCompactWindow: "300000" });
71 });
72
73 it("stores false boolean fields when true is the default", () => {
74 const next = nextProviderConfigWithFieldValue(
75 undefined,
76 {
77 key: "experimental",
78 control: "switch",
79 label: "Experimental",
80 clearWhenEmpty: "omit",
81 defaultBooleanValue: true,
82 },
83 false,
84 );
85
86 expect(next).toEqual({ experimental: false });
87 });
88});
89
90describe("reconcileRowsDraft", () => {
91 let nextId = 0;
92 const toRows = (values: ReadonlyArray<string>) =>
93 values.map((value) => ({ id: nextId++, value }));
94 const equal = (left: ReadonlyArray<string>, right: ReadonlyArray<string>) =>
95 left.length === right.length && left.every((value, index) => value === right[index]);
96
97 it("keeps rows when an equal value arrives with a new identity", () => {
98 const draft = seedRowsDraft(["a"], toRows);
99 expect(reconcileRowsDraft(draft, ["a"], equal, toRows)).toBe(draft);
100 });
101
102 it("keeps row ids when the published value echoes back", () => {
103 const seeded = seedRowsDraft(["a"], toRows);
104 const edited = { rows: [...seeded.rows, { id: 99, value: "" }], seen: seeded.seen };
105 const draft = { ...edited, lastPublished: ["a", ""] };
106 const next = reconcileRowsDraft(draft, ["a", ""], equal, toRows);
107 expect(next.rows).toBe(draft.rows);
108 expect(next.seen).toEqual(["a", ""]);
109 expect(next.lastPublished).toBeUndefined();
110 });
111
112 it("reseeds rows when the value changes from outside", () => {
113 const draft = { ...seedRowsDraft(["a"], toRows), lastPublished: ["b"] };
114 const next = reconcileRowsDraft(draft, ["c"], equal, toRows);
115 expect(next.rows.map((row) => row.value)).toEqual(["c"]);
116 expect(next.lastPublished).toBeUndefined();
117 });
118});