feat(housekeeping): compose operations workspace
This commit is contained in:
1 parent
5574e601bb
commit
85ad0452d3
22 files changed
+1240
-87
No files matched your search
@@ -0,0 +1,118 @@
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { PERMS } from "@/lib/permission-slugs";
|
||||
import {
|
||||
anyCapability,
|
||||
type HousekeepingRouteDefinition,
|
||||
type HousekeepingWidgetDefinition,
|
||||
ok,
|
||||
} from "../../../foundation/contracts";
|
||||
import { defaultHousekeepingPreferences } from "../../../foundation/preferences/schema";
|
||||
import type { OperationsWorkspaceLoadResult } from "../queries";
|
||||
import { OperationsWorkspacePage } from "./workspace";
|
||||
|
||||
const capability = anyCapability(PERMS.USERS_VIEW);
|
||||
const routes: readonly HousekeepingRouteDefinition[] = [
|
||||
{
|
||||
id: "people.users",
|
||||
labelKey: "Users",
|
||||
href: "/ase/people/users",
|
||||
capability,
|
||||
},
|
||||
];
|
||||
const widgets: readonly HousekeepingWidgetDefinition[] = [
|
||||
{
|
||||
id: "people.queue",
|
||||
owner: "people",
|
||||
capability,
|
||||
kind: "mandatory",
|
||||
load: async () => ok({}, "widget"),
|
||||
},
|
||||
];
|
||||
const preferences = {
|
||||
...defaultHousekeepingPreferences(),
|
||||
pinnedRouteIds: ["people.users"],
|
||||
shortcutOrder: ["people.users"],
|
||||
widgetOrder: ["people.queue"],
|
||||
};
|
||||
const result: OperationsWorkspaceLoadResult = {
|
||||
model: {
|
||||
inbox: {
|
||||
items: [
|
||||
{
|
||||
sourceId: "people.queue",
|
||||
itemId: "ticket-1",
|
||||
deduplicationKey: "people.queue:ticket-1",
|
||||
domain: "people",
|
||||
capability,
|
||||
severity: "warning",
|
||||
priority: "high",
|
||||
ageMs: 1_000,
|
||||
state: "open",
|
||||
occurredAt: "2026-08-30T10:00:00.000Z",
|
||||
titleKey: "Ticket",
|
||||
href: "/ase/people/users",
|
||||
freshness: "fresh",
|
||||
actions: [],
|
||||
},
|
||||
],
|
||||
errors: [{ sourceId: "system.alerts", code: "TIMEOUT" }],
|
||||
correlationId: "inbox",
|
||||
},
|
||||
recent: [
|
||||
{
|
||||
routeId: "people.users",
|
||||
canonicalHref: "/ase/people/users",
|
||||
labelKey: "Users",
|
||||
occurredAt: "2026-08-30T09:00:00.000Z",
|
||||
source: "route-visit",
|
||||
},
|
||||
],
|
||||
favorites: preferences,
|
||||
widgets: {
|
||||
widgets: [{ id: "people.queue", data: { count: 1 } }],
|
||||
errors: [{ widgetId: "system.health", code: "TIMEOUT" }],
|
||||
},
|
||||
},
|
||||
errors: [{ section: "recent", code: "DEPENDENCY_UNAVAILABLE" }],
|
||||
correlationId: "workspace",
|
||||
};
|
||||
|
||||
const savePreferences = vi.fn(async (value) => ok(value, "saved"));
|
||||
|
||||
describe("OperationsWorkspacePage", () => {
|
||||
it("renders capability-filtered sections, partial failures, and preview links", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<OperationsWorkspacePage
|
||||
result={result}
|
||||
routes={routes}
|
||||
widgetDefinitions={widgets}
|
||||
surface="preview"
|
||||
savePreferences={savePreferences}
|
||||
/>,
|
||||
);
|
||||
expect(html).toContain("Operations workspace");
|
||||
expect(html).toContain("Operational inbox");
|
||||
expect(html).toContain("Recent work");
|
||||
expect(html).toContain("Favorites");
|
||||
expect(html).toContain("Widget settings");
|
||||
expect(html).toContain("Some workspace sections are unavailable");
|
||||
expect(html).toContain("system.alerts");
|
||||
expect(html).toContain("system.health");
|
||||
expect(html).toContain('href="/ase-next/people/users"');
|
||||
});
|
||||
|
||||
it("renders an explicit state when no operational domain is accessible", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<OperationsWorkspacePage
|
||||
result={result}
|
||||
routes={[]}
|
||||
widgetDefinitions={[]}
|
||||
surface="preview"
|
||||
savePreferences={savePreferences}
|
||||
/>,
|
||||
);
|
||||
expect(html).toContain("No operational domains are available");
|
||||
expect(html).not.toContain("Operational inbox");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user