feat(housekeeping): add global command deck search
This commit is contained in:
1 parent
2e95a106e0
commit
bcb0ca977f
18 files changed
+1353
-23
No files matched your search
@@ -0,0 +1,124 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
CommandDeck,
|
||||
commandDeckKeyAction,
|
||||
flattenHousekeepingSearchResults,
|
||||
isCommandDeckShortcut,
|
||||
nextCommandDeckIndex,
|
||||
projectHousekeepingSearchHref,
|
||||
restoreCommandDeckFocus,
|
||||
} from "./command-deck";
|
||||
|
||||
vi.mock("@/actions/housekeeping-search", () => ({
|
||||
executeHousekeepingSearch: vi.fn(),
|
||||
}));
|
||||
|
||||
const labels = {
|
||||
trigger: "Search housekeeping",
|
||||
placeholder: "Search navigation, commands, and entities",
|
||||
navigation: "Navigation",
|
||||
commands: "Commands",
|
||||
entities: "Entities",
|
||||
loading: "Searching…",
|
||||
empty: "No results",
|
||||
partial: "Some providers are unavailable",
|
||||
close: "Close",
|
||||
};
|
||||
|
||||
describe("CommandDeck", () => {
|
||||
it("renders an enabled accessible cmdk trigger", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
<CommandDeck labels={labels} surface="preview" />,
|
||||
);
|
||||
expect(html).toContain("Search housekeeping");
|
||||
expect(html).toContain('aria-haspopup="dialog"');
|
||||
expect(html).not.toContain("disabled");
|
||||
expect(html).toContain("Ctrl+K");
|
||||
});
|
||||
|
||||
it("models shortcut, arrows, Enter, and Escape deterministically", () => {
|
||||
expect(
|
||||
isCommandDeckShortcut({ key: "k", ctrlKey: true, metaKey: false }),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isCommandDeckShortcut({ key: "K", ctrlKey: false, metaKey: true }),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isCommandDeckShortcut({
|
||||
key: "k",
|
||||
ctrlKey: true,
|
||||
metaKey: false,
|
||||
altKey: true,
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(commandDeckKeyAction("Escape", true)).toBe("close");
|
||||
expect(commandDeckKeyAction("ArrowDown", true)).toBe("next");
|
||||
expect(commandDeckKeyAction("ArrowUp", true)).toBe("previous");
|
||||
expect(commandDeckKeyAction("Enter", true)).toBe("activate");
|
||||
expect(commandDeckKeyAction("Enter", false)).toBe(null);
|
||||
expect(nextCommandDeckIndex(-1, 3, "next")).toBe(0);
|
||||
expect(nextCommandDeckIndex(2, 3, "next")).toBe(0);
|
||||
expect(nextCommandDeckIndex(0, 3, "previous")).toBe(2);
|
||||
});
|
||||
|
||||
it("restores trigger focus and projects canonical results to preview", () => {
|
||||
const focus = vi.fn();
|
||||
restoreCommandDeckFocus({ focus });
|
||||
expect(focus).toHaveBeenCalledOnce();
|
||||
expect(projectHousekeepingSearchHref("/ase/people/users", "preview")).toBe(
|
||||
"/ase-next/people/users",
|
||||
);
|
||||
expect(
|
||||
projectHousekeepingSearchHref("/ase/people/users", "canonical"),
|
||||
).toBe("/ase/people/users");
|
||||
});
|
||||
|
||||
it("keeps grouped result order and uses cmdk input/items in the client module", () => {
|
||||
const flattened = flattenHousekeepingSearchResults({
|
||||
navigation: [
|
||||
{
|
||||
id: "route:people.users",
|
||||
domain: "people",
|
||||
type: "navigation",
|
||||
title: "Users",
|
||||
href: "/ase/people/users",
|
||||
capability: { mode: "any", slugs: ["users.view"] },
|
||||
},
|
||||
],
|
||||
commands: [
|
||||
{
|
||||
id: "command:people.user.refresh",
|
||||
commandId: "people.user.refresh",
|
||||
domain: "people",
|
||||
type: "command",
|
||||
title: "User Refresh",
|
||||
href: "/ase/people",
|
||||
capability: { mode: "any", slugs: ["users.view"] },
|
||||
risk: "safe",
|
||||
requiresReason: false,
|
||||
},
|
||||
],
|
||||
entities: [],
|
||||
errors: [],
|
||||
correlationId: "deck",
|
||||
});
|
||||
expect(flattened.map((entry) => entry.group)).toEqual([
|
||||
"navigation",
|
||||
"commands",
|
||||
]);
|
||||
|
||||
const source = readFileSync(
|
||||
resolve(
|
||||
process.cwd(),
|
||||
"src/features/housekeeping/foundation/shell/command-deck.tsx",
|
||||
),
|
||||
"utf8",
|
||||
);
|
||||
expect(source).toContain("CommandInput");
|
||||
expect(source).toContain("CommandItem");
|
||||
expect(source).toContain("onSelect");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user