feat(housekeeping): persist operator preferences
This commit is contained in:
1 parent
86a2d9d069
commit
2eb0456999
8 files changed
+566
No files matched your search
@@ -0,0 +1,123 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
anyCapability,
|
||||
type HousekeepingCapabilityContext,
|
||||
} from "../contracts";
|
||||
import type { HousekeepingRegistry } from "../registry";
|
||||
import { reconcilePreferences } from "./reconcile";
|
||||
import { defaultHousekeepingPreferences } from "./schema";
|
||||
|
||||
const usersView = anyCapability("admin.users.view");
|
||||
const ticketsView = anyCapability("admin.tickets.view");
|
||||
const bansView = anyCapability("admin.bans.view");
|
||||
|
||||
const registry: HousekeepingRegistry = {
|
||||
domains: [
|
||||
{
|
||||
id: "people",
|
||||
labelKey: "people",
|
||||
descriptionKey: "people.description",
|
||||
iconId: "users",
|
||||
canonicalHref: "/ase/people",
|
||||
capability: usersView,
|
||||
routes: [
|
||||
{
|
||||
id: "people.users",
|
||||
labelKey: "users",
|
||||
href: "/ase/people/users",
|
||||
capability: usersView,
|
||||
},
|
||||
{
|
||||
id: "people.tickets",
|
||||
labelKey: "tickets",
|
||||
href: "/ase/people/tickets",
|
||||
capability: ticketsView,
|
||||
},
|
||||
{
|
||||
id: "people.bans",
|
||||
labelKey: "bans",
|
||||
href: "/ase/people/bans",
|
||||
capability: bansView,
|
||||
},
|
||||
],
|
||||
searchProviders: [],
|
||||
inboxSources: [],
|
||||
widgets: [
|
||||
{
|
||||
id: "people.summary",
|
||||
owner: "people",
|
||||
capability: usersView,
|
||||
kind: "mandatory",
|
||||
load: async () => ({ ok: true, data: null, correlationId: "widget" }),
|
||||
},
|
||||
{
|
||||
id: "people.queue",
|
||||
owner: "people",
|
||||
capability: ticketsView,
|
||||
kind: "optional",
|
||||
load: async () => ({ ok: true, data: null, correlationId: "widget" }),
|
||||
},
|
||||
{
|
||||
id: "people.bans",
|
||||
owner: "people",
|
||||
capability: bansView,
|
||||
kind: "optional",
|
||||
load: async () => ({ ok: true, data: null, correlationId: "widget" }),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const context: HousekeepingCapabilityContext = {
|
||||
actor: { id: 42, username: "operator", rank: 0 },
|
||||
isSuperAdmin: false,
|
||||
has: (slug) => slug === "admin.users.view" || slug === "admin.tickets.view",
|
||||
hasAny: (...slugs) => slugs.some(context.has),
|
||||
hasAll: (...slugs) => slugs.every(context.has),
|
||||
};
|
||||
|
||||
describe("reconcilePreferences", () => {
|
||||
it("drops unknown and unauthorized IDs before returning preferences", () => {
|
||||
const stored = {
|
||||
...defaultHousekeepingPreferences(),
|
||||
pinnedRouteIds: ["removed.route", "people.bans", "people.users"],
|
||||
pinnedCommandIds: ["removed.command"],
|
||||
shortcutOrder: [
|
||||
"removed.route",
|
||||
"people.bans",
|
||||
"people.tickets",
|
||||
"people.users",
|
||||
],
|
||||
widgetOrder: ["removed.widget", "people.bans", "people.queue"],
|
||||
enabledOptionalWidgetIds: [
|
||||
"removed.widget",
|
||||
"people.bans",
|
||||
"people.queue",
|
||||
],
|
||||
};
|
||||
|
||||
expect(reconcilePreferences(stored, registry, context)).toEqual({
|
||||
...defaultHousekeepingPreferences(),
|
||||
pinnedRouteIds: ["people.users"],
|
||||
shortcutOrder: ["people.tickets", "people.users"],
|
||||
widgetOrder: ["people.queue", "people.summary"],
|
||||
enabledOptionalWidgetIds: ["people.queue"],
|
||||
});
|
||||
});
|
||||
|
||||
it("retains mandatory widgets and preserves the relative order of valid entries", () => {
|
||||
const stored = {
|
||||
...defaultHousekeepingPreferences(),
|
||||
pinnedRouteIds: ["people.tickets", "people.users"],
|
||||
shortcutOrder: ["people.tickets", "people.users"],
|
||||
widgetOrder: ["people.queue"],
|
||||
};
|
||||
|
||||
expect(reconcilePreferences(stored, registry, context)).toMatchObject({
|
||||
pinnedRouteIds: ["people.tickets", "people.users"],
|
||||
shortcutOrder: ["people.tickets", "people.users"],
|
||||
widgetOrder: ["people.queue", "people.summary"],
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user