From 9c13ee60997ce875941666cbb5a30175ecce2732 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Wed, 20 Mar 2024 18:30:58 +0000 Subject: [PATCH] Add client tests --- src/client/client.ts | 10 +- tests/client/client.test.ts | 120 ++++++++++++- .../chatInputCommand.test.ts | 167 +++++++++++++++++- 3 files changed, 282 insertions(+), 15 deletions(-) diff --git a/src/client/client.ts b/src/client/client.ts index 1e16e08..0692aae 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -1,6 +1,5 @@ import { Client, Partials } from "discord.js"; import * as dotenv from "dotenv"; -import { createConnection } from "typeorm"; import { EventType } from "../constants/EventType"; import ICommandItem from "../contracts/ICommandItem"; import IEventItem from "../contracts/IEventItem"; @@ -39,9 +38,12 @@ export class CoreClient extends Client { return; } - await AppDataSource.initialize() - .then(() => console.log("Data Source Initialized")) - .catch((err) => console.error("Error Initialising Data Source", err)); + try { + await AppDataSource.initialize(); + } catch (err) { + console.error("Error Initialising Data Source", err); + return; + } super.on("interactionCreate", this._events.onInteractionCreate); super.on("ready", this._events.onReady); diff --git a/tests/client/client.test.ts b/tests/client/client.test.ts index 83a8c22..786a47b 100644 --- a/tests/client/client.test.ts +++ b/tests/client/client.test.ts @@ -1,23 +1,129 @@ +import { Partials, Client } from "discord.js"; +import { CoreClient } from "../../src/client/client"; +import * as dotenv from "dotenv"; +import AppDataSource from "../../src/database/dataSources/appDataSource"; +import { Util } from "../../src/client/util"; +import { Command } from "../../src/type/command"; +import { EventType } from "../../src/constants/EventType"; +import { ButtonEvent } from "../../src/type/buttonEvent"; + +jest.mock("dotenv"); + +beforeEach(() => { + jest.clearAllMocks(); + + process.env = {}; +}); + describe('constructor', () => { - test.todo("EXPECT properties to be set"); + test("EXPECT properties to be set", () => { + const client = new CoreClient([1, 2, 3], [Partials.User]); + + expect(dotenv.config).toHaveBeenCalledTimes(1); + + expect(client).toBeDefined(); + expect(CoreClient.commandItems).toEqual([]); + expect(CoreClient.eventItems).toEqual([]); + expect(CoreClient.buttonEvents).toEqual([]); + expect(client).toHaveProperty("_events"); + expect(client).toHaveProperty("_util"); + }); }); describe('start', () => { - test.todo("EXPECT bot to start"); + test("EXPECT bot to start", async () => { + process.env.BOT_TOKEN = "token"; + console.error = jest.fn(); + AppDataSource.initialize = jest.fn().mockResolvedValue(undefined); - test.todo("GIVEN BOT_TOKEN is not in env var, EXPECT error"); + const client = new CoreClient([1, 2, 3], [Partials.User]); - test.todo("GIVEN database connection can not be initialised, EXPECT error"); + const loadSlashCommands = jest.spyOn(Util.prototype, "loadSlashCommands").mockImplementation(); + const loadEvents = jest.spyOn(Util.prototype, "loadEvents").mockImplementation(); + + Client.prototype.login = jest.fn(); + Client.prototype.on = jest.fn(); + + await client.start(); + + expect(AppDataSource.initialize).toHaveBeenCalledTimes(1); + expect(console.error).not.toHaveBeenCalled(); + + expect(client.login).toHaveBeenCalledTimes(1); + expect(client.login).toHaveBeenCalledWith("token"); + + expect(client.on).toHaveBeenCalledTimes(2); + expect(client.on).toHaveBeenCalledWith("interactionCreate", expect.any(Function)); + expect(client.on).toHaveBeenCalledWith("ready", expect.any(Function)) + + expect(loadSlashCommands).toHaveBeenCalledTimes(1); + expect(loadSlashCommands).toHaveBeenCalledWith(client); + + expect(loadEvents).toHaveBeenCalledTimes(1); + expect(loadEvents).toHaveBeenCalledWith(client, []); + }); + + test("GIVEN BOT_TOKEN is not in env var, EXPECT error", async () => { + console.error = jest.fn(); + + const client = new CoreClient([1, 2, 3], [ Partials.User ]); + + await client.start(); + + expect(console.error).toHaveBeenCalledWith("BOT_TOKEN is not defined in .env"); + }); + + test("GIVEN database connection can not be initialised, EXPECT error", async () => { + process.env.BOT_TOKEN = "token"; + console.log = jest.fn(); + console.error = jest.fn(); + AppDataSource.initialize = jest.fn().mockRejectedValue("error"); + + const client = new CoreClient([1, 2, 3], [Partials.User]); + + await client.start(); + + expect(console.log).not.toHaveBeenCalled(); + expect(console.error).toHaveBeenCalledWith("Error Initialising Data Source", "error"); + }); }); describe('RegisterCommand', () => { - test.todo("EXPECT command to be added to list"); + test("EXPECT command to be added to list", () => { + CoreClient.RegisterCommand("name", {} as Command, "serverId"); + + expect(CoreClient.commandItems).toStrictEqual([ + { + Name: "name", + Command: {}, + ServerId: "serverId", + } + ]) + }); }); describe("RegisterEvent", () => { - test.todo("EXPECT event to be added to list"); + test("EXPECT event to be added to list", () => { + CoreClient.RegisterEvent(EventType.ChannelCreate, () => {}); + + expect(CoreClient.eventItems).toStrictEqual([ + { + EventType: EventType.ChannelCreate, + ExecutionFunction: expect.any(Function), + } + ]); + }); }); describe("RegisterButtonEvent", () => { - test.todo("EXPECT button event to be added to list"); + test("EXPECT button event to be added to list", () => { + CoreClient.RegisterButtonEvent("buttonId", {} as ButtonEvent); + + expect(CoreClient.buttonEvents).toStrictEqual([ + { + ButtonId: "buttonId", + Event: {}, + } + ]) + }); }); \ No newline at end of file diff --git a/tests/client/interactionCreate/chatInputCommand.test.ts b/tests/client/interactionCreate/chatInputCommand.test.ts index 97e8d69..8690cd8 100644 --- a/tests/client/interactionCreate/chatInputCommand.test.ts +++ b/tests/client/interactionCreate/chatInputCommand.test.ts @@ -1,9 +1,168 @@ +import { ChatInputCommandInteraction } from 'discord.js'; +import ChatInputComamnd from '../../../src/client/interactionCreate/chatInputCommand'; +import { CoreClient } from '../../../src/client/client'; +import ICommandItem from '../../../src/contracts/ICommandItem'; + +beforeEach(() => { + CoreClient.commandItems = []; +}); + describe('onChatInput', () => { - test.todo("GIVEN command is registered globally AND command is found, execute the global command"); + test("GIVEN command is registered globally AND command is found, execute the global command", async () => { + // Arrange + const interaction = { + reply: jest.fn(), + isChatInputCommand: jest.fn().mockReturnValue(true), + commandName: "test", + } as unknown as ChatInputCommandInteraction; - test.todo("GIVEN command is registered to a single server, execute the server command"); + const testCommand: ICommandItem = { + Name: "test", + Command: { + CommandBuilder: jest.fn(), + execute: jest.fn(), + }, + }; - test.todo("GIVEN interaction is not a chat input command, EXPECT nothing to happen"); + const testServerCommand: ICommandItem = { + Name: "test", + Command: { + CommandBuilder: jest.fn(), + execute: jest.fn(), + }, + ServerId: "123", + }; - test.todo("GIVEN command is registered globally AND command is not found, EXPECT error"); + CoreClient.commandItems = [ testCommand, testServerCommand ]; + + // Act + await ChatInputComamnd.onChatInput(interaction); + + // Assert + expect(interaction.isChatInputCommand).toHaveBeenCalledTimes(1); + expect(interaction.reply).not.toHaveBeenCalled(); + + expect(testCommand.Command.execute).toHaveBeenCalledTimes(1); + expect(testCommand.Command.execute).toHaveBeenCalledWith(interaction); + expect(testServerCommand.Command.execute).not.toHaveBeenCalled(); + }); + + test("GIVEN command is registered to a single server, execute the server command", async () => { + // Arrange + const interaction = { + reply: jest.fn(), + isChatInputCommand: jest.fn().mockReturnValue(true), + commandName: "test", + guildId: "123", + } as unknown as ChatInputCommandInteraction; + + const testCommand: ICommandItem = { + Name: "test", + Command: { + CommandBuilder: jest.fn(), + execute: jest.fn(), + }, + }; + + const testServerCommand: ICommandItem = { + Name: "test", + Command: { + CommandBuilder: jest.fn(), + execute: jest.fn(), + }, + ServerId: "123", + }; + + CoreClient.commandItems = [ testCommand, testServerCommand ]; + + // Act + await ChatInputComamnd.onChatInput(interaction); + + // Assert + expect(interaction.isChatInputCommand).toHaveBeenCalledTimes(1); + expect(interaction.reply).not.toHaveBeenCalled(); + + expect(testServerCommand.Command.execute).toHaveBeenCalledTimes(1); + expect(testServerCommand.Command.execute).toHaveBeenCalledWith(interaction); + expect(testCommand.Command.execute).not.toHaveBeenCalled(); + }); + + test("GIVEN interaction is not a chat input command, EXPECT nothing to happen", async () => { + // Arrange + const interaction = { + reply: jest.fn(), + isChatInputCommand: jest.fn().mockReturnValue(false), + commandName: "test", + guildId: "123", + } as unknown as ChatInputCommandInteraction; + + const testCommand: ICommandItem = { + Name: "test", + Command: { + CommandBuilder: jest.fn(), + execute: jest.fn(), + }, + }; + + const testServerCommand: ICommandItem = { + Name: "test", + Command: { + CommandBuilder: jest.fn(), + execute: jest.fn(), + }, + ServerId: "123", + }; + + CoreClient.commandItems = [ testCommand, testServerCommand ]; + + // Act + await ChatInputComamnd.onChatInput(interaction); + + // Assert + expect(interaction.isChatInputCommand).toHaveBeenCalledTimes(1); + expect(interaction.reply).not.toHaveBeenCalled(); + + expect(testServerCommand.Command.execute).not.toHaveBeenCalled(); + expect(testCommand.Command.execute).not.toHaveBeenCalled(); + }); + + test("GIVEN command is registered globally AND command is not found, EXPECT error", async () => { + // Arrange + const interaction = { + reply: jest.fn(), + isChatInputCommand: jest.fn().mockReturnValue(true), + commandName: "other", + guildId: "123", + } as unknown as ChatInputCommandInteraction; + + const testCommand: ICommandItem = { + Name: "test", + Command: { + CommandBuilder: jest.fn(), + execute: jest.fn(), + }, + }; + + const testServerCommand: ICommandItem = { + Name: "test", + Command: { + CommandBuilder: jest.fn(), + execute: jest.fn(), + }, + ServerId: "123", + }; + + CoreClient.commandItems = [ testCommand, testServerCommand ]; + + // Act + await ChatInputComamnd.onChatInput(interaction); + + // Assert + expect(interaction.isChatInputCommand).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Command not found."); + + expect(testServerCommand.Command.execute).not.toHaveBeenCalled(); + expect(testCommand.Command.execute).not.toHaveBeenCalled(); + }); }); \ No newline at end of file