Files
openclaw/ui/src/components/exec-approval.test.ts
saju01 cbc84767bd fix(exec-approval): stop misattributing Allow Always unavailability to policy (#97740)
* fix(exec-approval): stop misattributing Allow Always unavailability to policy

Allow Always is dropped both when policy ask=always AND when a command is
non-persistable (e.g. shell redirect `2>&1` -> one-shot), but the prompt always
claimed 'effective approval policy requires approval every time'. That's
misleading for the non-persistable case (#97069). Reword to reason-neutral
'Allow Always is unavailable for this command.' across all approval surfaces,
update en + 20 locale bundles, refresh i18n meta, and the matching tests.

Closes #97069

* fix(exec-approval): stop misattributing Allow Always unavailability to policy

* test(ui): await exec approval render updates

* chore(ui): sync approval i18n metadata

---------

Co-authored-by: saju01 <saju01@users.noreply.github.com>
Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
2026-07-11 18:09:51 +08:00

108 lines
3.0 KiB
TypeScript

/* @vitest-environment jsdom */
import { html, nothing, render, type LitElement } from "lit";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { ExecApprovalRequest } from "../app/exec-approval.ts";
import { i18n } from "../i18n/index.ts";
import { getRenderedModalDialog, installDialogPolyfill } from "../test-helpers/modal-dialog.ts";
import "./exec-approval.ts";
let container: HTMLDivElement;
let restoreDialogPolyfill: () => void;
function createExecRequest(overrides: Partial<ExecApprovalRequest> = {}): ExecApprovalRequest {
return {
id: "approval-1",
kind: "exec",
request: {
command: "echo hello",
ask: "on-request",
},
createdAtMs: Date.now() - 1_000,
expiresAtMs: Date.now() + 60_000,
...overrides,
};
}
async function renderApproval(request: ExecApprovalRequest) {
render(
html`<openclaw-exec-approval
.props=${{
queue: [request],
busy: false,
error: null,
onDecision: vi.fn(),
}}
></openclaw-exec-approval>`,
container,
);
const approval = container.querySelector<LitElement>("openclaw-exec-approval");
if (!approval) {
throw new Error("Expected exec approval");
}
await approval.updateComplete;
}
describe("openclaw-exec-approval", () => {
beforeEach(async () => {
restoreDialogPolyfill = installDialogPolyfill();
await i18n.setLocale("en");
container = document.createElement("div");
document.body.append(container);
});
afterEach(async () => {
render(nothing, container);
container.remove();
await i18n.setLocale("en");
restoreDialogPolyfill();
vi.restoreAllMocks();
});
it("uses neutral unavailable copy for exec allow-always decisions", async () => {
await renderApproval(
createExecRequest({
request: {
command: "echo hello",
ask: "always",
allowedDecisions: ["allow-once", "deny"],
},
}),
);
await getRenderedModalDialog(container);
expect(
Array.from(container.querySelectorAll(".exec-approval-actions button")).map((button) =>
button.textContent?.trim(),
),
).toEqual(["Allow once", "Deny"]);
expect(container.querySelector(".exec-approval-warning")?.textContent?.trim()).toBe(
"Allow Always is unavailable for this command.",
);
});
it("does not show exec unavailable copy for restricted plugin approvals", async () => {
await renderApproval(
createExecRequest({
id: "plugin-approval-1",
kind: "plugin",
request: {
command: "Plugin approval",
allowedDecisions: ["allow-once", "deny"],
},
pluginTitle: "Plugin approval",
}),
);
await getRenderedModalDialog(container);
expect(
Array.from(container.querySelectorAll(".exec-approval-actions button")).map((button) =>
button.textContent?.trim(),
),
).toEqual(["Allow once", "Deny"]);
expect(container.querySelector(".exec-approval-warning")).toBeNull();
});
});