96 lines
3.5 KiB
TypeScript
96 lines
3.5 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import {
|
|
buildGuideImportDraft,
|
|
charactersFromCombo,
|
|
parseCsv,
|
|
type GuideImportSource,
|
|
type ImportCatalog,
|
|
} from "@/lib/guides/google-sheet-import";
|
|
|
|
afterEach(() => vi.unstubAllGlobals());
|
|
|
|
describe("Google Sheet guide import", () => {
|
|
it("parses quoted commas, escaped quotes, and multiline cells", () => {
|
|
expect(parseCsv('"name","note"\n"A, B","line 1\nline ""2"""\n')).toEqual([
|
|
["name", "note"],
|
|
["A, B", 'line 1\nline "2"'],
|
|
]);
|
|
});
|
|
|
|
it("builds supported compact fields and reports missing catalog rows", async () => {
|
|
const source: GuideImportSource = {
|
|
characterName: "Hero",
|
|
overview: "Guide Hero",
|
|
workbookId: "sheet-id",
|
|
coverId: "cover-id",
|
|
layout: "compact",
|
|
infoSheet: "Hero Info",
|
|
teamSheets: [],
|
|
comboSheets: [],
|
|
weaponMetric: "overall-personal",
|
|
};
|
|
const catalog: ImportCatalog = {
|
|
characters: [{ key: "hero", name: "Hero", constellations: [] }],
|
|
weapons: [{ key: "weapon", name: "Known Weapon" }],
|
|
artifacts: [{ key: "artifact", name: "Known Set" }],
|
|
};
|
|
const rows = Array.from({ length: 24 }, () => Array.from({ length: 21 }, () => ""));
|
|
rows[0][10] = "Weapons อาวุธที่แนะนำ";
|
|
rows[1][11] = "Known Weapon R5";
|
|
rows[1][13] = "110%";
|
|
rows[1][14] = "105%";
|
|
rows[3][11] = "Missing Weapon R1";
|
|
rows[3][13] = "100%";
|
|
rows[5][10] = "Artifacts อาร์ติแฟกต์ที่แนะนำ (เลทเกม)";
|
|
rows[6][11] = "4 Known Set";
|
|
rows[6][13] = "100%";
|
|
rows[8][5] = "ATK (พลังโจมตี)";
|
|
rows[8][6] = "2000+";
|
|
rows[8][7] = "สแตทที่แนะนำ เลทเกม (AR 45+)";
|
|
vi.stubGlobal("fetch", vi.fn(async () => new Response(rows.map((row) => row.map((cell) => `"${cell}"`).join(",")).join("\n"))));
|
|
|
|
const draft = await buildGuideImportDraft(source, catalog);
|
|
|
|
expect(draft.weapons).toEqual([expect.objectContaining({ weaponKey: "weapon", refinement: 5, overallPercent: 110, personalPercent: 105 })]);
|
|
expect(draft.artifacts.groups[0].rows).toEqual([expect.objectContaining({ firstArtifactKey: "artifact", percent: 100 })]);
|
|
expect(draft.artifacts.targets).toEqual([{ stat: "ATK", value: "2000+" }]);
|
|
expect(draft.skipped).toContain("weapon not in catalog: Missing Weapon R1");
|
|
});
|
|
|
|
it("does not fetch or populate a keep-existing source", async () => {
|
|
const fetchMock = vi.fn();
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
const draft = await buildGuideImportDraft({
|
|
characterName: "Yumemizuki Mizuki",
|
|
overview: "existing",
|
|
workbookId: "sheet-id",
|
|
coverId: "cover-id",
|
|
layout: "full",
|
|
infoSheet: "Mizuki Info",
|
|
teamSheets: [],
|
|
comboSheets: [],
|
|
skipWrite: true,
|
|
}, {
|
|
characters: [{ key: "mizuki", name: "Yumemizuki Mizuki", constellations: [] }],
|
|
weapons: [],
|
|
artifacts: [],
|
|
});
|
|
expect(fetchMock).not.toHaveBeenCalled();
|
|
expect(draft.weapons).toEqual([]);
|
|
});
|
|
|
|
it("resolves the unique characters named by a combo", () => {
|
|
const characters = ["Yae Miko", "Odette", "Alyosha", "Sandrone"].map((name, index) => ({
|
|
key: String(index),
|
|
name,
|
|
constellations: [],
|
|
}));
|
|
expect(charactersFromCombo("Yae EEE > Odette EE > Alyosha EQ > Sandrone 3CE Q", {
|
|
characters,
|
|
weapons: [],
|
|
artifacts: [],
|
|
}).map((item) => item.name)).toEqual(["Yae Miko", "Odette", "Alyosha", "Sandrone"]);
|
|
});
|
|
});
|