Files
EpicNext-Cms/src/features/housekeeping/foundation/search/navigation-search.test.ts
T
Simo bcb0ca977f
CI / check (pull_request) Successful in 38s
CI / release (pull_request) Skipped
CI / deploy (pull_request) Skipped
feat(housekeeping): add global command deck search
2026-08-30 15:59:48 +02:00

120 lines
3.6 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { z } from "zod";
import { PERMS } from "@/lib/permission-slugs";
import type { HousekeepingCommand } from "../commands/registry";
import type {
HousekeepingCapabilityContext,
HousekeepingDomainManifest,
} from "../contracts";
import type { HousekeepingRegistry } from "../registry";
import { searchNavigationAndCommands } from "./navigation-search";
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 peopleManifest = {
id: "people",
labelKey: "pages.housekeeping.domains.people.title",
descriptionKey: "pages.housekeeping.domains.people.description",
iconId: "users",
canonicalHref: "/ase/people",
capability: { mode: "any", slugs: [PERMS.USERS_VIEW] },
routes: [
{
id: "people.users",
href: "/ase/people/users",
labelKey: "pages.housekeeping.routes.people.users",
capability: { mode: "any", slugs: [PERMS.USERS_VIEW] },
},
{
id: "people.moderation",
href: "/ase/people/moderation",
labelKey: "pages.housekeeping.routes.people.moderation",
capability: { mode: "any", slugs: [PERMS.MODERATION_VIEW] },
},
],
searchProviders: [],
inboxSources: [],
widgets: [],
} as const satisfies HousekeepingDomainManifest;
const registry: HousekeepingRegistry = { domains: [peopleManifest] };
function command(
id: string,
permission: string,
): HousekeepingCommand<Record<string, never>, never> {
return {
id,
owner: "people",
risk: "safe",
capability: { mode: "any", slugs: [permission] },
input: z.object({}),
requiresReason: false,
rateLimit: { attempts: 3, windowMs: 60_000 },
execute: async () => ({
ok: true,
data: undefined as never,
correlationId: "command",
}),
};
}
const translations: Record<string, string> = {
"pages.housekeeping.domains.people.title": "People",
"pages.housekeeping.domains.people.description": "Accounts and moderation",
"pages.housekeeping.routes.people.users": "User accounts",
"pages.housekeeping.routes.people.moderation": "Moderation queue",
};
describe("navigation and command search", () => {
it("matches permitted domain/routes/commands and omits forbidden entries", () => {
const result = searchNavigationAndCommands({
registry,
commands: [
command("people.user.refresh", PERMS.USERS_VIEW),
command("people.moderation.ban", PERMS.MODERATION_VIEW),
],
context: context([PERMS.USERS_VIEW]),
term: "user",
translate: (key) => translations[key] ?? key,
});
expect(result.navigation.map((hit) => hit.id)).toEqual([
"route:people.users",
]);
expect(result.commands.map((hit) => hit.commandId)).toEqual([
"people.user.refresh",
]);
expect(result.navigation[0]?.href).toBe("/ase/people/users");
expect(result.commands[0]?.href).toBe("/ase/people");
});
it("normalizes terms and keeps registry/command order stable", () => {
const result = searchNavigationAndCommands({
registry,
commands: [
command("people.user.refresh", PERMS.USERS_VIEW),
command("people.user.inspect", PERMS.USERS_VIEW),
],
context: context([PERMS.USERS_VIEW]),
term: " PEOPLE ",
translate: (key) => translations[key] ?? key,
});
expect(result.navigation.map((hit) => hit.id)).toEqual(["domain:people"]);
expect(result.commands.map((hit) => hit.commandId)).toEqual([
"people.user.refresh",
"people.user.inspect",
]);
});
});