From 05650ea6c5e28408cfd5681e3cd483b5b5718bc9 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Sat, 1 Apr 2023 21:03:54 +0100 Subject: [PATCH] WIP: Happy flow tests --- tests/commands/timeout.test.ts | 261 ++++++++++++++++++++------------- 1 file changed, 162 insertions(+), 99 deletions(-) diff --git a/tests/commands/timeout.test.ts b/tests/commands/timeout.test.ts index f0f96bb..966ddf2 100644 --- a/tests/commands/timeout.test.ts +++ b/tests/commands/timeout.test.ts @@ -1,8 +1,11 @@ -import { PermissionsBitField, SlashCommandBuilder } from "discord.js"; +import { APIEmbed, CommandInteraction, CommandInteractionOption, Embed, Guild, GuildChannel, GuildMember, InteractionReplyOptions, JSONEncodable, SlashCommandBuilder, TextChannel, User } from "discord.js"; +import { mock } from "jest-mock-extended"; import Timeout from "../../src/commands/timeout"; +import SettingsHelper from "../../src/helpers/SettingsHelper"; +import Audit from "../../src/entity/Audit"; describe('Constructor', () => { - test('Expect CommandBuilder to be configured', () => { + test('EXPECT CommandBuilder to be configured', () => { const command = new Timeout(); expect(command.CommandBuilder).toBeDefined(); @@ -16,130 +19,190 @@ describe('Constructor', () => { }); describe('execute', () => { - test.todo('Given targetUser is null, Expect validation error'); - test.todo('Given targetUser.user is null, Expect validation error'); - test.todo('Given targetUser.member is null, Expect validation error'); + // Happy flow + test('GIVEN all checks have passed, EXPECT user to be timed out', async () => { + let embeds: APIEmbed[] | undefined; - describe('Null checks', () => { - describe('GIVEN interaction.guild IS NULL', () => { - test.todo('EXPECT nothing to happen'); + const command = new Timeout(); + + const interactionReply = jest.fn((options: InteractionReplyOptions) => { + embeds = options.embeds as APIEmbed[]; }); - describe('GIVEN interaction.guildId IS NULL', () => { - test.todo('EXPECT nothing to happen'); - }); + // SettingsHelper.GetSetting = jest.fn().mockResolvedValue('mod-logs'); + const getSetting = jest.spyOn(SettingsHelper, 'GetSetting').mockResolvedValue('mod-logs'); + const auditSave = jest.spyOn(Audit.prototype, 'Save').mockImplementation(); + + const timeoutFunc = jest.fn(); + + const userInput = { + user: { + id: 'userId', + tag: 'userTag', + } as User, + member: { + manageable: true, + timeout: timeoutFunc, + } as unknown as GuildMember, + } as CommandInteractionOption; + + const lengthInput = { + value: '1s', + } as CommandInteractionOption; + + const reasonInput = { + value: 'Test reason', + } as CommandInteractionOption; + + const logsChannel = { + name: 'mod-logs', + send: jest.fn(), + } as unknown as TextChannel; + + const interaction = { + guild: { + channels: { + cache: { + find: jest.fn() + .mockReturnValue(logsChannel), + } + } + } as unknown as Guild, + guildId: 'guildId', + reply: interactionReply, + options: { + get: jest.fn() + .mockReturnValueOnce(userInput) + .mockReturnValueOnce(lengthInput) + .mockReturnValue(reasonInput), + }, + user: { + id: 'moderatorId' + } + } as unknown as CommandInteraction; + + await command.execute(interaction); + + // EXPECT user to be timed out + expect(timeoutFunc).toBeCalledWith(1000, 'Test reason'); + + // EXPECT embeds to be sent + expect(embeds).toBeDefined(); + expect(embeds!.length).toBe(1); + + // EXPECT resultEmbed to be correctly configured + const resultEmbed = embeds![0]; + + expect(resultEmbed.description).toBe('<@userId> has been timed out'); + expect(resultEmbed.fields).toBeDefined(); + expect(resultEmbed.fields!.length).toBe(1); + + // EXPECT DM field to be configured + const resultEmbedDMField = resultEmbed.fields![0]; + + expect(resultEmbedDMField.name).toBe("DM Sent"); + expect(resultEmbedDMField.value).toBe("true"); + + // TODO: User was timed out + // TODO: DM Embed check + // TODO: Log Embed check + // TODO: Audit check }); - describe('Validation checks', () => { - describe('targetUser', () => { - describe('GIVEN targetUser IS NULL', () => { - test.todo('EXPECT validation error'); - }); + // Null checks + test('GIVEN interaction.guild IS NULL, EXPECT nothing to happen', async () => { + const command = new Timeout(); - describe('GIVEN targetUser.user IS NULL', () => { - test.todo('EXPECT validation error'); - }); + const interaction = { + guild: null, + reply: jest.fn(), + } as unknown as CommandInteraction; - describe('GIVEN targetUser.member IS NULL', () => { - test.todo('EXPECT validation error'); - }); - }); + await command.execute(interaction); - describe('lengthInput', () => { - describe('GIVEN lengthInput IS NULL', () => { - test.todo('EXPECT validation error'); - }); - - describe('GIVEN lengthInput.value IS NULL', () => { - test.todo('EXPECT validation error'); - }); - }); + expect(interaction.reply).not.toBeCalled(); }); - describe('GIVEN targetMember IS NOT manageable by the bot', () => { - test.todo('EXPECT insufficient permissions error'); + test.todo('GIVEN interaction.guildId IS NULL, EXPECT nothing to happen'); + + // Validation + test('GIVEN targetUser IS NULL, EXPECT validation error', async () => { + const command = new Timeout(); + + const interaction = { + reply: jest.fn(), + guild: mock(), + guildId: 'guildId', + options: { + get: jest.fn().mockReturnValue(undefined), + } + } as unknown as CommandInteraction; + + await command.execute(interaction); + + expect(interaction.reply).toBeCalledWith('Fields are required.'); }); - describe('targetMember.timeout', () => { - test.todo('EXPECT to be ran with time length'); + test('GIVEN targetUser.user IS NULL, EXPECT validation error', async () => { + const command = new Timeout(); - describe('GIVEN reason IS NOT NULL', () => { - test.todo('EXPECT to be ran with reason set'); - }); + const interactionOption = { + user: undefined, + member: {} as GuildMember + } as CommandInteractionOption; - describe('GIVEN reason IS NULL', () => { - test.todo('EXPECT to be ran with empty string'); - }); + const interaction = { + reply: jest.fn(), + guild: mock(), + guildId: 'guildId', + options: { + get: jest.fn().mockReturnValue(interactionOption), + } + } as unknown as CommandInteraction; + + await command.execute(interaction); + + expect(interaction.reply).toBeCalledWith('Fields are required.'); }); - describe('Log Embed', () => { - test.todo('EXPECT moderator to be current user'); + test('GIVEN targetUser.member IS NULL, EXPECT validation error', async () => { + const command = new Timeout(); - test.todo('EXPECT length to be length'); + const interactionOption = { + user: {} as User, + member: undefined + } as CommandInteractionOption; - test.todo('EXPECT until to be until date'); + const interaction = { + reply: jest.fn(), + guild: mock(), + guildId: 'guildId', + options: { + get: jest.fn().mockReturnValue(interactionOption), + } + } as unknown as CommandInteraction; - describe('GIVEN reason IS NULL', () => { - test.todo('EXPECT reason to be "*none*"'); - }); + await command.execute(interaction); - describe('GIVEN reason IS NOT NULL', () => { - test.todo('EXPECT reason to be set to reason'); - }); - - describe('GIVEN channelName IS NULL', () => { - test.todo('EXPECT execution to return'); - }); - - describe('GIVEN channel IS NULL', () => { - test.todo('EXPECT embed to not be sent'); - }); - - describe('GIVEN channel IS NOT NULL', () => { - test.todo('EXPECT logEmbed to be sent to channel'); - }); + expect(interaction.reply).toBeCalledWith('Fields are required.'); }); - describe('Audit', () => { - test.todo('EXPECT audit to be saved'); + test.todo('GIVEN lengthInput IS NULL, EXPECT validation error'); - describe('GIVEN reason IS NULL', () => { - test.todo('EXPECT audit entity to set reason to "*none*"'); - }); + test.todo('GIVEN lengthInput.value IS NULL, EXPECT validation error'); - describe('GIVEN reason IS NOT NULL', () => { - test.todo('EXPECT audit entity to set reason to reason'); - }); - }); + test.todo('GIVEN targetMember IS NOT manageable by the bot, EXPECT insufficient permissions error'); - describe('DM User', () => { + // Reason variable + test.todo('GIVEN reason IS NOT NULL, EXPECT to be ran with reason set'); - describe('GIVEN user can be messaged', () => { - test.todo('EXPECT embed to be sent'); + test.todo('GIVEN reason IS NULL, EXPECT to be ran with empty string'); - test.todo('EXPECT length to be in fields'); + // Log embed + test.todo('GIVEN channelName IS NULL, EXPECT execution to return'); - test.todo('EXPECT until to be in fields'); + test.todo('GIVEN channel IS NULL, EXPECT embed to not be sent'); - test.todo('EXPECT resultEmbed to contain "DM Sent = true"'); - - describe('GIVEN reason IS NULL', () => { - test.todo('EXPECT reason to be "*none*"'); - }); - - describe('GIVEN reason IS NOT NULL', () => { - test.todo('EXPECT reason to be set to reason'); - }); - }); - - describe('GIVEN user can NOT be messaged', () => { - test.todo('EXPECT resultEmbed to contain "DM Sent = false"'); - }); - }); - - describe('Result Embed', () => { - test.todo('EXPECT resultEmbed to be sent to current channel'); - - test.todo('EXPECT embed description to be set to "You have been timed out in (GUILD NAME)'); - }); + // DM user + test.todo('GIVEN user can NOT be messaged, EXPECT resultEmbed to contain "DM Sent = false"'); }); \ No newline at end of file