openclaw/extensions/discord/src/monitor/message-handler.preflight.acp-bindings.test.ts
scoootscooob 5682ec37fa
refactor: move Discord channel implementation to extensions/ (#45660)
* refactor: move Discord channel implementation to extensions/discord/src/

Move all Discord source files from src/discord/ to extensions/discord/src/,
following the extension migration pattern. Source files in src/discord/ are
replaced with re-export shims. Channel-plugin files from
src/channels/plugins/*/discord* are similarly moved and shimmed.

- Copy all .ts source files preserving subdirectory structure (monitor/, voice/)
- Move channel-plugin files (actions, normalize, onboarding, outbound, status-issues)
- Fix all relative imports to use correct paths from new location
- Create re-export shims at original locations for backward compatibility
- Delete test files from shim locations (tests live in extension now)
- Update tsconfig.plugin-sdk.dts.json rootDir from "src" to "." to accommodate
  extension files outside src/
- Update write-plugin-sdk-entry-dts.ts to match new declaration output paths

* fix: add importOriginal to thread-bindings session-meta mock for extensions test

* style: fix formatting in thread-bindings lifecycle test
2026-03-14 02:53:57 -07:00

152 lines
4.5 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
const ensureConfiguredAcpBindingSessionMock = vi.hoisted(() => vi.fn());
const resolveConfiguredAcpBindingRecordMock = vi.hoisted(() => vi.fn());
vi.mock("../../../../src/acp/persistent-bindings.js", () => ({
ensureConfiguredAcpBindingSession: (...args: unknown[]) =>
ensureConfiguredAcpBindingSessionMock(...args),
resolveConfiguredAcpBindingRecord: (...args: unknown[]) =>
resolveConfiguredAcpBindingRecordMock(...args),
}));
import { __testing as sessionBindingTesting } from "../../../../src/infra/outbound/session-binding-service.js";
import { preflightDiscordMessage } from "./message-handler.preflight.js";
import {
createDiscordMessage,
createDiscordPreflightArgs,
createGuildEvent,
createGuildTextClient,
DEFAULT_PREFLIGHT_CFG,
} from "./message-handler.preflight.test-helpers.js";
const GUILD_ID = "guild-1";
const CHANNEL_ID = "channel-1";
function createConfiguredDiscordBinding() {
return {
spec: {
channel: "discord",
accountId: "default",
conversationId: CHANNEL_ID,
agentId: "codex",
mode: "persistent",
},
record: {
bindingId: "config:acp:discord:default:channel-1",
targetSessionKey: "agent:codex:acp:binding:discord:default:abc123",
targetKind: "session",
conversation: {
channel: "discord",
accountId: "default",
conversationId: CHANNEL_ID,
},
status: "active",
boundAt: 0,
metadata: {
source: "config",
mode: "persistent",
agentId: "codex",
},
},
} as const;
}
function createBasePreflightParams(overrides?: Record<string, unknown>) {
const message = createDiscordMessage({
id: "m-1",
channelId: CHANNEL_ID,
content: "<@bot-1> hello",
mentionedUsers: [{ id: "bot-1" }],
author: {
id: "user-1",
bot: false,
username: "alice",
},
});
return {
...createDiscordPreflightArgs({
cfg: DEFAULT_PREFLIGHT_CFG,
discordConfig: {
allowBots: true,
} as NonNullable<
import("../../../../src/config/config.js").OpenClawConfig["channels"]
>["discord"],
data: createGuildEvent({
channelId: CHANNEL_ID,
guildId: GUILD_ID,
author: message.author,
message,
}),
client: createGuildTextClient(CHANNEL_ID),
botUserId: "bot-1",
}),
discordConfig: {
allowBots: true,
} as NonNullable<
import("../../../../src/config/config.js").OpenClawConfig["channels"]
>["discord"],
...overrides,
} satisfies Parameters<typeof preflightDiscordMessage>[0];
}
describe("preflightDiscordMessage configured ACP bindings", () => {
beforeEach(() => {
sessionBindingTesting.resetSessionBindingAdaptersForTests();
ensureConfiguredAcpBindingSessionMock.mockReset();
resolveConfiguredAcpBindingRecordMock.mockReset();
resolveConfiguredAcpBindingRecordMock.mockReturnValue(createConfiguredDiscordBinding());
ensureConfiguredAcpBindingSessionMock.mockResolvedValue({
ok: true,
sessionKey: "agent:codex:acp:binding:discord:default:abc123",
});
});
it("does not initialize configured ACP bindings for rejected messages", async () => {
const result = await preflightDiscordMessage(
createBasePreflightParams({
guildEntries: {
[GUILD_ID]: {
id: GUILD_ID,
channels: {
[CHANNEL_ID]: {
allow: true,
enabled: false,
},
},
},
},
}),
);
expect(result).toBeNull();
expect(resolveConfiguredAcpBindingRecordMock).toHaveBeenCalledTimes(1);
expect(ensureConfiguredAcpBindingSessionMock).not.toHaveBeenCalled();
});
it("initializes configured ACP bindings only after preflight accepts the message", async () => {
const result = await preflightDiscordMessage(
createBasePreflightParams({
guildEntries: {
[GUILD_ID]: {
id: GUILD_ID,
channels: {
[CHANNEL_ID]: {
allow: true,
enabled: true,
requireMention: false,
},
},
},
},
}),
);
expect(result).not.toBeNull();
expect(resolveConfiguredAcpBindingRecordMock).toHaveBeenCalledTimes(1);
expect(ensureConfiguredAcpBindingSessionMock).toHaveBeenCalledTimes(1);
expect(result?.boundSessionKey).toBe("agent:codex:acp:binding:discord:default:abc123");
});
});