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,54 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { HousekeepingCapabilityContext } from "@/features/housekeeping/foundation/contracts";
|
||||
import { PERMS } from "@/lib/permission-slugs";
|
||||
|
||||
const { getContextMock, searchMock } = vi.hoisted(() => ({
|
||||
getContextMock: vi.fn(),
|
||||
searchMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/features/housekeeping/foundation/server-capability-context", () => ({
|
||||
getHousekeepingCapabilityContext: getContextMock,
|
||||
}));
|
||||
|
||||
vi.mock("@/features/housekeeping/foundation/search/search-service", () => ({
|
||||
searchHousekeeping: searchMock,
|
||||
}));
|
||||
|
||||
import { executeHousekeepingSearch } from "./housekeeping-search";
|
||||
|
||||
const context: HousekeepingCapabilityContext = {
|
||||
actor: { id: 42, username: "operator", rank: 7 },
|
||||
isSuperAdmin: false,
|
||||
has: (slug) => slug === PERMS.USERS_VIEW,
|
||||
hasAny: (...slugs) => slugs.includes(PERMS.USERS_VIEW),
|
||||
hasAll: (...slugs) => slugs.every((slug) => slug === PERMS.USERS_VIEW),
|
||||
};
|
||||
|
||||
describe("housekeeping search action", () => {
|
||||
beforeEach(() => {
|
||||
getContextMock.mockReset().mockResolvedValue(context);
|
||||
searchMock.mockReset().mockResolvedValue({
|
||||
navigation: [],
|
||||
commands: [],
|
||||
entities: [],
|
||||
errors: [],
|
||||
correlationId: "action-search",
|
||||
});
|
||||
});
|
||||
|
||||
it("binds search to the fresh server capability context", async () => {
|
||||
const result = await executeHousekeepingSearch(" users ");
|
||||
expect(searchMock).toHaveBeenCalledWith(" users ", context);
|
||||
expect(result.correlationId).toBe("action-search");
|
||||
});
|
||||
|
||||
it("rejects forged non-string terms without invoking dependencies", async () => {
|
||||
const result = await executeHousekeepingSearch({ term: "users" });
|
||||
expect(getContextMock).not.toHaveBeenCalled();
|
||||
expect(searchMock).not.toHaveBeenCalled();
|
||||
expect(result).toMatchObject({
|
||||
errors: [{ providerId: "search", code: "VALIDATION" }],
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
"use server";
|
||||
|
||||
import type { HousekeepingErrorCode } from "@/features/housekeeping/foundation/contracts";
|
||||
import { createCorrelationId } from "@/features/housekeeping/foundation/correlation";
|
||||
import {
|
||||
type HousekeepingSearchResponse,
|
||||
searchHousekeeping,
|
||||
} from "@/features/housekeeping/foundation/search/search-service";
|
||||
import { getHousekeepingCapabilityContext } from "@/features/housekeeping/foundation/server-capability-context";
|
||||
|
||||
function failedSearch(code: HousekeepingErrorCode): HousekeepingSearchResponse {
|
||||
return {
|
||||
navigation: [],
|
||||
commands: [],
|
||||
entities: [],
|
||||
errors: [{ providerId: "search", code }],
|
||||
correlationId: createCorrelationId(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function executeHousekeepingSearch(
|
||||
term: unknown,
|
||||
): Promise<HousekeepingSearchResponse> {
|
||||
if (typeof term !== "string") return failedSearch("VALIDATION");
|
||||
try {
|
||||
const context = await getHousekeepingCapabilityContext();
|
||||
return await searchHousekeeping(term, context);
|
||||
} catch {
|
||||
return failedSearch("INTERNAL");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user