restore old tests + more parallel things
This commit is contained in:
@@ -1,134 +0,0 @@
|
|||||||
import type { TextChannel } from "discord.js"
|
|
||||||
import { ChannelType, Client, IntentsBitField } from "discord.js"
|
|
||||||
import "dotenv/config"
|
|
||||||
import { kebabCase } from "lodash-es"
|
|
||||||
import * as React from "react"
|
|
||||||
import { useState } from "react"
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Option,
|
|
||||||
ReacordDiscordJs,
|
|
||||||
Select,
|
|
||||||
useInstance,
|
|
||||||
} from "../library/main"
|
|
||||||
|
|
||||||
const client = new Client({ intents: IntentsBitField.Flags.Guilds })
|
|
||||||
const reacord = new ReacordDiscordJs(client)
|
|
||||||
|
|
||||||
await client.login(process.env.TEST_BOT_TOKEN)
|
|
||||||
|
|
||||||
const guild = await client.guilds.fetch(process.env.TEST_GUILD_ID!)
|
|
||||||
|
|
||||||
const category = await guild.channels.fetch(process.env.TEST_CATEGORY_ID!)
|
|
||||||
if (category?.type !== ChannelType.GuildCategory) {
|
|
||||||
throw new Error(
|
|
||||||
`channel ${process.env.TEST_CATEGORY_ID} is not a guild category. received ${category?.type}`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [, channel] of category.children.cache) {
|
|
||||||
await channel.delete()
|
|
||||||
}
|
|
||||||
|
|
||||||
let prefix = 0
|
|
||||||
const createTest = async (
|
|
||||||
name: string,
|
|
||||||
block: (channel: TextChannel) => void | Promise<unknown>,
|
|
||||||
) => {
|
|
||||||
prefix += 1
|
|
||||||
const channel = await category.children.create({
|
|
||||||
type: ChannelType.GuildText,
|
|
||||||
name: `${String(prefix).padStart(3, "0")}-${kebabCase(name)}`,
|
|
||||||
})
|
|
||||||
await block(channel)
|
|
||||||
}
|
|
||||||
|
|
||||||
await createTest("basic", (channel) => {
|
|
||||||
reacord.send(channel.id, "Hello, world!")
|
|
||||||
})
|
|
||||||
|
|
||||||
await createTest("counter", (channel) => {
|
|
||||||
const Counter = () => {
|
|
||||||
const [count, setCount] = React.useState(0)
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
count: {count}
|
|
||||||
<Button
|
|
||||||
style="primary"
|
|
||||||
emoji="➕"
|
|
||||||
onClick={() => setCount(count + 1)}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
style="primary"
|
|
||||||
emoji="➖"
|
|
||||||
onClick={() => setCount(count - 1)}
|
|
||||||
/>
|
|
||||||
<Button label="reset" onClick={() => setCount(0)} />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
reacord.send(channel.id, <Counter />)
|
|
||||||
})
|
|
||||||
|
|
||||||
await createTest("select", (channel) => {
|
|
||||||
function FruitSelect({ onConfirm }: { onConfirm: (choice: string) => void }) {
|
|
||||||
const [value, setValue] = useState<string>()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Select
|
|
||||||
placeholder="choose a fruit"
|
|
||||||
value={value}
|
|
||||||
onChangeValue={setValue}
|
|
||||||
>
|
|
||||||
<Option value="🍎" emoji="🍎" label="apple" description="it red" />
|
|
||||||
<Option value="🍌" emoji="🍌" label="banana" description="bnanbna" />
|
|
||||||
<Option value="🍒" emoji="🍒" label="cherry" description="heh" />
|
|
||||||
</Select>
|
|
||||||
<Button
|
|
||||||
label="confirm"
|
|
||||||
disabled={value == undefined}
|
|
||||||
onClick={() => {
|
|
||||||
if (value) onConfirm(value)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const instance = reacord.send(
|
|
||||||
channel.id,
|
|
||||||
<FruitSelect
|
|
||||||
onConfirm={(value) => {
|
|
||||||
instance.render(`you chose ${value}`)
|
|
||||||
instance.deactivate()
|
|
||||||
}}
|
|
||||||
/>,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
await createTest("ephemeral button", (channel) => {
|
|
||||||
reacord.send(
|
|
||||||
channel.id,
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
label="public clic"
|
|
||||||
onClick={(event) =>
|
|
||||||
event.reply(`${event.guild?.member.displayName} clic`)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
label="clic"
|
|
||||||
onClick={(event) => event.ephemeralReply("you clic")}
|
|
||||||
/>
|
|
||||||
</>,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
await createTest("delete this", (channel) => {
|
|
||||||
function DeleteThis() {
|
|
||||||
const instance = useInstance()
|
|
||||||
return <Button label="delete this" onClick={() => instance.destroy()} />
|
|
||||||
}
|
|
||||||
reacord.send(channel.id, <DeleteThis />)
|
|
||||||
})
|
|
||||||
@@ -1,142 +1,185 @@
|
|||||||
import { raise } from "@reacord/helpers/raise.js"
|
|
||||||
import { waitFor } from "@reacord/helpers/wait-for.js"
|
|
||||||
import { ChannelType, Client, IntentsBitField, TextChannel } from "discord.js"
|
import { ChannelType, Client, IntentsBitField, TextChannel } from "discord.js"
|
||||||
import "dotenv/config"
|
import "dotenv/config"
|
||||||
import { kebabCase } from "lodash-es"
|
import { kebabCase } from "lodash-es"
|
||||||
import prettyMilliseconds from "pretty-ms"
|
import * as React from "react"
|
||||||
import React, { useEffect, useState } from "react"
|
import { useState } from "react"
|
||||||
import { Button, ReacordDiscordJs } from "../library.new/main"
|
import {
|
||||||
|
Button,
|
||||||
|
Option,
|
||||||
|
ReacordDiscordJs,
|
||||||
|
Select,
|
||||||
|
useInstance,
|
||||||
|
} from "../library/main"
|
||||||
|
|
||||||
const client = new Client({ intents: IntentsBitField.Flags.Guilds })
|
const client = new Client({ intents: IntentsBitField.Flags.Guilds })
|
||||||
const reacord = new ReacordDiscordJs(client)
|
const reacord = new ReacordDiscordJs(client)
|
||||||
|
|
||||||
|
type TestCase = {
|
||||||
|
name: string
|
||||||
|
run: (channel: TextChannel) => void | Promise<unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
const tests: TestCase[] = [
|
||||||
|
{
|
||||||
|
name: "basic",
|
||||||
|
run: async (channel) => {
|
||||||
|
await channel.send("hello world")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "counter",
|
||||||
|
run: (channel) => {
|
||||||
|
const Counter = () => {
|
||||||
|
const [count, setCount] = React.useState(0)
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
count: {count}
|
||||||
|
<Button
|
||||||
|
style="primary"
|
||||||
|
emoji="➕"
|
||||||
|
onClick={() => setCount(count + 1)}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
style="primary"
|
||||||
|
emoji="➖"
|
||||||
|
onClick={() => setCount(count - 1)}
|
||||||
|
/>
|
||||||
|
<Button label="reset" onClick={() => setCount(0)} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
reacord.send(channel.id, <Counter />)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ephemeral button",
|
||||||
|
run: (channel) => {
|
||||||
|
reacord.send(
|
||||||
|
channel.id,
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
label="public clic"
|
||||||
|
onClick={(event) =>
|
||||||
|
event.reply(`${event.guild?.member.displayName} clic`)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
label="clic"
|
||||||
|
onClick={(event) => event.ephemeralReply("you clic")}
|
||||||
|
/>
|
||||||
|
</>,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "select",
|
||||||
|
run: (channel) => {
|
||||||
|
function FruitSelect({
|
||||||
|
onConfirm,
|
||||||
|
}: {
|
||||||
|
onConfirm: (choice: string) => void
|
||||||
|
}) {
|
||||||
|
const [value, setValue] = useState<string>()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Select
|
||||||
|
placeholder="choose a fruit"
|
||||||
|
value={value}
|
||||||
|
onChangeValue={setValue}
|
||||||
|
>
|
||||||
|
<Option
|
||||||
|
value="🍎"
|
||||||
|
emoji="🍎"
|
||||||
|
label="apple"
|
||||||
|
description="it red"
|
||||||
|
/>
|
||||||
|
<Option
|
||||||
|
value="🍌"
|
||||||
|
emoji="🍌"
|
||||||
|
label="banana"
|
||||||
|
description="bnanbna"
|
||||||
|
/>
|
||||||
|
<Option value="🍒" emoji="🍒" label="cherry" description="heh" />
|
||||||
|
</Select>
|
||||||
|
<Button
|
||||||
|
label="confirm"
|
||||||
|
disabled={value == undefined}
|
||||||
|
onClick={() => {
|
||||||
|
if (value) onConfirm(value)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const instance = reacord.send(
|
||||||
|
channel.id,
|
||||||
|
<FruitSelect
|
||||||
|
onConfirm={(value) => {
|
||||||
|
instance.render(`you chose ${value}`)
|
||||||
|
instance.deactivate()
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "delete this",
|
||||||
|
run: (channel) => {
|
||||||
|
function DeleteThis() {
|
||||||
|
const instance = useInstance()
|
||||||
|
return <Button label="delete this" onClick={() => instance.destroy()} />
|
||||||
|
}
|
||||||
|
reacord.send(channel.id, <DeleteThis />)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
await client.login(process.env.TEST_BOT_TOKEN)
|
await client.login(process.env.TEST_BOT_TOKEN)
|
||||||
|
|
||||||
const guild = await client.guilds.fetch(process.env.TEST_GUILD_ID!)
|
const category = await client.channels.fetch(process.env.TEST_CATEGORY_ID!)
|
||||||
|
|
||||||
const category = await guild.channels.fetch(process.env.TEST_CATEGORY_ID!)
|
|
||||||
if (category?.type !== ChannelType.GuildCategory) {
|
if (category?.type !== ChannelType.GuildCategory) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`channel ${process.env.TEST_CATEGORY_ID} is not a guild category. received ${category?.type}`,
|
`channel ${process.env.TEST_CATEGORY_ID} is not a guild category. received ${category?.type}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let index = 0
|
const getTestCaseChannelName = (test: TestCase, index: number) =>
|
||||||
const createTest = async (
|
`${String(index).padStart(3, "0")}-${kebabCase(test.name)}`
|
||||||
name: string,
|
|
||||||
description: string,
|
|
||||||
block: (channel: TextChannel) => void | Promise<unknown>,
|
|
||||||
) => {
|
|
||||||
const channelName = `${String(index).padStart(3, "0")}-${kebabCase(name)}`
|
|
||||||
|
|
||||||
let channel = category.children.cache.find((ch) => ch.name === channelName)
|
const testCaseNames = new Set(
|
||||||
|
tests.map((test, index) => getTestCaseChannelName(test, index)),
|
||||||
|
)
|
||||||
|
|
||||||
|
const channelsWithoutTestCase = category.children.cache.filter(
|
||||||
|
(channel) => !testCaseNames.has(channel.name),
|
||||||
|
)
|
||||||
|
|
||||||
|
const getTestCaseChannel = async (channelName: string, index: number) => {
|
||||||
|
const channel = category.children.cache.find((ch) => ch.name === channelName)
|
||||||
if (channel instanceof TextChannel) {
|
if (channel instanceof TextChannel) {
|
||||||
for (const [, msg] of await channel.messages.fetch()) {
|
for (const [, msg] of await channel.messages.fetch()) {
|
||||||
await msg.delete()
|
await msg.delete()
|
||||||
}
|
}
|
||||||
} else {
|
return channel
|
||||||
|
}
|
||||||
|
|
||||||
await channel?.delete()
|
await channel?.delete()
|
||||||
channel = await category.children.create({
|
return await category.children.create({
|
||||||
type: ChannelType.GuildText,
|
type: ChannelType.GuildText,
|
||||||
name: channelName,
|
name: channelName,
|
||||||
topic: description,
|
|
||||||
position: index,
|
position: index,
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
await block(channel)
|
|
||||||
index += 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await createTest(
|
await Promise.all([
|
||||||
"buttons",
|
Promise.all(channelsWithoutTestCase.map((channel) => channel.delete())),
|
||||||
"should show button text, emojis, and make automatic action rows",
|
Promise.all(
|
||||||
async (channel) => {
|
tests.map(async (test, index) => {
|
||||||
reacord.send(
|
const channelName = getTestCaseChannelName(test, index)
|
||||||
channel.id,
|
const channel = await getTestCaseChannel(channelName, index)
|
||||||
<>
|
await test.run(channel)
|
||||||
<Button label="strawberry" onClick={() => {}} />
|
}),
|
||||||
<Button emoji="🍓" onClick={() => {}} />
|
),
|
||||||
<Button label="strawberry" emoji="🍓" onClick={() => {}} />
|
])
|
||||||
</>,
|
|
||||||
)
|
|
||||||
reacord.send(
|
|
||||||
channel.id,
|
|
||||||
<>
|
|
||||||
<Button label="primary" style="primary" onClick={() => {}} />
|
|
||||||
<Button label="secondary" style="secondary" onClick={() => {}} />
|
|
||||||
<Button label="success" style="success" onClick={() => {}} />
|
|
||||||
<Button label="danger" style="danger" onClick={() => {}} />
|
|
||||||
</>,
|
|
||||||
)
|
|
||||||
reacord.send(
|
|
||||||
channel.id,
|
|
||||||
<>
|
|
||||||
<Button label="disabled" disabled onClick={() => {}} />
|
|
||||||
</>,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
await createTest("basic", "should update over time", (channel) => {
|
|
||||||
function Timer() {
|
|
||||||
const [startDate] = useState(() => new Date())
|
|
||||||
const [currentDate, setCurrentDate] = useState(startDate)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const id = setInterval(() => {
|
|
||||||
setCurrentDate(new Date())
|
|
||||||
}, 3000)
|
|
||||||
return () => clearInterval(id)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
this component has been running for{" "}
|
|
||||||
{prettyMilliseconds(currentDate.valueOf() - startDate.valueOf(), {
|
|
||||||
verbose: true,
|
|
||||||
})}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
reacord.send(channel.id, <Timer />)
|
|
||||||
})
|
|
||||||
|
|
||||||
await createTest(
|
|
||||||
"immediate renders",
|
|
||||||
`should process renders in sequence; this should show "hi moon"`,
|
|
||||||
async (channel) => {
|
|
||||||
const instance = reacord.send(channel.id)
|
|
||||||
instance.render("hi world")
|
|
||||||
instance.render("hi moon")
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
await createTest(
|
|
||||||
"destroy",
|
|
||||||
"should remove the message; this channel should be empty",
|
|
||||||
async (channel) => {
|
|
||||||
const instance = reacord.send(channel.id)
|
|
||||||
instance.render("hi world")
|
|
||||||
instance.render("hi moon")
|
|
||||||
await waitFor(async () => {
|
|
||||||
const messages = await channel.messages.fetch({ limit: 1 })
|
|
||||||
if (messages.first()?.content !== "hi moon") {
|
|
||||||
raise("not ready")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
instance.destroy()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
await createTest(
|
|
||||||
"immediate destroy",
|
|
||||||
"should never show if called immediately; this channel should be empty",
|
|
||||||
async (channel) => {
|
|
||||||
const instance = reacord.send(channel.id)
|
|
||||||
instance.render("hi world")
|
|
||||||
instance.render("hi moon")
|
|
||||||
instance.destroy()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user