diff --git a/src/commands/config.ts b/src/commands/config.ts index 718d25d..c285464 100644 --- a/src/commands/config.ts +++ b/src/commands/config.ts @@ -140,22 +140,17 @@ export default class Config extends Command { } private async SetValue(interaction: CommandInteraction, server: Server) { - const key = interaction.options.get('key'); - const value = interaction.options.get('value'); - - if (!key || !key.value || !value || !value.value) { - await interaction.reply('Fields are required.'); - return; - } + const key = interaction.options.get('key', true); + const value = interaction.options.get('value', true); const setting = server.Settings.filter(x => x.Key == key.value)[0]; if (setting) { - setting.UpdateBasicDetails(key.value.toString(), value.value.toString()); + setting.UpdateBasicDetails(key.value!.toString(), value.value!.toString()); await setting.Save(Setting, setting); } else { - const newSetting = new Setting(key.value.toString(), value.value.toString()); + const newSetting = new Setting(key.value!.toString(), value.value!.toString()); await newSetting.Save(Setting, newSetting); diff --git a/src/commands/disable.ts b/src/commands/disable.ts index 3f19bdb..e38eaed 100644 --- a/src/commands/disable.ts +++ b/src/commands/disable.ts @@ -48,17 +48,12 @@ export default class Disable extends Command { private async Add(interaction: CommandInteraction) { if (!interaction.guildId) return; - const commandName = interaction.options.get('name'); - - if (!commandName || !commandName.value) { - await interaction.reply('Fields are required.'); - return; - } + const commandName = interaction.options.get('name', true); const disabledCommandsString = await SettingsHelper.GetSetting("commands.disabled", interaction.guildId); - const disabledCommands = disabledCommandsString != "" ? disabledCommandsString?.split(",") : []; + const disabledCommands = disabledCommandsString != undefined ? disabledCommandsString?.split(",") : []; - disabledCommands?.push(commandName.value.toString()); + disabledCommands?.push(commandName.value!.toString()); await SettingsHelper.SetSetting("commands.disabled", interaction.guildId, disabledCommands!.join(",")); @@ -68,23 +63,18 @@ export default class Disable extends Command { private async Remove(interaction: CommandInteraction) { if (!interaction.guildId) return; - const commandName = interaction.options.get('name'); - - if (!commandName || !commandName.value) { - await interaction.reply('Fields are required.'); - return; - } + const commandName = interaction.options.get('name', true); const disabledCommandsString = await SettingsHelper.GetSetting("commands.disabled", interaction.guildId); - const disabledCommands = disabledCommandsString != "" ? disabledCommandsString?.split(",") : []; + const disabledCommands = disabledCommandsString != undefined ? disabledCommandsString?.split(",") : []; const disabledCommandsInstance = disabledCommands?.findIndex(x => x == commandName.value!.toString()); - if (disabledCommandsInstance! > -1) { - disabledCommands?.splice(disabledCommandsInstance!, 1); + if (disabledCommandsInstance > -1) { + disabledCommands?.splice(disabledCommandsInstance, 1); } - await SettingsHelper.SetSetting("commands.disabled", interaction.guildId, disabledCommands!.join(",")); + await SettingsHelper.SetSetting("commands.disabled", interaction.guildId, disabledCommands.join(",")); await interaction.reply(`Enabled command ${commandName.value}`); } diff --git a/src/commands/ignore.ts b/src/commands/ignore.ts index f1ab7ac..335258f 100644 --- a/src/commands/ignore.ts +++ b/src/commands/ignore.ts @@ -13,23 +13,16 @@ export default class Ignore extends Command { } public override async execute(interaction: CommandInteraction) { - if (!interaction.guildId) return; - - const isChannelIgnored = await IgnoredChannel.IsChannelIgnored(interaction.guildId); + const isChannelIgnored = await IgnoredChannel.IsChannelIgnored(interaction.channelId); if (isChannelIgnored) { - const entity = await IgnoredChannel.FetchOneById(IgnoredChannel, interaction.guildId); + const entity = await IgnoredChannel.FetchOneById(IgnoredChannel, interaction.channelId); - if (!entity) { - await interaction.reply('Unable to find channel.'); - return; - } - - await IgnoredChannel.Remove(IgnoredChannel, entity); + await IgnoredChannel.Remove(IgnoredChannel, entity!); await interaction.reply('This channel will start being logged again.'); } else { - const entity = new IgnoredChannel(interaction.guildId); + const entity = new IgnoredChannel(interaction.channelId); await entity.Save(IgnoredChannel, entity); diff --git a/tests/commands/config.test.ts b/tests/commands/config.test.ts index dbea310..8eedb3e 100644 --- a/tests/commands/config.test.ts +++ b/tests/commands/config.test.ts @@ -558,13 +558,55 @@ describe("set", () => { expect(server.Settings[0].Save).toHaveBeenCalledWith(Setting, server.Settings[0]); }); - test.todo("GIVEN setting is not set, EXPECT setting to be added"); + test("GIVEN setting is not set, EXPECT setting to be added", async () => { + let savedSetting: Setting | undefined; - test.todo("GIVEN key is null, EXPECT error"); + // Assert + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + guildId: "guildId", + options: { + getSubcommand: jest.fn().mockReturnValue("set"), + get: jest.fn().mockReturnValueOnce({ + value: "test.key", + }).mockReturnValue({ + value: "54321", + }), + }, + reply: jest.fn(), + } as unknown as CommandInteraction; - test.todo("GIVEN key.value is undefined, EXPECT error"); + const server = { + Settings: [], + AddSettingToServer: jest.fn(), + Save: jest.fn(), + } as unknown as Server; - test.todo("GIVEN value is null, EXPECT error"); + Server.FetchOneById = jest.fn().mockResolvedValue(server); - test.todo("GIVEN value.value is undefined, EXPECT error"); + Setting.prototype.Save = jest.fn().mockImplementation((_, setting: Setting) => { + savedSetting = setting; + }); + + // Act + const command = new Command(); + await command.execute(interaction); + + // Assert + expect(Setting.prototype.Save).toHaveBeenCalledTimes(1); + expect(Setting.prototype.Save).toHaveBeenCalledWith(Setting, expect.any(Setting)); + + expect(server.AddSettingToServer).toHaveBeenCalledTimes(1); + expect(server.AddSettingToServer).toHaveBeenCalledWith(expect.any(Setting)); + + expect(server.Save).toHaveBeenCalledTimes(1); + expect(server.Save).toHaveBeenCalledWith(Server, server); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Setting has been set."); + + expect(savedSetting).toBeDefined(); + expect(savedSetting!.Key).toBe("test.key"); + expect(savedSetting!.Value).toBe("54321"); + }); }); \ No newline at end of file diff --git a/tests/commands/disable.test.ts b/tests/commands/disable.test.ts index 03be771..6c2a74d 100644 --- a/tests/commands/disable.test.ts +++ b/tests/commands/disable.test.ts @@ -1,35 +1,285 @@ +import { ChatInputCommandInteraction, PermissionsBitField, SlashCommandBuilder, SlashCommandStringOption, SlashCommandSubcommandBuilder } from "discord.js"; +import Command from "../../src/commands/disable"; +import SettingsHelper from "../../src/helpers/SettingsHelper"; + describe('constructor', () => { - test.todo('EXPECT properties to be set'); + test('EXPECT properties to be set', () => { + const command = new Command(); + + expect(command.CommandBuilder).toBeDefined(); + + const commandBuilder = command.CommandBuilder as SlashCommandBuilder; + + expect(commandBuilder.name).toBe("disable"); + expect(commandBuilder.description).toBe("Disables a command"); + expect(commandBuilder.default_member_permissions).toBe(PermissionsBitField.Flags.Administrator.toString()); + expect(commandBuilder.options.length).toBe(2); + + const commandBuilderAddSubcommand = commandBuilder.options[0] as SlashCommandSubcommandBuilder; + + expect(commandBuilderAddSubcommand.name).toBe("add"); + expect(commandBuilderAddSubcommand.description).toBe("Disables a command for the server"); + expect(commandBuilderAddSubcommand.options.length).toBe(1); + + const commandBuilderAddSubcommandNameOption = commandBuilderAddSubcommand.options[0] as SlashCommandStringOption; + + expect(commandBuilderAddSubcommandNameOption.name).toBe("name"); + expect(commandBuilderAddSubcommandNameOption.description).toBe("The name of the command"); + expect(commandBuilderAddSubcommandNameOption.required).toBe(true); + + const commandBuilderRemoveSubcommand = commandBuilder.options[1] as SlashCommandSubcommandBuilder; + + expect(commandBuilderRemoveSubcommand.name).toBe("remove"); + expect(commandBuilderRemoveSubcommand.description).toBe("Enables a command for the server"); + expect(commandBuilderRemoveSubcommand.options.length).toBe(1); + + const commandBuilderRemoveSubcommandNameOption = commandBuilderRemoveSubcommand.options[0] as SlashCommandStringOption; + + expect(commandBuilderRemoveSubcommandNameOption.name).toBe("name"); + expect(commandBuilderRemoveSubcommandNameOption.description).toBe("The name of the command"); + expect(commandBuilderRemoveSubcommandNameOption.required).toBe(true); + }); }); 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 () => { + // Arrange + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(false), + reply: jest.fn(), + } as unknown as ChatInputCommandInteraction; - test.todo("GIVEN subcommand is invalid, EXPECT error"); + // Act + const command = new Command(); + await command.execute(interaction); + + // Assert + expect(interaction.isChatInputCommand).toHaveBeenCalledTimes(1); + expect(interaction.reply).not.toHaveBeenCalled(); + }); + + test("GIVEN subcommand is invalid, EXPECT error", async () => { + // Arrange + const interaction = { + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("invalid"), + }, + reply: jest.fn(), + } as unknown as ChatInputCommandInteraction; + + // Act + const command = new Command(); + await command.execute(interaction); + + // Assert + expect(interaction.options.getSubcommand).toHaveBeenCalledTimes(1); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Subcommand not found."); + }); }); describe('add', () => { - test.todo("EXPECT command to be added to disabled list"); + test("EXPECT command to be added to disabled list", async () => { + // Arrange + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("add"), + get: jest.fn().mockReturnValue({ + value: "testCommand", + }), + }, + reply: jest.fn(), + } as unknown as ChatInputCommandInteraction; - test.todo("GIVEN interaction.guildId is null, EXPECT nothing to happen"); + SettingsHelper.GetSetting = jest.fn().mockResolvedValue("otherCommand"); + SettingsHelper.SetSetting = jest.fn(); - test.todo("GIVEN commandName is null, EXPECT error"); + // Act + const command = new Command(); + await command.execute(interaction); - test.todo("GIVEN commandName.value is undefined, EXEPCT error"); + // Assert + expect(interaction.options.get).toHaveBeenCalledTimes(1); + expect(interaction.options.get).toHaveBeenCalledWith("name", true); - test.todo("GIVEN disabledCommandsString is empty, EXPECT empty disabledCommands array to be used"); + expect(SettingsHelper.GetSetting).toHaveBeenCalledTimes(1); + expect(SettingsHelper.GetSetting).toHaveBeenCalledWith("commands.disabled", "guildId"); + + expect(SettingsHelper.SetSetting).toHaveBeenCalledTimes(1); + expect(SettingsHelper.SetSetting).toHaveBeenCalledWith("commands.disabled", "guildId", "otherCommand,testCommand"); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Disabled command testCommand"); + }); + + test("GIVEN interaction.guildId is null, EXPECT nothing to happen", async () => { + // Arrange + const interaction = { + guildId: null, + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("add"), + get: jest.fn().mockReturnValue({ + value: "testCommand", + }), + }, + reply: jest.fn(), + } as unknown as ChatInputCommandInteraction; + + SettingsHelper.GetSetting = jest.fn().mockResolvedValue("otherCommand"); + SettingsHelper.SetSetting = jest.fn(); + + // Act + const command = new Command(); + await command.execute(interaction); + + // Assert + expect(interaction.reply).not.toHaveBeenCalled(); + expect(SettingsHelper.SetSetting).not.toHaveBeenCalled(); + }); + + test("GIVEN disabledCommandsString is undefined, EXPECT empty disabledCommands array to be used", async () => { + // Arrange + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("add"), + get: jest.fn().mockReturnValue({ + value: "testCommand", + }), + }, + reply: jest.fn(), + } as unknown as ChatInputCommandInteraction; + + SettingsHelper.GetSetting = jest.fn().mockResolvedValue(undefined); + SettingsHelper.SetSetting = jest.fn(); + + // Act + const command = new Command(); + await command.execute(interaction); + + // Assert + expect(SettingsHelper.SetSetting).toHaveBeenCalledTimes(1); + expect(SettingsHelper.SetSetting).toHaveBeenCalledWith("commands.disabled", "guildId", "testCommand"); + }); }); describe("remove", () => { - test.todo("EXPECT command to be removed from disabled list"); + test("EXPECT command to be removed from disabled list", async () => { + // Arrange + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("remove"), + get: jest.fn().mockReturnValue({ + value: "testCommand", + }), + }, + reply: jest.fn(), + } as unknown as ChatInputCommandInteraction; - test.todo("GIVEN interaction.guildId is null, EXPECT nothing to happen"); + SettingsHelper.GetSetting = jest.fn().mockResolvedValue("otherCommand,testCommand"); + SettingsHelper.SetSetting = jest.fn(); - test.todo("GIVEN commandName is null, EXPECT error"); + // Act + const command = new Command(); + await command.execute(interaction); - test.todo("GIVEN commandName.value is undefined, EXPECT error"); + // Assert + expect(interaction.options.get).toHaveBeenCalledTimes(1); + expect(interaction.options.get).toHaveBeenCalledWith("name", true); - test.todo("GIVEN disabledCommandsString is empty, EXPECT empty disabledCommands array to be used"); + expect(SettingsHelper.GetSetting).toHaveBeenCalledTimes(1); + expect(SettingsHelper.GetSetting).toHaveBeenCalledWith("commands.disabled", "guildId"); - test.todo("GIVEN instance of commandName is not found in disabledCommands array, EXPECT it not to try to remove it"); + expect(SettingsHelper.SetSetting).toHaveBeenCalledTimes(1); + expect(SettingsHelper.SetSetting).toHaveBeenCalledWith("commands.disabled", "guildId", "otherCommand"); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("Enabled command testCommand"); + }); + + test("GIVEN interaction.guildId is null, EXPECT nothing to happen", async () => { + // Arrange + const interaction = { + guildId: null, + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("remove"), + get: jest.fn().mockReturnValue({ + value: "testCommand", + }), + }, + reply: jest.fn(), + } as unknown as ChatInputCommandInteraction; + + SettingsHelper.GetSetting = jest.fn().mockResolvedValue("otherCommand,testCommand"); + SettingsHelper.SetSetting = jest.fn(); + + // Act + const command = new Command(); + await command.execute(interaction); + + // Assert + expect(interaction.reply).not.toHaveBeenCalled(); + expect(SettingsHelper.SetSetting).not.toHaveBeenCalled(); + }); + + test("GIVEN disabledCommandsString is undefined, EXPECT empty disabledCommands array to be used", async () => { + // Arrange + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("remove"), + get: jest.fn().mockReturnValue({ + value: "testCommand", + }), + }, + reply: jest.fn(), + } as unknown as ChatInputCommandInteraction; + + SettingsHelper.GetSetting = jest.fn().mockResolvedValue(undefined); + SettingsHelper.SetSetting = jest.fn(); + + // Act + const command = new Command(); + await command.execute(interaction); + + // Assert + expect(SettingsHelper.SetSetting).toHaveBeenCalledTimes(1); + expect(SettingsHelper.SetSetting).toHaveBeenCalledWith("commands.disabled", "guildId", ""); + }); + + test("GIVEN instance of commandName is not found in disabledCommands array, EXPECT it not to try to remove it", async () => { + // Arrange + const interaction = { + guildId: "guildId", + isChatInputCommand: jest.fn().mockReturnValue(true), + options: { + getSubcommand: jest.fn().mockReturnValue("remove"), + get: jest.fn().mockReturnValue({ + value: "testCommand", + }), + }, + reply: jest.fn(), + } as unknown as ChatInputCommandInteraction; + + SettingsHelper.GetSetting = jest.fn().mockResolvedValue("otherCommand"); + SettingsHelper.SetSetting = jest.fn(); + + // Act + const command = new Command(); + await command.execute(interaction); + + // Assert + expect(SettingsHelper.SetSetting).toHaveBeenCalledTimes(1); + expect(SettingsHelper.SetSetting).toHaveBeenCalledWith("commands.disabled", "guildId", "otherCommand"); + }); }); \ No newline at end of file diff --git a/tests/commands/ignore.test.ts b/tests/commands/ignore.test.ts index d60ba60..fad4cd6 100644 --- a/tests/commands/ignore.test.ts +++ b/tests/commands/ignore.test.ts @@ -1,11 +1,79 @@ +import { CommandInteraction, PermissionsBitField, SlashCommandBuilder } from "discord.js"; +import Command from "../../src/commands/ignore"; +import IgnoredChannel from "../../src/database/entities/IgnoredChannel"; + describe('constructor', () => { - test.todo("EXPECT properties to be set"); + test("EXPECT properties to be set", () => { + const command = new Command(); + + expect(command.CommandBuilder).toBeDefined(); + + const commandBuilder = command.CommandBuilder as SlashCommandBuilder; + + expect(commandBuilder.name).toBe("ignore"); + expect(commandBuilder.description).toBe("Ignore events in this channel"); + expect(commandBuilder.default_member_permissions).toBe(PermissionsBitField.Flags.Administrator.toString()); + }); }); describe("execute", () => { - test.todo("GIVEN channel is currently ignored, EXPECT channel to be removed from list"); + test("GIVEN channel is currently ignored, EXPECT channel to be removed from list", async () => { + // Arrange + const interaction = { + guildId: "guildId", + channelId: "channelId", + reply: jest.fn(), + } as unknown as CommandInteraction; - test.todo("GIVEN channel is not currently ignored, EXPECT channel to be added to list"); + IgnoredChannel.IsChannelIgnored = jest.fn().mockResolvedValue(true); + IgnoredChannel.FetchOneById = jest.fn().mockResolvedValue({}); + IgnoredChannel.Remove = jest.fn(); - test.todo("GIVEN channel is currently ignored but not found in database, EXPECT error"); + // Act + const command = new Command(); + await command.execute(interaction); + + // Assert + expect(IgnoredChannel.IsChannelIgnored).toHaveBeenCalledTimes(1); + expect(IgnoredChannel.IsChannelIgnored).toHaveBeenCalledWith("channelId"); + + expect(IgnoredChannel.FetchOneById).toHaveBeenCalledTimes(1); + expect(IgnoredChannel.FetchOneById).toHaveBeenCalledWith(IgnoredChannel, "channelId"); + + expect(IgnoredChannel.Remove).toHaveBeenCalledTimes(1); + expect(IgnoredChannel.Remove).toHaveBeenCalledWith(IgnoredChannel, {}); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("This channel will start being logged again."); + }); + + test("GIVEN channel is not currently ignored, EXPECT channel to be added to list", async () => { + let savedChannel: IgnoredChannel | undefined; + + // Arrange + const interaction = { + guildId: "guildId", + channelId: "channelId", + reply: jest.fn(), + } as unknown as CommandInteraction; + + IgnoredChannel.IsChannelIgnored = jest.fn().mockResolvedValue(false); + IgnoredChannel.prototype.Save = jest.fn().mockImplementation((_, channel: IgnoredChannel) => { + savedChannel = channel; + }); + + // Act + const command = new Command(); + await command.execute(interaction); + + // Assert + expect(IgnoredChannel.prototype.Save).toHaveBeenCalledTimes(1); + expect(IgnoredChannel.prototype.Save).toHaveBeenCalledWith(IgnoredChannel, expect.any(IgnoredChannel)); + + expect(interaction.reply).toHaveBeenCalledTimes(1); + expect(interaction.reply).toHaveBeenCalledWith("This channel will now be ignored from logging."); + + expect(savedChannel).toBeDefined(); + expect(savedChannel!.Id).toBe("channelId"); + }); }); \ No newline at end of file