Files
EpicNext-Cms/src/features/housekeeping/domains/economy/commands/economy-commands.test.ts
T
Simo 43470ebf82
CI / check (pull_request) Failing after 10s
CI / deploy (pull_request) Skipped
CI / release (pull_request) Skipped
feat(housekeeping): unify complete rebuild in gated preview
2026-08-31 20:37:51 +02:00

157 lines
4.8 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import { PERMS } from "@/lib/permission-slugs";
import type { HousekeepingCapabilityContext } from "../../../foundation/contracts";
import { createEconomyCommands, ECONOMY_COMMAND_IDS } from "./economy-commands";
const expected = [
["economy.catalog.page.change", "catalog-page.change", PERMS.CATALOG_EDIT],
["economy.catalog.page.reorder", "catalog-page.reorder", PERMS.CATALOG_EDIT],
[
"economy.catalog.page.delete-tree",
"catalog-page.delete-tree",
PERMS.CATALOG_EDIT,
],
["economy.catalog.bc-page.change", "bc-page.change", PERMS.CATALOG_EDIT],
["economy.catalog.bc-page.reorder", "bc-page.reorder", PERMS.CATALOG_EDIT],
[
"economy.catalog.bc-page.delete-tree",
"bc-page.delete-tree",
PERMS.CATALOG_EDIT,
],
["economy.catalog.bc-item.change", "bc-item.change", PERMS.CATALOG_EDIT],
["economy.catalog.item.change", "catalog-item.change", PERMS.CATALOG_EDIT],
[
"economy.catalog.item.bulk-create",
"catalog-item.bulk-create",
PERMS.CATALOG_EDIT,
],
["economy.catalog.item.move", "catalog-item.move", PERMS.CATALOG_EDIT],
["economy.catalog.item.reorder", "catalog-item.reorder", PERMS.CATALOG_EDIT],
[
"economy.catalog.item.translate",
"catalog-item.translate",
PERMS.CATALOG_EDIT,
],
[
"economy.catalog.maintenance.fix-offers",
"maintenance.fix-offers",
PERMS.CATALOG_EDIT,
],
[
"economy.catalog.maintenance.fix-everything",
"maintenance.fix-everything",
PERMS.CATALOG_EDIT,
],
[
"economy.catalog.maintenance.fix-sprite-ids",
"maintenance.fix-sprite-ids",
PERMS.CATALOG_EDIT,
],
[
"economy.catalog.maintenance.reconcile-ids",
"maintenance.reconcile-ids",
PERMS.CATALOG_EDIT,
],
[
"economy.catalog.maintenance.align-ids",
"maintenance.align-ids",
PERMS.CATALOG_EDIT,
],
[
"economy.catalog.maintenance.remove-duplicates",
"maintenance.remove-duplicates",
PERMS.CATALOG_EDIT,
],
["economy.items.base.update", "items-base.update", PERMS.CATALOG_EDIT],
[
"economy.commerce.shop-article.change",
"shop-article.change",
PERMS.SHOP_EDIT,
],
[
"economy.commerce.marketplace.cancel",
"marketplace.cancel",
PERMS.SHOP_EDIT,
],
["economy.commerce.voucher.change", "voucher.change", PERMS.SHOP_EDIT],
["economy.value.category.change", "rare-category.change", PERMS.SHOP_EDIT],
["economy.value.rare.change", "rare-value.change", PERMS.SHOP_EDIT],
["economy.rewards.badge.give", "badge.give", PERMS.CATALOG_EDIT],
["economy.rewards.badge.upload", "badge.upload", PERMS.CATALOG_EDIT],
[
"economy.rewards.soundtrack.change",
"soundtrack.change",
PERMS.CATALOG_EDIT,
],
] as const;
function context(): HousekeepingCapabilityContext {
return {
actor: { id: 42, username: "operator", rank: 7 },
isSuperAdmin: false,
has: () => true,
hasAny: () => true,
hasAll: () => true,
};
}
describe("Economy commands", () => {
it("registers the exact 27-operation matrix with existing ACLs", () => {
const commands = createEconomyCommands({ execute: vi.fn() } as never);
expect(ECONOMY_COMMAND_IDS).toEqual(expected.map(([id]) => id));
expect(
commands.map((command) => [
command.id,
command.operation,
command.capability.slugs[0],
]),
).toEqual(expected);
expect(commands.every((command) => command.owner === "economy")).toBe(true);
expect(commands.every((command) => command.risk === "sensitive")).toBe(
true,
);
});
it("requires a reason for destructive, maintenance, cancellation, and grant operations", () => {
const commands = createEconomyCommands({ execute: vi.fn() } as never);
const required = commands
.filter((command) => command.requiresReason)
.map((command) => command.id);
expect(required).toEqual([
"economy.catalog.page.delete-tree",
"economy.catalog.bc-page.delete-tree",
"economy.catalog.maintenance.fix-offers",
"economy.catalog.maintenance.fix-everything",
"economy.catalog.maintenance.fix-sprite-ids",
"economy.catalog.maintenance.reconcile-ids",
"economy.catalog.maintenance.align-ids",
"economy.catalog.maintenance.remove-duplicates",
"economy.commerce.marketplace.cancel",
"economy.rewards.badge.give",
"economy.rewards.badge.upload",
]);
});
it("binds real execution to the server-authorized actor", async () => {
const execute = vi.fn(async () => ({
ok: true as const,
data: { before: null, after: { id: "1" } },
correlationId: "economy-command",
}));
const [command] = createEconomyCommands({ execute } as never);
await command.execute(
{
capability: context(),
correlationId: "economy-command",
ipAddress: "127.0.0.1",
},
{ action: "update", id: "1", caption: "Seasonal" },
);
expect(execute).toHaveBeenCalledWith(
{ correlationId: "economy-command", expectedActorId: 42 },
"catalog-page.change",
{ action: "update", id: "1", caption: "Seasonal" },
);
});
});