Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
import { beforeEach, describe, expect, it, vi } from "vitest";
const sendMessageMock = vi.fn();
const sendPhotoMock = vi.fn();
const resolveZaloProxyFetchMock = vi.fn();
vi.mock("./api.js", () => ({
sendMessage: (...args: unknown[]) => sendMessageMock(...args),
sendPhoto: (...args: unknown[]) => sendPhotoMock(...args),
}));
vi.mock("./proxy.js", () => ({
resolveZaloProxyFetch: (...args: unknown[]) => resolveZaloProxyFetchMock(...args),
}));
import { sendMessageZalo, sendPhotoZalo } from "./send.js";
describe("zalo send", () => {
beforeEach(() => {
sendMessageMock.mockReset();
sendPhotoMock.mockReset();
resolveZaloProxyFetchMock.mockReset();
resolveZaloProxyFetchMock.mockReturnValue(undefined);
});
it("sends text messages through the message API", async () => {
sendMessageMock.mockResolvedValueOnce({
ok: true,
result: { message_id: "z-msg-1" },
});
const result = await sendMessageZalo("dm-chat-1", "hello there", {
token: "zalo-token",
});
expect(sendMessageMock).toHaveBeenCalledWith(
"zalo-token",
{
chat_id: "dm-chat-1",
text: "hello there",
},
undefined,
);
expect(sendPhotoMock).not.toHaveBeenCalled();
expect(result).toEqual({ ok: true, messageId: "z-msg-1" });
});
it("routes media-bearing sends through the photo API and uses text as caption", async () => {
sendPhotoMock.mockResolvedValueOnce({
ok: true,
result: { message_id: "z-photo-1" },
});
const result = await sendMessageZalo("dm-chat-2", "caption text", {
token: "zalo-token",
mediaUrl: "
https://example.com/photo.jpg",
caption: "ignored fallback caption",
});
expect(sendPhotoMock).toHaveBeenCalledWith(
"zalo-token",
{
chat_id: "dm-chat-2",
photo: "
https://example.com/photo.jpg",
caption: "caption text",
},
undefined,
);
expect(sendMessageMock).not.toHaveBeenCalled();
expect(result).toEqual({ ok: true, messageId: "z-photo-1" });
});
it("fails fast for missing token or blank photo URLs", async () => {
await expect(sendMessageZalo("dm-chat-3", "hello", {})).resolves.toEqual({
ok: false,
error: "No Zalo bot token configured",
});
await expect(
sendPhotoZalo("dm-chat-4", " ", {
token: "zalo-token",
}),
).resolves.toEqual({
ok: false,
error: "No photo URL provided",
});
expect(sendMessageMock).not.toHaveBeenCalled();
expect(sendPhotoMock).not.toHaveBeenCalled();
});
it("sends cfg-backed media directly without hosted-media rewrites", async () => {
sendPhotoMock.mockResolvedValueOnce({
ok: true,
result: { message_id: "z-photo-2" },
});
const result = await sendPhotoZalo("dm-chat-5", "
https://example.com/photo.jpg", {
cfg: {
channels: {
zalo: {
botToken: "zalo-token",
webhookUrl: "
https://gateway.example.com/zalo-webhook",
},
},
} as never,
});
expect(sendPhotoMock).toHaveBeenCalledWith(
"zalo-token",
{
chat_id: "dm-chat-5",
photo: "
https://example.com/photo.jpg",
caption: undefined,
},
undefined,
);
expect(result).toEqual({ ok: true, messageId: "z-photo-2" });
});
});