From 7ecff9642573560d32fecc947564eda9e16465d7 Mon Sep 17 00:00:00 2001 From: froemic Date: Wed, 22 Apr 2026 18:57:08 +0200 Subject: [PATCH] Fix Slack HTTP route registry dispatch --- .../src/http/plugin-routes.dispatch.test.ts | 52 +++++++++++++++++++ extensions/slack/src/http/plugin-routes.ts | 11 +--- 2 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 extensions/slack/src/http/plugin-routes.dispatch.test.ts diff --git a/extensions/slack/src/http/plugin-routes.dispatch.test.ts b/extensions/slack/src/http/plugin-routes.dispatch.test.ts new file mode 100644 index 00000000000..5b649017388 --- /dev/null +++ b/extensions/slack/src/http/plugin-routes.dispatch.test.ts @@ -0,0 +1,52 @@ +import type { IncomingMessage, ServerResponse } from "node:http"; +import { describe, expect, it, vi } from "vitest"; +import { createTestPluginApi } from "../../../../test/helpers/plugins/plugin-api.js"; +import type { OpenClawConfig, OpenClawPluginApi } from "../runtime-api.js"; + +function createApi(config: OpenClawConfig, registerHttpRoute = vi.fn()): OpenClawPluginApi { + return createTestPluginApi({ + id: "slack", + config, + registerHttpRoute, + }); +} + +describe("registerSlackPluginHttpRoutes dispatch", () => { + it("uses the shared Slack HTTP handler registry", async () => { + vi.resetModules(); + const staleRuntimeHandler = vi.fn(async () => false); + vi.doMock("./handler.runtime.js", () => ({ + handleSlackHttpRequest: staleRuntimeHandler, + })); + + const [{ registerSlackPluginHttpRoutes }, { registerSlackHttpHandler }] = await Promise.all([ + import("./plugin-routes.js"), + import("./registry.js"), + ]); + const routeHandler = vi.fn(); + const unregister = registerSlackHttpHandler({ + path: "/slack/events", + handler: routeHandler, + }); + const registerHttpRoute = vi.fn(); + + try { + registerSlackPluginHttpRoutes(createApi({}, registerHttpRoute)); + const route = registerHttpRoute.mock.calls[0]?.[0] as + | { + handler: (req: IncomingMessage, res: ServerResponse) => Promise; + } + | undefined; + const req = { url: "/slack/events" } as IncomingMessage; + const res = {} as ServerResponse; + + await expect(route?.handler(req, res)).resolves.toBe(true); + + expect(routeHandler).toHaveBeenCalledWith(req, res); + expect(staleRuntimeHandler).not.toHaveBeenCalled(); + } finally { + unregister(); + vi.doUnmock("./handler.runtime.js"); + } + }); +}); diff --git a/extensions/slack/src/http/plugin-routes.ts b/extensions/slack/src/http/plugin-routes.ts index 481901f042d..ef4bd060eab 100644 --- a/extensions/slack/src/http/plugin-routes.ts +++ b/extensions/slack/src/http/plugin-routes.ts @@ -2,13 +2,7 @@ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id"; import type { OpenClawPluginApi } from "openclaw/plugin-sdk/channel-plugin-common"; import { listSlackAccountIds, mergeSlackAccountConfig } from "../accounts.js"; import { normalizeSlackWebhookPath } from "./paths.js"; - -let slackHttpHandlerRuntimePromise: Promise | null = null; - -async function loadSlackHttpHandlerRuntime() { - slackHttpHandlerRuntimePromise ??= import("./handler.runtime.js"); - return await slackHttpHandlerRuntimePromise; -} +import { handleSlackHttpRequest } from "./registry.js"; export function registerSlackPluginHttpRoutes(api: OpenClawPluginApi): void { const accountIds = new Set([DEFAULT_ACCOUNT_ID, ...listSlackAccountIds(api.config)]); @@ -25,8 +19,7 @@ export function registerSlackPluginHttpRoutes(api: OpenClawPluginApi): void { api.registerHttpRoute({ path, auth: "plugin", - handler: async (req, res) => - await (await loadSlackHttpHandlerRuntime()).handleSlackHttpRequest(req, res), + handler: async (req, res) => await handleSlackHttpRequest(req, res), }); } }