75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import { PERMS } from "@/lib/permission-slugs";
|
|
import type { HousekeepingCapabilityContext } from "../../foundation/contracts";
|
|
import { createHotelInboxSources } from "./inbox";
|
|
import { createHotelSearchProviders } from "./search";
|
|
import { createHotelWidgets } from "./widgets";
|
|
|
|
function context(granted: readonly string[]): HousekeepingCapabilityContext {
|
|
const permissions = new Set(granted);
|
|
return {
|
|
actor: { id: 42, username: "operator", rank: 7 },
|
|
isSuperAdmin: false,
|
|
has: (slug) => permissions.has(slug),
|
|
hasAny: (...slugs) => slugs.some((slug) => permissions.has(slug)),
|
|
hasAll: (...slugs) => slugs.every((slug) => permissions.has(slug)),
|
|
};
|
|
}
|
|
|
|
describe("Hotel Studio providers", () => {
|
|
it("publishes searchable Studio operations with capability filtering", async () => {
|
|
const [provider] = createHotelSearchProviders({
|
|
studio: vi.fn(async () => [
|
|
{
|
|
id: "op-1",
|
|
title: "Furniture import",
|
|
description: "running",
|
|
href: "/ase-next/hotel/studio/furni",
|
|
},
|
|
]),
|
|
});
|
|
const result = await provider.search(context([PERMS.ASSETS_IMPORT]), {
|
|
term: " furni ",
|
|
limit: 50,
|
|
});
|
|
expect(result).toMatchObject({
|
|
ok: true,
|
|
data: [{ id: "op-1", domain: "hotel" }],
|
|
});
|
|
});
|
|
|
|
it("exposes an operational inbox source and mandatory active widget", async () => {
|
|
const operation = {
|
|
operationId: "op-1",
|
|
kind: "sync" as const,
|
|
phase: "failed" as const,
|
|
completed: 3,
|
|
total: 5,
|
|
messageKey: "errors.housekeeping.dependencyUnavailable",
|
|
correlationId: "corr-1",
|
|
actorId: 42,
|
|
createdAt: "2026-08-30T10:00:00.000Z",
|
|
updatedAt: "2026-08-30T10:01:00.000Z",
|
|
};
|
|
const [source] = createHotelInboxSources({
|
|
operations: vi.fn(async () => [operation]),
|
|
});
|
|
const [widget] = createHotelWidgets({
|
|
activeOperations: vi.fn(async () => ({ running: 2, failed: 1 })),
|
|
});
|
|
expect(widget.kind).toBe("mandatory");
|
|
expect(
|
|
await source.getItems(
|
|
context([PERMS.ASSETS_IMPORT]),
|
|
new AbortController().signal,
|
|
),
|
|
).toMatchObject({ ok: true, data: { items: [{ state: "failed" }] } });
|
|
expect(
|
|
await widget.load(
|
|
context([PERMS.ASSETS_IMPORT]),
|
|
new AbortController().signal,
|
|
),
|
|
).toMatchObject({ ok: true, data: { running: 2, failed: 1 } });
|
|
});
|
|
});
|