109 lines
5.2 KiB
TypeScript
109 lines
5.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
lunarisStygianScheduleSchema,
|
|
selectedStygianBosses,
|
|
stygianImageFileName,
|
|
stygianImageName,
|
|
stygianRecommendationsSchema,
|
|
} from "@/lib/stygian/schema";
|
|
|
|
function level(monsterLevel: number) {
|
|
return {
|
|
monsterLevel,
|
|
levelConfigs: Array.from({ length: 3 }, (_, index) => ({
|
|
id: monsterLevel * 10 + index,
|
|
specialMonsterIcon: `UI_MonsterIcon_Boss_${index}`,
|
|
monsterStats: { hp: 1234.56 + index },
|
|
enLevelName: `Boss ${index}`,
|
|
enMonsterSpecialDesc: `Description ${index}`,
|
|
enMonsterSpecialMechanicName: ["Mechanic", "", "Missing description"],
|
|
enLevelMaxDescription: ["Do the thing", "Ignored", ""],
|
|
enRecommendedLevelMechanic: ["{SPRITE_PRESET#11003} characters", "", " {SPRITE_PRESET#11002} characters "],
|
|
tagType: ["Advantage", "None", "Disadvantage"],
|
|
})),
|
|
};
|
|
}
|
|
|
|
const schedule = {
|
|
scheduleId: 5269001,
|
|
challengeName: "5.7",
|
|
scheduleStartTime: "2025-06-25 10:00:00",
|
|
scheduleEndTime: "2025-08-06 09:59:59",
|
|
levels: [level(40), level(105), level(110)],
|
|
};
|
|
|
|
describe("Stygian Lunaris parsing", () => {
|
|
it("selects exactly the three level 105 and 110 bosses", () => {
|
|
const parsed = lunarisStygianScheduleSchema.parse(schedule);
|
|
const bosses = selectedStygianBosses(parsed);
|
|
expect(bosses).toHaveLength(6);
|
|
expect(bosses.map((boss) => boss.level)).toEqual([105, 105, 105, 110, 110, 110]);
|
|
expect(bosses[0]).toMatchObject({
|
|
name: "Boss 0",
|
|
hp: 1234.56,
|
|
mechanics: [{ name: "Mechanic", description: "Do the thing" }],
|
|
recommendedMechanics: ["{SPRITE_PRESET#11003} characters", "", "{SPRITE_PRESET#11002} characters"],
|
|
recommendedMechanicTypes: ["Advantage", "None", "Disadvantage"],
|
|
imageName: "UI_Img_LeyLineChallenge_Boss_0",
|
|
});
|
|
});
|
|
|
|
it("rejects a schedule missing one of the three required bosses", () => {
|
|
const parsed = lunarisStygianScheduleSchema.parse({
|
|
...schedule,
|
|
levels: [level(105), { ...level(110), levelConfigs: level(110).levelConfigs.slice(0, 2) }],
|
|
});
|
|
expect(() => selectedStygianBosses(parsed)).toThrow("exactly three level 110 bosses");
|
|
});
|
|
|
|
it("preserves existing Ley Line image names", () => {
|
|
expect(stygianImageName("UI_Img_LeyLineChallenge_Gastrobot01")).toBe("UI_Img_LeyLineChallenge_Gastrobot01");
|
|
expect(stygianImageName("UI_Img_LeyLineChallenge_Gastrobot01.png")).toBe("UI_Img_LeyLineChallenge_Gastrobot01");
|
|
expect(stygianImageFileName("UI_Img_LeyLineChallenge_Gastrobot01")).toBe("UI_Img_LeyLineChallenge_Gastrobot01.png");
|
|
expect(stygianImageFileName("UI_Img_LeyLineChallenge_Gastrobot01.png")).toBe("UI_Img_LeyLineChallenge_Gastrobot01.png");
|
|
});
|
|
});
|
|
|
|
describe("Stygian recommendation validation", () => {
|
|
const base = { expectedVersion: 1, level: 110, bossPosition: 0, units: [] };
|
|
|
|
it("accepts teams containing one to four characters", () => {
|
|
expect(stygianRecommendationsSchema.safeParse({
|
|
...base,
|
|
teams: [[
|
|
{ kind: "character", catalogKey: "10000001", weaponKey: null, artifactKey: null, constellationLevel: null },
|
|
{ kind: "character", catalogKey: "10000002", weaponKey: "WEAPON", artifactKey: null, constellationLevel: 2, refinement: 5 },
|
|
{ kind: "character", catalogKey: "10000003", weaponKey: null, artifactKey: "ARTIFACT", constellationLevel: 0 },
|
|
{ kind: "character", catalogKey: "10000004", weaponKey: null, artifactKey: null, constellationLevel: 6 },
|
|
]],
|
|
}).success).toBe(true);
|
|
expect(stygianRecommendationsSchema.safeParse({
|
|
...base,
|
|
teams: [[{ kind: "character", catalogKey: "10000001", weaponKey: null, artifactKey: null, constellationLevel: null }]],
|
|
}).success).toBe(true);
|
|
});
|
|
|
|
it("rejects empty, non-character, oversized, or duplicate teams", () => {
|
|
const character = { kind: "character", catalogKey: "10000001", weaponKey: null, artifactKey: null, constellationLevel: null };
|
|
expect(stygianRecommendationsSchema.safeParse({ ...base, teams: [[]] }).success).toBe(false);
|
|
expect(stygianRecommendationsSchema.safeParse({ ...base, teams: [[character, character]] }).success).toBe(false);
|
|
expect(stygianRecommendationsSchema.safeParse({ ...base, teams: [[character, ...Array.from({ length: 4 }, (_, index) => ({ kind: "weapon", catalogKey: `W${index}` }))]] }).success).toBe(false);
|
|
expect(stygianRecommendationsSchema.safeParse({ ...base, teams: [[character, { kind: "element", element: "Cryo" }, character, character]] }).success).toBe(false);
|
|
});
|
|
|
|
it("allows an unrestricted number of team rows and flexible units", () => {
|
|
const teams = Array.from({ length: 100 }, (_, index) => Array.from({ length: 4 }, (_, member) => ({ kind: "character", catalogKey: `C${index}-${member}`, weaponKey: null, artifactKey: null, constellationLevel: null })));
|
|
const units = Array.from({ length: 100 }, (_, index) => ({ kind: "artifact", catalogKey: `A${index}` }));
|
|
expect(stygianRecommendationsSchema.safeParse({ ...base, teams, units }).success).toBe(true);
|
|
});
|
|
|
|
it("rejects constellation units", () => {
|
|
expect(stygianRecommendationsSchema.safeParse({
|
|
...base,
|
|
teams: [],
|
|
units: [{ kind: "constellation", characterKey: "10000001", constellationLevel: 1 }],
|
|
}).success).toBe(false);
|
|
});
|
|
});
|