mirror of https://github.com/openclaw/openclaw.git
test: dedupe slack message event tests
This commit is contained in:
parent
c8898034f9
commit
67f7d1e65f
|
|
@ -57,6 +57,30 @@ async function writeGatewayScript(env: Record<string, string>, port = 18789) {
|
|||
"utf8",
|
||||
);
|
||||
}
|
||||
async function writeStartupFallbackEntry(env: Record<string, string>) {
|
||||
const startupEntryPath = resolveStartupEntryPath(env);
|
||||
await fs.mkdir(path.dirname(startupEntryPath), { recursive: true });
|
||||
await fs.writeFile(startupEntryPath, "@echo off\r\n", "utf8");
|
||||
return startupEntryPath;
|
||||
}
|
||||
|
||||
function expectStartupFallbackSpawn(env: Record<string, string>) {
|
||||
expect(spawn).toHaveBeenCalledWith(
|
||||
"cmd.exe",
|
||||
["/d", "/s", "/c", quoteCmdScriptArg(resolveTaskScriptPath(env))],
|
||||
expect.objectContaining({ detached: true, stdio: "ignore", windowsHide: true }),
|
||||
);
|
||||
}
|
||||
|
||||
function addStartupFallbackMissingResponses(
|
||||
extraResponses: Array<{ code: number; stdout: string; stderr: string }> = [],
|
||||
) {
|
||||
schtasksResponses.push(
|
||||
{ code: 0, stdout: "", stderr: "" },
|
||||
{ code: 1, stdout: "", stderr: "not found" },
|
||||
...extraResponses,
|
||||
);
|
||||
}
|
||||
beforeEach(() => {
|
||||
resetSchtasksBaseMocks();
|
||||
spawn.mockClear();
|
||||
|
|
@ -119,22 +143,14 @@ describe("Windows startup fallback", () => {
|
|||
});
|
||||
|
||||
await expect(fs.access(resolveStartupEntryPath(env))).resolves.toBeUndefined();
|
||||
expect(spawn).toHaveBeenCalledWith(
|
||||
"cmd.exe",
|
||||
["/d", "/s", "/c", quoteCmdScriptArg(resolveTaskScriptPath(env))],
|
||||
expect.objectContaining({ detached: true, stdio: "ignore", windowsHide: true }),
|
||||
);
|
||||
expectStartupFallbackSpawn(env);
|
||||
});
|
||||
});
|
||||
|
||||
it("treats an installed Startup-folder launcher as loaded", async () => {
|
||||
await withWindowsEnv("openclaw-win-startup-", async ({ env }) => {
|
||||
schtasksResponses.push(
|
||||
{ code: 0, stdout: "", stderr: "" },
|
||||
{ code: 1, stdout: "", stderr: "not found" },
|
||||
);
|
||||
await fs.mkdir(path.dirname(resolveStartupEntryPath(env)), { recursive: true });
|
||||
await fs.writeFile(resolveStartupEntryPath(env), "@echo off\r\n", "utf8");
|
||||
addStartupFallbackMissingResponses();
|
||||
await writeStartupFallbackEntry(env);
|
||||
|
||||
await expect(isScheduledTaskInstalled({ env })).resolves.toBe(true);
|
||||
});
|
||||
|
|
@ -142,12 +158,8 @@ describe("Windows startup fallback", () => {
|
|||
|
||||
it("reports runtime from the gateway listener when using the Startup fallback", async () => {
|
||||
await withWindowsEnv("openclaw-win-startup-", async ({ env }) => {
|
||||
schtasksResponses.push(
|
||||
{ code: 0, stdout: "", stderr: "" },
|
||||
{ code: 1, stdout: "", stderr: "not found" },
|
||||
);
|
||||
await fs.mkdir(path.dirname(resolveStartupEntryPath(env)), { recursive: true });
|
||||
await fs.writeFile(resolveStartupEntryPath(env), "@echo off\r\n", "utf8");
|
||||
addStartupFallbackMissingResponses();
|
||||
await writeStartupFallbackEntry(env);
|
||||
inspectPortUsage.mockResolvedValue({
|
||||
port: 18789,
|
||||
status: "busy",
|
||||
|
|
@ -164,14 +176,11 @@ describe("Windows startup fallback", () => {
|
|||
|
||||
it("restarts the Startup fallback by killing the current pid and relaunching the entry", async () => {
|
||||
await withWindowsEnv("openclaw-win-startup-", async ({ env }) => {
|
||||
schtasksResponses.push(
|
||||
addStartupFallbackMissingResponses([
|
||||
{ code: 0, stdout: "", stderr: "" },
|
||||
{ code: 1, stdout: "", stderr: "not found" },
|
||||
{ code: 0, stdout: "", stderr: "" },
|
||||
{ code: 1, stdout: "", stderr: "not found" },
|
||||
);
|
||||
await fs.mkdir(path.dirname(resolveStartupEntryPath(env)), { recursive: true });
|
||||
await fs.writeFile(resolveStartupEntryPath(env), "@echo off\r\n", "utf8");
|
||||
]);
|
||||
await writeStartupFallbackEntry(env);
|
||||
inspectPortUsage.mockResolvedValue({
|
||||
port: 18789,
|
||||
status: "busy",
|
||||
|
|
@ -184,11 +193,7 @@ describe("Windows startup fallback", () => {
|
|||
outcome: "completed",
|
||||
});
|
||||
expect(killProcessTree).toHaveBeenCalledWith(5151, { graceMs: 300 });
|
||||
expect(spawn).toHaveBeenCalledWith(
|
||||
"cmd.exe",
|
||||
["/d", "/s", "/c", quoteCmdScriptArg(resolveTaskScriptPath(env))],
|
||||
expect.objectContaining({ detached: true, stdio: "ignore", windowsHide: true }),
|
||||
);
|
||||
expectStartupFallbackSpawn(env);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -196,8 +201,7 @@ describe("Windows startup fallback", () => {
|
|||
await withWindowsEnv("openclaw-win-startup-", async ({ env }) => {
|
||||
schtasksResponses.push({ code: 0, stdout: "", stderr: "" });
|
||||
await writeGatewayScript(env);
|
||||
await fs.mkdir(path.dirname(resolveStartupEntryPath(env)), { recursive: true });
|
||||
await fs.writeFile(resolveStartupEntryPath(env), "@echo off\r\n", "utf8");
|
||||
await writeStartupFallbackEntry(env);
|
||||
inspectPortUsage
|
||||
.mockResolvedValueOnce({
|
||||
port: 18789,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ vi.mock("../../../pairing/pairing-store.js", () => ({
|
|||
|
||||
type MessageHandler = (args: { event: Record<string, unknown>; body: unknown }) => Promise<void>;
|
||||
type AppMentionHandler = MessageHandler;
|
||||
type RegisteredEventName = "message" | "app_mention";
|
||||
|
||||
type MessageCase = {
|
||||
overrides?: SlackSystemEventTestOverrides;
|
||||
|
|
@ -25,7 +26,7 @@ type MessageCase = {
|
|||
body?: unknown;
|
||||
};
|
||||
|
||||
function createMessageHandlers(overrides?: SlackSystemEventTestOverrides) {
|
||||
function createHandlers(eventName: RegisteredEventName, overrides?: SlackSystemEventTestOverrides) {
|
||||
const harness = createSlackSystemEventTestHarness(overrides);
|
||||
const handleSlackMessage = vi.fn(async () => {});
|
||||
registerSlackMessageEvents({
|
||||
|
|
@ -33,22 +34,14 @@ function createMessageHandlers(overrides?: SlackSystemEventTestOverrides) {
|
|||
handleSlackMessage,
|
||||
});
|
||||
return {
|
||||
handler: harness.getHandler("message") as MessageHandler | null,
|
||||
handler: harness.getHandler(eventName) as MessageHandler | null,
|
||||
handleSlackMessage,
|
||||
};
|
||||
}
|
||||
|
||||
function createAppMentionHandlers(overrides?: SlackSystemEventTestOverrides) {
|
||||
const harness = createSlackSystemEventTestHarness(overrides);
|
||||
const handleSlackMessage = vi.fn(async () => {});
|
||||
registerSlackMessageEvents({
|
||||
ctx: harness.ctx,
|
||||
handleSlackMessage,
|
||||
});
|
||||
return {
|
||||
handler: harness.getHandler("app_mention") as AppMentionHandler | null,
|
||||
handleSlackMessage,
|
||||
};
|
||||
function resetMessageMocks(): void {
|
||||
messageQueueMock.mockClear();
|
||||
messageAllowMock.mockReset().mockResolvedValue([]);
|
||||
}
|
||||
|
||||
function makeChangedEvent(overrides?: { channel?: string; user?: string }) {
|
||||
|
|
@ -89,10 +82,40 @@ function makeThreadBroadcastEvent(overrides?: { channel?: string; user?: string
|
|||
};
|
||||
}
|
||||
|
||||
function makeAppMentionEvent(overrides?: {
|
||||
channel?: string;
|
||||
channelType?: "channel" | "group" | "im" | "mpim";
|
||||
ts?: string;
|
||||
}) {
|
||||
return {
|
||||
type: "app_mention",
|
||||
channel: overrides?.channel ?? "C123",
|
||||
channel_type: overrides?.channelType ?? "channel",
|
||||
user: "U1",
|
||||
text: "<@U_BOT> hello",
|
||||
ts: overrides?.ts ?? "123.456",
|
||||
};
|
||||
}
|
||||
|
||||
async function invokeRegisteredHandler(input: {
|
||||
eventName: RegisteredEventName;
|
||||
overrides?: SlackSystemEventTestOverrides;
|
||||
event: Record<string, unknown>;
|
||||
body?: unknown;
|
||||
}) {
|
||||
resetMessageMocks();
|
||||
const { handler, handleSlackMessage } = createHandlers(input.eventName, input.overrides);
|
||||
expect(handler).toBeTruthy();
|
||||
await handler!({
|
||||
event: input.event,
|
||||
body: input.body ?? {},
|
||||
});
|
||||
return { handleSlackMessage };
|
||||
}
|
||||
|
||||
async function runMessageCase(input: MessageCase = {}): Promise<void> {
|
||||
messageQueueMock.mockClear();
|
||||
messageAllowMock.mockReset().mockResolvedValue([]);
|
||||
const { handler } = createMessageHandlers(input.overrides);
|
||||
resetMessageMocks();
|
||||
const { handler } = createHandlers("message", input.overrides);
|
||||
expect(handler).toBeTruthy();
|
||||
await handler!({
|
||||
event: (input.event ?? makeChangedEvent()) as Record<string, unknown>,
|
||||
|
|
@ -151,12 +174,9 @@ describe("registerSlackMessageEvents", () => {
|
|||
});
|
||||
|
||||
it("passes regular message events to the message handler", async () => {
|
||||
messageQueueMock.mockClear();
|
||||
messageAllowMock.mockReset().mockResolvedValue([]);
|
||||
const { handler, handleSlackMessage } = createMessageHandlers({ dmPolicy: "open" });
|
||||
expect(handler).toBeTruthy();
|
||||
|
||||
await handler!({
|
||||
const { handleSlackMessage } = await invokeRegisteredHandler({
|
||||
eventName: "message",
|
||||
overrides: { dmPolicy: "open" },
|
||||
event: {
|
||||
type: "message",
|
||||
channel: "D1",
|
||||
|
|
@ -164,7 +184,6 @@ describe("registerSlackMessageEvents", () => {
|
|||
text: "hello",
|
||||
ts: "123.456",
|
||||
},
|
||||
body: {},
|
||||
});
|
||||
|
||||
expect(handleSlackMessage).toHaveBeenCalledTimes(1);
|
||||
|
|
@ -172,9 +191,8 @@ describe("registerSlackMessageEvents", () => {
|
|||
});
|
||||
|
||||
it("handles channel and group messages via the unified message handler", async () => {
|
||||
messageQueueMock.mockClear();
|
||||
messageAllowMock.mockReset().mockResolvedValue([]);
|
||||
const { handler, handleSlackMessage } = createMessageHandlers({
|
||||
resetMessageMocks();
|
||||
const { handler, handleSlackMessage } = createHandlers("message", {
|
||||
dmPolicy: "open",
|
||||
channelType: "channel",
|
||||
});
|
||||
|
|
@ -206,23 +224,18 @@ describe("registerSlackMessageEvents", () => {
|
|||
});
|
||||
|
||||
it("applies subtype system-event handling for channel messages", async () => {
|
||||
messageQueueMock.mockClear();
|
||||
messageAllowMock.mockReset().mockResolvedValue([]);
|
||||
const { handler, handleSlackMessage } = createMessageHandlers({
|
||||
dmPolicy: "open",
|
||||
channelType: "channel",
|
||||
});
|
||||
|
||||
expect(handler).toBeTruthy();
|
||||
|
||||
// message_changed events from channels arrive via the generic "message"
|
||||
// handler with channel_type:"channel" — not a separate event type.
|
||||
await handler!({
|
||||
const { handleSlackMessage } = await invokeRegisteredHandler({
|
||||
eventName: "message",
|
||||
overrides: {
|
||||
dmPolicy: "open",
|
||||
channelType: "channel",
|
||||
},
|
||||
event: {
|
||||
...makeChangedEvent({ channel: "C1", user: "U1" }),
|
||||
channel_type: "channel",
|
||||
},
|
||||
body: {},
|
||||
});
|
||||
|
||||
expect(handleSlackMessage).not.toHaveBeenCalled();
|
||||
|
|
@ -230,38 +243,20 @@ describe("registerSlackMessageEvents", () => {
|
|||
});
|
||||
|
||||
it("skips app_mention events for DM channel ids even with contradictory channel_type", async () => {
|
||||
const { handler, handleSlackMessage } = createAppMentionHandlers({ dmPolicy: "open" });
|
||||
expect(handler).toBeTruthy();
|
||||
|
||||
await handler!({
|
||||
event: {
|
||||
type: "app_mention",
|
||||
channel: "D123",
|
||||
channel_type: "channel",
|
||||
user: "U1",
|
||||
text: "<@U_BOT> hello",
|
||||
ts: "123.456",
|
||||
},
|
||||
body: {},
|
||||
const { handleSlackMessage } = await invokeRegisteredHandler({
|
||||
eventName: "app_mention",
|
||||
overrides: { dmPolicy: "open" },
|
||||
event: makeAppMentionEvent({ channel: "D123", channelType: "channel" }),
|
||||
});
|
||||
|
||||
expect(handleSlackMessage).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("routes app_mention events from channels to the message handler", async () => {
|
||||
const { handler, handleSlackMessage } = createAppMentionHandlers({ dmPolicy: "open" });
|
||||
expect(handler).toBeTruthy();
|
||||
|
||||
await handler!({
|
||||
event: {
|
||||
type: "app_mention",
|
||||
channel: "C123",
|
||||
channel_type: "channel",
|
||||
user: "U1",
|
||||
text: "<@U_BOT> hello",
|
||||
ts: "123.789",
|
||||
},
|
||||
body: {},
|
||||
const { handleSlackMessage } = await invokeRegisteredHandler({
|
||||
eventName: "app_mention",
|
||||
overrides: { dmPolicy: "open" },
|
||||
event: makeAppMentionEvent({ channel: "C123", channelType: "channel", ts: "123.789" }),
|
||||
});
|
||||
|
||||
expect(handleSlackMessage).toHaveBeenCalledTimes(1);
|
||||
|
|
|
|||
Loading…
Reference in New Issue