feat(weapon) : share public cards with inline admin editing
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { act, createElement, type ComponentProps } from "react";
|
||||
import { createRoot, type Root } from "react-dom/client";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { WeaponComparisonCard } from "@/components/weapon-comparison-card";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { useManualSave } from "@/hooks/use-manual-save";
|
||||
import { WeaponEditor } from "./weapon-editor";
|
||||
|
||||
vi.mock("@/app/admin/actions", () => ({ saveWeaponSection: vi.fn() }));
|
||||
vi.mock("@/hooks/use-manual-save", () => ({
|
||||
useManualSave: vi.fn(() => ({ state: "saved", canSave: false })),
|
||||
}));
|
||||
|
||||
let root: Root;
|
||||
let container: HTMLDivElement;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
|
||||
vi.clearAllMocks();
|
||||
container = document.createElement("div");
|
||||
document.body.append(container);
|
||||
root = createRoot(container);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await act(async () => root.unmount());
|
||||
container.remove();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
async function render(value: string) {
|
||||
const props = {
|
||||
guide: { id: "guide", characterKey: "character", version: 1 },
|
||||
characters: [{ key: "character", weaponType: "sword" }],
|
||||
weapons: [{ key: "weapon", name: "Weapon", weaponType: "sword", rarity: 5, imageUrl: "/weapon.png" }],
|
||||
initial: { sectionNote: null, weaponGroups: [{
|
||||
id: "condition", name: null, note: null, rows: [{
|
||||
id: "row", weaponKey: "weapon", refinement: "1", overallPercent: value, personalPercent: null, note: null,
|
||||
}],
|
||||
}] },
|
||||
} as unknown as ComponentProps<typeof WeaponEditor>;
|
||||
await act(async () => root.render(createElement(WeaponEditor, props)));
|
||||
return container.querySelector<HTMLInputElement>("#weapon-overall-row")!;
|
||||
}
|
||||
|
||||
describe("weapon damage editing", () => {
|
||||
it("uses the public curve and damage typography with more room for inputs", async () => {
|
||||
const input = await render("120.00");
|
||||
const publicCard = document.createElement("div");
|
||||
publicCard.innerHTML = renderToStaticMarkup(createElement(WeaponComparisonCard, {
|
||||
weapon: { key: "weapon", name: "Weapon", rarity: 5, imageUrl: "/weapon.png" },
|
||||
rank: 1, refinement: "1", note: null, overallPercent: "120.00", personalPercent: null,
|
||||
weaponHref: "https://lunaris.moe/weapon/weapon",
|
||||
}));
|
||||
const publicContent = publicCard.querySelector('[data-slot="card-content"]')!;
|
||||
const adminContent = input.closest('[data-slot="card-content"]')!;
|
||||
expect(adminContent.className.replace(/md:grid-cols-\S+/u, ""))
|
||||
.toBe(publicContent.className.replace(/md:grid-cols-\S+/u, ""));
|
||||
expect(adminContent.className).toContain("md:grid-cols-[minmax(0,5fr)_minmax(0,2fr)]");
|
||||
expect(adminContent.firstElementChild!.className.replace(" relative", ""))
|
||||
.toBe(publicContent.firstElementChild!.className);
|
||||
const publicValue = publicContent.lastElementChild!.querySelector("p")!;
|
||||
expect(input.parentElement!.className).toBe(publicValue.className);
|
||||
expect(input.value).toBe(publicValue.textContent);
|
||||
expect(adminContent.lastElementChild!.className).toBe(publicContent.lastElementChild!.className);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["0.00", "-"],
|
||||
["120.00", "120%"],
|
||||
["120.125", "120.13%"],
|
||||
["", ""],
|
||||
])("displays %s as %s while preserving its raw draft value", async (raw, display) => {
|
||||
const input = await render(raw);
|
||||
expect(input.value).toBe(display);
|
||||
await act(async () => input.focus());
|
||||
expect(input.value).toBe(raw);
|
||||
await act(async () => input.blur());
|
||||
expect(input.value).toBe(display);
|
||||
const options = vi.mocked(useManualSave).mock.lastCall![0];
|
||||
expect(options.value).toMatchObject({ groups: [{ rows: [{ overallPercent: raw === "" ? null : Number(raw) }] }] });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user