From e860a19bfeb8d2b3d1d6dec3b73b175e9964b8bb Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Wed, 27 Mar 2024 16:49:39 +0000 Subject: [PATCH] Create audits command tests --- src/commands/audits.ts | 3 +- tests/commands/audits.test.ts | 767 ++++++++++++++++++++++++++++++++-- 2 files changed, 742 insertions(+), 28 deletions(-) diff --git a/src/commands/audits.ts b/src/commands/audits.ts index 55c7fa9..fe324ef 100644 --- a/src/commands/audits.ts +++ b/src/commands/audits.ts @@ -60,8 +60,7 @@ export default class Audits extends Command { { name: 'Mute', value: AuditType.Mute.toString() }, { name: 'Kick', value: AuditType.Kick.toString() }, { name: 'Ban', value: AuditType.Ban.toString() }, - ) - .setRequired(true)) + )) .addStringOption(option => option .setName('reason') diff --git a/tests/commands/audits.test.ts b/tests/commands/audits.test.ts index a876ce0..1085e19 100644 --- a/tests/commands/audits.test.ts +++ b/tests/commands/audits.test.ts @@ -1,63 +1,778 @@ +import { CommandInteraction, EmbedBuilder, PermissionsBitField, SlashCommandBuilder, SlashCommandStringOption, SlashCommandSubcommandBuilder, SlashCommandUserOption } from "discord.js"; +import Audits from "../../src/commands/audits"; +import Audit from "../../src/database/entities/Audit"; +import { AuditType } from "../../src/constants/AuditType"; +import AuditTools from "../../src/helpers/AuditTools"; +import EmbedColours from "../../src/constants/EmbedColours"; +import StringTools from "../../src/helpers/StringTools"; + describe("constructor", () => { - test.todo("EXPECT properties to be set"); + test("EXPECT properties to be set", () => { + const audits = new Audits(); + + expect(audits.CommandBuilder).toBeDefined(); + + const commandBuilder = audits.CommandBuilder as SlashCommandBuilder; + + expect(commandBuilder.name).toBe("audits"); + expect(commandBuilder.description).toBe("View audits of a particular user in the server"); + expect(commandBuilder.default_member_permissions).toBe(PermissionsBitField.Flags.ModerateMembers.toString()); + expect(commandBuilder.options.length).toBe(4); + + const userSubcommand = commandBuilder.options[0] as SlashCommandSubcommandBuilder; + + expect(userSubcommand.name).toBe("user"); + expect(userSubcommand.description).toBe("View all audits done against a user"); + expect(userSubcommand.options.length).toBe(1); + + const userSubcommandUserOption = userSubcommand.options[0] as SlashCommandUserOption; + + expect(userSubcommandUserOption.name).toBe("target"); + expect(userSubcommandUserOption.description).toBe("The user"); + expect(userSubcommandUserOption.required).toBe(true); + + const viewSubcommand = commandBuilder.options[1] as SlashCommandSubcommandBuilder; + + expect(viewSubcommand.name).toBe("view"); + expect(viewSubcommand.description).toBe("View a particular audit"); + expect(viewSubcommand.options.length).toBe(1); + + const viewSubcommandAuditIdOption = viewSubcommand.options[0] as SlashCommandStringOption; + + expect(viewSubcommandAuditIdOption.name).toBe("auditid"); + expect(viewSubcommandAuditIdOption.description).toBe("The audit id in caps"); + expect(viewSubcommandAuditIdOption.required).toBe(true); + + const clearSubcommand = commandBuilder.options[2] as SlashCommandSubcommandBuilder; + + expect(clearSubcommand.name).toBe("clear"); + expect(clearSubcommand.description).toBe("Clears an audit from a user"); + expect(clearSubcommand.options.length).toBe(1); + + const clearSubcommandAuditIdOption = clearSubcommand.options[0] as SlashCommandStringOption; + + expect(clearSubcommandAuditIdOption.name).toBe("auditid"); + expect(clearSubcommandAuditIdOption.description).toBe("The audit id in caps"); + expect(clearSubcommandAuditIdOption.required).toBe(true); + + const addSubcommand = commandBuilder.options[3] as SlashCommandSubcommandBuilder; + + expect(addSubcommand.name).toBe("add"); + expect(addSubcommand.description).toBe("Manually add an audit"); + expect(addSubcommand.options.length).toBe(3); + + const addSubcommandUserOption = addSubcommand.options[0] as SlashCommandUserOption; + + expect(addSubcommandUserOption.name).toBe("target"); + expect(addSubcommandUserOption.description).toBe("The user"); + expect(addSubcommandUserOption.required).toBe(true); + + const addSubcommandTypeOption = addSubcommand.options[1] as SlashCommandStringOption; + + expect(addSubcommandTypeOption.name).toBe("type"); + expect(addSubcommandTypeOption.description).toBe("The type of audit"); + expect(addSubcommandTypeOption.required).toBe(true); + expect(addSubcommandTypeOption.choices).toBeDefined(); + expect(addSubcommandTypeOption.choices!.length).toBe(5); + + const addSubcommandReasonOption = addSubcommand.options[2] as SlashCommandStringOption; + + expect(addSubcommandReasonOption.name).toBe("reason"); + expect(addSubcommandReasonOption.description).toBe("The reason"); + }); }); describe('execute', () => { - test.todo("GIVEN interaction is not a chat input command, EXPECT nothing to happen"); + test("GIVEN interaction is not a chat input command, EXPECT nothing to happen", async () => { + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(false), + reply: jest.fn(), + } as unknown as CommandInteraction; - test.todo("GIVEN subcommand is invalid, EXPECT error"); + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.isChatInputCommand).toHaveBeenCalledTimes(1); + expect(interaction.reply).not.toHaveBeenCalled(); + }); + + test("GIVEN subcommand is invalid, EXPECT error", async () => { + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("invalid"), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Subcommand doesn't exist."); + }); }); describe("user", () => { - test.todo("EXPECT audits for user to be sent"); + test("EXPECT audits for user to be sent", async () => { + let repliedWith; - test.todo("GIVEN interaction.guildId is null, EXPECT nothing to happen"); + const user = { + id: "userId", + }; + const audit = { + AuditId: "auditId", + AuditType: AuditType.Warn, + WhenCreated: new Date(5 * 60 * 1000), + }; - test.todo("GIVEN user is null, EXPECT error"); + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("user"), + getUser: jest.fn().mockReturnValue(user), + }, + guildId: "guildId", + reply: jest.fn().mockImplementation((options) => { + repliedWith = options; + }) + } as unknown as CommandInteraction; - test.todo("GIVEN audits null, EXPECT no audits to be displayed"); + Audit.FetchAuditsByUserId = jest.fn().mockReturnValue([ audit ]); + AuditTools.TypeToFriendlyText = jest.fn().mockReturnValue("Warn"); - test.todo("GIVEN audits length is 0, EXPECT no audits to be displayed"); + const audits = new Audits(); + await audits.execute(interaction); + + expect(Audit.FetchAuditsByUserId).toHaveBeenCalledTimes(1); + expect(Audit.FetchAuditsByUserId).toHaveBeenCalledWith("userId", "guildId"); + + expect(AuditTools.TypeToFriendlyText).toHaveBeenCalledTimes(1); + expect(AuditTools.TypeToFriendlyText).toHaveBeenCalledWith(AuditType.Warn); + + expect(interaction.options.getUser).toHaveBeenCalledTimes(1); + expect(interaction.options.getUser).toHaveBeenCalledWith("target"); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(repliedWith).toBeDefined(); + expect(repliedWith!.embeds).toBeDefined(); + expect(repliedWith!.embeds.length).toBe(1); + + const embed = repliedWith!.embeds[0] as EmbedBuilder; + + expect(embed.data.color).toBe(EmbedColours.Ok); + expect(embed.data.title).toBe("Audits"); + expect(embed.data.description).toBe("Audits: 1"); + expect(embed.data.fields).toBeDefined(); + expect(embed.data.fields?.length).toBe(1); + + const embedField = embed.data.fields![0]; + + expect(embedField.name).toBe("auditId // Warn"); + expect(embedField.value).toBe(new Date(5 * 60 * 1000).toString()); + }); + + test("GIVEN interaction.guildId is null, EXPECT nothing to happen", async () => { + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("user"), + }, + guildId: null, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.reply).not.toHaveBeenCalled(); + }); + + test("GIVEN user is null, EXPECT error", async () => { + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("user"), + getUser: jest.fn().mockReturnValue(null), + }, + guildId: "guildId", + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.options.getUser).toHaveBeenCalledTimes(1); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("User not found."); + }); + + test("GIVEN audits null, EXPECT no audits to be displayed", async () => { + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("user"), + getUser: jest.fn().mockReturnValue({}), + }, + guildId: "guildId", + reply: jest.fn(), + } as unknown as CommandInteraction; + + Audit.FetchAuditsByUserId = jest.fn().mockResolvedValue(null); + + const audits = new Audits(); + await audits.execute(interaction); + + expect(Audit.FetchAuditsByUserId).toHaveBeenCalledTimes(1); + + expect(interaction.options.getUser).toHaveBeenCalledTimes(1); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("There are no audits for this user."); + }); + + test("GIVEN audits length is 0, EXPECT no audits to be displayed", async () => { + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("user"), + getUser: jest.fn().mockReturnValue({}), + }, + guildId: "guildId", + reply: jest.fn(), + } as unknown as CommandInteraction; + + Audit.FetchAuditsByUserId = jest.fn().mockResolvedValue([]); + + const audits = new Audits(); + await audits.execute(interaction); + + expect(Audit.FetchAuditsByUserId).toHaveBeenCalledTimes(1); + + expect(interaction.options.getUser).toHaveBeenCalledTimes(1); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("There are no audits for this user."); + }); }); describe("view", () => { - test.todo("EXPECT specific audit defaults to be sent"); + test("EXPECT specific audit defaults to be sent", async () => { + let repliedWith; - test.todo("GIVEN interaction.guildId is null, expect nothing to happen"); + const auditOption = { + value: "auditId", + }; - test.todo("GIVEN auditId is null, EXPECT error"); + const audit = { + Reason: "Test reason", + AuditType: AuditType.Warn, + ModeratorId: "moderatorId", + AuditId: "auditId", + }; - test.todo("GIVEN auditId.value is undefined, EXPECT error"); + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("view"), + get: jest.fn().mockReturnValue(auditOption), + }, + reply: jest.fn().mockImplementation((options) => { + repliedWith = options; + }), + } as unknown as CommandInteraction; - test.todo("GIVEN audit is not in database, EXPECT error"); + Audit.FetchAuditByAuditId = jest.fn().mockResolvedValue(audit); + AuditTools.TypeToFriendlyText = jest.fn().mockReturnValue("Warn"); - test.todo("GIVEN audit.Reason was not supplied, EXPECT reason to be defaulted"); + const audits = new Audits(); + await audits.execute(interaction); + + expect(Audit.FetchAuditByAuditId).toHaveBeenCalledTimes(1); + expect(Audit.FetchAuditByAuditId).toHaveBeenCalledWith("AUDITID", "guildId"); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(repliedWith).toBeDefined(); + expect(repliedWith!.embeds).toBeDefined(); + expect(repliedWith!.embeds.length).toBe(1); + + const embed = repliedWith!.embeds[0] as EmbedBuilder; + + expect(embed.data.color).toBe(EmbedColours.Ok); + expect(embed.data.title).toBe("Audit"); + expect(embed.data.description).toBe("AUDITID"); + expect(embed.data.fields).toBeDefined(); + expect(embed.data.fields!.length).toBe(3); + + const embedReasonField = embed.data.fields![0]; + + expect(embedReasonField.name).toBe("Reason"); + expect(embedReasonField.value).toBe("Test reason"); + expect(embedReasonField.inline).toBe(true); + + const embedTypeField = embed.data.fields![1]; + + expect(embedTypeField.name).toBe("Type"); + expect(embedTypeField.value).toBe("Warn"); + expect(embedTypeField.inline).toBe(true); + + const embedModeratorField = embed.data.fields![2]; + + expect(embedModeratorField.name).toBe("Moderator"); + expect(embedModeratorField.value).toBe("<@moderatorId>"); + expect(embedModeratorField.inline).toBe(true); + }); + + test("GIVEN interaction.guildId is null, expect nothing to happen", async () => { + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("view"), + }, + guildId: null, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.reply).not.toHaveBeenCalled(); + }); + + test("GIVEN auditId is null, EXPECT error", async () => { + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("view"), + get: jest.fn().mockReturnValue(null), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.options.get).toHaveBeenCalledTimes(1); + expect(interaction.options.get).toHaveBeenCalledWith("auditid"); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("AuditId not found."); + }); + + test("GIVEN auditId.value is undefined, EXPECT error", async () => { + const audit = { + value: undefined, + } + + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("view"), + get: jest.fn().mockReturnValue(audit), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.options.get).toHaveBeenCalledTimes(1); + expect(interaction.options.get).toHaveBeenCalledWith("auditid"); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("AuditId not found."); + }); + + test("GIVEN audit is not in database, EXPECT error", async () => { + const audit = { + value: "auditId", + } + + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("view"), + get: jest.fn().mockReturnValue(audit), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + Audit.FetchAuditByAuditId = jest.fn().mockResolvedValue(null); + + const audits = new Audits(); + await audits.execute(interaction); + + expect(Audit.FetchAuditByAuditId).toHaveBeenCalledTimes(1); + + expect(interaction.options.get).toHaveBeenCalledTimes(1); + expect(interaction.options.get).toHaveBeenCalledWith("auditid"); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Audit not found."); + }); + + test("GIVEN audit.Reason was not supplied, EXPECT reason to be defaulted", async () => { + let repliedWith; + + const auditOption = { + value: "auditId", + }; + + const audit = { + Reason: undefined, + AuditType: AuditType.Warn, + ModeratorId: "moderatorId", + AuditId: "auditId", + }; + + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("view"), + get: jest.fn().mockReturnValue(auditOption), + }, + reply: jest.fn().mockImplementation((options) => { + repliedWith = options; + }), + } as unknown as CommandInteraction; + + Audit.FetchAuditByAuditId = jest.fn().mockResolvedValue(audit); + AuditTools.TypeToFriendlyText = jest.fn().mockReturnValue("Warn"); + + const audits = new Audits(); + await audits.execute(interaction); + + const embed = repliedWith!.embeds[0] as EmbedBuilder; + + const embedReasonField = embed.data.fields![0]; + + expect(embedReasonField.name).toBe("Reason"); + expect(embedReasonField.value).toBe("*none*"); + expect(embedReasonField.inline).toBe(true); + }); }); describe("clear", () => { - test.todo("EXPECT audit to be cleared"); + test("EXPECT audit to be cleared", async () => { + const auditOption = { + value: "auditId", + } - test.todo("GIVEN interaction.guildId is null, EXPECT nothing to happen"); + const audit = {}; - test.todo("GIVEN auditId is null, EXPECT error"); + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("clear"), + get: jest.fn().mockReturnValue(auditOption), + }, + guildId: "guildId", + reply: jest.fn(), + } as unknown as CommandInteraction; - test.todo("GIVEN auditId.value is undefined, EXPECT error"); + Audit.FetchAuditByAuditId = jest.fn().mockReturnValue(audit); + Audit.Remove = jest.fn(); - test.todo("GIVEN audit is not found, EXPECT error"); + const audits = new Audits(); + await audits.execute(interaction); + + expect(Audit.FetchAuditByAuditId).toHaveBeenCalledTimes(1); + expect(Audit.FetchAuditByAuditId).toHaveBeenCalledWith("AUDITID", "guildId"); + + expect(Audit.Remove).toHaveBeenCalledTimes(1); + + expect(interaction.options.get).toHaveBeenCalledTimes(1); + expect(interaction.options.get).toHaveBeenCalledWith("auditid"); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Audit cleared."); + }); + + test("GIVEN interaction.guildId is null, EXPECT nothing to happen", async () => { + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("clear"), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.reply).not.toHaveBeenCalled(); + }); + + test("GIVEN auditId is null, EXPECT error", async () => { + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("clear"), + get: jest.fn().mockReturnValue(null), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("AuditId not found."); + }); + + test("GIVEN auditId.value is undefined, EXPECT error", async () => { + const auditOption = { + value: undefined, + } + + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("clear"), + get: jest.fn().mockReturnValue(auditOption), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("AuditId not found."); + }); + + test("GIVEN audit is not found, EXPECT error", async () => { + const auditOption = { + value: "auditId", + } + + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("clear"), + get: jest.fn().mockReturnValue(auditOption), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + Audit.FetchAuditByAuditId = jest.fn().mockReturnValue(null); + + const audits = new Audits(); + await audits.execute(interaction); + + expect(Audit.FetchAuditByAuditId).toHaveBeenCalledTimes(1); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Audit not found."); + }); }); describe("add", () => { - test.todo("EXPECT audit to be added"); + test("EXPECT audit to be added", async () => { + const user = { + id: "userId", + }; - test.todo("GIVEN interaction.guildId is null, EXPECT nothing to happen"); + const type = { + value: AuditType.Warn, + }; - test.todo("GIVEN user is null, EXPECT error"); + const reason = {}; - test.todo("GIVEN auditType is null, EXPECT error"); + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("add"), + getUser: jest.fn().mockReturnValue(user), + get: jest.fn().mockReturnValueOnce(type) + .mockReturnValue(reason), + }, + user: { + id: "userId", + }, + reply: jest.fn(), + } as unknown as CommandInteraction; - test.todo("GIVEN auditType.value is undefined, EXPECT error"); + Audit.prototype.Save = jest.fn(); + StringTools.RandomString = jest.fn().mockReturnValue("AUDITID"); - test.todo("GIVEN reasonInput is null, EXPECT reason to be empty"); + const audits = new Audits(); + await audits.execute(interaction); - test.todo("GIVEN reasonType.value is undefined, EXPECT reason to be empty"); + expect(Audit.prototype.Save).toHaveBeenCalledTimes(1); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Created new audit with ID `AUDITID`"); + }); + + test("GIVEN interaction.guildId is null, EXPECT nothing to happen", async () => { + const interaction = { + guildId: null, + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("add"), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.reply).not.toHaveBeenCalled(); + }); + + test("GIVEN user is null, EXPECT error", async () => { + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("add"), + getUser: jest.fn().mockReturnValue(null), + get: jest.fn().mockReturnValue({}), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Invalid input."); + }); + + test("GIVEN auditType is null, EXPECT error", async () => { + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("add"), + getUser: jest.fn().mockReturnValue(null), + get: jest.fn().mockReturnValueOnce(null) + .mockReturnValue({}), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Invalid input."); + }); + + test("GIVEN auditType.value is undefined, EXPECT error", async () => { + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("add"), + getUser: jest.fn().mockReturnValue(null), + get: jest.fn().mockReturnValueOnce({ + value: undefined + }) + .mockReturnValue({}), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + const audits = new Audits(); + await audits.execute(interaction); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Invalid input."); + }); + + test("GIVEN reasonInput is null, EXPECT reason to be empty", async ()=> { + let savedAudit: Audit | undefined; + + const user = { + id: "userId", + }; + + const type = { + value: AuditType.Warn, + }; + + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("add"), + getUser: jest.fn().mockReturnValue(user), + get: jest.fn().mockReturnValueOnce(type) + .mockReturnValue(null), + }, + user: { + id: "userId", + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => { + savedAudit = audit; + }); + StringTools.RandomString = jest.fn().mockReturnValue("AUDITID"); + + const audits = new Audits(); + await audits.execute(interaction); + + expect(Audit.prototype.Save).toHaveBeenCalledTimes(1); + + expect(savedAudit).toBeDefined(); + expect(savedAudit!.Reason).toBe(""); + }); + + test("GIVEN reasonType.value is undefined, EXPECT reason to be empty", async () => { + let savedAudit: Audit | undefined; + + const user = { + id: "userId", + }; + + const type = { + value: AuditType.Warn, + }; + + const reason = { + value: undefined, + }; + + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("add"), + getUser: jest.fn().mockReturnValue(user), + get: jest.fn().mockReturnValueOnce(type) + .mockReturnValue(reason), + }, + user: { + id: "userId", + }, + reply: jest.fn(), + } as unknown as CommandInteraction; + + Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => { + savedAudit = audit; + }); + StringTools.RandomString = jest.fn().mockReturnValue("AUDITID"); + + const audits = new Audits(); + await audits.execute(interaction); + + expect(Audit.prototype.Save).toHaveBeenCalledTimes(1); + + expect(savedAudit).toBeDefined(); + expect(savedAudit!.Reason).toBe(""); + }); }); \ No newline at end of file