73 lines
2.2 KiB
TypeScript
73 lines
2.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const { getContextMock, loadRecentMock, recordVisitMock } = vi.hoisted(() => ({
|
|
getContextMock: vi.fn(),
|
|
loadRecentMock: vi.fn(),
|
|
recordVisitMock: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@/features/housekeeping/foundation/server-capability-context", () => ({
|
|
getHousekeepingCapabilityContext: getContextMock,
|
|
}));
|
|
|
|
vi.mock("@/lib/housekeeping-recent-work", () => ({
|
|
loadHousekeepingRecentWork: loadRecentMock,
|
|
recordHousekeepingRouteVisit: recordVisitMock,
|
|
}));
|
|
|
|
import {
|
|
executeHousekeepingRecent,
|
|
recordHousekeepingRouteVisitAction,
|
|
} from "./housekeeping-recent";
|
|
|
|
const context = {
|
|
actor: { id: 42, username: "operator", rank: 7 },
|
|
isSuperAdmin: false,
|
|
has: () => true,
|
|
hasAny: () => true,
|
|
hasAll: () => true,
|
|
};
|
|
|
|
describe("housekeeping recent actions", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
getContextMock.mockResolvedValue(context);
|
|
loadRecentMock.mockResolvedValue({
|
|
ok: true,
|
|
data: [],
|
|
correlationId: "recent-action",
|
|
});
|
|
recordVisitMock.mockResolvedValue({
|
|
ok: true,
|
|
data: { routeId: "people.users" },
|
|
correlationId: "visit-action",
|
|
});
|
|
});
|
|
|
|
it("binds load and visit recording to a fresh server capability context", async () => {
|
|
await expect(executeHousekeepingRecent()).resolves.toMatchObject({
|
|
ok: true,
|
|
});
|
|
await expect(
|
|
recordHousekeepingRouteVisitAction("people.users"),
|
|
).resolves.toMatchObject({ ok: true });
|
|
expect(loadRecentMock).toHaveBeenCalledWith(context);
|
|
expect(recordVisitMock).toHaveBeenCalledWith("people.users", context);
|
|
});
|
|
|
|
it("rejects a forged route identifier before resolving server context", async () => {
|
|
const result = await recordHousekeepingRouteVisitAction({
|
|
routeId: "people.users",
|
|
});
|
|
expect(result).toMatchObject({ ok: false, error: { code: "VALIDATION" } });
|
|
expect(getContextMock).not.toHaveBeenCalled();
|
|
expect(recordVisitMock).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("maps unexpected boundary failures to typed internal results", async () => {
|
|
loadRecentMock.mockRejectedValueOnce(new Error("audit unavailable"));
|
|
const result = await executeHousekeepingRecent();
|
|
expect(result).toMatchObject({ ok: false, error: { code: "INTERNAL" } });
|
|
});
|
|
});
|