59 lines
3.5 KiB
TypeScript
59 lines
3.5 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import {
|
|
DUNGEON_REPORT_STATUSES, fetchDungeonReports, filterDungeonReports, sessionCanManageDungeonReports,
|
|
submitDungeonReport, updateDungeonReport, type DungeonReport,
|
|
} from "./dungeonReports";
|
|
import { useGameStore } from "../game/store";
|
|
|
|
function report(id: string, dungeonId: string, status: DungeonReport["status"]): DungeonReport {
|
|
return { id, dungeonId, status, comment: "Door does not open", submittedBy: "Player", createdAt: 1, updatedAt: 1, updatedBy: null, revision: 0 };
|
|
}
|
|
|
|
afterEach(() => { vi.unstubAllGlobals(); useGameStore.getState().closeOverlay(); });
|
|
|
|
describe("dungeon reports", () => {
|
|
it("shows all statuses by default, including Closed, and combines status and dungeon filters", () => {
|
|
const reports = DUNGEON_REPORT_STATUSES.flatMap((status, index) => [
|
|
report(`stock-${index}`, "stormwind-stockade", status), report(`cave-${index}`, "wailing-caverns", status),
|
|
]);
|
|
expect(filterDungeonReports(reports, "all", "all")).toEqual(reports);
|
|
expect(filterDungeonReports(reports, "Closed", "all")).toHaveLength(2);
|
|
expect(filterDungeonReports(reports, "all", "wailing-caverns")).toHaveLength(4);
|
|
expect(filterDungeonReports(reports, "Testing Fixes", "stormwind-stockade").map((item) => item.id)).toEqual(["stock-2"]);
|
|
expect(filterDungeonReports(reports, "Submitted", "missing")).toEqual([]);
|
|
});
|
|
|
|
it("allows GM report management in the ordinary release and rejects offline or local-only authority", () => {
|
|
const gm = { kind: "account" as const, ownerId: "gm", displayName: "Phenom", accessToken: "token", roles: ["gm" as const] };
|
|
expect(sessionCanManageDungeonReports(gm)).toBe(true);
|
|
expect(sessionCanManageDungeonReports({ ...gm, roles: [] })).toBe(false);
|
|
expect(sessionCanManageDungeonReports({ ...gm, kind: "offline" })).toBe(false);
|
|
expect(sessionCanManageDungeonReports({ ...gm, accessToken: undefined })).toBe(false);
|
|
expect(sessionCanManageDungeonReports(null)).toBe(false);
|
|
});
|
|
|
|
it("sends the active dungeon and preserves the expected report revision for GM updates", async () => {
|
|
const item = report("report-id", "stormwind-stockade", "Submitted");
|
|
const fetchMock = vi.fn().mockResolvedValue({ ok: true, json: async () => ({ report: item }) });
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
const gm = { kind: "account" as const, ownerId: "gm", displayName: "Phenom", accessToken: "token", roles: ["gm" as const] };
|
|
await submitDungeonReport(gm, item.dungeonId, "Door does not open");
|
|
expect(JSON.parse(fetchMock.mock.calls[0][1].body)).toEqual({ dungeonId: item.dungeonId, comment: "Door does not open" });
|
|
expect(fetchMock.mock.calls[0][1].headers.get("Authorization")).toBe("Bearer token");
|
|
await updateDungeonReport(gm, { ...item, revision: 3 }, "Closed");
|
|
expect(fetchMock.mock.calls[1][1].method).toBe("PATCH");
|
|
expect(JSON.parse(fetchMock.mock.calls[1][1].body)).toEqual({ status: "Closed", expectedRevision: 3 });
|
|
await fetchDungeonReports();
|
|
expect(fetchMock.mock.calls[2][0]).toBe("/api/dungeon-reports");
|
|
});
|
|
|
|
it("keeps the game paused and camera look stopped while reporting and returning to pause", () => {
|
|
const game = useGameStore.getState();
|
|
game.setCameraLookActive(true);
|
|
game.openOverlay("report-issue");
|
|
expect(useGameStore.getState()).toMatchObject({ paused: true, overlay: "report-issue", cameraLookActive: false });
|
|
game.openOverlay("pause");
|
|
expect(useGameStore.getState()).toMatchObject({ paused: true, overlay: "pause", cameraLookActive: false });
|
|
});
|
|
});
|