import { describe, expect, it } from "vitest"; import { parseAdminBillingPayload, parseMemberBillingPayload } from "@/lib/client/billing-api"; const wallet = { organizationId: "org-1", balanceFen: 0, totalRechargedFen: 0, totalChargedFen: 0, updatedAt: "2026-08-17T00:00:00.000Z" }; const ledgerEntry = { id: "ledger-1", organizationId: "org-1", kind: "recharge", deltaFen: 100, balanceAfterFen: 100, description: "充值", metadata: {}, createdAt: "2026-08-17T00:00:00.000Z" }; function validAdminPayload() { return { billingAccount: {}, organizations: [], members: [], ledger: [], priceRules: [] }; } function validMemberPayload() { return { organization: { id: "org-1", name: "测试组织" }, billingAccount: {}, wallet, ledger: [], summary: { rechargeFen: 0, chargedFen: 0, refundedFen: 0, netConsumedFen: 0 }, personal: { rechargeFen: 0, chargedFen: 0, refundedFen: 0, netConsumedFen: 0 } }; } describe("billing API payload contract", () => { it("accepts valid empty collection payloads", () => { const admin = validAdminPayload(); const member = validMemberPayload(); expect(parseAdminBillingPayload(admin)).toBe(admin); expect(parseMemberBillingPayload(member)).toBe(member); }); it.each(["organizations", "members", "ledger", "priceRules"])( "rejects a missing admin %s collection", (field) => { const payload: Record = validAdminPayload(); delete payload[field]; expect(() => parseAdminBillingPayload(payload)) .toThrow(`超管计费数据格式错误:${field} 必须是数组。`); } ); it("rejects a malformed admin price-rule element", () => { expect(() => parseAdminBillingPayload({ ...validAdminPayload(), priceRules: [null] })) .toThrow("超管计费数据格式错误:priceRules[0] 必须是对象。"); }); it("rejects malformed admin organization elements and wallets", () => { expect(() => parseAdminBillingPayload({ ...validAdminPayload(), organizations: [null] })) .toThrow("超管计费数据格式错误:organizations[0] 必须是对象。"); expect(() => parseAdminBillingPayload({ ...validAdminPayload(), organizations: [{ id: "org-1", name: "测试组织", status: "active", wallet: { ...wallet, balanceFen: "0" } }] })).toThrow("超管计费数据格式错误:organizations[0].wallet.balanceFen 必须是有限数字。"); }); it("rejects a malformed admin member element", () => { expect(() => parseAdminBillingPayload({ ...validAdminPayload(), members: [null] })) .toThrow("超管计费数据格式错误:members[0] 必须是对象。"); }); it("accepts a fresh super administrator without organizationId", () => { const payload = { ...validAdminPayload(), members: [{ id: "root", displayName: "管理员", phone: "13800000000", role: "super_admin", status: "active" }] }; expect(parseAdminBillingPayload(payload)).toBe(payload); }); it("rejects a malformed admin ledger element", () => { expect(() => parseAdminBillingPayload({ ...validAdminPayload(), ledger: [null] })) .toThrow("超管计费数据格式错误:ledger[0] 必须是对象。"); }); it("rejects malformed member objects used by the renderer", () => { expect(() => parseMemberBillingPayload({ ...validMemberPayload(), organization: null })) .toThrow("成员计费数据格式错误:organization 必须是对象。"); expect(() => parseMemberBillingPayload({ ...validMemberPayload(), wallet: null })) .toThrow("成员计费数据格式错误:wallet 必须是对象。"); expect(() => parseMemberBillingPayload({ ...validMemberPayload(), summary: null })) .toThrow("成员计费数据格式错误:summary 必须是对象。"); expect(() => parseMemberBillingPayload({ ...validMemberPayload(), personal: null })) .toThrow("成员计费数据格式错误:personal 必须是对象。"); }); it("rejects a malformed member ledger element", () => { expect(() => parseMemberBillingPayload({ ...validMemberPayload(), ledger: [null] })) .toThrow("成员计费数据格式错误:ledger[0] 必须是对象。"); }); it("accepts fully populated collection elements", () => { const admin = { ...validAdminPayload(), organizations: [{ id: "org-1", name: "测试组织", status: "active", wallet }], members: [{ id: "member-1", displayName: "成员", phone: "13800000000", role: "user", organizationId: "org-1", status: "active" }], ledger: [ledgerEntry], priceRules: [{ id: "rule-1", provider: "evolink", capability: "image.generate", unit: "image", standardUnitPriceFen: 100, markupMultiplier: 1.2, enabled: true, parameterDimensions: [{ key: "quality", label: "质量", baselineValue: "standard", tiers: [{ value: "standard", label: "标准", standardFactor: 1, markupMultiplier: 1.2, enabled: true }] }] }] }; const member = { ...validMemberPayload(), ledger: [ledgerEntry] }; expect(parseAdminBillingPayload(admin)).toBe(admin); expect(parseMemberBillingPayload(member)).toBe(member); }); it("rejects non-object responses", () => { expect(() => parseAdminBillingPayload("unexpected")) .toThrow("超管计费数据格式错误:响应必须是对象。"); expect(() => parseMemberBillingPayload(null)) .toThrow("成员计费数据格式错误:响应必须是对象。"); }); });