2026-08-27 11:57:16 -07:00
|
|
|
import { describe, it, expect } from "vitest";
|
2026-08-27 12:16:43 -07:00
|
|
|
import { describeImport, describeImportWarnings } from "./settingsImportPreview";
|
2026-08-27 11:57:16 -07:00
|
|
|
import type { SettingsImportPreview } from "./types";
|
|
|
|
|
|
|
|
|
|
function preview(overrides: Partial<SettingsImportPreview> = {}): SettingsImportPreview {
|
|
|
|
|
return {
|
|
|
|
|
exported_at: "2026-08-27T00:00:00Z",
|
|
|
|
|
app_version: "0.4.14",
|
|
|
|
|
custom_env_var_count: 0,
|
|
|
|
|
gateway_model_count: 0,
|
|
|
|
|
has_claude_code_settings: false,
|
|
|
|
|
has_claude_oauth_token: false,
|
|
|
|
|
has_gateway_api_key: false,
|
|
|
|
|
has_gateway_master_key: false,
|
2026-08-27 12:16:43 -07:00
|
|
|
has_web_terminal_access_token: false,
|
|
|
|
|
enables_web_terminal: false,
|
2026-08-27 13:13:48 -07:00
|
|
|
ollama_base_url: null,
|
|
|
|
|
llamacpp_base_url: null,
|
|
|
|
|
openai_compatible_base_url: null,
|
|
|
|
|
gateway_api_base: null,
|
2026-08-27 14:24:06 -07:00
|
|
|
image_source: "registry",
|
|
|
|
|
custom_image_name: null,
|
2026-08-27 11:57:16 -07:00
|
|
|
...overrides,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
describe("describeImport", () => {
|
|
|
|
|
it("always names the settings replacement, even with nothing else set", () => {
|
|
|
|
|
expect(describeImport(preview())).toEqual([
|
|
|
|
|
"Your global settings (all of them — this replaces what's here now)",
|
|
|
|
|
]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("singularizes a count of exactly one", () => {
|
|
|
|
|
const items = describeImport(preview({ custom_env_var_count: 1, gateway_model_count: 1 }));
|
|
|
|
|
expect(items).toContain("1 global custom env var");
|
|
|
|
|
expect(items).toContain("1 gateway model");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("pluralizes counts greater than one", () => {
|
|
|
|
|
const items = describeImport(preview({ custom_env_var_count: 3, gateway_model_count: 2 }));
|
|
|
|
|
expect(items).toContain("3 global custom env vars");
|
|
|
|
|
expect(items).toContain("2 gateway models");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("names every present secret and setting without naming absent ones", () => {
|
|
|
|
|
const items = describeImport(
|
|
|
|
|
preview({
|
|
|
|
|
has_claude_code_settings: true,
|
|
|
|
|
has_claude_oauth_token: true,
|
|
|
|
|
has_gateway_api_key: true,
|
|
|
|
|
has_gateway_master_key: true,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
expect(items).toContain("Global Claude Code settings");
|
|
|
|
|
expect(items).toContain("Your shared Claude login");
|
|
|
|
|
expect(items).toContain("The gateway provider API key");
|
|
|
|
|
expect(items).toContain("The gateway master key");
|
|
|
|
|
// None of the count-based items, since both counts are 0.
|
|
|
|
|
expect(items.some((i) => i.includes("env var"))).toBe(false);
|
|
|
|
|
expect(items.some((i) => i.includes("gateway model"))).toBe(false);
|
|
|
|
|
});
|
2026-08-27 12:16:43 -07:00
|
|
|
|
|
|
|
|
it("names the web terminal access token like any other present secret", () => {
|
|
|
|
|
const items = describeImport(preview({ has_web_terminal_access_token: true }));
|
|
|
|
|
expect(items).toContain("The web terminal access token");
|
|
|
|
|
});
|
2026-08-27 13:13:48 -07:00
|
|
|
|
|
|
|
|
it("names custom base URLs verbatim, since they're endpoints rather than secrets", () => {
|
|
|
|
|
const items = describeImport(
|
|
|
|
|
preview({
|
|
|
|
|
ollama_base_url: "http://10.0.0.5:11434",
|
|
|
|
|
gateway_api_base: "https://gateway.example/v1",
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
expect(items).toContain("Ollama server: http://10.0.0.5:11434");
|
|
|
|
|
expect(items).toContain("Gateway upstream: https://gateway.example/v1");
|
|
|
|
|
expect(items.some((i) => i.includes("llama.cpp"))).toBe(false);
|
|
|
|
|
expect(items.some((i) => i.includes("OpenAI-compatible"))).toBe(false);
|
|
|
|
|
});
|
2026-08-27 14:24:06 -07:00
|
|
|
|
|
|
|
|
it("names a custom Docker image when set, falling back to a placeholder if unnamed", () => {
|
|
|
|
|
expect(
|
|
|
|
|
describeImport(preview({ image_source: "custom", custom_image_name: "ghcr.io/me/triple-c" })),
|
|
|
|
|
).toContain("Docker image: ghcr.io/me/triple-c");
|
|
|
|
|
expect(describeImport(preview({ image_source: "custom", custom_image_name: null }))).toContain(
|
|
|
|
|
"Docker image: (no image name set)",
|
|
|
|
|
);
|
|
|
|
|
expect(describeImport(preview({ image_source: "registry" })).some((i) => i.includes("Docker image"))).toBe(
|
|
|
|
|
false,
|
|
|
|
|
);
|
|
|
|
|
});
|
2026-08-27 12:16:43 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe("describeImportWarnings", () => {
|
|
|
|
|
it("is empty when nothing about the import needs extra attention", () => {
|
|
|
|
|
expect(describeImportWarnings(preview())).toEqual([]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("warns when the import enables the web terminal, regardless of the token", () => {
|
|
|
|
|
// `enabled` and the token are independent — the warning is about the
|
|
|
|
|
// service turning on, whether or not a token came with it.
|
|
|
|
|
expect(describeImportWarnings(preview({ enables_web_terminal: true }))).toEqual([
|
|
|
|
|
"Enables the remote web terminal, which listens on your network.",
|
|
|
|
|
]);
|
|
|
|
|
expect(
|
|
|
|
|
describeImportWarnings(
|
|
|
|
|
preview({ enables_web_terminal: true, has_web_terminal_access_token: true }),
|
|
|
|
|
),
|
|
|
|
|
).toHaveLength(1);
|
|
|
|
|
});
|
|
|
|
|
|
2026-08-27 13:13:48 -07:00
|
|
|
it("warns about a dormant web terminal token even while the terminal stays off", () => {
|
|
|
|
|
expect(describeImportWarnings(preview({ has_web_terminal_access_token: true }))).toEqual([
|
|
|
|
|
"Includes a web terminal access token that will activate the next time the web terminal is turned on.",
|
|
|
|
|
]);
|
2026-08-27 12:16:43 -07:00
|
|
|
});
|
2026-08-27 14:24:06 -07:00
|
|
|
|
|
|
|
|
it("warns about a custom Docker image every time, not only when it changes", () => {
|
|
|
|
|
expect(
|
|
|
|
|
describeImportWarnings(preview({ image_source: "custom", custom_image_name: "evil:latest" })),
|
|
|
|
|
).toEqual(["Runs every project container from a custom Docker image: evil:latest."]);
|
|
|
|
|
expect(describeImportWarnings(preview({ image_source: "registry" }))).toEqual([]);
|
|
|
|
|
});
|
2026-08-27 11:57:16 -07:00
|
|
|
});
|