import { createElement } from "react"; import { renderToStaticMarkup } from "react-dom/server"; import { beforeEach, describe, expect, it, vi } from "vitest"; const combatMedia = vi.hoisted(() => ({ ready: false })); vi.mock("../game/combatMediaPack", async (importOriginal) => ({ ...(await importOriginal()), combatMediaPackReady: () => combatMedia.ready, })); import { DEFAULT_COMBAT_PRESENTATION_SETTINGS, type CombatVfxMode } from "../game/combatPresentation"; import { DEFAULT_GAMEPLAY_SETTINGS } from "../game/combatStore"; import { OptionsPanel, nextCombatVfxMode } from "./OptionsPanel"; function renderOptions(mode: CombatVfxMode, originalMediaEnabled = DEFAULT_COMBAT_PRESENTATION_SETTINGS.originalMediaEnabled): string { return renderToStaticMarkup(createElement(OptionsPanel, { settings: DEFAULT_GAMEPLAY_SETTINGS, onChange: () => undefined, onReset: () => undefined, presentationSettings: { ...DEFAULT_COMBAT_PRESENTATION_SETTINGS, originalMediaEnabled, vfxMode: mode }, onPresentationChange: () => undefined, onPresentationReset: () => undefined, open: true, onClose: () => undefined, })); } describe("combat visual mode option", () => { beforeEach(() => { combatMedia.ready = false; }); it("allows an explicit generated override of the original-first default", () => { expect(nextCombatVfxMode("generated")).toBe("original"); expect(nextCombatVfxMode("original")).toBe("generated"); }); it("renders original as the default selection while media is unavailable", () => { const markup = renderOptions(DEFAULT_COMBAT_PRESENTATION_SETTINGS.vfxMode); expect(markup).toContain("Spell visual mode"); expect(markup).toContain("Original spell effects & sounds"); expect(markup).toContain("download automatically when enabled."); expect(markup).toContain(">Download"); expect(markup).toContain("Generated visuals are the backup while original media is unavailable."); expect(markup).toContain("missing sounds stay silent."); expect(markup).toContain(">Original"); }); it("explains original effects take priority and generated visuals are only a fallback", () => { combatMedia.ready = true; const markup = renderOptions("original", true); expect(markup).toContain("Use original spell effects first, with generated visuals only when an original effect is unavailable."); expect(markup).toContain("Missing sounds stay silent."); expect(markup).toContain(">Original"); expect(markup).toContain(">Remove"); }); it("offers to enable an already downloaded pack without downloading it again", () => { combatMedia.ready = true; const markup = renderOptions("generated", false); expect(markup).toContain("Stored on this device. Enable the pack"); expect(markup).toContain(">Enable"); }); it("offers independent damage and healing number switches", () => { const markup = renderOptions(DEFAULT_COMBAT_PRESENTATION_SETTINGS.vfxMode); expect(markup).toContain("Your damage"); expect(markup).toContain("Ally damage"); expect(markup).toContain("Incoming damage"); expect(markup).toContain("Party healing numbers"); }); it("shows dungeon graphics controls with the saved defaults", () => { const markup = renderOptions(DEFAULT_COMBAT_PRESENTATION_SETTINGS.vfxMode); expect(markup).toContain("Render resolution"); expect(markup).toContain("Texture filtering"); expect(markup).toContain("Shadows"); expect(markup).toContain("Ambient fill"); expect(markup).toContain(">Adaptive"); expect(markup).toContain(">Standard"); }); });