Files
openclaw/extensions/telegram/src/approval-callback-data.test.ts
moguangyu5-design 0b140c3546 fix(telegram): rewrite allow-always alias for any whitespace separator (#104942)
* fix(telegram): rewrite allow-always alias for any whitespace separator

* fix(telegram): require absolute approval alias suffix

---------

Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-12 07:13:05 +01:00

135 lines
4.6 KiB
TypeScript

// Telegram tests cover approval callback data plugin behavior.
import { buildApprovalResolutionRef } from "openclaw/plugin-sdk/approval-reference-runtime";
import { describe, expect, it } from "vitest";
import {
buildTelegramApprovalCallbackData,
fitsTelegramCallbackData,
parseTelegramApprovalCallbackData,
rewriteTelegramApprovalDecisionAlias,
sanitizeTelegramCallbackData,
} from "./approval-callback-data.js";
describe("approval callback data", () => {
it("enforces Telegram callback byte boundaries", () => {
expect(fitsTelegramCallbackData("x".repeat(63))).toBe(true);
expect(fitsTelegramCallbackData("x".repeat(64))).toBe(true);
expect(fitsTelegramCallbackData("x".repeat(65))).toBe(false);
});
it("rewrites /approve allow-always callbacks to always", () => {
const approvalId = `plugin:${"a".repeat(36)}`;
expect(rewriteTelegramApprovalDecisionAlias(`/approve ${approvalId} allow-always`)).toBe(
`/approve ${approvalId} always`,
);
});
it("rewrites allow-always callbacks separated by any whitespace", () => {
const approvalId = `plugin:${"a".repeat(36)}`;
expect(rewriteTelegramApprovalDecisionAlias(`/approve\t${approvalId}\tallow-always`)).toBe(
`/approve\t${approvalId}\talways`,
);
});
it.each(["\n", "\r\n"])("does not corrupt callbacks ending in a line terminator", (ending) => {
const value = `/approve plugin:abc allow-always${ending}`;
expect(rewriteTelegramApprovalDecisionAlias(value)).toBe(value);
});
it("keeps rewritten allow-always callbacks when canonical form would overflow", () => {
const approvalId = `plugin:${"a".repeat(36)}`;
expect(sanitizeTelegramCallbackData(`/approve ${approvalId} allow-always`)).toBe(
`/approve ${approvalId} always`,
);
});
it("keeps 64-byte callbacks and drops 65-byte callbacks through sanitize", () => {
expect(sanitizeTelegramCallbackData("x".repeat(64))).toBe("x".repeat(64));
expect(sanitizeTelegramCallbackData("x".repeat(65))).toBeUndefined();
});
it.each([
["exec", "allow-once", "tga1:e:o:approval:with:delimiters"],
["exec", "allow-always", "tga1:e:a:approval:with:delimiters"],
["plugin", "deny", "tga1:p:d:approval:with:delimiters"],
] as const)("round-trips explicit %s %s actions", (approvalKind, decision, callbackData) => {
const action = {
type: "approval" as const,
approvalId: "approval:with:delimiters",
approvalKind,
decision,
};
expect(buildTelegramApprovalCallbackData(action)).toBe(callbackData);
expect(parseTelegramApprovalCallbackData(callbackData)).toEqual(action);
});
it("does not infer approval kind from id spelling", () => {
const callbackData = buildTelegramApprovalCallbackData({
type: "approval",
approvalId: "plugin:still-an-exec-id",
approvalKind: "exec",
decision: "deny",
});
expect(parseTelegramApprovalCallbackData(callbackData)).toEqual({
type: "approval",
approvalId: "plugin:still-an-exec-id",
approvalKind: "exec",
decision: "deny",
});
});
it("preserves unicode approval ids exactly", () => {
const action = {
type: "approval" as const,
approvalId: "approval/🦀/%/:",
approvalKind: "plugin" as const,
decision: "allow-once" as const,
};
const callbackData = buildTelegramApprovalCallbackData(action);
expect(parseTelegramApprovalCallbackData(callbackData)).toEqual(action);
});
it("uses the canonical id at the Unicode byte boundary and compacts beyond it", () => {
const exactId = "\u{1F4F1}".repeat(13);
const compactedId = "\u{1F4F1}".repeat(14);
expect(
buildTelegramApprovalCallbackData({
type: "approval",
approvalId: exactId,
approvalKind: "exec",
decision: "deny",
}),
).toBe(`tga1:e:d:${exactId}`);
const compacted = buildTelegramApprovalCallbackData({
type: "approval",
approvalId: compactedId,
approvalKind: "exec",
decision: "deny",
});
expect(compacted).toHaveLength(52);
expect(parseTelegramApprovalCallbackData(compacted)).toEqual({
type: "approval",
approvalId: buildApprovalResolutionRef({
approvalId: compactedId,
approvalKind: "exec",
}),
approvalKind: "exec",
decision: "deny",
});
});
it.each([
"tga2:e:o:approval-1",
"tga1:x:o:approval-1",
"tga1:e:x:approval-1",
"tga1:e:o:",
"tga1:e:o",
`tga1:e:o:${"x".repeat(56)}`,
])("rejects malformed private approval callback data: %s", (callbackData) => {
expect(parseTelegramApprovalCallbackData(callbackData)).toBeNull();
});
});