Files
moltbot/extensions/slack/src/errors.test.ts
Peter Steinberger 909ab191a7 fix(slack): include api error details
Rewrite #53966 on current main, preserving Slack SDK structured fields while routing the final text through OpenClaw redaction.

Co-authored-by: Dennis Maskevich <dennis.maskevich@gmail.com>
2026-05-10 19:03:59 +01:00

78 lines
2.8 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { formatSlackError } from "./errors.js";
describe("formatSlackError", () => {
it("formats missing and unserializable values with fallback text", () => {
const circular: Record<string, unknown> = {};
circular.self = circular;
expect(formatSlackError(undefined)).toBe("no error detail");
expect(formatSlackError(null)).toBe("no error detail");
expect(formatSlackError("")).toBe("no error detail");
expect(formatSlackError(new Error(""))).toBe("Error");
expect(formatSlackError(circular)).toBe('{"self":"[Circular]"}');
});
it("includes Slack platform error fields and response metadata", () => {
const err = Object.assign(new Error("An API error occurred: missing_scope"), {
code: "slack_webapi_platform_error",
data: {
error: "missing_scope",
needed: "channels:write",
provided: "chat:write,app_mentions:read",
response_metadata: {
scopes: ["chat:write", "app_mentions:read"],
acceptedScopes: ["channels:write", "groups:write"],
messages: ["[ERROR] missing required scope"],
},
},
});
expect(formatSlackError(err)).toBe(
"An API error occurred: missing_scope; code: slack_webapi_platform_error; slack error: missing_scope; needed: channels:write; provided: chat:write,app_mentions:read; scopes: chat:write, app_mentions:read; accepted: channels:write, groups:write; slack message: [ERROR] missing required scope",
);
});
it("uses the Slack SDK top-level retryAfter field for rate limit errors", () => {
const err = Object.assign(new Error("rate limited"), {
code: "slack_webapi_rate_limited_error",
retryAfter: 30,
});
expect(formatSlackError(err)).toBe(
"rate limited; code: slack_webapi_rate_limited_error; retryAfter: 30",
);
});
it("includes HTTP status details", () => {
const err = Object.assign(new Error("http failed"), {
code: "slack_webapi_http_error",
statusCode: 429,
statusMessage: "Too Many Requests",
body: "slow down",
});
expect(formatSlackError(err)).toBe(
"http failed; code: slack_webapi_http_error; statusCode: 429; statusMessage: Too Many Requests; body: slow down",
);
});
it("redacts token-shaped values before returning", () => {
const token = "xoxb-1234567890abcdef";
const err = Object.assign(new Error(`Authorization: Bearer ${token}`), {
code: "slack_webapi_platform_error",
data: {
error: "missing_scope",
response_metadata: {
messages: [`token ${token} lacked scope`],
},
},
});
const formatted = formatSlackError(err);
expect(formatted).not.toContain(token);
expect(formatted).toContain("Authorization: Bearer xoxb-1…cdef");
expect(formatted).toContain("token xoxb-1…cdef lacked scope");
});
});