refactor(test): dedupe slack inbound contract prep

This commit is contained in:
Peter Steinberger
2026-02-14 20:21:17 +00:00
parent 8188fcb90d
commit 2f67564c93

View File

@@ -14,6 +14,67 @@ import { createSlackMonitorContext } from "../context.js";
import { prepareSlackMessage } from "./prepare.js";
describe("slack prepareSlackMessage inbound contract", () => {
function createDefaultSlackCtx() {
const slackCtx = createSlackMonitorContext({
cfg: {
channels: { slack: { enabled: true } },
} as OpenClawConfig,
accountId: "default",
botToken: "token",
app: { client: {} } as App,
runtime: {} as RuntimeEnv,
botUserId: "B1",
teamId: "T1",
apiAppId: "A1",
historyLimit: 0,
sessionScope: "per-sender",
mainKey: "main",
dmEnabled: true,
dmPolicy: "open",
allowFrom: [],
groupDmEnabled: true,
groupDmChannels: [],
defaultRequireMention: true,
groupPolicy: "open",
useAccessGroups: false,
reactionMode: "off",
reactionAllowlist: [],
replyToMode: "off",
threadHistoryScope: "thread",
threadInheritParent: false,
slashCommand: {
enabled: false,
name: "openclaw",
sessionPrefix: "slack:slash",
ephemeral: true,
},
textLimit: 4000,
ackReactionScope: "group-mentions",
mediaMaxBytes: 1024,
removeAckAfterReply: false,
});
// oxlint-disable-next-line typescript/no-explicit-any
slackCtx.resolveUserName = async () => ({ name: "Alice" }) as any;
return slackCtx;
}
const defaultAccount: ResolvedSlackAccount = {
accountId: "default",
enabled: true,
botTokenSource: "config",
appTokenSource: "config",
config: {},
};
async function prepareWithDefaultCtx(message: SlackMessageEvent) {
return prepareSlackMessage({
ctx: createDefaultSlackCtx(),
account: defaultAccount,
message,
opts: { source: "message" },
});
}
it("produces a finalized MsgContext", async () => {
const slackCtx = createSlackMonitorContext({
cfg: {
@@ -443,55 +504,6 @@ describe("slack prepareSlackMessage inbound contract", () => {
});
it("includes thread_ts and parent_user_id metadata in thread replies", async () => {
const slackCtx = createSlackMonitorContext({
cfg: {
channels: { slack: { enabled: true } },
} as OpenClawConfig,
accountId: "default",
botToken: "token",
app: { client: {} } as App,
runtime: {} as RuntimeEnv,
botUserId: "B1",
teamId: "T1",
apiAppId: "A1",
historyLimit: 0,
sessionScope: "per-sender",
mainKey: "main",
dmEnabled: true,
dmPolicy: "open",
allowFrom: [],
groupDmEnabled: true,
groupDmChannels: [],
defaultRequireMention: true,
groupPolicy: "open",
useAccessGroups: false,
reactionMode: "off",
reactionAllowlist: [],
replyToMode: "off",
threadHistoryScope: "thread",
threadInheritParent: false,
slashCommand: {
enabled: false,
name: "openclaw",
sessionPrefix: "slack:slash",
ephemeral: true,
},
textLimit: 4000,
ackReactionScope: "group-mentions",
mediaMaxBytes: 1024,
removeAckAfterReply: false,
});
// oxlint-disable-next-line typescript/no-explicit-any
slackCtx.resolveUserName = async () => ({ name: "Alice" }) as any;
const account: ResolvedSlackAccount = {
accountId: "default",
enabled: true,
botTokenSource: "config",
appTokenSource: "config",
config: {},
};
const message: SlackMessageEvent = {
channel: "D123",
channel_type: "im",
@@ -502,12 +514,7 @@ describe("slack prepareSlackMessage inbound contract", () => {
parent_user_id: "U2",
} as SlackMessageEvent;
const prepared = await prepareSlackMessage({
ctx: slackCtx,
account,
message,
opts: { source: "message" },
});
const prepared = await prepareWithDefaultCtx(message);
expect(prepared).toBeTruthy();
// Verify thread metadata is in the message footer
@@ -517,55 +524,6 @@ describe("slack prepareSlackMessage inbound contract", () => {
});
it("excludes thread_ts from top-level messages", async () => {
const slackCtx = createSlackMonitorContext({
cfg: {
channels: { slack: { enabled: true } },
} as OpenClawConfig,
accountId: "default",
botToken: "token",
app: { client: {} } as App,
runtime: {} as RuntimeEnv,
botUserId: "B1",
teamId: "T1",
apiAppId: "A1",
historyLimit: 0,
sessionScope: "per-sender",
mainKey: "main",
dmEnabled: true,
dmPolicy: "open",
allowFrom: [],
groupDmEnabled: true,
groupDmChannels: [],
defaultRequireMention: true,
groupPolicy: "open",
useAccessGroups: false,
reactionMode: "off",
reactionAllowlist: [],
replyToMode: "off",
threadHistoryScope: "thread",
threadInheritParent: false,
slashCommand: {
enabled: false,
name: "openclaw",
sessionPrefix: "slack:slash",
ephemeral: true,
},
textLimit: 4000,
ackReactionScope: "group-mentions",
mediaMaxBytes: 1024,
removeAckAfterReply: false,
});
// oxlint-disable-next-line typescript/no-explicit-any
slackCtx.resolveUserName = async () => ({ name: "Alice" }) as any;
const account: ResolvedSlackAccount = {
accountId: "default",
enabled: true,
botTokenSource: "config",
appTokenSource: "config",
config: {},
};
const message: SlackMessageEvent = {
channel: "D123",
channel_type: "im",
@@ -574,12 +532,7 @@ describe("slack prepareSlackMessage inbound contract", () => {
ts: "1.000",
} as SlackMessageEvent;
const prepared = await prepareSlackMessage({
ctx: slackCtx,
account,
message,
opts: { source: "message" },
});
const prepared = await prepareWithDefaultCtx(message);
expect(prepared).toBeTruthy();
// Top-level messages should NOT have thread_ts in the footer
@@ -588,55 +541,6 @@ describe("slack prepareSlackMessage inbound contract", () => {
});
it("excludes thread metadata when thread_ts equals ts without parent_user_id", async () => {
const slackCtx = createSlackMonitorContext({
cfg: {
channels: { slack: { enabled: true } },
} as OpenClawConfig,
accountId: "default",
botToken: "token",
app: { client: {} } as App,
runtime: {} as RuntimeEnv,
botUserId: "B1",
teamId: "T1",
apiAppId: "A1",
historyLimit: 0,
sessionScope: "per-sender",
mainKey: "main",
dmEnabled: true,
dmPolicy: "open",
allowFrom: [],
groupDmEnabled: true,
groupDmChannels: [],
defaultRequireMention: true,
groupPolicy: "open",
useAccessGroups: false,
reactionMode: "off",
reactionAllowlist: [],
replyToMode: "off",
threadHistoryScope: "thread",
threadInheritParent: false,
slashCommand: {
enabled: false,
name: "openclaw",
sessionPrefix: "slack:slash",
ephemeral: true,
},
textLimit: 4000,
ackReactionScope: "group-mentions",
mediaMaxBytes: 1024,
removeAckAfterReply: false,
});
// oxlint-disable-next-line typescript/no-explicit-any
slackCtx.resolveUserName = async () => ({ name: "Alice" }) as any;
const account: ResolvedSlackAccount = {
accountId: "default",
enabled: true,
botTokenSource: "config",
appTokenSource: "config",
config: {},
};
const message: SlackMessageEvent = {
channel: "D123",
channel_type: "im",
@@ -646,12 +550,7 @@ describe("slack prepareSlackMessage inbound contract", () => {
thread_ts: "1.000",
} as SlackMessageEvent;
const prepared = await prepareSlackMessage({
ctx: slackCtx,
account,
message,
opts: { source: "message" },
});
const prepared = await prepareWithDefaultCtx(message);
expect(prepared).toBeTruthy();
expect(prepared!.ctxPayload.Body).toMatch(/\[slack message id: 1\.000 channel: D123\]$/);