feat : update

This commit is contained in:
2026-09-03 21:39:51 +07:00 Unverified
parent 1b014d7c8f
commit ecc2b1749a
8 changed files with 1818 additions and 8 deletions
+95
View File
@@ -0,0 +1,95 @@
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"]);
});
});
File diff suppressed because it is too large Load Diff