From 03631e3c6ec245a3e94b7ffa7e28db32fa4e70ed Mon Sep 17 00:00:00 2001 From: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Date: Fri, 9 Apr 2021 12:46:38 +0000 Subject: [PATCH] refactor: base complete for unit tests --- src/structures/guild.ts | 4 +- src/util/utils.ts | 4 +- tests/README.md | 23 ++++++++ {test => tests}/deps.ts | 0 tests/guilds/create_guild.ts | 23 ++++++++ tests/guilds/delete_server.ts | 19 +++++++ tests/mod.ts | 14 +++++ .../util/utils.test.ts => tests/util/utils.ts | 0 test/mod.test.ts => tests/ws/start_bot.ts | 56 ++----------------- tests/ws/ws_close.ts | 16 ++++++ 10 files changed, 104 insertions(+), 55 deletions(-) create mode 100644 tests/README.md rename {test => tests}/deps.ts (100%) create mode 100644 tests/guilds/create_guild.ts create mode 100644 tests/guilds/delete_server.ts create mode 100644 tests/mod.ts rename test/util/utils.test.ts => tests/util/utils.ts (100%) rename test/mod.test.ts => tests/ws/start_bot.ts (84%) create mode 100644 tests/ws/ws_close.ts diff --git a/src/structures/guild.ts b/src/structures/guild.ts index 488450f11..284934f09 100644 --- a/src/structures/guild.ts +++ b/src/structures/guild.ts @@ -131,7 +131,7 @@ export async function createGuildStruct( } = snakeKeysToCamelCase(data) as Guild; const roles = await Promise.all( - data.roles.map((role) => + (data.roles || []).map((role) => structures.createRoleStruct({ role, guild_id: rest.id }) ), ); @@ -163,7 +163,7 @@ export async function createGuildStruct( ), memberCount: createNewProp(memberCount), emojis: createNewProp( - new Collection(emojis.map((emoji) => [emoji.id ?? emoji.name, emoji])), + new Collection((emojis || []).map((emoji) => [emoji.id ?? emoji.name, emoji])), ), voiceStates: createNewProp( new Collection( diff --git a/src/util/utils.ts b/src/util/utils.ts index 4d97a83bf..7b55f94f4 100644 --- a/src/util/utils.ts +++ b/src/util/utils.ts @@ -74,8 +74,8 @@ function isObject(obj: unknown) { ); } -// deno-lint-ignore no-explicit-any export function camelKeysToSnakeCase( + // deno-lint-ignore no-explicit-any obj: Record | Record[], ): T { if (isObject(obj)) { @@ -96,8 +96,8 @@ export function camelKeysToSnakeCase( return obj as T; } -// deno-lint-ignore no-explicit-any export function snakeKeysToCamelCase( + // deno-lint-ignore no-explicit-any obj: Record | Record[], ): T { if (isObject(obj)) { diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 000000000..8c6f43821 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,23 @@ +# Discordeno Unit Test Guideline + +Unit tests are MANDATORY! + +Every time you create a new function in the library, you must also add a unit test for it. A PR should/will not be merged without a valid unit test for it. If you are unable to create a unit test, please leave a comment in your PR asking for help. + +## Test Locally + +You do not need to push to the github repo to have the CI do the tests for you. You can test them locally by doing the following: + +```shell +DISCORD_TOKEN=YOUR_BOT_TOKEN_HERE deno test --no-check -A tests/mod.ts +``` + +> Please note that the token you use should be for a trivial unused bot. Never use your main bot tokens for this. + +## Ordering + +The order of unit tests is very important. Please do not move/change the order of the tests unless you know what you are doing. Certain tests depend on other previous tests. You may add a test but becareful where you add it. + +## Naming + +Each function should have it's own separate file for it's tests. The file should be organized under it's main category which will be the `[]` portion of the tests name. For example, `[guild] create a new guild` will be found in `tests/guilds/create_guild.ts` diff --git a/test/deps.ts b/tests/deps.ts similarity index 100% rename from test/deps.ts rename to tests/deps.ts diff --git a/tests/guilds/create_guild.ts b/tests/guilds/create_guild.ts new file mode 100644 index 000000000..bf7ec974b --- /dev/null +++ b/tests/guilds/create_guild.ts @@ -0,0 +1,23 @@ +import { cache, createGuild, delay } from "../../mod.ts"; +import { tempData, defaultTestOptions } from "../ws/start_bot.ts"; +import { assertExists, assertEquals } from "../deps.ts"; + +Deno.test({ + name: "[guild] create a new guild", + async fn() { + const guild = await createGuild({ + name: "Discordeno Test", + }); + console.log(guild); + + // Assertions + assertExists(guild); + + tempData.guildId = guild.id; + assertEquals(tempData.guildId, guild.id); + + // Delay the execution by 5 seconds to allow GUILD_CREATE event to be processed + await delay(5000); + }, + ...defaultTestOptions, +}); diff --git a/tests/guilds/delete_server.ts b/tests/guilds/delete_server.ts new file mode 100644 index 000000000..a6fc0f42f --- /dev/null +++ b/tests/guilds/delete_server.ts @@ -0,0 +1,19 @@ +import { cache, deleteServer, delay } from "../../mod.ts"; +import { tempData, defaultTestOptions } from "../ws/start_bot.ts"; + +Deno.test({ + name: "[guild] delete a guild", + async fn() { + if (!tempData.guildId) + throw new Error("The guild id was not available to be deleted."); + if (!cache.guilds.has(tempData.guildId)) + throw new Error("The guild was not cached so impossible to delete."); + + await deleteServer(tempData.guildId); + await delay(3000); + + if (cache.guilds.has(tempData.guildId)) + throw new Error("The guild was not able to be deleted."); + }, + ...defaultTestOptions, +}); diff --git a/tests/mod.ts b/tests/mod.ts new file mode 100644 index 000000000..e99fc3c18 --- /dev/null +++ b/tests/mod.ts @@ -0,0 +1,14 @@ +// THE ORDER OF THE IMPORTS IN THIS FILE MATTER! +// DO NOT MOVE THEM UNLESS YOU KNOW WHAT YOUR DOING! + +// First complete non-api reliant testing. +// Don't waste api rate limits if a early test fails. +import "./util/utils.ts"; + +// API TESTING BELOW + +// First initate the connection +import "./ws/start_bot.ts"; +import "./guilds/create_guild.ts"; +import "./guilds/delete_server.ts"; +import "./ws/ws_close.ts"; diff --git a/test/util/utils.test.ts b/tests/util/utils.ts similarity index 100% rename from test/util/utils.test.ts rename to tests/util/utils.ts diff --git a/test/mod.test.ts b/tests/ws/start_bot.ts similarity index 84% rename from test/mod.test.ts rename to tests/ws/start_bot.ts index 0ff2f5b47..f78ebb9b8 100644 --- a/test/mod.test.ts +++ b/tests/ws/start_bot.ts @@ -1,5 +1,7 @@ -import { botId, delay, startBot, ws } from "../mod.ts"; -import { assertExists } from "./deps.ts"; +import { startBot, botId } from "../../src/bot.ts"; +import { delay } from "../../src/util/utils.ts"; +import { ws } from "../../src/ws/ws.ts"; +import { assertExists } from "../deps.ts"; // Set necessary settings // Disables the logger which logs everything @@ -23,9 +25,8 @@ export const tempData = { messageId: "", }; -// Main Deno.test({ - name: "[main] connect to gateway", + name: "[ws] connect to gateway", async fn() { const token = Deno.env.get("DISCORD_TOKEN"); if (!token) throw new Error("Token is not provided"); @@ -44,26 +45,6 @@ Deno.test({ ...defaultTestOptions, }); -// Guild - -// Deno.test({ -// name: "[guild] create a new guild", -// async fn() { -// const guild = await createGuild({ -// name: "Discordeno Test", -// }) as Guild; - -// // Assertions -// assertExists(guild); - -// tempData.guildId = guild.id; - -// // Delay the execution by 5 seconds to allow GUILD_CREATE event to be processed -// await delay(5000); -// }, -// ...defaultTestOptions, -// }); - // // Role // Deno.test({ @@ -297,30 +278,3 @@ Deno.test({ // }, // ...defaultTestOptions, // }); - -// Deno.test({ -// name: "[guild] delete a guild", -// async fn() { -// await deleteServer(tempData.guildId); - -// // TODO(ayntee): remove this weird shit lol -// // TODO(ayntee): check if the GUILD_DELETE event is fired -// tempData.guildId = ""; -// assertEquals(tempData.guildId, ""); -// }, -// ...defaultTestOptions, -// }); - -// Exit the Deno process once all tests are done. -Deno.test({ - name: "[main] Close all shards manually.", - async fn() { - ws.shards.forEach((shard) => { - clearInterval(shard.heartbeat.intervalId); - shard.ws.close(3064, "Discordeno Testing Finished! Do Not RESUME!"); - }); - - await delay(3000); - }, - ...defaultTestOptions, -}); diff --git a/tests/ws/ws_close.ts b/tests/ws/ws_close.ts new file mode 100644 index 000000000..76be8db08 --- /dev/null +++ b/tests/ws/ws_close.ts @@ -0,0 +1,16 @@ +import { ws, delay } from "../../mod.ts"; +import { defaultTestOptions } from "./start_bot.ts"; + +// Exit the Deno process once all tests are done. +Deno.test({ + name: "[ws] Close all shards manually.", + async fn() { + ws.shards.forEach((shard) => { + clearInterval(shard.heartbeat.intervalId); + shard.ws.close(3064, "Discordeno Testing Finished! Do Not RESUME!"); + }); + + await delay(3000); + }, + ...defaultTestOptions, +});