Files

106 lines
4.0 KiB
TypeScript

// The approval queue's markup: the EXACT stored proposed arguments are rendered (never a
// narration), the Art. 50 disclosure rides with them, and the controls are named for a keyboard.
import { buildRegistry } from "@conusai-kit/core"
import { createI18n } from "@conusai-kit/i18n"
import { TransportProvider } from "@conusai-kit/ui"
import { renderToStaticMarkup } from "react-dom/server"
import { describe, expect, it } from "vitest"
import { appModules } from "../../index.js"
import type { ApprovalView } from "../contract/index.js"
import { ApprovalQueue } from "../ui/approval-queue.js"
import { RunControls } from "../ui/run-controls.js"
const catalogues = buildRegistry([...appModules]).catalogues
const i18n = createI18n("en", { en: { agent: catalogues.en?.agent ?? {} } })
const t = (key: string, values?: Record<string, string | number>) => i18n.message(`agent.${key}`, values)
const failed = "That did not work: {detail}"
const slugs = { org: "acme", workspace: "ws", project: "p" }
const inProvider = (node: React.ReactNode) =>
renderToStaticMarkup(
<TransportProvider call={async () => undefined} describe={() => "x"}>
{node}
</TransportProvider>,
)
const approval: ApprovalView = {
runId: "r1",
stepKey: "read",
goal: "Review the contract",
tool: "orders.create",
arguments: { total: 4200, currency: "EUR" },
reviewUrl: "https://console/tool-approvals?action=act-1",
createdAt: "2026-10-23T00:00:00.000Z",
}
const labels = {
heading: t("approvals.heading"),
empty: t("approvals.empty"),
proposed: t("approvals.proposed"),
review: t("approvals.review"),
approve: t("approvals.approve"),
reject: t("approvals.reject"),
decided: t("approvals.decided"),
disclosure: t("approvals.disclosure"),
failed,
}
describe("the approval queue", () => {
const html = inProvider(<ApprovalQueue slugs={slugs} approvals={[approval]} labels={labels} />)
it("renders the exact stored proposed arguments, pretty-printed, with the disclosure", () => {
// The exact stored arguments, HTML-escaped as any rendered text is.
expect(html).toContain("&quot;total&quot;: 4200")
expect(html).toContain("&quot;currency&quot;: &quot;EUR&quot;")
expect(html).toContain(t("approvals.disclosure"))
expect(html).toContain(t("approvals.proposed"))
})
it("names the decision controls and links the console review", () => {
expect(html).toContain(`>${t("approvals.approve")}<`)
expect(html).toContain(`>${t("approvals.reject")}<`)
expect(html).toContain('href="https://console/tool-approvals?action=act-1"')
})
it("announces an empty queue", () => {
const empty = inProvider(<ApprovalQueue slugs={slugs} approvals={[]} labels={labels} />)
expect(empty).toContain(t("approvals.empty"))
})
})
describe("the run controls", () => {
const labels = {
cancel: t("runs.cancel"),
cancelling: t("runs.cancelling"),
refresh: t("runs.refresh"),
failedHint: t("recovery.failedHint"),
cancelledHint: t("recovery.cancelledHint"),
uncertainHint: t("recovery.uncertainHint"),
budgetExhausted: t("recovery.budgetExhausted"),
approvalUnavailable: t("recovery.approvalUnavailable"),
toolError: t("recovery.toolError"),
planRefused: t("recovery.planRefused"),
internal: t("recovery.internal"),
}
it("offers cancel on an active run and recovery copy on an uncertain one", () => {
const active = inProvider(
<RunControls slugs={slugs} run={{ runId: "r1", status: "running", failureCode: null }} labels={labels} />,
)
expect(active).toContain(`>${t("runs.cancel")}<`)
const uncertain = inProvider(
<RunControls slugs={slugs} run={{ runId: "r1", status: "uncertain", failureCode: null }} labels={labels} />,
)
expect(uncertain).toContain(
t("recovery.uncertainHint")
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll(String.fromCharCode(34), "&quot;")
.replaceAll(String.fromCharCode(39), "&#x27;"),
)
expect(uncertain).not.toContain(`>${t("runs.cancel")}<`)
})
})