Files
openclaw/extensions/slack/src/approval-handler.enterprise.test.ts
Sarah Fortune a968d15f63 feat(slack): enable Enterprise Grid identity, DMs, routing, actions, approvals, and presence (#121373)
* refactor(slack): detect Enterprise Grid installs at runtime

* fix(slack): preserve enterprise bot identity

* style(slack): format enterprise identity test

* fix(slack): scope enterprise config by workspace

* fix(slack): preserve qualified binding casing

* feat(slack): enable enterprise presence polling

* fix(slack): normalize enterprise binding accounts

* fix(slack): require workspace-scoped Grid targets

* docs(slack): document Enterprise policy target forms

* fix(slack): preserve Grid pairing workspace scope

* refactor(slack): simplify scoped target formatting

* fix(slack): repair Enterprise Grid CI checks

* chore: refresh generated Slack metadata

* refactor(slack): simplify optional workspace scope

* test(slack): infer installation state handle types

* chore: resolve plugin SDK baseline conflict

* fix(ci): regenerate plugin SDK API baseline on Linux

* fix(slack): allow standalone workspace sends

---------

Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>
2026-08-10 07:10:06 +00:00

167 lines
4.6 KiB
TypeScript

// Slack tests cover Enterprise Grid native approval delivery behavior.
import { beforeEach, describe, expect, it, vi } from "vitest";
const sendMessageSlackMock = vi.hoisted(() => vi.fn());
vi.mock("./send.js", () => ({
sendMessageSlack: sendMessageSlackMock,
}));
const { slackApprovalNativeRuntime } = await import("./approval-handler.runtime.js");
describe("Slack Enterprise Grid approval delivery", () => {
beforeEach(() => {
sendMessageSlackMock.mockReset().mockResolvedValue({
channelId: "C123",
messageId: "1712345678.123456",
});
});
it("prepares a qualified target without losing its team", async () => {
await expect(
slackApprovalNativeRuntime.transport.prepareTarget({
plannedTarget: {
surface: "origin",
reason: "preferred",
target: {
to: "team:T123:channel:C123",
threadId: "1712345678.000001",
},
},
} as never),
).resolves.toEqual({
dedupeKey: expect.any(String),
target: {
to: "channel:C123",
teamId: "T123",
threadTs: "1712345678.000001",
},
});
});
it("uses the team client without requiring an Enterprise app id", async () => {
const chatUpdate = vi.fn().mockResolvedValue({ ok: true });
const teamClient = {
chat: { update: chatUpdate },
conversations: { open: vi.fn() },
};
const resolveClient = vi.fn().mockReturnValue(teamClient);
const context = {
app: { client: { chat: { update: vi.fn() } } },
config: {},
enterprise: { enterpriseId: "E123" },
resolveClient,
};
const entry = await slackApprovalNativeRuntime.transport.deliverPending({
cfg: {
channels: {
slack: {
botToken: "xoxb-test",
appToken: "xapp-test",
},
},
},
accountId: "default",
context,
preparedTarget: {
to: "channel:C123",
teamId: "T123",
},
pendingPayload: { text: "approve", blocks: [] },
} as never);
expect(entry).toEqual({
channelId: "C123",
messageTs: "1712345678.123456",
teamId: "T123",
});
expect(resolveClient).toHaveBeenCalledWith("T123");
expect(sendMessageSlackMock).toHaveBeenCalledWith(
"channel:C123",
"approve",
expect.objectContaining({
client: teamClient,
eventScope: {
teamId: "T123",
client: teamClient,
},
}),
);
await slackApprovalNativeRuntime.transport.updateEntry?.({
cfg: {} as never,
accountId: "default",
context,
entry,
payload: { text: "approved", blocks: [] },
phase: "resolved",
} as never);
expect(resolveClient).toHaveBeenLastCalledWith("T123");
expect(chatUpdate).toHaveBeenCalledWith({
channel: "C123",
ts: "1712345678.123456",
text: "approved",
blocks: [],
});
});
it.each([
["missing", undefined],
["unusable", () => undefined],
])("fails closed when the workspace client resolver is %s", async (_name, resolveClient) => {
await expect(
slackApprovalNativeRuntime.transport.deliverPending({
cfg: {} as never,
accountId: "default",
context: {
app: { client: {} },
config: {},
enterprise: { enterpriseId: "E123" },
...(resolveClient ? { resolveClient } : {}),
},
preparedTarget: {
to: "channel:C123",
teamId: "T123",
},
pendingPayload: { text: "approve", blocks: [] },
} as never),
).rejects.toThrow("Slack Enterprise Grid approval client is unavailable");
expect(sendMessageSlackMock).not.toHaveBeenCalled();
});
it("opens an approver DM with the same team client", async () => {
const open = vi.fn().mockResolvedValue({ channel: { id: "D123" } });
const teamClient = {
chat: { update: vi.fn() },
conversations: { open },
};
await slackApprovalNativeRuntime.transport.deliverPending({
cfg: {} as never,
accountId: "default",
context: {
app: { client: {} },
config: {},
enterprise: { enterpriseId: "E123" },
resolveClient: () => teamClient,
},
preparedTarget: {
to: "user:U123",
teamId: "T123",
},
pendingPayload: { text: "approve", blocks: [] },
} as never);
expect(open).toHaveBeenCalledWith({ users: "U123", return_im: true });
expect(sendMessageSlackMock).toHaveBeenCalledWith(
"channel:D123",
"approve",
expect.objectContaining({
eventScope: expect.objectContaining({ teamId: "T123" }),
}),
);
});
});