diff --git a/src/infra/plugin-approval-forwarder.test.ts b/src/infra/plugin-approval-forwarder.test.ts index a88ae603773..3498522ed00 100644 --- a/src/infra/plugin-approval-forwarder.test.ts +++ b/src/infra/plugin-approval-forwarder.test.ts @@ -12,6 +12,8 @@ afterEach(() => { }); const emptyRegistry = createTestRegistry([]); +type SlackAdapterPlugin = Pick & + Partial>; const PLUGIN_TARGETS_CFG = { approvals: { @@ -66,6 +68,38 @@ async function flushPendingDelivery(): Promise { await Promise.resolve(); } +function registerSlackAdapterPlugin(plugin: SlackAdapterPlugin): void { + const registry = createTestRegistry([{ pluginId: "slack", plugin, source: "test" }]); + setActivePluginRegistry(registry); +} + +function createSlackAdapterPlugin(overrides: Partial): SlackAdapterPlugin { + return { + ...createChannelTestPluginBase({ id: "slack" as ChannelPlugin["id"] }), + ...overrides, + }; +} + +async function registerPendingApproval( + forwarder: ReturnType["forwarder"], + deliver: ReturnType, +): Promise { + await forwarder.handlePluginApprovalRequested!(makePluginRequest()); + await flushPendingDelivery(); + expect(deliver).toHaveBeenCalled(); + deliver.mockClear(); +} + +function makePluginResolved(overrides?: Partial): PluginApprovalResolved { + return { + id: "plugin-req-1", + decision: "allow-once", + resolvedBy: "telegram:user123", + ts: 2000, + ...overrides, + }; +} + describe("plugin approval forwarding", () => { beforeEach(() => { setActivePluginRegistry(emptyRegistry); @@ -176,23 +210,17 @@ describe("plugin approval forwarding", () => { describe("channel adapter hooks", () => { it("uses buildPluginPendingPayload from channel adapter when available", async () => { const mockPayload = { text: "custom adapter payload" }; - const adapterPlugin: Pick< - ChannelPlugin, - "id" | "meta" | "capabilities" | "config" | "approvalCapability" - > = { - ...createChannelTestPluginBase({ id: "slack" as ChannelPlugin["id"] }), - approvalCapability: { - render: { - plugin: { - buildPendingPayload: vi.fn().mockReturnValue(mockPayload), + registerSlackAdapterPlugin( + createSlackAdapterPlugin({ + approvalCapability: { + render: { + plugin: { + buildPendingPayload: vi.fn().mockReturnValue(mockPayload), + }, }, }, - }, - }; - const registry = createTestRegistry([ - { pluginId: "slack", plugin: adapterPlugin, source: "test" }, - ]); - setActivePluginRegistry(registry); + }), + ); const deliver = vi.fn().mockResolvedValue([]); const { forwarder } = createForwarder({ cfg: PLUGIN_TARGETS_CFG, deliver }); @@ -207,20 +235,14 @@ describe("plugin approval forwarding", () => { it("calls outbound beforeDeliverPayload before plugin approval delivery", async () => { const beforeDeliverPayload = vi.fn(); - const adapterPlugin: Pick< - ChannelPlugin, - "id" | "meta" | "capabilities" | "config" | "outbound" - > = { - ...createChannelTestPluginBase({ id: "slack" as ChannelPlugin["id"] }), - outbound: { - deliveryMode: "direct", - beforeDeliverPayload, - }, - }; - const registry = createTestRegistry([ - { pluginId: "slack", plugin: adapterPlugin, source: "test" }, - ]); - setActivePluginRegistry(registry); + registerSlackAdapterPlugin( + createSlackAdapterPlugin({ + outbound: { + deliveryMode: "direct", + beforeDeliverPayload, + }, + }), + ); const deliver = vi.fn().mockResolvedValue([]); const { forwarder } = createForwarder({ cfg: PLUGIN_TARGETS_CFG, deliver }); @@ -232,40 +254,24 @@ describe("plugin approval forwarding", () => { it("uses buildPluginResolvedPayload from channel adapter for resolved messages", async () => { const mockPayload = { text: "custom resolved payload" }; - const adapterPlugin: Pick< - ChannelPlugin, - "id" | "meta" | "capabilities" | "config" | "approvalCapability" - > = { - ...createChannelTestPluginBase({ id: "slack" as ChannelPlugin["id"] }), - approvalCapability: { - render: { - plugin: { - buildResolvedPayload: vi.fn().mockReturnValue(mockPayload), + registerSlackAdapterPlugin( + createSlackAdapterPlugin({ + approvalCapability: { + render: { + plugin: { + buildResolvedPayload: vi.fn().mockReturnValue(mockPayload), + }, }, }, - }, - }; - const registry = createTestRegistry([ - { pluginId: "slack", plugin: adapterPlugin, source: "test" }, - ]); - setActivePluginRegistry(registry); + }), + ); const deliver = vi.fn().mockResolvedValue([]); const { forwarder } = createForwarder({ cfg: PLUGIN_TARGETS_CFG, deliver }); - // First register request so targets are tracked - await forwarder.handlePluginApprovalRequested!(makePluginRequest()); - await flushPendingDelivery(); - expect(deliver).toHaveBeenCalled(); - deliver.mockClear(); + await registerPendingApproval(forwarder, deliver); - const resolved: PluginApprovalResolved = { - id: "plugin-req-1", - decision: "allow-once", - resolvedBy: "telegram:user123", - ts: 2000, - }; - await forwarder.handlePluginApprovalResolved!(resolved); + await forwarder.handlePluginApprovalResolved!(makePluginResolved()); await flushPendingDelivery(); expect(deliver).toHaveBeenCalled(); const deliveryArgs = deliver.mock.calls[0]?.[0] as @@ -280,19 +286,9 @@ describe("plugin approval forwarding", () => { const deliver = vi.fn().mockResolvedValue([]); const { forwarder } = createForwarder({ cfg: PLUGIN_TARGETS_CFG, deliver }); - // First register request so targets are tracked - await forwarder.handlePluginApprovalRequested!(makePluginRequest()); - await flushPendingDelivery(); - expect(deliver).toHaveBeenCalled(); - deliver.mockClear(); + await registerPendingApproval(forwarder, deliver); - const resolved: PluginApprovalResolved = { - id: "plugin-req-1", - decision: "allow-once", - resolvedBy: "telegram:user123", - ts: 2000, - }; - await forwarder.handlePluginApprovalResolved!(resolved); + await forwarder.handlePluginApprovalResolved!(makePluginResolved()); expect(deliver).toHaveBeenCalled(); const text = (deliver.mock.calls[0]?.[0] as { payloads?: Array<{ text?: string }> })?.payloads?.[0]