import { describe, expect, it } from "vitest"; import { calculateTeamMetrics } from "@/lib/guides/calculations"; import { artifactSectionSchema, createGuideSchema, teamSectionSchema, weaponSectionSchema } from "@/lib/guides/schemas"; describe("structured guide validation", () => { const artifactGroups = [ { name: "Late Game", rows: [] }, { name: "Early Game", rows: [] }, ] as const; it("allows creating a guide without an overview", () => { expect(createGuideSchema.safeParse({ characterKey: "1", coverMediaId: "550e8400-e29b-41d4-a716-446655440000", overview: "" }).success).toBe(true); }); it("requires at least one weapon percentage", () => { expect(weaponSectionSchema.safeParse({ expectedVersion: 1, rows: [{ weaponKey: "1", refinement: 5, overallPercent: null, personalPercent: null }] }).success).toBe(false); expect(weaponSectionSchema.safeParse({ expectedVersion: 1, rows: [{ weaponKey: "1", refinement: 5, overallPercent: 104, personalPercent: null }] }).success).toBe(true); }); it("limits artifact main stats to two per slot", () => { const result = artifactSectionSchema.safeParse({ expectedVersion: 1, groups: artifactGroups, sands: ["EM", "ER", "ATK%"], goblet: [], circlet: [], substats: [], targets: [], talents: [], note: null }); expect(result.success).toBe(false); }); it("requires the fixed Late Game and Early Game artifact groups", () => { const base = { expectedVersion: 1, sands: [], goblet: [], circlet: [], substats: [], targets: [], talents: [], note: null }; expect(artifactSectionSchema.safeParse({ ...base, groups: artifactGroups }).success).toBe(true); expect(artifactSectionSchema.safeParse({ ...base, groups: [...artifactGroups].reverse() }).success).toBe(false); expect(artifactSectionSchema.safeParse({ ...base, groups: [...artifactGroups, { name: "Other", rows: [] }] }).success).toBe(false); }); it("requires four unique team members and non-zero damage", () => { const member = (characterKey: string) => ({ characterKey, weaponKey: null, artifactKey: null, constellation: 0, refinement: 1, damage: 100 }); const base = { expectedVersion: 1, teams: [{ title: "Test", rotationSeconds: 20, combo: "E > Q", members: ["1", "2", "3", "4"].map(member) }] }; expect(teamSectionSchema.safeParse(base).success).toBe(true); expect(teamSectionSchema.safeParse({ ...base, teams: [{ ...base.teams[0], members: ["1", "1", "3", "4"].map(member) }] }).success).toBe(false); }); }); describe("Team Calc", () => { it("calculates exact shares and total DPS", () => { expect(calculateTeamMetrics([50, 25, 15, 10], 20)).toEqual({ totalDamage: 100, totalDps: 5, shares: [50, 25, 15, 10] }); }); it("rejects an empty damage rotation", () => { expect(() => calculateTeamMetrics([0, 0, 0, 0], 20)).toThrow(); }); });