feat(housekeeping): compose operational inbox
This commit is contained in:
1 parent
bcb0ca977f
commit
300ac0ef95
13 files changed
+1594
-7
No files matched your search
@@ -0,0 +1,128 @@
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { anyCapability, type HousekeepingWorkItem } from "../contracts";
|
||||
import {
|
||||
filterOperationalInboxItems,
|
||||
OperationalInbox,
|
||||
projectOperationalInboxHref,
|
||||
} from "./operational-inbox";
|
||||
|
||||
const labels = {
|
||||
title: "Operational inbox",
|
||||
domainFilter: "Filter by domain",
|
||||
stateFilter: "Filter by state",
|
||||
priorityFilter: "Filter by priority",
|
||||
all: "All",
|
||||
loading: "Loading operational work",
|
||||
empty: "No operational work",
|
||||
partial: "Some sources are unavailable",
|
||||
open: "Open workflow",
|
||||
};
|
||||
|
||||
function item(
|
||||
itemId: string,
|
||||
options: Partial<HousekeepingWorkItem> = {},
|
||||
): HousekeepingWorkItem {
|
||||
return {
|
||||
sourceId: "people.queue",
|
||||
itemId,
|
||||
deduplicationKey: `people.queue:${itemId}`,
|
||||
domain: "people",
|
||||
capability: anyCapability("admin.users.view"),
|
||||
severity: "warning",
|
||||
priority: "high",
|
||||
ageMs: 1_000,
|
||||
state: "open",
|
||||
occurredAt: "2026-08-30T10:00:00.000Z",
|
||||
titleKey: `Item ${itemId}`,
|
||||
href: "/ase/people/users",
|
||||
freshness: "fresh",
|
||||
actions: [],
|
||||
...options,
|
||||
};
|
||||
}
|
||||
|
||||
describe("OperationalInbox", () => {
|
||||
it("filters deterministically by domain, state, and priority", () => {
|
||||
const items = [
|
||||
item("people-open"),
|
||||
item("content-draft", {
|
||||
domain: "content",
|
||||
state: "draft",
|
||||
priority: "normal",
|
||||
href: "/ase/content/editorial/articles",
|
||||
}),
|
||||
];
|
||||
expect(
|
||||
filterOperationalInboxItems(items, {
|
||||
domain: "people",
|
||||
state: "open",
|
||||
priority: "high",
|
||||
}).map((entry) => entry.itemId),
|
||||
).toEqual(["people-open"]);
|
||||
expect(
|
||||
filterOperationalInboxItems(items, {
|
||||
domain: "all",
|
||||
state: "draft",
|
||||
priority: "all",
|
||||
}).map((entry) => entry.itemId),
|
||||
).toEqual(["content-draft"]);
|
||||
});
|
||||
|
||||
it("renders accessible filters, partial errors, and preview links", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<OperationalInbox
|
||||
labels={labels}
|
||||
surface="preview"
|
||||
response={{
|
||||
items: [item("ticket-1")],
|
||||
errors: [{ sourceId: "content.publication", code: "TIMEOUT" }],
|
||||
correlationId: "inbox-ui",
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
expect(html).toContain('aria-label="Filter by domain"');
|
||||
expect(html).toContain('aria-label="Filter by state"');
|
||||
expect(html).toContain('aria-label="Filter by priority"');
|
||||
expect(html).toContain("Some sources are unavailable");
|
||||
expect(html).toContain("content.publication");
|
||||
expect(html).toContain('href="/ase-next/people/users"');
|
||||
expect(html).not.toContain("Dismiss");
|
||||
expect(html).not.toContain("Assign");
|
||||
});
|
||||
|
||||
it("renders explicit loading and empty states", () => {
|
||||
const response = {
|
||||
items: [],
|
||||
errors: [],
|
||||
correlationId: "inbox-empty",
|
||||
} as const;
|
||||
const loading = renderToStaticMarkup(
|
||||
<OperationalInbox
|
||||
labels={labels}
|
||||
surface="preview"
|
||||
response={response}
|
||||
loading
|
||||
/>,
|
||||
);
|
||||
const empty = renderToStaticMarkup(
|
||||
<OperationalInbox
|
||||
labels={labels}
|
||||
surface="preview"
|
||||
response={response}
|
||||
/>,
|
||||
);
|
||||
expect(loading).toContain('role="status"');
|
||||
expect(loading).toContain("Loading operational work");
|
||||
expect(empty).toContain("No operational work");
|
||||
});
|
||||
|
||||
it("projects canonical hrefs without changing production destinations", () => {
|
||||
expect(
|
||||
projectOperationalInboxHref("/ase/system/operations/alerts", "preview"),
|
||||
).toBe("/ase-next/system/operations/alerts");
|
||||
expect(
|
||||
projectOperationalInboxHref("/ase/system/operations/alerts", "canonical"),
|
||||
).toBe("/ase/system/operations/alerts");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user