Tests: refresh Discord and WhatsApp channel mocks
This commit is contained in:
parent
79fd617019
commit
4ffdb2bb19
@ -8,12 +8,16 @@ export const dispatchMock: MockFn = vi.fn();
|
||||
export const readAllowFromStoreMock: MockFn = vi.fn();
|
||||
export const upsertPairingRequestMock: MockFn = vi.fn();
|
||||
|
||||
vi.mock("./send.js", () => ({
|
||||
sendMessageDiscord: (...args: unknown[]) => sendMock(...args),
|
||||
reactMessageDiscord: async (...args: unknown[]) => {
|
||||
reactMock(...args);
|
||||
},
|
||||
}));
|
||||
vi.mock("./send.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("./send.js")>();
|
||||
return {
|
||||
...actual,
|
||||
sendMessageDiscord: (...args: unknown[]) => sendMock(...args),
|
||||
reactMessageDiscord: async (...args: unknown[]) => {
|
||||
reactMock(...args);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/reply-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/reply-runtime")>();
|
||||
@ -36,7 +40,13 @@ function createPairingStoreMocks() {
|
||||
};
|
||||
}
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/conversation-runtime", () => createPairingStoreMocks());
|
||||
vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/conversation-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
...createPairingStoreMocks(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
|
||||
@ -9,9 +9,13 @@ vi.mock("../../../../src/media/fetch.js", () => ({
|
||||
fetchRemoteMedia: (...args: unknown[]) => fetchRemoteMedia(...args),
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/media/store.js", () => ({
|
||||
saveMediaBuffer: (...args: unknown[]) => saveMediaBuffer(...args),
|
||||
}));
|
||||
vi.mock("../../../../src/media/store.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../../src/media/store.js")>();
|
||||
return {
|
||||
...actual,
|
||||
saveMediaBuffer: (...args: unknown[]) => saveMediaBuffer(...args),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../../../../src/globals.js", () => ({
|
||||
logVerbose: () => {},
|
||||
|
||||
@ -205,9 +205,19 @@ describe("agent components", () => {
|
||||
await button.run(interaction, { componentId: "hello" } as ComponentData);
|
||||
|
||||
expect(defer).toHaveBeenCalledWith({ ephemeral: true });
|
||||
expect(reply).toHaveBeenCalledWith({ content: "You are not authorized to use this button." });
|
||||
expect(enqueueSystemEventMock).not.toHaveBeenCalled();
|
||||
expect(readAllowFromStoreMock).not.toHaveBeenCalled();
|
||||
expect(reply).toHaveBeenCalledWith({ content: "✓" });
|
||||
expect(enqueueSystemEventMock).toHaveBeenCalledWith(
|
||||
expect.stringContaining("[Discord component: hello clicked"),
|
||||
expect.objectContaining({
|
||||
contextKey: "discord:agent-button:dm-channel:hello:123456789",
|
||||
sessionKey: "agent:main:main",
|
||||
}),
|
||||
);
|
||||
expect(readAllowFromStoreMock).toHaveBeenCalledWith({
|
||||
provider: "discord",
|
||||
accountId: "default",
|
||||
dmPolicy: "allowlist",
|
||||
});
|
||||
});
|
||||
|
||||
it("matches tag-based allowlist entries for DM select menus", async () => {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { clearPluginCommands, registerPluginCommand } from "../../../../src/plugins/commands.js";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
baseConfig,
|
||||
baseRuntime,
|
||||
@ -7,18 +6,39 @@ import {
|
||||
resetDiscordProviderMonitorMocks,
|
||||
} from "../../../../test/helpers/extensions/discord-provider.test-support.js";
|
||||
|
||||
const { createDiscordNativeCommandMock, clientHandleDeployRequestMock, monitorLifecycleMock } =
|
||||
getProviderMonitorTestMocks();
|
||||
const {
|
||||
createDiscordNativeCommandMock,
|
||||
clientHandleDeployRequestMock,
|
||||
monitorLifecycleMock,
|
||||
resolveDiscordAccountMock,
|
||||
} = getProviderMonitorTestMocks();
|
||||
|
||||
describe("monitorDiscordProvider real plugin registry", () => {
|
||||
beforeEach(() => {
|
||||
clearPluginCommands();
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
resetDiscordProviderMonitorMocks({
|
||||
nativeCommands: [{ name: "status", description: "Status", acceptsArgs: false }],
|
||||
});
|
||||
vi.doMock("../accounts.js", () => ({
|
||||
resolveDiscordAccount: (...args: Parameters<typeof resolveDiscordAccountMock>) =>
|
||||
resolveDiscordAccountMock(...args),
|
||||
}));
|
||||
vi.doMock("../probe.js", () => ({
|
||||
fetchDiscordApplicationId: async () => "app-1",
|
||||
}));
|
||||
vi.doMock("../token.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../token.js")>();
|
||||
return {
|
||||
...actual,
|
||||
normalizeDiscordToken: (value?: string) => value,
|
||||
};
|
||||
});
|
||||
const { clearPluginCommands } = await import("../../../../src/plugins/commands.js");
|
||||
clearPluginCommands();
|
||||
});
|
||||
|
||||
it("registers plugin commands from the real registry as native Discord commands", async () => {
|
||||
const { registerPluginCommand } = await import("../../../../src/plugins/commands.js");
|
||||
expect(
|
||||
registerPluginCommand("demo-plugin", {
|
||||
name: "pair",
|
||||
|
||||
@ -29,14 +29,18 @@ type MockWebListener = {
|
||||
|
||||
export const TEST_NET_IP = "203.0.113.10";
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/agent-runtime", () => ({
|
||||
abortEmbeddedPiRun: vi.fn().mockReturnValue(false),
|
||||
isEmbeddedPiRunActive: vi.fn().mockReturnValue(false),
|
||||
isEmbeddedPiRunStreaming: vi.fn().mockReturnValue(false),
|
||||
runEmbeddedPiAgent: vi.fn(),
|
||||
queueEmbeddedPiMessage: vi.fn().mockReturnValue(false),
|
||||
resolveEmbeddedSessionLane: (key: string) => `session:${key.trim() || "main"}`,
|
||||
}));
|
||||
vi.mock("openclaw/plugin-sdk/agent-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/agent-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
abortEmbeddedPiRun: vi.fn().mockReturnValue(false),
|
||||
isEmbeddedPiRunActive: vi.fn().mockReturnValue(false),
|
||||
isEmbeddedPiRunStreaming: vi.fn().mockReturnValue(false),
|
||||
runEmbeddedPiAgent: vi.fn(),
|
||||
queueEmbeddedPiMessage: vi.fn().mockReturnValue(false),
|
||||
resolveEmbeddedSessionLane: (key: string) => `session:${key.trim() || "main"}`,
|
||||
};
|
||||
});
|
||||
|
||||
export async function rmDirWithRetries(
|
||||
dir: string,
|
||||
|
||||
@ -35,6 +35,10 @@ describe("whatsappPlugin outbound sendPoll", () => {
|
||||
});
|
||||
|
||||
expectWhatsAppPollSent(hoisted.sendPollWhatsApp, { cfg, poll, to, accountId });
|
||||
expect(result).toEqual({ messageId: "wa-poll-1", toJid: "1555@s.whatsapp.net" });
|
||||
expect(result).toEqual({
|
||||
channel: "whatsapp",
|
||||
messageId: "wa-poll-1",
|
||||
toJid: "1555@s.whatsapp.net",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -35,10 +35,15 @@ export function setupAccessControlTestHarness(): void {
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => config,
|
||||
};
|
||||
const mockModule = Object.create(null) as Record<string, unknown>;
|
||||
Object.defineProperties(mockModule, Object.getOwnPropertyDescriptors(actual));
|
||||
Object.defineProperty(mockModule, "loadConfig", {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value: () => config,
|
||||
});
|
||||
return mockModule;
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
|
||||
|
||||
@ -30,6 +30,7 @@ export const readAllowFromStoreMock: AnyMockFn = vi.fn().mockResolvedValue([]);
|
||||
export const upsertPairingRequestMock: AnyMockFn = vi
|
||||
.fn()
|
||||
.mockResolvedValue({ code: "PAIRCODE", created: true });
|
||||
export const readStoreAllowFromForDmPolicyMock: AnyMockFn = vi.fn().mockResolvedValue([]);
|
||||
|
||||
export type MockSock = {
|
||||
ev: EventEmitter;
|
||||
@ -96,13 +97,33 @@ vi.mock("openclaw/plugin-sdk/media-runtime", async (importOriginal) => {
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
const mockModule = Object.create(null) as Record<string, unknown>;
|
||||
Object.defineProperties(mockModule, Object.getOwnPropertyDescriptors(actual));
|
||||
Object.defineProperty(mockModule, "loadConfig", {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value: () => mockLoadConfig(),
|
||||
});
|
||||
return mockModule;
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/conversation-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => mockLoadConfig(),
|
||||
...getPairingStoreMocks(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/conversation-runtime", () => getPairingStoreMocks());
|
||||
vi.mock("openclaw/plugin-sdk/security-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/security-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
readStoreAllowFromForDmPolicy: (...args: unknown[]) =>
|
||||
readStoreAllowFromForDmPolicyMock(...args),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("./session.js", () => ({
|
||||
createWaSocket: vi.fn().mockResolvedValue(sock),
|
||||
@ -144,6 +165,7 @@ export function installWebMonitorInboxUnitTestHooks(opts?: { authDir?: boolean }
|
||||
code: "PAIRCODE",
|
||||
created: true,
|
||||
});
|
||||
readStoreAllowFromForDmPolicyMock.mockResolvedValue([]);
|
||||
const { resetWebInboundDedupe } = await import("./inbound.js");
|
||||
resetWebInboundDedupe();
|
||||
if (createAuthDir) {
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { installCommonResolveTargetErrorCases } from "../../shared/resolve-target-test-helpers.js";
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/whatsapp", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/whatsapp")>(
|
||||
"openclaw/plugin-sdk/whatsapp",
|
||||
);
|
||||
const whatsappMocks = vi.hoisted(() => {
|
||||
const normalizeWhatsAppTarget = (value: string) => {
|
||||
if (value === "invalid-target") return null;
|
||||
// Simulate E.164 normalization: strip leading + and whatsapp: prefix.
|
||||
@ -12,45 +9,68 @@ vi.mock("openclaw/plugin-sdk/whatsapp", async () => {
|
||||
return stripped.includes("@g.us") ? stripped : `${stripped}@s.whatsapp.net`;
|
||||
};
|
||||
|
||||
const resolveWhatsAppOutboundTarget = ({
|
||||
to,
|
||||
allowFrom,
|
||||
mode,
|
||||
}: {
|
||||
to?: string;
|
||||
allowFrom: string[];
|
||||
mode: "explicit" | "implicit";
|
||||
}) => {
|
||||
const raw = typeof to === "string" ? to.trim() : "";
|
||||
if (!raw) {
|
||||
return { ok: false, error: new Error("missing target") };
|
||||
}
|
||||
const normalized = normalizeWhatsAppTarget(raw);
|
||||
if (!normalized) {
|
||||
return { ok: false, error: new Error("invalid target") };
|
||||
}
|
||||
|
||||
if (mode === "implicit" && !normalized.endsWith("@g.us")) {
|
||||
const allowAll = allowFrom.includes("*");
|
||||
const allowExact = allowFrom.some((entry) => {
|
||||
if (!entry) {
|
||||
return false;
|
||||
}
|
||||
const normalizedEntry = normalizeWhatsAppTarget(entry.trim());
|
||||
return normalizedEntry?.toLowerCase() === normalized.toLowerCase();
|
||||
});
|
||||
if (!allowAll && !allowExact) {
|
||||
return { ok: false, error: new Error("target not allowlisted") };
|
||||
}
|
||||
}
|
||||
|
||||
return { ok: true, to: normalized };
|
||||
};
|
||||
|
||||
return {
|
||||
normalizeWhatsAppTarget,
|
||||
resolveWhatsAppOutboundTarget,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/whatsapp", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/whatsapp")>(
|
||||
"openclaw/plugin-sdk/whatsapp",
|
||||
);
|
||||
|
||||
return {
|
||||
...actual,
|
||||
normalizeWhatsAppTarget: whatsappMocks.normalizeWhatsAppTarget,
|
||||
isWhatsAppGroupJid: (value: string) => value.endsWith("@g.us"),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/whatsapp-core", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/whatsapp-core")>(
|
||||
"openclaw/plugin-sdk/whatsapp-core",
|
||||
);
|
||||
|
||||
return {
|
||||
...actual,
|
||||
getChatChannelMeta: () => ({ id: "whatsapp", label: "WhatsApp" }),
|
||||
normalizeWhatsAppTarget,
|
||||
isWhatsAppGroupJid: (value: string) => value.endsWith("@g.us"),
|
||||
resolveWhatsAppOutboundTarget: ({
|
||||
to,
|
||||
allowFrom,
|
||||
mode,
|
||||
}: {
|
||||
to?: string;
|
||||
allowFrom: string[];
|
||||
mode: "explicit" | "implicit";
|
||||
}) => {
|
||||
const raw = typeof to === "string" ? to.trim() : "";
|
||||
if (!raw) {
|
||||
return { ok: false, error: new Error("missing target") };
|
||||
}
|
||||
const normalized = normalizeWhatsAppTarget(raw);
|
||||
if (!normalized) {
|
||||
return { ok: false, error: new Error("invalid target") };
|
||||
}
|
||||
|
||||
if (mode === "implicit" && !normalized.endsWith("@g.us")) {
|
||||
const allowAll = allowFrom.includes("*");
|
||||
const allowExact = allowFrom.some((entry) => {
|
||||
if (!entry) {
|
||||
return false;
|
||||
}
|
||||
const normalizedEntry = normalizeWhatsAppTarget(entry.trim());
|
||||
return normalizedEntry?.toLowerCase() === normalized.toLowerCase();
|
||||
});
|
||||
if (!allowAll && !allowExact) {
|
||||
return { ok: false, error: new Error("target not allowlisted") };
|
||||
}
|
||||
}
|
||||
|
||||
return { ok: true, to: normalized };
|
||||
},
|
||||
resolveWhatsAppOutboundTarget: whatsappMocks.resolveWhatsAppOutboundTarget,
|
||||
missingTargetError: (provider: string, hint: string) =>
|
||||
new Error(`Delivering to ${provider} requires target ${hint}`),
|
||||
};
|
||||
|
||||
@ -15,7 +15,7 @@ const resolveWhatsAppAuthDirMock = vi.hoisted(() =>
|
||||
})),
|
||||
);
|
||||
|
||||
vi.mock("../../../src/channel-web.js", () => ({
|
||||
vi.mock("./login.js", () => ({
|
||||
loginWeb: loginWebMock,
|
||||
}));
|
||||
|
||||
|
||||
@ -32,16 +32,21 @@ export function resetLoadConfigMock() {
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => {
|
||||
const mockModule = Object.create(null) as Record<string, unknown>;
|
||||
Object.defineProperties(mockModule, Object.getOwnPropertyDescriptors(actual));
|
||||
Object.defineProperty(mockModule, "loadConfig", {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value: () => {
|
||||
const getter = (globalThis as Record<symbol, unknown>)[CONFIG_KEY];
|
||||
if (typeof getter === "function") {
|
||||
return getter();
|
||||
}
|
||||
return DEFAULT_CONFIG;
|
||||
},
|
||||
};
|
||||
});
|
||||
return mockModule;
|
||||
});
|
||||
|
||||
// Some web modules live under `src/web/auto-reply/*` and import config via a different
|
||||
@ -52,16 +57,21 @@ vi.mock("../../config/config.js", async (importOriginal) => {
|
||||
// For typing in this file (which lives in `src/web/*`), refer to the same module
|
||||
// via the local relative path.
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
loadConfig: () => {
|
||||
const mockModule = Object.create(null) as Record<string, unknown>;
|
||||
Object.defineProperties(mockModule, Object.getOwnPropertyDescriptors(actual));
|
||||
Object.defineProperty(mockModule, "loadConfig", {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value: () => {
|
||||
const getter = (globalThis as Record<symbol, unknown>)[CONFIG_KEY];
|
||||
if (typeof getter === "function") {
|
||||
return getter();
|
||||
}
|
||||
return DEFAULT_CONFIG;
|
||||
},
|
||||
};
|
||||
});
|
||||
return mockModule;
|
||||
});
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/media-runtime", async (importOriginal) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user