/* eslint-disable unicorn/no-null */ import type { Message } from "discord.js" import { Client, TextChannel } from "discord.js" import type { ReacordRoot } from "reacord" import { createRoot, Embed, EmbedAuthor, Text } from "reacord" import { pick } from "reacord-helpers/pick.js" import { raise } from "reacord-helpers/raise.js" import React from "react" import { afterAll, beforeAll, expect, test } from "vitest" import { testBotToken, testChannelId } from "./test-environment.js" const client = new Client({ intents: ["GUILDS"], }) let channel: TextChannel let root: ReacordRoot beforeAll(async () => { await client.login(testBotToken) const result = client.channels.cache.get(testChannelId) ?? (await client.channels.fetch(testChannelId)) ?? raise("Channel not found") if (!(result instanceof TextChannel)) { throw new TypeError("Channel must be a text channel") } channel = result for (const [, message] of await channel.messages.fetch()) { await message.delete() } root = createRoot(channel) }) afterAll(() => { client.destroy() }) test("rapid updates", async () => { // rapid updates void root.render("hi world") void root.render("hi the") await root.render("hi moon") await assertMessages([{ content: "hi moon" }]) }) test("nested text", async () => { await root.render( hi world{" "} hi moon hi sun , ) await assertMessages([{ content: "hi world hi moon hi sun" }]) }) test("empty embed fallback", async () => { await root.render() await assertMessages([{ embeds: [{ description: "_ _" }] }]) }) test("embed with only author", async () => { await root.render( only author , ) await assertMessages([ { embeds: [{ description: "_ _", author: { name: "only author" } }] }, ]) }) test("empty embed author", async () => { await root.render( , ) await assertMessages([{ embeds: [{ description: "_ _" }] }]) }) test("kitchen sink", async () => { await root.render( <> message content no space description more description hi craw another hi , ) await assertMessages([ { content: "message contentno space", embeds: [ { color: 0xfe_ee_ef, description: "description more description", author: { name: "hi craw", url: "https://example.com", iconURL: "https://cdn.discordapp.com/avatars/109677308410875904/3e53fcb70760a08fa63f73376ede5d1f.png?size=1024", }, }, { author: {}, color: null, description: "another hi" }, ], }, ]) }) test("destroy", async () => { await root.destroy() await assertMessages([]) }) type MessageData = ReturnType function extractMessageData(message: Message) { return { content: message.content, embeds: message.embeds.map((embed) => ({ ...pick(embed, "color", "description"), author: embed.author ? pick(embed.author, "name", "url", "iconURL") : { name: "" }, })), } } async function assertMessages(expected: Array>) { const messages = await channel.messages.fetch() expect(messages.map((message) => extractMessageData(message))).toEqual( expected.map((message) => ({ content: "", ...message, embeds: message.embeds?.map((embed) => ({ color: null, description: "", ...embed, author: { name: "", ...embed?.author, }, })) ?? [], })), ) } type DeepPartial = Subject extends object ? { [Key in keyof Subject]?: DeepPartial } : Subject