返回 DeepSeek-Reasonix
settings-provider-normalization.test.ts
根目录 / desktop / frontend / src / __tests__ / settings-provider-normalization.test.ts
1 import {
2 formatProviderExtraBody,
3 normalizeProviderView,
4 parseProviderExtraBody,
5 providerEditorEffectiveKind,
6 providerExtraBodyParseError,
7 } from "../components/SettingsPanel";
8 import type { ProviderView } from "../lib/types";
9
10 let passed = 0;
11 let failed = 0;
12 function ok(value: boolean, label: string) {
13 process.stdout.write(` ${value ? "PASS" : "FAIL"} ${label}\n`);
14 if (value) passed += 1; else failed += 1;
15 }
16 function eq(actual: unknown, expected: unknown, label: string) {
17 ok(actual === expected, actual === expected ? label : `${label}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
18 }
19
20 console.log("\nsettings provider normalization");
21 const nullable = normalizeProviderView({ name: null, baseUrl: null } as unknown as ProviderView);
22 eq(nullable.name, "", "provider snapshots normalize a null name at the settings boundary");
23 eq(nullable.baseUrl, "", "provider snapshots normalize a null base URL at the settings boundary");
24 eq(normalizeProviderView({ name: "glm", baseUrl: "https://gateway.example/v1", reasoningProtocol: "glm" } as ProviderView).reasoningProtocol, "glm", "provider snapshots preserve the GLM protocol");
25 eq(normalizeProviderView({ name: "anthropic", kind: "anthropic", baseUrl: "https://gateway.example", serverWebSearchCapability: true } as ProviderView).serverWebSearchCapability, true, "provider snapshots preserve server web-search capability");
26 eq(normalizeProviderView({ name: "legacy", kind: "anthropic", baseUrl: "https://gateway.example" } as ProviderView).serverWebSearchCapability, undefined, "older snapshots keep an absent capability distinguishable");
27 eq(providerEditorEffectiveKind(true, "anthropic", ["anthropic", "openai"]), "anthropic", "new custom providers keep the selected kind");
28 eq(providerEditorEffectiveKind(false, "anthropic", ["anthropic", "openai"]), "anthropic", "existing providers preserve their stored kind");
29 eq(formatProviderExtraBody({ top_p: 0.7, enable_thinking: true }), "{\n \"enable_thinking\": true,\n \"top_p\": 0.7\n}", "extra body editor formats stable JSON");
30 eq(JSON.stringify(parseProviderExtraBody('{ "enable_thinking": true, "top_p": 0.7 }')), '{"enable_thinking":true,"top_p":0.7}', "extra body editor parses an object");
31 let rejected = false;
32 try { parseProviderExtraBody("[true]"); } catch { rejected = true; }
33 ok(rejected, "extra body editor rejects non-object JSON");
34 const t = ((key: string, vars?: Record<string, string | number>) => key === "settings.providerExtraBodyNull" ? `${vars?.path} localized null` : key === "settings.providerExtraBodyError" ? "localized fallback" : key) as any;
35 eq(providerExtraBodyParseError(new SyntaxError("bad JSON"), t), "localized fallback", "extra body editor localizes syntax errors");
36 try {
37 parseProviderExtraBody('{ "nested": { "value": null } }', t);
38 ok(false, "extra body editor rejects null values");
39 } catch (error) {
40 eq(providerExtraBodyParseError(error, t), "extra_body.nested.value localized null", "extra body editor retains the structured validation path");
41 }
42
43 console.log(`\n${passed} passed, ${failed} failed`);
44 if (failed) process.exit(1);
45
45 lines TYPESCRIPT