import { describe, expect, it } from "vitest"; import type { StoredArtifactRecord } from "../types/storage"; import { mergeIdentity, mergeRescannedArtifacts, substatName } from "./artifactMerge"; function record(overrides: Partial = {}): StoredArtifactRecord { return { id: "x", name: "Gladiator's Nostalgia", slot: "Flower of Life", level: 0, setName: "Gladiator's Finale", mainStat: "HP", mainValue: "717", substats: ["CRIT DMG+5.4%", "ATK+19", "HP%+4.1%", "Energy Recharge+5.2%"], equipped: "Not detected", confidence: 80, needsReview: false, source: "auto-scan", ...overrides, }; } describe("artifactMerge", () => { it("strips values to get the substat name", () => { expect(substatName("CRIT DMG+13.2%")).toBe("CRIT DMG"); expect(substatName("ATK+19")).toBe("ATK"); }); it("identity ignores level and substat values", () => { const low = record({ level: 0, substats: ["CRIT DMG+5.4%", "ATK+19"] }); const high = record({ level: 20, substats: ["CRIT DMG+13.2%", "ATK+37"] }); expect(mergeIdentity(low)).toBe(mergeIdentity(high)); }); it("collapses a leveled re-scan into one record, keeping the higher level", () => { const low = record({ id: "a", level: 0, timesSeen: 1 }); const high = record({ id: "b", level: 20, timesSeen: 1, substats: ["CRIT DMG+13.2%", "ATK+37", "HP%+15.7%", "Energy Recharge+11.7%"], equipped: "Bennett", }); const { merged, collapsed } = mergeRescannedArtifacts([low, high]); expect(collapsed).toBe(1); expect(merged).toHaveLength(1); expect(merged[0].level).toBe(20); expect(merged[0].equipped).toBe("Bennett"); expect(merged[0].timesSeen).toBe(2); }); it("does not merge pieces with different substat lineups", () => { const threeLine = record({ id: "a", substats: ["CRIT DMG+5.4%", "ATK+19", "HP%+4.1%"] }); const fourLine = record({ id: "b", substats: ["CRIT DMG+5.4%", "ATK+19", "HP%+4.1%", "DEF+16"] }); const { merged, collapsed } = mergeRescannedArtifacts([threeLine, fourLine]); expect(collapsed).toBe(0); expect(merged).toHaveLength(2); }); it("keeps distinct sets/slots/mains apart", () => { const flower = record({ slot: "Flower of Life", mainStat: "HP" }); const plume = record({ slot: "Plume of Death", mainStat: "ATK" }); const { merged } = mergeRescannedArtifacts([flower, plume]); expect(merged).toHaveLength(2); }); it("preserves the earliest firstSeenAt and latest lastSeenAt", () => { const older = record({ id: "a", level: 0, firstSeenAt: "2026-01-01", lastSeenAt: "2026-01-02" }); const newer = record({ id: "b", level: 20, firstSeenAt: "2026-06-01", lastSeenAt: "2026-06-10" }); const { merged } = mergeRescannedArtifacts([older, newer]); expect(merged[0].firstSeenAt).toBe("2026-01-01"); expect(merged[0].lastSeenAt).toBe("2026-06-10"); }); });