import { describe, expect, it } from "vitest"; import type { ProviderDisplay } from "@/types/provider"; import { analyzeBatchProviderSettings } from "@/app/[locale]/settings/providers/_components/batch-edit/analyze-batch-settings"; describe("analyzeBatchProviderSettings", () => { describe("空列表", () => { it("应该返回所有字段为 empty 状态", () => { const result = analyzeBatchProviderSettings([]); expect(result.routing.priority.status).toBe("empty"); expect(result.routing.weight.status).toBe("empty"); expect(result.rateLimit.limit5hUsd.status).toBe("empty"); }); }); describe("uniform 值", () => { it("应该识别所有供应商有相同的基本类型值", () => { const providers: ProviderDisplay[] = [ { priority: 10, weight: 5, costMultiplier: 1.5 } as ProviderDisplay, { priority: 10, weight: 5, costMultiplier: 1.5 } as ProviderDisplay, { priority: 10, weight: 5, costMultiplier: 1.5 } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.routing.priority).toEqual({ status: "uniform", value: 10 }); expect(result.routing.weight).toEqual({ status: "uniform", value: 5 }); expect(result.routing.costMultiplier).toEqual({ status: "uniform", value: 1.5 }); }); it("应该识别所有供应商有相同的对象值", () => { const providers: ProviderDisplay[] = [ { modelRedirects: { "model-a": "model-b" } } as ProviderDisplay, { modelRedirects: { "model-a": "model-b" } } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.routing.modelRedirects).toEqual({ status: "uniform", value: { "model-a": "model-b" }, }); }); it("应该识别所有供应商有相同的数组值", () => { const providers: ProviderDisplay[] = [ { allowedModels: ["model-1", "model-2"] } as ProviderDisplay, { allowedModels: ["model-1", "model-2"] } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.routing.allowedModels).toEqual({ status: "uniform", value: ["model-1", "model-2"], }); }); it("应该识别所有供应商都为 null 的字段", () => { const providers: ProviderDisplay[] = [ { limit5hUsd: null } as ProviderDisplay, { limit5hUsd: null } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.rateLimit.limit5hUsd.status).toBe("empty"); }); }); describe("mixed 值", () => { it("应该识别供应商有不同的基本类型值", () => { const providers: ProviderDisplay[] = [ { priority: 10 } as ProviderDisplay, { priority: 20 } as ProviderDisplay, { priority: 30 } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.routing.priority.status).toBe("mixed"); if (result.routing.priority.status === "mixed") { expect(result.routing.priority.values).toEqual([10, 20, 30]); } }); it("应该识别供应商有不同的对象值", () => { const providers: ProviderDisplay[] = [ { modelRedirects: { "model-a": "model-b" } } as ProviderDisplay, { modelRedirects: { "model-c": "model-d" } } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.routing.modelRedirects.status).toBe("mixed"); if (result.routing.modelRedirects.status === "mixed") { expect(result.routing.modelRedirects.values).toEqual([ { "model-a": "model-b" }, { "model-c": "model-d" }, ]); } }); it("应该去重 mixed 值", () => { const providers: ProviderDisplay[] = [ { priority: 10 } as ProviderDisplay, { priority: 20 } as ProviderDisplay, { priority: 10 } as ProviderDisplay, // 重复 { priority: 20 } as ProviderDisplay, // 重复 ]; const result = analyzeBatchProviderSettings(providers); expect(result.routing.priority.status).toBe("mixed"); if (result.routing.priority.status === "mixed") { expect(result.routing.priority.values).toEqual([10, 20]); } }); }); describe("复杂字段", () => { it("应该正确处理 groupTag 字段(字符串转数组)", () => { const providers: ProviderDisplay[] = [ { groupTag: "tag1, tag2" } as ProviderDisplay, { groupTag: "tag1, tag2" } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.routing.groupTag).toEqual({ status: "uniform", value: ["tag1", "tag2"], }); }); it("应该正确处理空 groupTag", () => { const providers: ProviderDisplay[] = [ { groupTag: null } as ProviderDisplay, { groupTag: "" } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.routing.groupTag).toEqual({ status: "uniform", value: [], }); }); it("应该正确处理 circuitBreaker 时间单位转换(ms -> minutes)", () => { const providers: ProviderDisplay[] = [ { circuitBreakerOpenDuration: 300000 } as ProviderDisplay, // 5 分钟 { circuitBreakerOpenDuration: 300000 } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.circuitBreaker.openDurationMinutes).toEqual({ status: "uniform", value: 5, }); }); it("应该正确处理 network 时间单位转换(ms -> seconds)", () => { const providers: ProviderDisplay[] = [ { firstByteTimeoutStreamingMs: 30000 } as ProviderDisplay, // 30 秒 { firstByteTimeoutStreamingMs: 30000 } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.network.firstByteTimeoutStreamingSeconds).toEqual({ status: "uniform", value: 30, }); }); it("应该正确处理 anthropicAdaptiveThinking 复杂对象", () => { const config = { effort: "high" as const, modelMatchMode: "specific" as const, models: ["claude-opus-4-6"], }; const providers: ProviderDisplay[] = [ { anthropicAdaptiveThinking: config } as ProviderDisplay, { anthropicAdaptiveThinking: config } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); expect(result.routing.anthropicAdaptiveThinking).toEqual({ status: "uniform", value: config, }); }); }); describe("默认值处理", () => { it("应该为未设置的字段使用默认值", () => { const providers: ProviderDisplay[] = [ { preserveClientIp: false, cacheTtlPreference: "inherit", dailyResetMode: "fixed", } as ProviderDisplay, { preserveClientIp: false, cacheTtlPreference: "inherit", dailyResetMode: "fixed", } as ProviderDisplay, ]; const result = analyzeBatchProviderSettings(providers); // 检查一些有默认值的字段 expect(result.routing.cacheTtlPreference).toEqual({ status: "uniform", value: "inherit", }); expect(result.routing.preserveClientIp).toEqual({ status: "uniform", value: false, }); expect(result.rateLimit.dailyResetMode).toEqual({ status: "uniform", value: "fixed", }); }); }); });