import { renderToStaticMarkup } from "react-dom/server"; import { describe, expect, it } from "vitest"; import { PERMS } from "@/lib/permission-slugs"; import { fail, type HousekeepingCapabilityContext, ok, } from "../../../foundation/contracts"; import { EconomyCatalogPage } from "./catalog"; import { EconomyCommercePage } from "./commerce"; import { EconomyHistoryPage } from "./history"; import { EconomyItemsPage } from "./items"; import { EconomyRewardsPage } from "./rewards"; import { EconomyValuePage } from "./value"; function context(granted: readonly string[]): HousekeepingCapabilityContext { const permissions = new Set(granted); return { actor: { id: 42, username: "operator", rank: 7 }, isSuperAdmin: false, has: (slug) => permissions.has(slug), hasAny: (...slugs) => slugs.some((slug) => permissions.has(slug)), hasAll: (...slugs) => slugs.every((slug) => permissions.has(slug)), }; } const cases = [ ["catalog", EconomyCatalogPage], ["items", EconomyItemsPage], ["commerce", EconomyCommercePage], ["history", EconomyHistoryPage], ["value", EconomyValuePage], ["rewards", EconomyRewardsPage], ] as const; describe.each(cases)("Economy %s page", (kind, Component) => { it("renders loading, forbidden, empty, and canonical ready states", () => { const render = (result?: unknown) => renderToStaticMarkup( , ); expect(render()).toContain('data-housekeeping-state="loading"'); expect( render(fail("FORBIDDEN", "errors.housekeeping.forbidden", "denied")), ).toContain('data-housekeeping-state="forbidden"'); expect( render( ok({ kind, items: [], total: 0, partialDependencies: [] }, "empty"), ), ).toContain('data-housekeeping-state="empty"'); const ready = render( ok( { kind, items: [ { id: "18446744073709551615", title: "Canonical economy item", status: "active", href: `/ase-next/economy/${kind}`, }, ], total: 1, partialDependencies: [], }, "ready", ), ); expect(ready).toContain('data-housekeeping-state="ready"'); expect(ready).toContain("Canonical economy item"); expect(ready).not.toContain("/admin"); }); }); describe("Economy mutation forms", () => { it("renders edit controls only with the exact mutation capability", () => { const result = ok( { kind: "commerce" as const, items: [{ id: "1", title: "Package", status: "active" }], total: 1, partialDependencies: [], }, "shop", ); const readOnly = renderToStaticMarkup( , ); const editor = renderToStaticMarkup( , ); expect(readOnly).not.toContain("economy.commerce.shop-article.change"); expect(editor).toContain("economy.commerce.shop-article.change"); expect(editor).toContain(" { const all = context(Object.values(PERMS)); const empty = (kind: "catalog" | "commerce" | "value" | "rewards") => ok({ kind, items: [], total: 0, partialDependencies: [] }, kind); const catalog = renderToStaticMarkup( , ); for (const field of ["id", "caption", "parentId", "pageLayout"]) { expect(catalog).toContain(`name="${field}"`); } const commerce = renderToStaticMarkup( , ); for (const field of ["code", "amount", "maxUses", "expiresAt"]) { expect(commerce).toContain(`name="${field}"`); } const value = renderToStaticMarkup( , ); for (const field of [ "categoryId", "name", "currencyValue", "currencyType", ]) { expect(value).toContain(`name="${field}"`); } const rewards = renderToStaticMarkup( , ); for (const field of ["id", "name", "author", "track", "length"]) { expect(rewards).toContain(`name="${field}"`); } }); });