import { afterEach, describe, expect, it, vi } from "vitest"; import { useBossTestingReviews } from "./bossTestingReviews"; import { submitDungeonReport } from "./dungeonReports"; afterEach(() => { vi.unstubAllGlobals(); useBossTestingReviews.setState({ reviews: {} }); }); describe("boss feedback", () => { const boss = { key: "wailing-caverns/lady-anacondra", sourceDungeonId: "wailing-caverns", name: "Lady Anacondra" }; it("retains offline readiness and syncs it before refreshing server labels", async () => { const storage = { setItem: vi.fn() }; vi.stubGlobal("window", { localStorage: storage }); const fetch = vi.fn().mockRejectedValueOnce(new Error("offline")); vi.stubGlobal("fetch", fetch); expect(await useBossTestingReviews.getState().save(boss, "not-ready", null)).toBe(false); expect(useBossTestingReviews.getState().reviews[boss.key]).toMatchObject({ status: "not-ready", pending: true }); expect(storage.setItem).toHaveBeenCalled(); const review = { bossKey: boss.key, dungeonId: boss.sourceDungeonId, bossName: boss.name, status: "not-ready", reviewedAt: 1, reviewedBy: "Guest player" }; fetch.mockResolvedValueOnce({ ok: true, json: async () => ({ review }) }).mockResolvedValueOnce({ ok: true, json: async () => ({ reviews: [review] }) }); await useBossTestingReviews.getState().refresh(null); expect(useBossTestingReviews.getState().reviews[boss.key]).toEqual(review); expect(fetch.mock.calls[1][1].method).toBe("POST"); expect(fetch.mock.calls[2][0]).toBe("/api/boss-testing/reviews"); }); it("submits boss identity as structured metadata without consuming report text", async () => { const fetch = vi.fn().mockResolvedValue({ ok: true, json: async () => ({ report: {} }) }); vi.stubGlobal("fetch", fetch); await submitDungeonReport(null, boss.sourceDungeonId, "x".repeat(500), { bossKey: boss.key, bossName: boss.name }); expect(JSON.parse(fetch.mock.calls[0][1].body)).toEqual({ dungeonId: boss.sourceDungeonId, comment: "x".repeat(500), bossKey: boss.key, bossName: boss.name }); }); });