feat(housekeeping): personalize command deck
This commit is contained in:
1 parent
300ac0ef95
commit
5574e601bb
12 files changed
+1549
-1
No files matched your search
@@ -0,0 +1,72 @@
|
||||
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" } });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
"use server";
|
||||
|
||||
import {
|
||||
fail,
|
||||
type HousekeepingResult,
|
||||
mapUnknownError,
|
||||
} from "@/features/housekeeping/foundation/contracts";
|
||||
import { createCorrelationId } from "@/features/housekeeping/foundation/correlation";
|
||||
import type { HousekeepingRecentItem } from "@/features/housekeeping/foundation/recent/recent-work";
|
||||
import { getHousekeepingCapabilityContext } from "@/features/housekeeping/foundation/server-capability-context";
|
||||
import {
|
||||
loadHousekeepingRecentWork,
|
||||
recordHousekeepingRouteVisit,
|
||||
} from "@/lib/housekeeping-recent-work";
|
||||
|
||||
export async function executeHousekeepingRecent(): Promise<
|
||||
HousekeepingResult<readonly HousekeepingRecentItem[]>
|
||||
> {
|
||||
try {
|
||||
const context = await getHousekeepingCapabilityContext();
|
||||
return await loadHousekeepingRecentWork(context);
|
||||
} catch (error) {
|
||||
return mapUnknownError(error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function recordHousekeepingRouteVisitAction(
|
||||
routeId: unknown,
|
||||
): Promise<HousekeepingResult<HousekeepingRecentItem>> {
|
||||
if (
|
||||
typeof routeId !== "string" ||
|
||||
!routeId.trim() ||
|
||||
routeId !== routeId.trim() ||
|
||||
routeId.length > 128
|
||||
) {
|
||||
return fail(
|
||||
"VALIDATION",
|
||||
"errors.housekeeping.recent.invalidRoute",
|
||||
createCorrelationId(),
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const context = await getHousekeepingCapabilityContext();
|
||||
return await recordHousekeepingRouteVisit(routeId, context);
|
||||
} catch (error) {
|
||||
return mapUnknownError(error);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user