Files
openwork/apps/app/tests/permission-approval-modal.test.ts

101 lines
3.2 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import { DomUtils, parseDocument } from "htmlparser2";
import React from "react";
import { renderToStaticMarkup } from "react-dom/server";
import type { PendingPermission } from "../src/app/types";
import {
PermissionApprovalPanel,
permissionDetailRows,
} from "../src/react-app/domains/session/chat/permission-approval-modal";
function pendingPermission(overrides: Partial<PendingPermission> = {}): PendingPermission {
return {
id: "permission-1",
sessionID: "session-1",
permission: "bash",
patterns: ["rm -rf dist"],
metadata: {},
always: {
session: false,
project: false,
},
receivedAt: 1,
protocol: "legacy",
...overrides,
};
}
function buttonText(markup: string): string[] {
const document = parseDocument(markup);
return DomUtils.findAll((element) => element.name === "button", document.children)
.map((button) => DomUtils.textContent(button).replace(/\s+/g, " ").trim());
}
describe("permission approval modal helpers", () => {
test("surfaces risk-bearing metadata as review rows", () => {
expect(
permissionDetailRows({
command: "rm -rf dist",
description: "Remove build output",
cwd: "/workspace/project",
filepath: "/workspace/project/src/app.ts",
diff: "-old\n+new",
output: "not shown before approval",
}).map((row) => [row.label, row.value]),
).toEqual([
["Command", "rm -rf dist"],
["Description", "Remove build output"],
["Working directory", "/workspace/project"],
["File", "/workspace/project/src/app.ts"],
["Diff", "-old\n+new"],
]);
});
test("deduplicates alternate file metadata keys", () => {
expect(
permissionDetailRows({
filepath: "/workspace/project/a.ts",
filePath: "/workspace/project/b.ts",
}).map((row) => [row.label, row.value]),
).toEqual([["File", "/workspace/project/a.ts"]]);
});
test("summarizes apply-patch file metadata", () => {
expect(
permissionDetailRows({
files: [
{ type: "add", relativePath: "src/new.ts" },
{ type: "delete", filePath: "/workspace/project/src/old.ts" },
{ type: "", path: "src/update.ts" },
],
}).map((row) => [row.label, row.value]),
).toEqual([
["Files", "add: src/new.ts\ndelete: /workspace/project/src/old.ts\nchange: src/update.ts"],
]);
});
test("keeps keyboard order on the safer one-shot approval before session approval", () => {
const html = renderToStaticMarkup(
React.createElement(PermissionApprovalPanel, {
permission: pendingPermission(),
respondPermission: () => {},
}),
);
expect(buttonText(html)).toEqual(["Deny", "Allow once", "Allow for session"]);
});
test("uses readable labels for generic permission titles", () => {
const html = renderToStaticMarkup(
React.createElement(PermissionApprovalPanel, {
permission: pendingPermission({ permission: "todowrite" }),
respondPermission: () => {},
}),
);
expect(html).toContain("Approve Todo write?");
expect(html).not.toContain("Approve todowrite?");
});
});