evOo-local/packages/adapters/src/team-chat-messaging.test.ts
cynarAI 6c7eed7580 Initial clean evOo-local from f00577b
Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline
(Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/*
packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
2026-09-20 17:15:16 +02:00

141 lines
4.5 KiB
TypeScript

import type { MessagingInboundMessage, MessagingSurface } from "@rakazo/adapter-kit";
import { describe, expect, it, vi } from "vitest";
import {
createMessagingTeamChatSender,
resolveMessagingThreadId,
toTeamChatInbound,
} from "./team-chat-messaging.js";
function baseEvent(overrides: Partial<MessagingInboundMessage> = {}): MessagingInboundMessage {
return {
type: "message",
provider: "slack",
handle: "Ev1",
threadId: "slack:C1",
isDirect: false,
from: "U1",
fromLabel: "Ada",
channelName: "launch",
participants: ["U1", "U2"],
content: "Ship Friday?",
mediaUrl: null,
...overrides,
};
}
describe("toTeamChatInbound", () => {
it("returns null when content and media are empty", () => {
expect(toTeamChatInbound(baseEvent({ content: " ", mediaUrl: null }))).toBeNull();
});
it("appends mediaUrl to content", () => {
const mapped = toTeamChatInbound(
baseEvent({ content: "see this", mediaUrl: "https://cdn.example/a.png" }),
);
expect(mapped?.content).toBe("see this\nhttps://cdn.example/a.png");
});
it("marks directs as direct", () => {
expect(toTeamChatInbound(baseEvent({ isDirect: true }))?.kind).toBe("direct");
});
it("uses conversationKey and workspaceId when provided", () => {
const mapped = toTeamChatInbound(
baseEvent({
workspaceId: "T1",
conversationKey: "channel:C1",
kind: "mention",
replyThreadId: "100.1",
senderIsBot: true,
participantNames: ["Ada", "Grace"],
}),
);
expect(mapped).toMatchObject({
eventId: "Ev1",
workspaceId: "T1",
kind: "mention",
conversationKey: "channel:C1",
conversationId: "slack:C1",
replyThreadId: "100.1",
senderIsBot: true,
participantNames: ["Ada", "Grace"],
});
});
it("falls back workspaceId to provider and conversationKey to threadId", () => {
const mapped = toTeamChatInbound(baseEvent());
expect(mapped?.workspaceId).toBe("slack");
expect(mapped?.conversationKey).toBe("slack:C1");
expect(mapped?.kind).toBe("ambient");
});
it("treats @mentions as mention when kind is omitted", () => {
expect(toTeamChatInbound(baseEvent({ content: "hey @rakazo look" }))?.kind).toBe("mention");
});
});
describe("resolveMessagingThreadId", () => {
it("keeps conversationId when there is no reply thread", () => {
expect(resolveMessagingThreadId("slack:C1", null)).toBe("slack:C1");
});
it("appends replyThreadId onto provider:channel ids", () => {
expect(resolveMessagingThreadId("slack:C1", "100.1")).toBe("slack:C1:100.1");
});
it("replaces a stale thread segment when replyThreadId differs", () => {
expect(resolveMessagingThreadId("slack:C1:999.9", "100.1")).toBe("slack:C1:100.1");
});
it("leaves conversationId alone when it already ends with replyThreadId", () => {
expect(resolveMessagingThreadId("slack:C1:100.1", "100.1")).toBe("slack:C1:100.1");
});
});
describe("createMessagingTeamChatSender", () => {
it("posts through messaging.sendToThread using the reply thread id", async () => {
const sendToThread = vi.fn(async () => ({ handle: "msg-1" }));
const messaging = { sendToThread } as unknown as MessagingSurface;
const send = createMessagingTeamChatSender(messaging);
await expect(
send({
conversationId: "slack:C1",
replyThreadId: "100.1",
content: "Done",
}),
).resolves.toEqual({ handle: "msg-1" });
expect(sendToThread).toHaveBeenCalledWith(
{ threadId: "slack:C1:100.1", body: "Done" },
expect.objectContaining({
operationId: expect.stringMatching(/^team-chat-send:/),
spaceId: "",
userId: "",
}),
);
});
it("forwards idempotencyKey into the messaging send and operation id", async () => {
const sendToThread = vi.fn(async () => ({ handle: "msg-2" }));
const messaging = { sendToThread } as unknown as MessagingSurface;
const send = createMessagingTeamChatSender(messaging);
await expect(
send({
conversationId: "slack:C1",
replyThreadId: null,
content: "Retry safe",
idempotencyKey: "external-message:m-1",
}),
).resolves.toEqual({ handle: "msg-2" });
expect(sendToThread).toHaveBeenCalledWith(
{
threadId: "slack:C1",
body: "Retry safe",
idempotencyKey: "external-message:m-1",
},
expect.objectContaining({
operationId: "team-chat-send:external-message:m-1",
}),
);
});
});