import { beforeEach, describe, expect, it, vi } from "vitest"; const gatewayRuntimeHoisted = vi.hoisted(() => ({ requestSpy: vi.fn(), withClientSpy: vi.fn(), })); vi.mock("openclaw/plugin-sdk/gateway-runtime", () => ({ withOperatorApprovalsGatewayClient: gatewayRuntimeHoisted.withClientSpy, })); describe("resolveTelegramExecApproval", () => { beforeEach(() => { gatewayRuntimeHoisted.requestSpy.mockReset(); gatewayRuntimeHoisted.withClientSpy.mockReset().mockImplementation(async (_params, run) => { await run({ request: gatewayRuntimeHoisted.requestSpy, } as never); }); }); it("routes plugin approval ids through plugin.approval.resolve", async () => { const { resolveTelegramExecApproval } = await import("./exec-approval-resolver.js"); await resolveTelegramExecApproval({ cfg: {} as never, approvalId: "plugin:abc123", decision: "allow-once", senderId: "9", }); expect(gatewayRuntimeHoisted.requestSpy).toHaveBeenCalledWith("plugin.approval.resolve", { id: "plugin:abc123", decision: "allow-once", }); }); it("falls back to plugin.approval.resolve when exec approval ids are unknown", async () => { gatewayRuntimeHoisted.requestSpy .mockRejectedValueOnce(new Error("unknown or expired approval id")) .mockResolvedValueOnce(undefined); const { resolveTelegramExecApproval } = await import("./exec-approval-resolver.js"); await resolveTelegramExecApproval({ cfg: {} as never, approvalId: "legacy-plugin-123", decision: "allow-always", senderId: "9", allowPluginFallback: true, }); expect(gatewayRuntimeHoisted.requestSpy).toHaveBeenNthCalledWith(1, "exec.approval.resolve", { id: "legacy-plugin-123", decision: "allow-always", }); expect(gatewayRuntimeHoisted.requestSpy).toHaveBeenNthCalledWith(2, "plugin.approval.resolve", { id: "legacy-plugin-123", decision: "allow-always", }); }); it("falls back to plugin.approval.resolve for structured approval-not-found errors", async () => { const err = new Error("approval not found"); (err as Error & { gatewayCode?: string; details?: { reason?: string } }).gatewayCode = "INVALID_REQUEST"; (err as Error & { gatewayCode?: string; details?: { reason?: string } }).details = { reason: "APPROVAL_NOT_FOUND", }; gatewayRuntimeHoisted.requestSpy.mockRejectedValueOnce(err).mockResolvedValueOnce(undefined); const { resolveTelegramExecApproval } = await import("./exec-approval-resolver.js"); await resolveTelegramExecApproval({ cfg: {} as never, approvalId: "legacy-plugin-123", decision: "allow-always", senderId: "9", allowPluginFallback: true, }); expect(gatewayRuntimeHoisted.requestSpy).toHaveBeenNthCalledWith(1, "exec.approval.resolve", { id: "legacy-plugin-123", decision: "allow-always", }); expect(gatewayRuntimeHoisted.requestSpy).toHaveBeenNthCalledWith(2, "plugin.approval.resolve", { id: "legacy-plugin-123", decision: "allow-always", }); }); it("does not fall back to plugin.approval.resolve without explicit permission", async () => { gatewayRuntimeHoisted.requestSpy.mockRejectedValueOnce( new Error("unknown or expired approval id"), ); const { resolveTelegramExecApproval } = await import("./exec-approval-resolver.js"); await expect( resolveTelegramExecApproval({ cfg: {} as never, approvalId: "legacy-plugin-123", decision: "allow-always", senderId: "9", }), ).rejects.toThrow("unknown or expired approval id"); expect(gatewayRuntimeHoisted.requestSpy).toHaveBeenCalledTimes(1); expect(gatewayRuntimeHoisted.requestSpy).toHaveBeenCalledWith("exec.approval.resolve", { id: "legacy-plugin-123", decision: "allow-always", }); }); });