diff --git a/src/commands/timeout.ts b/src/commands/timeout.ts index 867ee15..659e7d3 100644 --- a/src/commands/timeout.ts +++ b/src/commands/timeout.ts @@ -33,10 +33,12 @@ export default class Timeout extends Command { public override async execute(interaction: CommandInteraction) { if (!interaction.guild || !interaction.guildId) return; + // Interaction Inputs const targetUser = interaction.options.get('target'); const lengthInput = interaction.options.get('length'); const reasonInput = interaction.options.get('reason'); + // Validation if (!targetUser || !targetUser.user || !targetUser.member) { await interaction.reply('Fields are required.'); return; @@ -47,6 +49,7 @@ export default class Timeout extends Command { return; } + // General Variables const targetMember = targetUser.member as GuildMember; const reason = reasonInput && reasonInput.value ? reasonInput.value.toString() : null; @@ -75,13 +78,16 @@ export default class Timeout extends Command { }, ]); + // Bot Permissions Check if (!targetMember.manageable) { await interaction.reply('Insufficient bot permissions. Please contact a moderator.'); return; } + // Execute Timeout await targetMember.timeout(timeLength.GetMilliseconds(), reason || ""); + // Log Embed To Channel const channelName = await SettingsHelper.GetSetting('channels.logs.mod', interaction.guildId); if (!channelName) return; @@ -92,9 +98,11 @@ export default class Timeout extends Command { await channel.send({ embeds: [ logEmbed ]}); } + // Create Audit const audit = new Audit(targetUser.user.id, AuditType.Timeout, reason || "*none*", interaction.user.id, interaction.guildId); await audit.Save(Audit, audit); + // DM User, if possible const resultEmbed = new EmbedBuilder() .setColor(EmbedColours.Ok) .setDescription(`<@${targetUser.user.id}> has been timed out`); @@ -137,6 +145,7 @@ export default class Timeout extends Command { ]); } + // Success Reply await interaction.reply({ embeds: [ resultEmbed ]}); } } \ No newline at end of file diff --git a/tests/commands/timeout.test.ts b/tests/commands/timeout.test.ts index 8be4627..f0f96bb 100644 --- a/tests/commands/timeout.test.ts +++ b/tests/commands/timeout.test.ts @@ -13,4 +13,133 @@ describe('Constructor', () => { expect(commandBuilder.description).toBe("Timeouts a user out, sending them a DM with the reason if possible"); expect(commandBuilder.options.length).toBe(3); }); +}); + +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'); + + describe('Null checks', () => { + describe('GIVEN interaction.guild IS NULL', () => { + test.todo('EXPECT nothing to happen'); + }); + + describe('GIVEN interaction.guildId IS NULL', () => { + test.todo('EXPECT nothing to happen'); + }); + }); + + describe('Validation checks', () => { + describe('targetUser', () => { + describe('GIVEN targetUser IS NULL', () => { + test.todo('EXPECT validation error'); + }); + + describe('GIVEN targetUser.user IS NULL', () => { + test.todo('EXPECT validation error'); + }); + + describe('GIVEN targetUser.member IS NULL', () => { + test.todo('EXPECT validation error'); + }); + }); + + describe('lengthInput', () => { + describe('GIVEN lengthInput IS NULL', () => { + test.todo('EXPECT validation error'); + }); + + describe('GIVEN lengthInput.value IS NULL', () => { + test.todo('EXPECT validation error'); + }); + }); + }); + + describe('GIVEN targetMember IS NOT manageable by the bot', () => { + test.todo('EXPECT insufficient permissions error'); + }); + + describe('targetMember.timeout', () => { + test.todo('EXPECT to be ran with time length'); + + describe('GIVEN reason IS NOT NULL', () => { + test.todo('EXPECT to be ran with reason set'); + }); + + describe('GIVEN reason IS NULL', () => { + test.todo('EXPECT to be ran with empty string'); + }); + }); + + describe('Log Embed', () => { + test.todo('EXPECT moderator to be current user'); + + test.todo('EXPECT length to be length'); + + test.todo('EXPECT until to be until date'); + + 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 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'); + }); + }); + + describe('Audit', () => { + test.todo('EXPECT audit to be saved'); + + describe('GIVEN reason IS NULL', () => { + test.todo('EXPECT audit entity to set reason to "*none*"'); + }); + + describe('GIVEN reason IS NOT NULL', () => { + test.todo('EXPECT audit entity to set reason to reason'); + }); + }); + + describe('DM User', () => { + + describe('GIVEN user can be messaged', () => { + test.todo('EXPECT embed to be sent'); + + test.todo('EXPECT length to be in fields'); + + test.todo('EXPECT until to be in fields'); + + 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)'); + }); }); \ No newline at end of file