refactor(test): share discord send rest harness
This commit is contained in:
@@ -16,43 +16,12 @@ import {
|
||||
uploadEmojiDiscord,
|
||||
uploadStickerDiscord,
|
||||
} from "./send.js";
|
||||
import { makeDiscordRest } from "./send.test-harness.js";
|
||||
|
||||
vi.mock("../web/media.js", () => ({
|
||||
loadWebMedia: vi.fn().mockResolvedValue({
|
||||
buffer: Buffer.from("img"),
|
||||
fileName: "photo.jpg",
|
||||
contentType: "image/jpeg",
|
||||
kind: "image",
|
||||
}),
|
||||
loadWebMediaRaw: vi.fn().mockResolvedValue({
|
||||
buffer: Buffer.from("img"),
|
||||
fileName: "asset.png",
|
||||
contentType: "image/png",
|
||||
kind: "image",
|
||||
}),
|
||||
}));
|
||||
|
||||
const makeRest = () => {
|
||||
const postMock = vi.fn();
|
||||
const putMock = vi.fn();
|
||||
const getMock = vi.fn();
|
||||
const patchMock = vi.fn();
|
||||
const deleteMock = vi.fn();
|
||||
return {
|
||||
rest: {
|
||||
post: postMock,
|
||||
put: putMock,
|
||||
get: getMock,
|
||||
patch: patchMock,
|
||||
delete: deleteMock,
|
||||
} as unknown as import("@buape/carbon").RequestClient,
|
||||
postMock,
|
||||
putMock,
|
||||
getMock,
|
||||
patchMock,
|
||||
deleteMock,
|
||||
};
|
||||
};
|
||||
vi.mock("../web/media.js", async () => {
|
||||
const { discordWebMediaMockFactory } = await import("./send.test-harness.js");
|
||||
return discordWebMediaMockFactory();
|
||||
});
|
||||
|
||||
describe("sendMessageDiscord", () => {
|
||||
beforeEach(() => {
|
||||
@@ -60,7 +29,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("creates a thread", async () => {
|
||||
const { rest, getMock, postMock } = makeRest();
|
||||
const { rest, getMock, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "t1" });
|
||||
await createThreadDiscord("chan1", { name: "thread", messageId: "m1" }, { rest, token: "t" });
|
||||
expect(getMock).not.toHaveBeenCalled();
|
||||
@@ -71,7 +40,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("creates forum threads with an initial message", async () => {
|
||||
const { rest, getMock, postMock } = makeRest();
|
||||
const { rest, getMock, postMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue({ type: ChannelType.GuildForum });
|
||||
postMock.mockResolvedValue({ id: "t1" });
|
||||
await createThreadDiscord("chan1", { name: "thread" }, { rest, token: "t" });
|
||||
@@ -88,7 +57,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("creates media threads with provided content", async () => {
|
||||
const { rest, getMock, postMock } = makeRest();
|
||||
const { rest, getMock, postMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue({ type: ChannelType.GuildMedia });
|
||||
postMock.mockResolvedValue({ id: "t1" });
|
||||
await createThreadDiscord(
|
||||
@@ -108,7 +77,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("falls back when channel lookup is unavailable", async () => {
|
||||
const { rest, getMock, postMock } = makeRest();
|
||||
const { rest, getMock, postMock } = makeDiscordRest();
|
||||
getMock.mockRejectedValue(new Error("lookup failed"));
|
||||
postMock.mockResolvedValue({ id: "t1" });
|
||||
await createThreadDiscord("chan1", { name: "thread" }, { rest, token: "t" });
|
||||
@@ -121,7 +90,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("respects explicit thread type for standalone threads", async () => {
|
||||
const { rest, getMock, postMock } = makeRest();
|
||||
const { rest, getMock, postMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue({ type: ChannelType.GuildText });
|
||||
postMock.mockResolvedValue({ id: "t1" });
|
||||
await createThreadDiscord(
|
||||
@@ -139,14 +108,14 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("lists active threads by guild", async () => {
|
||||
const { rest, getMock } = makeRest();
|
||||
const { rest, getMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue({ threads: [] });
|
||||
await listThreadsDiscord({ guildId: "g1" }, { rest, token: "t" });
|
||||
expect(getMock).toHaveBeenCalledWith(Routes.guildActiveThreads("g1"));
|
||||
});
|
||||
|
||||
it("times out a member", async () => {
|
||||
const { rest, patchMock } = makeRest();
|
||||
const { rest, patchMock } = makeDiscordRest();
|
||||
patchMock.mockResolvedValue({ id: "m1" });
|
||||
await timeoutMemberDiscord(
|
||||
{ guildId: "g1", userId: "u1", durationMinutes: 10 },
|
||||
@@ -163,7 +132,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("adds and removes roles", async () => {
|
||||
const { rest, putMock, deleteMock } = makeRest();
|
||||
const { rest, putMock, deleteMock } = makeDiscordRest();
|
||||
putMock.mockResolvedValue({});
|
||||
deleteMock.mockResolvedValue({});
|
||||
await addRoleDiscord({ guildId: "g1", userId: "u1", roleId: "r1" }, { rest, token: "t" });
|
||||
@@ -173,7 +142,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("bans a member", async () => {
|
||||
const { rest, putMock } = makeRest();
|
||||
const { rest, putMock } = makeDiscordRest();
|
||||
putMock.mockResolvedValue({});
|
||||
await banMemberDiscord(
|
||||
{ guildId: "g1", userId: "u1", deleteMessageDays: 2 },
|
||||
@@ -192,7 +161,7 @@ describe("listGuildEmojisDiscord", () => {
|
||||
});
|
||||
|
||||
it("lists emojis for a guild", async () => {
|
||||
const { rest, getMock } = makeRest();
|
||||
const { rest, getMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue([{ id: "e1", name: "party" }]);
|
||||
await listGuildEmojisDiscord("g1", { rest, token: "t" });
|
||||
expect(getMock).toHaveBeenCalledWith(Routes.guildEmojis("g1"));
|
||||
@@ -205,7 +174,7 @@ describe("uploadEmojiDiscord", () => {
|
||||
});
|
||||
|
||||
it("uploads emoji assets", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "e1" });
|
||||
await uploadEmojiDiscord(
|
||||
{
|
||||
@@ -235,7 +204,7 @@ describe("uploadStickerDiscord", () => {
|
||||
});
|
||||
|
||||
it("uploads sticker assets", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "s1" });
|
||||
await uploadStickerDiscord(
|
||||
{
|
||||
@@ -272,7 +241,7 @@ describe("sendStickerDiscord", () => {
|
||||
});
|
||||
|
||||
it("sends sticker payloads", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "msg1", channel_id: "789" });
|
||||
const res = await sendStickerDiscord("channel:789", ["123"], {
|
||||
rest,
|
||||
@@ -298,7 +267,7 @@ describe("sendPollDiscord", () => {
|
||||
});
|
||||
|
||||
it("sends polls with answers", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "msg1", channel_id: "789" });
|
||||
const res = await sendPollDiscord(
|
||||
"channel:789",
|
||||
@@ -350,7 +319,7 @@ describe("retry rate limits", () => {
|
||||
});
|
||||
|
||||
it("retries on Discord rate limits", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
const rateLimitError = createMockRateLimitError(0);
|
||||
|
||||
postMock
|
||||
@@ -370,7 +339,7 @@ describe("retry rate limits", () => {
|
||||
it("uses retry_after delays when rate limited", async () => {
|
||||
vi.useFakeTimers();
|
||||
const setTimeoutSpy = vi.spyOn(global, "setTimeout");
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
const rateLimitError = createMockRateLimitError(0.5);
|
||||
|
||||
postMock
|
||||
@@ -394,7 +363,7 @@ describe("retry rate limits", () => {
|
||||
});
|
||||
|
||||
it("stops after max retry attempts", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
const rateLimitError = createMockRateLimitError(0);
|
||||
|
||||
postMock.mockRejectedValue(rateLimitError);
|
||||
@@ -410,7 +379,7 @@ describe("retry rate limits", () => {
|
||||
});
|
||||
|
||||
it("does not retry non-rate-limit errors", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock.mockRejectedValueOnce(new Error("network error"));
|
||||
|
||||
await expect(sendMessageDiscord("channel:789", "hello", { rest, token: "t" })).rejects.toThrow(
|
||||
@@ -420,7 +389,7 @@ describe("retry rate limits", () => {
|
||||
});
|
||||
|
||||
it("retries reactions on rate limits", async () => {
|
||||
const { rest, putMock } = makeRest();
|
||||
const { rest, putMock } = makeDiscordRest();
|
||||
const rateLimitError = createMockRateLimitError(0);
|
||||
|
||||
putMock.mockRejectedValueOnce(rateLimitError).mockResolvedValueOnce(undefined);
|
||||
@@ -436,7 +405,7 @@ describe("retry rate limits", () => {
|
||||
});
|
||||
|
||||
it("retries media upload without duplicating overflow text", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
const rateLimitError = createMockRateLimitError(0);
|
||||
const text = "a".repeat(2005);
|
||||
|
||||
|
||||
@@ -14,43 +14,12 @@ import {
|
||||
sendMessageDiscord,
|
||||
unpinMessageDiscord,
|
||||
} from "./send.js";
|
||||
import { makeDiscordRest } from "./send.test-harness.js";
|
||||
|
||||
vi.mock("../web/media.js", () => ({
|
||||
loadWebMedia: vi.fn().mockResolvedValue({
|
||||
buffer: Buffer.from("img"),
|
||||
fileName: "photo.jpg",
|
||||
contentType: "image/jpeg",
|
||||
kind: "image",
|
||||
}),
|
||||
loadWebMediaRaw: vi.fn().mockResolvedValue({
|
||||
buffer: Buffer.from("img"),
|
||||
fileName: "asset.png",
|
||||
contentType: "image/png",
|
||||
kind: "image",
|
||||
}),
|
||||
}));
|
||||
|
||||
const makeRest = () => {
|
||||
const postMock = vi.fn();
|
||||
const putMock = vi.fn();
|
||||
const getMock = vi.fn();
|
||||
const patchMock = vi.fn();
|
||||
const deleteMock = vi.fn();
|
||||
return {
|
||||
rest: {
|
||||
post: postMock,
|
||||
put: putMock,
|
||||
get: getMock,
|
||||
patch: patchMock,
|
||||
delete: deleteMock,
|
||||
} as unknown as import("@buape/carbon").RequestClient,
|
||||
postMock,
|
||||
putMock,
|
||||
getMock,
|
||||
patchMock,
|
||||
deleteMock,
|
||||
};
|
||||
};
|
||||
vi.mock("../web/media.js", async () => {
|
||||
const { discordWebMediaMockFactory } = await import("./send.test-harness.js");
|
||||
return discordWebMediaMockFactory();
|
||||
});
|
||||
|
||||
describe("sendMessageDiscord", () => {
|
||||
beforeEach(() => {
|
||||
@@ -58,7 +27,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("sends basic channel messages", async () => {
|
||||
const { rest, postMock, getMock } = makeRest();
|
||||
const { rest, postMock, getMock } = makeDiscordRest();
|
||||
// Channel type lookup returns a normal text channel (not a forum).
|
||||
getMock.mockResolvedValueOnce({ type: ChannelType.GuildText });
|
||||
postMock.mockResolvedValue({
|
||||
@@ -77,7 +46,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("auto-creates a forum thread when target is a Forum channel", async () => {
|
||||
const { rest, postMock, getMock } = makeRest();
|
||||
const { rest, postMock, getMock } = makeDiscordRest();
|
||||
// Channel type lookup returns a Forum channel.
|
||||
getMock.mockResolvedValueOnce({ type: ChannelType.GuildForum });
|
||||
postMock.mockResolvedValue({
|
||||
@@ -102,7 +71,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("posts media as a follow-up message in forum channels", async () => {
|
||||
const { rest, postMock, getMock } = makeRest();
|
||||
const { rest, postMock, getMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValueOnce({ type: ChannelType.GuildForum });
|
||||
postMock
|
||||
.mockResolvedValueOnce({
|
||||
@@ -138,7 +107,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("chunks long forum posts into follow-up messages", async () => {
|
||||
const { rest, postMock, getMock } = makeRest();
|
||||
const { rest, postMock, getMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValueOnce({ type: ChannelType.GuildForum });
|
||||
postMock
|
||||
.mockResolvedValueOnce({
|
||||
@@ -160,7 +129,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("starts DM when recipient is a user", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock
|
||||
.mockResolvedValueOnce({ id: "chan1" })
|
||||
.mockResolvedValueOnce({ id: "msg1", channel_id: "chan1" });
|
||||
@@ -182,7 +151,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("rejects bare numeric IDs as ambiguous", async () => {
|
||||
const { rest } = makeRest();
|
||||
const { rest } = makeDiscordRest();
|
||||
await expect(
|
||||
sendMessageDiscord("273512430271856640", "hello", { rest, token: "t" }),
|
||||
).rejects.toThrow(/Ambiguous Discord recipient/);
|
||||
@@ -195,7 +164,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("adds missing permission hints on 50013", async () => {
|
||||
const { rest, postMock, getMock } = makeRest();
|
||||
const { rest, postMock, getMock } = makeDiscordRest();
|
||||
const perms = PermissionFlagsBits.ViewChannel;
|
||||
const apiError = Object.assign(new Error("Missing Permissions"), {
|
||||
code: 50013,
|
||||
@@ -228,7 +197,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("uploads media attachments", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "msg", channel_id: "789" });
|
||||
const res = await sendMessageDiscord("channel:789", "photo", {
|
||||
rest,
|
||||
@@ -247,7 +216,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("sends media with empty text without content field", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "msg", channel_id: "789" });
|
||||
const res = await sendMessageDiscord("channel:789", "", {
|
||||
rest,
|
||||
@@ -261,7 +230,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("preserves whitespace in media captions", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "msg", channel_id: "789" });
|
||||
await sendMessageDiscord("channel:789", " spaced ", {
|
||||
rest,
|
||||
@@ -273,7 +242,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("includes message_reference when replying", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "msg1", channel_id: "789" });
|
||||
await sendMessageDiscord("channel:789", "hello", {
|
||||
rest,
|
||||
@@ -288,7 +257,7 @@ describe("sendMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("replies only on the first chunk", async () => {
|
||||
const { rest, postMock } = makeRest();
|
||||
const { rest, postMock } = makeDiscordRest();
|
||||
postMock.mockResolvedValue({ id: "msg1", channel_id: "789" });
|
||||
await sendMessageDiscord("channel:789", "a".repeat(2001), {
|
||||
rest,
|
||||
@@ -312,7 +281,7 @@ describe("reactMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("reacts with unicode emoji", async () => {
|
||||
const { rest, putMock } = makeRest();
|
||||
const { rest, putMock } = makeDiscordRest();
|
||||
await reactMessageDiscord("chan1", "msg1", "✅", { rest, token: "t" });
|
||||
expect(putMock).toHaveBeenCalledWith(
|
||||
Routes.channelMessageOwnReaction("chan1", "msg1", "%E2%9C%85"),
|
||||
@@ -320,7 +289,7 @@ describe("reactMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("normalizes variation selectors in unicode emoji", async () => {
|
||||
const { rest, putMock } = makeRest();
|
||||
const { rest, putMock } = makeDiscordRest();
|
||||
await reactMessageDiscord("chan1", "msg1", "⭐️", { rest, token: "t" });
|
||||
expect(putMock).toHaveBeenCalledWith(
|
||||
Routes.channelMessageOwnReaction("chan1", "msg1", "%E2%AD%90"),
|
||||
@@ -328,7 +297,7 @@ describe("reactMessageDiscord", () => {
|
||||
});
|
||||
|
||||
it("reacts with custom emoji syntax", async () => {
|
||||
const { rest, putMock } = makeRest();
|
||||
const { rest, putMock } = makeDiscordRest();
|
||||
await reactMessageDiscord("chan1", "msg1", "<:party_blob:123>", {
|
||||
rest,
|
||||
token: "t",
|
||||
@@ -345,7 +314,7 @@ describe("removeReactionDiscord", () => {
|
||||
});
|
||||
|
||||
it("removes a unicode emoji reaction", async () => {
|
||||
const { rest, deleteMock } = makeRest();
|
||||
const { rest, deleteMock } = makeDiscordRest();
|
||||
await removeReactionDiscord("chan1", "msg1", "✅", { rest, token: "t" });
|
||||
expect(deleteMock).toHaveBeenCalledWith(
|
||||
Routes.channelMessageOwnReaction("chan1", "msg1", "%E2%9C%85"),
|
||||
@@ -359,7 +328,7 @@ describe("removeOwnReactionsDiscord", () => {
|
||||
});
|
||||
|
||||
it("removes all own reactions on a message", async () => {
|
||||
const { rest, getMock, deleteMock } = makeRest();
|
||||
const { rest, getMock, deleteMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue({
|
||||
reactions: [
|
||||
{ emoji: { name: "✅", id: null } },
|
||||
@@ -386,7 +355,7 @@ describe("fetchReactionsDiscord", () => {
|
||||
});
|
||||
|
||||
it("returns reactions with users", async () => {
|
||||
const { rest, getMock } = makeRest();
|
||||
const { rest, getMock } = makeDiscordRest();
|
||||
getMock
|
||||
.mockResolvedValueOnce({
|
||||
reactions: [
|
||||
@@ -421,7 +390,7 @@ describe("fetchChannelPermissionsDiscord", () => {
|
||||
});
|
||||
|
||||
it("calculates permissions from guild roles", async () => {
|
||||
const { rest, getMock } = makeRest();
|
||||
const { rest, getMock } = makeDiscordRest();
|
||||
const perms = PermissionFlagsBits.ViewChannel | PermissionFlagsBits.SendMessages;
|
||||
getMock
|
||||
.mockResolvedValueOnce({
|
||||
@@ -449,7 +418,7 @@ describe("fetchChannelPermissionsDiscord", () => {
|
||||
});
|
||||
|
||||
it("treats Administrator as all permissions despite overwrites", async () => {
|
||||
const { rest, getMock } = makeRest();
|
||||
const { rest, getMock } = makeDiscordRest();
|
||||
getMock
|
||||
.mockResolvedValueOnce({
|
||||
id: "chan1",
|
||||
@@ -483,7 +452,7 @@ describe("readMessagesDiscord", () => {
|
||||
});
|
||||
|
||||
it("passes query params as an object", async () => {
|
||||
const { rest, getMock } = makeRest();
|
||||
const { rest, getMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue([]);
|
||||
await readMessagesDiscord("chan1", { limit: 5, before: "10" }, { rest, token: "t" });
|
||||
const call = getMock.mock.calls[0];
|
||||
@@ -498,7 +467,7 @@ describe("edit/delete message helpers", () => {
|
||||
});
|
||||
|
||||
it("edits message content", async () => {
|
||||
const { rest, patchMock } = makeRest();
|
||||
const { rest, patchMock } = makeDiscordRest();
|
||||
patchMock.mockResolvedValue({ id: "m1" });
|
||||
await editMessageDiscord("chan1", "m1", { content: "hello" }, { rest, token: "t" });
|
||||
expect(patchMock).toHaveBeenCalledWith(
|
||||
@@ -508,7 +477,7 @@ describe("edit/delete message helpers", () => {
|
||||
});
|
||||
|
||||
it("deletes message", async () => {
|
||||
const { rest, deleteMock } = makeRest();
|
||||
const { rest, deleteMock } = makeDiscordRest();
|
||||
deleteMock.mockResolvedValue({});
|
||||
await deleteMessageDiscord("chan1", "m1", { rest, token: "t" });
|
||||
expect(deleteMock).toHaveBeenCalledWith(Routes.channelMessage("chan1", "m1"));
|
||||
@@ -521,7 +490,7 @@ describe("pin helpers", () => {
|
||||
});
|
||||
|
||||
it("pins and unpins messages", async () => {
|
||||
const { rest, putMock, deleteMock } = makeRest();
|
||||
const { rest, putMock, deleteMock } = makeDiscordRest();
|
||||
putMock.mockResolvedValue({});
|
||||
deleteMock.mockResolvedValue({});
|
||||
await pinMessageDiscord("chan1", "m1", { rest, token: "t" });
|
||||
@@ -537,7 +506,7 @@ describe("searchMessagesDiscord", () => {
|
||||
});
|
||||
|
||||
it("uses URLSearchParams for search", async () => {
|
||||
const { rest, getMock } = makeRest();
|
||||
const { rest, getMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue({ total_results: 0, messages: [] });
|
||||
await searchMessagesDiscord(
|
||||
{ guildId: "g1", content: "hello", limit: 5 },
|
||||
@@ -548,7 +517,7 @@ describe("searchMessagesDiscord", () => {
|
||||
});
|
||||
|
||||
it("supports channel/author arrays and clamps limit", async () => {
|
||||
const { rest, getMock } = makeRest();
|
||||
const { rest, getMock } = makeDiscordRest();
|
||||
getMock.mockResolvedValue({ total_results: 0, messages: [] });
|
||||
await searchMessagesDiscord(
|
||||
{
|
||||
|
||||
41
src/discord/send.test-harness.ts
Normal file
41
src/discord/send.test-harness.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { vi } from "vitest";
|
||||
|
||||
export function discordWebMediaMockFactory() {
|
||||
return {
|
||||
loadWebMedia: vi.fn().mockResolvedValue({
|
||||
buffer: Buffer.from("img"),
|
||||
fileName: "photo.jpg",
|
||||
contentType: "image/jpeg",
|
||||
kind: "image",
|
||||
}),
|
||||
loadWebMediaRaw: vi.fn().mockResolvedValue({
|
||||
buffer: Buffer.from("img"),
|
||||
fileName: "asset.png",
|
||||
contentType: "image/png",
|
||||
kind: "image",
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
export function makeDiscordRest() {
|
||||
const postMock = vi.fn();
|
||||
const putMock = vi.fn();
|
||||
const getMock = vi.fn();
|
||||
const patchMock = vi.fn();
|
||||
const deleteMock = vi.fn();
|
||||
|
||||
return {
|
||||
rest: {
|
||||
post: postMock,
|
||||
put: putMock,
|
||||
get: getMock,
|
||||
patch: patchMock,
|
||||
delete: deleteMock,
|
||||
} as unknown as import("@buape/carbon").RequestClient,
|
||||
postMock,
|
||||
putMock,
|
||||
getMock,
|
||||
patchMock,
|
||||
deleteMock,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user