test(gateway): dedupe send delivery fixtures

This commit is contained in:
Peter Steinberger
2026-02-18 12:52:25 +00:00
parent 3a09d85cd3
commit fc29588329

View File

@@ -1,4 +1,5 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { resolveOutboundTarget } from "../../infra/outbound/targets.js";
import { sendHandlers } from "./send.js";
import type { GatewayRequestContext } from "./types.js";
@@ -6,6 +7,7 @@ const mocks = vi.hoisted(() => ({
deliverOutboundPayloads: vi.fn(),
appendAssistantMessageToSessionTranscript: vi.fn(async () => ({ ok: true, sessionFile: "x" })),
recordSessionMetaFromInbound: vi.fn(async () => ({ ok: true })),
resolveOutboundTarget: vi.fn(() => ({ ok: true, to: "resolved" })),
}));
vi.mock("../../config/config.js", async () => {
@@ -23,7 +25,7 @@ vi.mock("../../channels/plugins/index.js", () => ({
}));
vi.mock("../../infra/outbound/targets.js", () => ({
resolveOutboundTarget: () => ({ ok: true, to: "resolved" }),
resolveOutboundTarget: mocks.resolveOutboundTarget,
}));
vi.mock("../../infra/outbound/deliver.js", () => ({
@@ -59,13 +61,18 @@ async function runSend(params: Record<string, unknown>) {
return { respond };
}
function mockDeliverySuccess(messageId: string) {
mocks.deliverOutboundPayloads.mockResolvedValue([{ messageId, channel: "slack" }]);
}
describe("gateway send mirroring", () => {
beforeEach(() => {
vi.clearAllMocks();
mocks.resolveOutboundTarget.mockReturnValue({ ok: true, to: "resolved" });
});
it("accepts media-only sends without message", async () => {
mocks.deliverOutboundPayloads.mockResolvedValue([{ messageId: "m-media", channel: "slack" }]);
mockDeliverySuccess("m-media");
const { respond } = await runSend({
to: "channel:C1",
@@ -151,7 +158,7 @@ describe("gateway send mirroring", () => {
});
it("mirrors media filenames when delivery succeeds", async () => {
mocks.deliverOutboundPayloads.mockResolvedValue([{ messageId: "m1", channel: "slack" }]);
mockDeliverySuccess("m1");
await runSend({
to: "channel:C1",
@@ -174,7 +181,7 @@ describe("gateway send mirroring", () => {
});
it("mirrors MEDIA tags as attachments", async () => {
mocks.deliverOutboundPayloads.mockResolvedValue([{ messageId: "m2", channel: "slack" }]);
mockDeliverySuccess("m2");
await runSend({
to: "channel:C1",
@@ -196,7 +203,7 @@ describe("gateway send mirroring", () => {
});
it("lowercases provided session keys for mirroring", async () => {
mocks.deliverOutboundPayloads.mockResolvedValue([{ messageId: "m-lower", channel: "slack" }]);
mockDeliverySuccess("m-lower");
await runSend({
to: "channel:C1",
@@ -216,7 +223,7 @@ describe("gateway send mirroring", () => {
});
it("derives a target session key when none is provided", async () => {
mocks.deliverOutboundPayloads.mockResolvedValue([{ messageId: "m3", channel: "slack" }]);
mockDeliverySuccess("m3");
await runSend({
to: "channel:C1",
@@ -237,7 +244,7 @@ describe("gateway send mirroring", () => {
});
it("forwards threadId to outbound delivery when provided", async () => {
mocks.deliverOutboundPayloads.mockResolvedValue([{ messageId: "m-thread", channel: "slack" }]);
mockDeliverySuccess("m-thread");
await runSend({
to: "channel:C1",
@@ -253,4 +260,27 @@ describe("gateway send mirroring", () => {
}),
);
});
it("returns invalid request when outbound target resolution fails", async () => {
vi.mocked(resolveOutboundTarget).mockReturnValue({ ok: false, error: "target not found" });
const { respond } = await runSend({
to: "channel:C1",
message: "hi",
channel: "slack",
idempotencyKey: "idem-target-fail",
});
expect(mocks.deliverOutboundPayloads).not.toHaveBeenCalled();
expect(respond).toHaveBeenCalledWith(
false,
undefined,
expect.objectContaining({
message: expect.stringContaining("target not found"),
}),
expect.objectContaining({
channel: "slack",
}),
);
});
});