test: share plugin approval forwarding fixtures

This commit is contained in:
Peter Steinberger
2026-04-19 01:18:29 +01:00
parent 1bef457cb6
commit 13e707fb7f

View File

@@ -12,6 +12,8 @@ afterEach(() => {
});
const emptyRegistry = createTestRegistry([]);
type SlackAdapterPlugin = Pick<ChannelPlugin, "id" | "meta" | "capabilities" | "config"> &
Partial<Pick<ChannelPlugin, "approvalCapability" | "outbound">>;
const PLUGIN_TARGETS_CFG = {
approvals: {
@@ -66,6 +68,38 @@ async function flushPendingDelivery(): Promise<void> {
await Promise.resolve();
}
function registerSlackAdapterPlugin(plugin: SlackAdapterPlugin): void {
const registry = createTestRegistry([{ pluginId: "slack", plugin, source: "test" }]);
setActivePluginRegistry(registry);
}
function createSlackAdapterPlugin(overrides: Partial<SlackAdapterPlugin>): SlackAdapterPlugin {
return {
...createChannelTestPluginBase({ id: "slack" as ChannelPlugin["id"] }),
...overrides,
};
}
async function registerPendingApproval(
forwarder: ReturnType<typeof createForwarder>["forwarder"],
deliver: ReturnType<typeof vi.fn>,
): Promise<void> {
await forwarder.handlePluginApprovalRequested!(makePluginRequest());
await flushPendingDelivery();
expect(deliver).toHaveBeenCalled();
deliver.mockClear();
}
function makePluginResolved(overrides?: Partial<PluginApprovalResolved>): 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]