170 lines
6.1 KiB
TypeScript
170 lines
6.1 KiB
TypeScript
/*
|
|
* Slopbot backend tests: discord.js message mapping and paging. Offline, fake fetcher.
|
|
* Run with: pnpm test:media (from poc/).
|
|
*/
|
|
|
|
import assert from "node:assert/strict";
|
|
import { SlopbotBackend, type SlopbotFetcher } from "../slopbot/backend.js";
|
|
import { mapSlopbotMessage } from "../slopbot/backend.js";
|
|
|
|
let failures = 0;
|
|
|
|
async function test(name: string, fn: () => void | Promise<void>): Promise<void> {
|
|
try {
|
|
await fn();
|
|
console.log(`ok - ${name}`);
|
|
} catch (error) {
|
|
failures++;
|
|
console.error(`not ok - ${name}`);
|
|
console.error(error);
|
|
}
|
|
}
|
|
|
|
const noFlags = { has: () => false };
|
|
const voiceFlags = { has: (bit: number) => (bit & (1 << 13)) !== 0 };
|
|
|
|
function discordMessage(extra: Record<string, unknown> = {}) {
|
|
return {
|
|
id: "1000",
|
|
author: { id: "7", username: "user", avatar: "abc" },
|
|
content: "hello",
|
|
createdAt: new Date("2026-09-16T12:00:00.000Z"),
|
|
editedAt: null,
|
|
reference: null,
|
|
flags: noFlags,
|
|
attachments: new Map(),
|
|
embeds: [],
|
|
stickers: new Map(),
|
|
messageSnapshots: new Map(),
|
|
...extra
|
|
};
|
|
}
|
|
|
|
class FakeFetcher implements SlopbotFetcher {
|
|
readonly calls: Array<{ channelId: string; limit: number; before?: string }> = [];
|
|
|
|
constructor(private readonly pages: unknown[][]) {}
|
|
|
|
async fetchMessages(channelId: string, options: { limit: number; before?: string }): Promise<unknown[]> {
|
|
this.calls.push({ channelId, ...options });
|
|
return this.pages.shift() ?? [];
|
|
}
|
|
}
|
|
|
|
void (async () => {
|
|
await test("maps attachments, embeds, stickers, and replies", () => {
|
|
const mapped = mapSlopbotMessage(
|
|
discordMessage({
|
|
reference: { messageId: "900" },
|
|
attachments: new Map([
|
|
[
|
|
"a1",
|
|
{
|
|
id: "a1",
|
|
name: "pic.png",
|
|
url: "https://cdn.discordapp.com/attachments/1/pic.png",
|
|
contentType: "image/png",
|
|
size: 10,
|
|
width: 5,
|
|
height: 6,
|
|
duration: null
|
|
}
|
|
]
|
|
]),
|
|
embeds: [
|
|
{
|
|
data: {
|
|
type: "video",
|
|
url: "https://www.youtube.com/watch?v=x",
|
|
provider: { name: "YouTube" },
|
|
video: { url: "https://www.youtube.com/embed/x" },
|
|
image: null,
|
|
thumbnail: { url: "https://i.ytimg.com/vi/x/hqdefault.jpg" }
|
|
}
|
|
}
|
|
],
|
|
stickers: new Map([["s1", { id: "s1", name: "wave", format: 4 }]])
|
|
})
|
|
);
|
|
|
|
assert.equal(mapped.attachments[0].filename, "pic.png");
|
|
assert.equal(mapped.attachments[0].contentType, "image/png");
|
|
assert.equal(mapped.attachments[0].size, 10);
|
|
assert.equal(mapped.embeds[0].provider, "YouTube");
|
|
assert.equal(mapped.embeds[0].videoUrl, "https://www.youtube.com/embed/x");
|
|
assert.equal(mapped.stickerItems[0].formatType, 4);
|
|
assert.equal(mapped.replyTo?.id, "900");
|
|
assert.equal(mapped.voiceMessage, false);
|
|
assert.equal(mapped.timestamp, "2026-09-16T12:00:00.000Z");
|
|
});
|
|
|
|
await test("maps forwarded snapshots and voice flags", () => {
|
|
const mapped = mapSlopbotMessage(
|
|
discordMessage({
|
|
flags: voiceFlags,
|
|
messageSnapshots: new Map([
|
|
[
|
|
"s1",
|
|
{
|
|
content: "forwarded",
|
|
createdAt: new Date("2026-09-15T00:00:00.000Z"),
|
|
flags: noFlags,
|
|
attachments: new Map([
|
|
[
|
|
"a2",
|
|
{
|
|
id: "a2",
|
|
name: "clip.webm",
|
|
url: "https://cdn.discordapp.com/attachments/1/clip.webm",
|
|
contentType: "video/webm",
|
|
size: null,
|
|
width: null,
|
|
height: null,
|
|
duration: null
|
|
}
|
|
]
|
|
]),
|
|
embeds: [],
|
|
stickers: new Map()
|
|
}
|
|
]
|
|
])
|
|
})
|
|
);
|
|
|
|
assert.equal(mapped.voiceMessage, true);
|
|
assert.equal(mapped.forwarded.length, 1);
|
|
assert.equal(mapped.forwarded[0].content, "forwarded");
|
|
assert.equal(mapped.forwarded[0].attachments[0].filename, "clip.webm");
|
|
});
|
|
|
|
await test("backend pages oldest first and passes before and limit", async () => {
|
|
const fetcher = new FakeFetcher([
|
|
[discordMessage({ id: "1002" }), discordMessage({ id: "1001" })],
|
|
[discordMessage({ id: "999" })]
|
|
]);
|
|
const backend = new SlopbotBackend(fetcher);
|
|
|
|
const page = await backend.fetchPage("123", null, 2);
|
|
assert.deepEqual(
|
|
page.messages.map(message => message.id),
|
|
["1001", "1002"]
|
|
);
|
|
assert.deepEqual(fetcher.calls[0], { channelId: "123", limit: 2 });
|
|
|
|
const next = await backend.fetchPage("123", "1001", 2);
|
|
assert.deepEqual(
|
|
next.messages.map(message => message.id),
|
|
["999"]
|
|
);
|
|
assert.deepEqual(fetcher.calls[1], { channelId: "123", limit: 2, before: "1001" });
|
|
});
|
|
|
|
if (failures > 0) {
|
|
console.error(`${failures} test(s) failed`);
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log("all slopbot tests passed");
|
|
})();
|