Compare commits

..

8 commits

Author SHA1 Message Date
e860a19bfe Create audits command tests
Some checks failed
continuous-integration/drone/push Build is failing
2024-03-27 16:49:39 +00:00
e7fde3a2ea Add role command tests 2024-03-27 13:57:36 +00:00
d5a5282371 Create config tests 2024-03-27 12:51:51 +00:00
00f6a60a43 Add entry command tests 2024-03-27 12:27:20 +00:00
946422b2ac Create remove lobby tests 2024-03-27 11:51:26 +00:00
5e30962053 Create lobby command tests 2024-03-27 11:31:32 +00:00
f770e3f4fc Add list lobby tests 2024-03-27 11:01:18 +00:00
53a084b3b1 Create add lobby tests 2024-03-27 10:40:42 +00:00
11 changed files with 2147 additions and 91 deletions

View file

@ -53,6 +53,6 @@ export default class AddRole extends Command {
const entity = new eLobby(channel.channel.id, role.role.id, cooldown.value as number, gameName.value as string); const entity = new eLobby(channel.channel.id, role.role.id, cooldown.value as number, gameName.value as string);
await entity.Save(eLobby, entity); await entity.Save(eLobby, entity);
await interaction.reply(`Added \`${channel.name}\` as a new lobby channel with a cooldown of \`${cooldown.value} minutes \` and will ping \`${role.name}\` on use`); await interaction.reply(`Added \`${channel.name}\` as a new lobby channel with a cooldown of \`${cooldown.value} minutes\` and will ping \`${role.name}\` on use`);
} }
} }

View file

@ -72,20 +72,18 @@ export default class Role extends Command {
const userRole = roleManager.cache.find(x => x.name == requestedRole.role!.name); const userRole = roleManager.cache.find(x => x.name == requestedRole.role!.name);
const assignRole = interaction.guild.roles.cache.find(x => x.id == requestedRole.role!.id); const assignRole = interaction.guild.roles.cache.find(x => x.id == requestedRole.role!.id);
if (!assignRole) return; if (!assignRole!.editable) {
if (!assignRole.editable) {
await interaction.reply('Insufficient permissions. Please contact a moderator.'); await interaction.reply('Insufficient permissions. Please contact a moderator.');
return; return;
} }
if (!userRole) { if (!userRole) {
await roleManager.add(assignRole); await roleManager.add(assignRole!);
await interaction.reply(`Gave role: \`${assignRole.name}\``); await interaction.reply(`Gave role: \`${assignRole!.name}\``);
} else { } else {
await roleManager.remove(assignRole); await roleManager.remove(assignRole!);
await interaction.reply(`Removed role: \`${assignRole.name}\``); await interaction.reply(`Removed role: \`${assignRole!.name}\``);
} }
} }

View file

@ -60,8 +60,7 @@ export default class Audits extends Command {
{ name: 'Mute', value: AuditType.Mute.toString() }, { name: 'Mute', value: AuditType.Mute.toString() },
{ name: 'Kick', value: AuditType.Kick.toString() }, { name: 'Kick', value: AuditType.Kick.toString() },
{ name: 'Ban', value: AuditType.Ban.toString() }, { name: 'Ban', value: AuditType.Ban.toString() },
) ))
.setRequired(true))
.addStringOption(option => .addStringOption(option =>
option option
.setName('reason') .setName('reason')

View file

@ -1,5 +1,6 @@
import { PermissionsBitField, SlashCommandBuilder, SlashCommandChannelOption, SlashCommandNumberOption, SlashCommandRoleOption, SlashCommandStringOption } from "discord.js"; import { CommandInteraction, PermissionsBitField, SlashCommandBuilder, SlashCommandChannelOption, SlashCommandNumberOption, SlashCommandRoleOption, SlashCommandStringOption } from "discord.js";
import Add from "../../../../src/commands/501231711271780357/Lobby/add"; import Add from "../../../../src/commands/501231711271780357/Lobby/add";
import Lobby from "../../../../src/database/entities/501231711271780357/Lobby";
describe('constuctor', () => { describe('constuctor', () => {
test("EXPECT properties to be set", () => { test("EXPECT properties to be set", () => {
@ -42,23 +43,349 @@ describe('constuctor', () => {
}); });
describe('execute', () => { describe('execute', () => {
test.todo("EXPECT channel to be added to the lobby database table"); test("EXPECT channel to be added to the lobby database table", async () => {
const channel = {
channel: {
id: "channelId",
},
name: "channelName",
};
const role = {
role: {},
name: "roleName",
};
const cooldown = {
value: "5",
};
const gameName = {
value: "test",
};
test.todo("GIVEN channel is null, EXPECT error"); const interaction = {
options: {
get: jest.fn()
.mockReturnValueOnce(channel)
.mockReturnValueOnce(role)
.mockReturnValueOnce(cooldown)
.mockReturnValueOnce(gameName),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
test.todo("GIVEN channel.channel is undefined, EXPECT error"); Lobby.FetchOneByChannelId = jest.fn().mockReturnValue(null);
Lobby.prototype.Save = jest.fn();
test.todo("GIVEN role is null, EXPECT error"); const add = new Add();
await add.execute(interaction);
test.todo("GIVEN role.role is undefined, EXPECT error"); expect(interaction.options.get).toHaveBeenCalledTimes(4);
expect(interaction.options.get).toHaveBeenCalledWith("channel");
expect(interaction.options.get).toHaveBeenCalledWith("role");
expect(interaction.options.get).toHaveBeenCalledWith("cooldown");
expect(interaction.options.get).toHaveBeenCalledWith("name");
test.todo("GIVEN cooldown is null, EXPECT error"); expect(Lobby.FetchOneByChannelId).toHaveBeenCalledTimes(1);
expect(Lobby.FetchOneByChannelId).toHaveBeenCalledWith("channelId");
test.todo("GIVEN cooldown.value is undefined, EXPECT error"); expect(Lobby.prototype.Save).toHaveBeenCalledTimes(1);
test.todo("GIVEN gameName is null, EXPECT error"); expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Added `channelName` as a new lobby channel with a cooldown of `5 minutes` and will ping `roleName` on use");
});
test.todo("GIVEN gameName.value is undefined, EXPECT error"); test("GIVEN channel is null, EXPECT error", async () => {
const channel = null;
const role = {
role: {},
name: "roleName",
};
const cooldown = {
value: "5",
};
const gameName = {
value: "test",
};
test.todo("GIVEN channel has already been set up in the database, EXPECT error"); const interaction = {
options: {
get: jest.fn()
.mockReturnValueOnce(channel)
.mockReturnValueOnce(role)
.mockReturnValueOnce(cooldown)
.mockReturnValueOnce(gameName),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const add = new Add();
await add.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN channel.channel is undefined, EXPECT error", async () => {
const channel = {
channel: undefined,
};
const role = {
role: {},
name: "roleName",
};
const cooldown = {
value: "5",
};
const gameName = {
value: "test",
};
const interaction = {
options: {
get: jest.fn()
.mockReturnValueOnce(channel)
.mockReturnValueOnce(role)
.mockReturnValueOnce(cooldown)
.mockReturnValueOnce(gameName),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const add = new Add();
await add.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN role is null, EXPECT error", async () => {
const channel = {
channel: {},
};
const role = null;
const cooldown = {
value: "5",
};
const gameName = {
value: "test",
};
const interaction = {
options: {
get: jest.fn()
.mockReturnValueOnce(channel)
.mockReturnValueOnce(role)
.mockReturnValueOnce(cooldown)
.mockReturnValueOnce(gameName),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const add = new Add();
await add.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN role.role is undefined, EXPECT error", async () => {
const channel = {
channel: {},
};
const role = {
role: undefined
};
const cooldown = {
value: "5",
};
const gameName = {
value: "test",
};
const interaction = {
options: {
get: jest.fn()
.mockReturnValueOnce(channel)
.mockReturnValueOnce(role)
.mockReturnValueOnce(cooldown)
.mockReturnValueOnce(gameName),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const add = new Add();
await add.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN cooldown is null, EXPECT error", async () => {
const channel = {
channel: {},
};
const role = {
role: {},
name: "roleName",
};
const cooldown = null;
const gameName = {
value: "test",
};
const interaction = {
options: {
get: jest.fn()
.mockReturnValueOnce(channel)
.mockReturnValueOnce(role)
.mockReturnValueOnce(cooldown)
.mockReturnValueOnce(gameName),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const add = new Add();
await add.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN cooldown.value is undefined, EXPECT error", async () => {
const channel = {
channel: {},
};
const role = {
role: {},
name: "roleName",
};
const cooldown = {
value: undefined,
};
const gameName = {
value: "test",
};
const interaction = {
options: {
get: jest.fn()
.mockReturnValueOnce(channel)
.mockReturnValueOnce(role)
.mockReturnValueOnce(cooldown)
.mockReturnValueOnce(gameName),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const add = new Add();
await add.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN gameName is null, EXPECT error", async () => {
const channel = {
channel: {},
};
const role = {
role: {},
name: "roleName",
};
const cooldown = {
value: "5",
};
const gameName = null;
const interaction = {
options: {
get: jest.fn()
.mockReturnValueOnce(channel)
.mockReturnValueOnce(role)
.mockReturnValueOnce(cooldown)
.mockReturnValueOnce(gameName),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const add = new Add();
await add.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN gameName.value is undefined, EXPECT error", async () => {
const channel = {
channel: {},
};
const role = {
role: {},
name: "roleName",
};
const cooldown = {
value: "5",
};
const gameName = {
value: undefined,
};
const interaction = {
options: {
get: jest.fn()
.mockReturnValueOnce(channel)
.mockReturnValueOnce(role)
.mockReturnValueOnce(cooldown)
.mockReturnValueOnce(gameName),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const add = new Add();
await add.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN channel has already been set up in the database, EXPECT error", async () => {
const channel = {
channel: {
id: "channelId",
},
name: "channelName",
};
const role = {
role: {},
name: "roleName",
};
const cooldown = {
value: "5",
};
const gameName = {
value: "test",
};
const interaction = {
options: {
get: jest.fn()
.mockReturnValueOnce(channel)
.mockReturnValueOnce(role)
.mockReturnValueOnce(cooldown)
.mockReturnValueOnce(gameName),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
Lobby.FetchOneByChannelId = jest.fn().mockReturnValue({});
Lobby.prototype.Save = jest.fn();
const add = new Add();
await add.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("This channel has already been setup.");
expect(Lobby.FetchOneByChannelId).toHaveBeenCalledTimes(1);
expect(Lobby.prototype.Save).not.toHaveBeenCalled();
});
}); });

View file

@ -1,9 +1,82 @@
import { APIEmbedField, CommandInteraction, EmbedBuilder, PermissionsBitField, SlashCommandBuilder } from "discord.js";
import List from "../../../../src/commands/501231711271780357/Lobby/list";
import Lobby from "../../../../src/database/entities/501231711271780357/Lobby";
import EmbedColours from "../../../../src/constants/EmbedColours";
describe('constructor', () => { describe('constructor', () => {
test.todo("EXPECT properties to be set"); test("EXPECT properties to be set", () => {
const list = new List();
expect(list.CommandBuilder).toBeDefined();
const commandBulder = list.CommandBuilder as SlashCommandBuilder;
expect(commandBulder.name).toBe("listlobby");
expect(commandBulder.description).toBe("Lists all channels set up as lobbies");
expect(commandBulder.default_member_permissions).toBe(PermissionsBitField.Flags.ModerateMembers.toString());
});
}); });
describe("execute", () => { describe("execute", () => {
test.todo('EXPECT list of lobby channels to be sent'); test('EXPECT list of lobby channels to be sent', async () => {
let repliedWith;
test.todo("GIVEN interaction.guild is null, EXPECT error"); const interaction = {
guild: {
channels: {
cache: {
map: jest.fn().mockReturnValue([{
id: "channelId",
}]),
}
}
},
reply: jest.fn().mockImplementation((options) => {
repliedWith = options;
}),
} as unknown as CommandInteraction;
Lobby.FetchOneByChannelId = jest.fn().mockReturnValue({
Name: "lobbyName",
LastUsed: "lastUsed",
});
const list = new List();
await list.execute(interaction);
expect(Lobby.FetchOneByChannelId).toHaveBeenCalledTimes(1);
expect(Lobby.FetchOneByChannelId).toHaveBeenCalledWith("channelId");
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(repliedWith).toBeDefined();
expect(repliedWith!.embeds).toBeDefined();
expect(repliedWith!.embeds.length).toBe(1);
const repliedEmbed: EmbedBuilder = repliedWith!.embeds[0];
expect(repliedEmbed.data.color).toBe(EmbedColours.Ok);
expect(repliedEmbed.data.title).toBe("Lobbies");
expect(repliedEmbed.data.description).toBe("Channels: 1");
expect(repliedEmbed.data.fields).toBeDefined();
expect(repliedEmbed.data.fields!.length).toBe(1);
const repliedEmbedField1: APIEmbedField = repliedEmbed.data.fields![0];
expect(repliedEmbedField1.name).toBe("# lobbyName");
expect(repliedEmbedField1.value).toBe("Last Used: lastUsed");
});
test("GIVEN interaction.guild is null, EXPECT error", async () => {
const interaction = {
guild: null,
reply: jest.fn(),
} as unknown as CommandInteraction;
const list = new List();
await list.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Guild not found.");
});
}); });

View file

@ -1,13 +1,112 @@
import { CommandInteraction, SlashCommandBuilder } from "discord.js";
import Command from "../../../../src/commands/501231711271780357/Lobby/lobby";
import Lobby from "../../../../src/database/entities/501231711271780357/Lobby";
describe('constructor', () => { describe('constructor', () => {
test.todo("EXPECT properties to be set"); test("EXPECT properties to be set", () => {
const lobby = new Command();
expect(lobby.CommandBuilder).toBeDefined();
const commandBuilder = lobby.CommandBuilder as SlashCommandBuilder;
expect(commandBuilder.name).toBe("lobby");
expect(commandBuilder.description).toBe("Attempt to organise a lobby");
});
}); });
describe("execute", () => { describe("execute", () => {
test.todo("EXPECT lobby command to announce a lobby setup"); test("EXPECT lobby command to announce a lobby setup", async () => {
const interaction = {
user: "user",
channelId: "channelId",
reply: jest.fn(),
} as unknown as CommandInteraction;
test.todo("GIVEN interaction.channelId is null, EXPECT nothing to happen"); const markAsUsed = jest.fn();
const lobbySave = jest.fn();
test.todo("GIVEN channel is not setup in the database as a lobby, EXPECT error"); Lobby.FetchOneByChannelId = jest.fn().mockResolvedValue({
Cooldown: 5,
LastUsed: new Date(2 * 60 * 1000),
Name: "gameName",
RoleId: "roleId",
MarkAsUsed: markAsUsed,
Save: lobbySave,
});
test.todo("GIVEN lobby command was last used within the cooldown, EXPECT error"); Date.now = jest.fn().mockReturnValue(10 * 60 * 1000);
const lobby = new Command();
await lobby.execute(interaction);
expect(Lobby.FetchOneByChannelId).toHaveBeenCalledTimes(1);
expect(Lobby.FetchOneByChannelId).toHaveBeenCalledWith("channelId");
expect(Date.now).toHaveBeenCalledTimes(1);
expect(markAsUsed).toHaveBeenCalledTimes(1);
expect(lobbySave).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("user would like to organise a lobby of **gameName**! <@&roleId>");
});
test("GIVEN interaction.channelId is null, EXPECT nothing to happen", async () => {
const interaction = {
channelId: null,
reply: jest.fn(),
} as unknown as CommandInteraction;
const lobby = new Command();
await lobby.execute(interaction);
expect(interaction.reply).not.toHaveBeenCalled();
});
test("GIVEN channel is not setup in the database as a lobby, EXPECT error", async () => {
const interaction = {
channelId: "channelId",
reply: jest.fn(),
} as unknown as CommandInteraction;
Lobby.FetchOneByChannelId = jest.fn().mockResolvedValue(null);
const lobby = new Command();
await lobby.execute(interaction);
expect(Lobby.FetchOneByChannelId).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("This channel is disabled from using the lobby command.");
});
test("GIVEN lobby command was last used within the cooldown, EXPECT error", async () => {
const interaction = {
user: "user",
channelId: "channelId",
reply: jest.fn(),
} as unknown as CommandInteraction;
const markAsUsed = jest.fn();
const lobbySave = jest.fn();
Lobby.FetchOneByChannelId = jest.fn().mockResolvedValue({
Cooldown: 5,
LastUsed: new Date(2 * 60 * 1000),
Name: "gameName",
RoleId: "roleId",
MarkAsUsed: markAsUsed,
Save: lobbySave,
});
Date.now = jest.fn().mockReturnValue(5 * 60 * 1000);
const lobby = new Command();
await lobby.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Requesting a lobby for this game is on cooldown! Please try again in **2 minutes**.");
});
}); });

View file

@ -1,13 +1,116 @@
import { CommandInteraction, PermissionsBitField, SlashCommandBuilder, SlashCommandChannelOption } from "discord.js";
import Remove from "../../../../src/commands/501231711271780357/Lobby/remove";
import Lobby from "../../../../src/database/entities/501231711271780357/Lobby";
import BaseEntity from "../../../../src/contracts/BaseEntity";
describe('constructor', () => { describe('constructor', () => {
test.todo("EXPECT properties to be set"); test("EXPECT properties to be set", () => {
const remove = new Remove();
expect(remove.CommandBuilder).toBeDefined();
const commandBuilder = remove.CommandBuilder as SlashCommandBuilder;
expect(commandBuilder.name).toBe("removelobby");
expect(commandBuilder.description).toBe("Remove a lobby channel");
expect(commandBuilder.default_member_permissions).toBe(PermissionsBitField.Flags.ModerateMembers.toString());
expect(commandBuilder.options.length).toBe(1);
const channelOption = commandBuilder.options[0] as SlashCommandChannelOption;
expect(channelOption.name).toBe("channel");
expect(channelOption.description).toBe("The channel");
expect(channelOption.required).toBe(true);
});
}); });
describe("execute", () => { describe("execute", () => {
test.todo("EXPECT channel to be removed from database"); test("EXPECT channel to be removed from database", async () => {
const channel = {
channel: {
id: "channelId",
},
};
test.todo("GIVEN channel is null, EXPECT error"); const interaction = {
options: {
get: jest.fn().mockReturnValue(channel),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
test.todo("GIVEN channel.channel is undefined, EXPECT error"); Lobby.FetchOneByChannelId = jest.fn().mockResolvedValue({});
BaseEntity.Remove = jest.fn();
test.todo("GIVEN channel is not set up as a lobby, EXPECT error"); const remove = new Remove();
await remove.execute(interaction);
expect(Lobby.FetchOneByChannelId).toHaveBeenCalledTimes(1);
expect(Lobby.FetchOneByChannelId).toHaveBeenCalledWith("channelId");
expect(BaseEntity.Remove).toHaveBeenCalledTimes(1);
expect(interaction.options.get).toHaveBeenCalledTimes(1);
expect(interaction.options.get).toHaveBeenCalledWith("channel");
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Removed <#channelId> from the list of lobby channels");
});
test("GIVEN channel is null, EXPECT error", async () => {
const interaction = {
options: {
get: jest.fn().mockReturnValue(null),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const remove = new Remove();
await remove.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Channel is required.");
});
test("GIVEN channel.channel is undefined, EXPECT error", async () => {
const channel = {
channel: undefined,
};
const interaction = {
options: {
get: jest.fn().mockReturnValue(channel),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const remove = new Remove();
await remove.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Channel is required.");
});
test("GIVEN channel is not set up as a lobby, EXPECT error", async () => {
const channel = {
channel: {
id: "channelId",
},
};
const interaction = {
options: {
get: jest.fn().mockReturnValue(channel),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
Lobby.FetchOneByChannelId = jest.fn().mockResolvedValue(null);
const remove = new Remove();
await remove.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Channel not found.");
});
}); });

View file

@ -1,13 +1,111 @@
import { CommandInteraction, EmbedBuilder, PermissionsBitField, SlashCommandBuilder } from "discord.js";
import Entry from "../../../src/commands/501231711271780357/entry";
import SettingsHelper from "../../../src/helpers/SettingsHelper";
import EmbedColours from "../../../src/constants/EmbedColours";
describe('constructor', () => { describe('constructor', () => {
test.todo("EXPECT properties to be set"); test("EXPECT properties to be set", () => {
const entry = new Entry();
expect(entry.CommandBuilder).toBeDefined();
const commandBuilder = entry.CommandBuilder as SlashCommandBuilder;
expect(commandBuilder.name).toBe("entry");
expect(commandBuilder.description).toBe("Sends the entry embed");
expect(commandBuilder.default_member_permissions).toBe(PermissionsBitField.Flags.ModerateMembers.toString());
});
}); });
describe("execute", () => { describe("execute", () => {
test.todo("EXPECT entry embed to be sent"); test("EXPECT entry embed to be sent", async () => {
let sentWith;
test.todo("GIVEN interaction.guildId is null, EXPECT error"); const interaction = {
guildId: "guildId",
channel: {
send: jest.fn().mockImplementation((options) => {
sentWith = options;
}),
},
} as unknown as CommandInteraction;
test.todo("GIVEN interaction.channel is null, EXPECT error"); SettingsHelper.GetSetting = jest.fn().mockResolvedValue("channelId");
test.todo("GIVEN channels.rules setting is not set, EXPECT channel id to be defaulted"); const entry = new Entry();
await entry.execute(interaction);
expect(SettingsHelper.GetSetting).toHaveBeenCalledTimes(1);
expect(SettingsHelper.GetSetting).toHaveBeenCalledWith("channels.rules", "guildId");
expect(interaction.channel!.send).toHaveBeenCalledTimes(1);
expect(sentWith).toBeDefined();
expect(sentWith!.embeds).toBeDefined();
expect(sentWith!.embeds.length).toBe(1);
const embed = sentWith!.embeds[0] as EmbedBuilder;
expect(embed.data.color).toBe(EmbedColours.Ok);
expect(embed.data.title).toBe("Welcome");
expect(embed.data.description).toBe("Welcome to the server! Please make sure to read the rules in the <#channelId> channel and type the code found there in here to proceed to the main part of the server.");
});
test("GIVEN interaction.guildId is null, EXPECT error", async () => {
const interaction = {
guildId: null,
} as unknown as CommandInteraction;
SettingsHelper.GetSetting = jest.fn();
const entry = new Entry();
await entry.execute(interaction);
expect(SettingsHelper.GetSetting).not.toHaveBeenCalled();
});
test("GIVEN interaction.channel is null, EXPECT error", async () => {
const interaction = {
guildId: "guildId",
channel: null,
} as unknown as CommandInteraction;
SettingsHelper.GetSetting = jest.fn();
const entry = new Entry();
await entry.execute(interaction);
expect(SettingsHelper.GetSetting).not.toHaveBeenCalled();
});
test("GIVEN channels.rules setting is not set, EXPECT channel id to be defaulted", async () => {
let sentWith;
const interaction = {
guildId: "guildId",
channel: {
send: jest.fn().mockImplementation((options) => {
sentWith = options;
}),
},
} as unknown as CommandInteraction;
SettingsHelper.GetSetting = jest.fn().mockResolvedValue(undefined);
const entry = new Entry();
await entry.execute(interaction);
expect(SettingsHelper.GetSetting).toHaveBeenCalledTimes(1);
expect(SettingsHelper.GetSetting).toHaveBeenCalledWith("channels.rules", "guildId");
expect(interaction.channel!.send).toHaveBeenCalledTimes(1);
expect(sentWith).toBeDefined();
expect(sentWith!.embeds).toBeDefined();
expect(sentWith!.embeds.length).toBe(1);
const embed = sentWith!.embeds[0] as EmbedBuilder;
expect(embed.data.color).toBe(EmbedColours.Ok);
expect(embed.data.title).toBe("Welcome");
expect(embed.data.description).toBe("Welcome to the server! Please make sure to read the rules in the <#rules> channel and type the code found there in here to proceed to the main part of the server.");
});
}); });

View file

@ -1,21 +1,227 @@
import { CommandInteraction, PermissionsBitField, SlashCommandBuilder, SlashCommandRoleOption } from "discord.js";
import Config from "../../../src/commands/Role/config";
import Role from "../../../src/database/entities/Role";
import Server from "../../../src/database/entities/Server";
describe('constructor', () => { describe('constructor', () => {
test.todo('EXPECT properties to be set'); test('EXPECT properties to be set', () => {
const config = new Config();
expect(config.CommandBuilder).toBeDefined();
const commandBuilder = config.CommandBuilder as SlashCommandBuilder;
expect(commandBuilder.name).toBe("configrole");
expect(commandBuilder.description).toBe("Toggle your roles");
expect(commandBuilder.default_member_permissions).toBe(PermissionsBitField.Flags.ManageRoles.toString());
expect(commandBuilder.options.length).toBe(1);
const roleOption = commandBuilder.options[0] as SlashCommandRoleOption;
expect(roleOption.name).toBe("role");
expect(roleOption.description).toBe("The role name");
expect(roleOption.required).toBe(true);
});
}); });
describe("execute", () => { describe("execute", () => {
test.todo("GIVEN role is marked as assignable, EXPECT role to be removed"); test("GIVEN role is marked as assignable, EXPECT role to be removed", async () => {
const role = {
role: {
id: "roleId",
},
};
test.todo("GIVEN role is not marked as assignable, EXPECT role to be added"); const interaction = {
guildId: "guildId",
guild: {},
member: {},
options: {
get: jest.fn().mockReturnValue(role),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
test.todo("GIVEN interaction.guildId is null, EXPECT error"); Role.FetchOneByRoleId = jest.fn().mockResolvedValue({});
Role.Remove = jest.fn();
test.todo("GIVEN interaction.guild is null, EXPECT error"); const config = new Config();
await config.execute(interaction);
test.todo("GIVEN interaction.member is null, EXPECT error"); expect(Role.FetchOneByRoleId).toHaveBeenCalledTimes(1);
expect(Role.FetchOneByRoleId).toHaveBeenCalledWith("roleId");
test.todo("GIVEN role is null, EXPECT error"); expect(Role.Remove).toHaveBeenCalledTimes(1);
test.todo("GIVEN role.role is undefined, EXPECT error"); expect(interaction.options.get).toHaveBeenCalledTimes(1);
expect(interaction.options.get).toHaveBeenCalledWith("role");
test.todo("GIVEN server is not configured in the database, EXPECT error"); expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Removed role from configuration.");
});
test("GIVEN role is not marked as assignable, EXPECT role to be added", async () => {
let newRole: Role | undefined;
const role = {
role: {
id: "roleId",
},
};
const interaction = {
guildId: "guildId",
guild: {},
member: {},
options: {
get: jest.fn().mockReturnValue(role),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
Role.FetchOneByRoleId = jest.fn().mockResolvedValue(null);
Role.prototype.SetServer = jest.fn();
Role.prototype.Save = jest.fn().mockImplementation((_, role) => {
newRole = role;
});
Server.FetchOneById = jest.fn().mockResolvedValue({});
const config = new Config();
await config.execute(interaction);
expect(Role.FetchOneByRoleId).toHaveBeenCalledTimes(1);
expect(Role.FetchOneByRoleId).toHaveBeenCalledWith("roleId");
expect(Role.prototype.SetServer).toHaveBeenCalledTimes(1);
expect(Role.prototype.Save).toHaveBeenCalledTimes(1);
expect(newRole).toBeDefined();
expect(newRole!.RoleId).toBe("roleId");
expect(interaction.options.get).toHaveBeenCalledTimes(1);
expect(interaction.options.get).toHaveBeenCalledWith("role");
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Added role to configuration.");
});
test("GIVEN interaction.guildId is null, EXPECT error", async () => {
const interaction = {
guildId: null,
options: {
get: jest.fn(),
}
} as unknown as CommandInteraction;
const config = new Config();
await config.execute(interaction);
expect(interaction.options.get).not.toHaveBeenCalled();
});
test("GIVEN interaction.guild is null, EXPECT error", async () => {
const interaction = {
guildId: "guildId",
guild: null,
options: {
get: jest.fn(),
}
} as unknown as CommandInteraction;
const config = new Config();
await config.execute(interaction);
expect(interaction.options.get).not.toHaveBeenCalled();
});
test("GIVEN interaction.member is null, EXPECT error", async () => {
const interaction = {
guildId: "guildId",
guild: {},
member: null,
options: {
get: jest.fn(),
}
} as unknown as CommandInteraction;
const config = new Config();
await config.execute(interaction);
expect(interaction.options.get).not.toHaveBeenCalled();
});
test("GIVEN role is null, EXPECT error", async () => {
const interaction = {
guildId: "guildId",
guild: {},
member: {},
options: {
get: jest.fn().mockReturnValue(null),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const config = new Config();
await config.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN role.role is undefined, EXPECT error", async () => {
const role = {
role: null,
}
const interaction = {
guildId: "guildId",
guild: {},
member: {},
options: {
get: jest.fn().mockReturnValue(role),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const config = new Config();
await config.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN server is not configured in the database, EXPECT error", async () => {
let newRole: Role | undefined;
const role = {
role: {
id: "roleId",
},
};
const interaction = {
guildId: "guildId",
guild: {},
member: {},
options: {
get: jest.fn().mockReturnValue(role),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
Role.FetchOneByRoleId = jest.fn().mockResolvedValue(null);
Role.prototype.SetServer = jest.fn();
Role.prototype.Save = jest.fn().mockImplementation((_, role) => {
newRole = role;
});
Server.FetchOneById = jest.fn().mockResolvedValue(null);
const config = new Config();
await config.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("This server has not been setup.");
});
}); });

View file

@ -1,37 +1,475 @@
beforeEach(() => { import { CommandInteraction, GuildMemberRoleManager, SlashCommandBuilder, SlashCommandRoleOption, SlashCommandSubcommandBuilder } from "discord.js";
process.env = {}; import Command from "../../../src/commands/Role/role";
}); import Role from "../../../src/database/entities/Role";
import { EmbedBuilder } from "@discordjs/builders";
import EmbedColours from "../../../src/constants/EmbedColours";
describe('Constructor', () => { describe('Constructor', () => {
test.todo('EXPECT properties are set'); test('EXPECT properties are set', () => {
const command = new Command();
expect(command.CommandBuilder).toBeDefined();
const commandBuilder = command.CommandBuilder as SlashCommandBuilder;
expect(commandBuilder.name).toBe("role");
expect(commandBuilder.description).toBe("Toggle your roles");
expect(commandBuilder.options.length).toBe(2);
const toggleSubcommand = commandBuilder.options[0] as SlashCommandSubcommandBuilder;
expect(toggleSubcommand.name).toBe("toggle");
expect(toggleSubcommand.description).toBe("Toggle your role");
expect(toggleSubcommand.options.length).toBe(1);
const toggleRoleOption = toggleSubcommand.options[0] as SlashCommandRoleOption;
expect(toggleRoleOption.name).toBe("role");
expect(toggleRoleOption.description).toBe("The role name");
expect(toggleRoleOption.required).toBe(true);
const listSubcommand = commandBuilder.options[1] as SlashCommandSubcommandBuilder;
expect(listSubcommand.name).toBe("list");
expect(listSubcommand.description).toBe("List togglable roles");
});
}); });
describe('Execute', () => { 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 an invalid subcommand is given, EXPECT not found error"); const command = new Command();
await command.execute(interaction);
expect(interaction.reply).not.toHaveBeenCalled();
});
test("GIVEN an invalid subcommand is given, EXPECT not found error", async () => {
const interaction = {
isChatInputCommand: jest.fn().mockReturnValue(true),
options: {
getSubcommand: jest.fn().mockReturnValue("other"),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
const command = new Command();
await command.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Subcommand not found.");
});
}); });
describe("toggle", () => { describe("toggle", () => {
test.todo("GIVEN user has the role, EXPECT role to be removed"); test("GIVEN user has the role, EXPECT role to be removed", async () => {
const role = {
id: "roleId",
name: "roleName",
editable: true,
};
test.todo("GIVEN user does not have the role, EXPECT role to be added") const requestedRole = {
role: {
name: "roleName",
},
};
test.todo("GIVEN interaction.guild is null, EXPECT nothing to happen"); const userRole = {};
test.todo("GIVEN interaction.member is null, EXPECT nothing to happen"); const interaction = {
isChatInputCommand: jest.fn().mockReturnValue(true),
guildId: "guildId",
guild: {
roles: {
cache: {
find: jest.fn().mockReturnValue(role),
}
}
},
member: {
roles: {
cache: {
find: jest.fn().mockReturnValue(userRole),
},
remove: jest.fn(),
},
},
options: {
get: jest.fn().mockReturnValue(requestedRole),
getSubcommand: jest.fn().mockReturnValue("toggle"),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
test.todo("GIVEN requestedRole is null, EXPECT invalid error"); Role.FetchAllByServerId = jest.fn().mockResolvedValue([{}]);
test.todo("GIVEN requestedRole.role is undefined, EXPECT invalid error"); const command = new Command();
await command.execute(interaction);
test.todo("GIVEN role is not assignable, EXPECT unassignable error"); expect(Role.FetchAllByServerId).toHaveBeenCalledTimes(1);
expect(Role.FetchAllByServerId).toHaveBeenCalledWith("guildId");
test.todo("GIVEN assignRole is not foundm, EXPECT nothing to happen"); expect(interaction.guild?.roles.cache.find).toHaveBeenCalledTimes(2);
expect(interaction.options.get).toHaveBeenCalledTimes(1);
expect(interaction.options.get).toHaveBeenCalledWith("role");
test.todo("GIVEN assignRole is not editable, EXPECT insufficient permissions error"); const roleManager = interaction.member!.roles as GuildMemberRoleManager;
expect(roleManager.cache.find).toHaveBeenCalledTimes(1);
expect(roleManager.remove).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Removed role: `roleName`");
});
test("GIVEN user does not have the role, EXPECT role to be added", async () => {
const role = {
id: "roleId",
name: "roleName",
editable: true,
};
const requestedRole = {
role: {
name: "roleName",
},
};
const interaction = {
isChatInputCommand: jest.fn().mockReturnValue(true),
guildId: "guildId",
guild: {
roles: {
cache: {
find: jest.fn().mockReturnValue(role),
}
}
},
member: {
roles: {
cache: {
find: jest.fn().mockReturnValue(undefined),
},
add: jest.fn(),
},
},
options: {
get: jest.fn().mockReturnValue(requestedRole),
getSubcommand: jest.fn().mockReturnValue("toggle"),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
Role.FetchAllByServerId = jest.fn().mockResolvedValue([{}]);
const command = new Command();
await command.execute(interaction);
expect(Role.FetchAllByServerId).toHaveBeenCalledTimes(1);
expect(Role.FetchAllByServerId).toHaveBeenCalledWith("guildId");
expect(interaction.guild?.roles.cache.find).toHaveBeenCalledTimes(2);
expect(interaction.options.get).toHaveBeenCalledTimes(1);
expect(interaction.options.get).toHaveBeenCalledWith("role");
const roleManager = interaction.member!.roles as GuildMemberRoleManager;
expect(roleManager.cache.find).toHaveBeenCalledTimes(1);
expect(roleManager.add).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Gave role: `roleName`");
})
test("GIVEN interaction.guild is null, EXPECT nothing to happen", async () => {
const role = {
id: "roleId",
name: "roleName",
editable: true,
};
const requestedRole = {
role: {
name: "roleName",
},
};
const userRole = {};
const interaction = {
isChatInputCommand: jest.fn().mockReturnValue(true),
guildId: "guildId",
guild: null,
member: {
roles: {
cache: {
find: jest.fn().mockReturnValue(userRole),
},
add: jest.fn(),
remove: jest.fn(),
},
},
options: {
get: jest.fn().mockReturnValue(requestedRole),
getSubcommand: jest.fn().mockReturnValue("toggle"),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
Role.FetchAllByServerId = jest.fn().mockResolvedValue([{}]);
const command = new Command();
await command.execute(interaction);
expect(interaction.reply).not.toHaveBeenCalled();
const roleManager = interaction.member!.roles as GuildMemberRoleManager;
expect(roleManager.add).not.toHaveBeenCalled();
expect(roleManager.remove).not.toHaveBeenCalled();
});
test("GIVEN interaction.member is null, EXPECT nothing to happen", async () => {
const role = {
id: "roleId",
name: "roleName",
editable: true,
};
const requestedRole = {
role: {
name: "roleName",
},
};
const userRole = {};
const interaction = {
isChatInputCommand: jest.fn().mockReturnValue(true),
guildId: "guildId",
guild: null,
member: {
roles: {
cache: {
find: jest.fn().mockReturnValue(userRole),
},
add: jest.fn(),
remove: jest.fn(),
},
},
options: {
get: jest.fn().mockReturnValue(requestedRole),
getSubcommand: jest.fn().mockReturnValue("toggle"),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
Role.FetchAllByServerId = jest.fn().mockResolvedValue([{}]);
const command = new Command();
await command.execute(interaction);
expect(interaction.reply).not.toHaveBeenCalled();
const roleManager = interaction.member!.roles as GuildMemberRoleManager;
expect(roleManager.add).not.toHaveBeenCalled();
expect(roleManager.remove).not.toHaveBeenCalled();
});
test("GIVEN requestedRole is null, EXPECT invalid error", async () => {
const role = {
id: "roleId",
name: "roleName",
editable: true,
};
const userRole = {};
const interaction = {
isChatInputCommand: jest.fn().mockReturnValue(true),
guildId: "guildId",
guild: {
roles: {
cache: {
find: jest.fn().mockReturnValue(role),
}
}
},
member: {
roles: {
cache: {
find: jest.fn().mockReturnValue(userRole),
},
remove: jest.fn(),
},
},
options: {
get: jest.fn().mockReturnValue(null),
getSubcommand: jest.fn().mockReturnValue("toggle"),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
Role.FetchAllByServerId = jest.fn().mockResolvedValue([{}]);
const command = new Command();
await command.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN requestedRole.role is undefined, EXPECT invalid error", async () => {
const role = {
id: "roleId",
name: "roleName",
editable: true,
};
const userRole = {};
const requestedRole = {
role: undefined,
};
const interaction = {
isChatInputCommand: jest.fn().mockReturnValue(true),
guildId: "guildId",
guild: {
roles: {
cache: {
find: jest.fn().mockReturnValue(role),
}
}
},
member: {
roles: {
cache: {
find: jest.fn().mockReturnValue(userRole),
},
remove: jest.fn(),
},
},
options: {
get: jest.fn().mockReturnValue(requestedRole),
getSubcommand: jest.fn().mockReturnValue("toggle"),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
Role.FetchAllByServerId = jest.fn().mockResolvedValue([{}]);
const command = new Command();
await command.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Fields are required.");
});
test("GIVEN assignRole is not editable, EXPECT insufficient permissions error", async () => {
const role = {
id: "roleId",
name: "roleName",
editable: false,
};
const userRole = {};
const requestedRole = {
role: {
name: "roleName",
},
};
const interaction = {
isChatInputCommand: jest.fn().mockReturnValue(true),
guildId: "guildId",
guild: {
roles: {
cache: {
find: jest.fn().mockReturnValue(role),
}
}
},
member: {
roles: {
cache: {
find: jest.fn().mockReturnValue(userRole),
},
remove: jest.fn(),
},
},
options: {
get: jest.fn().mockReturnValue(requestedRole),
getSubcommand: jest.fn().mockReturnValue("toggle"),
},
reply: jest.fn(),
} as unknown as CommandInteraction;
Role.FetchAllByServerId = jest.fn().mockResolvedValue([{}]);
const command = new Command();
await command.execute(interaction);
expect(interaction.reply).toHaveBeenCalledTimes(1);
expect(interaction.reply).toHaveBeenCalledWith("Insufficient permissions. Please contact a moderator.");
});
}); });
describe("list", () => { describe("list", () => {
test.todo("EXPECT role list to be sent"); test("EXPECT role list to be sent", async () => {
let repliedWith;
const role = {
name: "roleName",
};
const interaction = {
guildId: "guildId",
guild: {
roles: {
cache: {
find: jest.fn().mockReturnValue(role),
}
}
},
isChatInputCommand: jest.fn().mockReturnValue(true),
options: {
getSubcommand: jest.fn().mockReturnValue("list"),
},
reply: jest.fn().mockImplementation((options) => {
repliedWith = options;
}),
} as unknown as CommandInteraction;
Role.FetchAllByServerId = jest.fn().mockResolvedValue([role]);
const command = new Command();
await command.execute(interaction);
expect(Role.FetchAllByServerId).toHaveBeenCalledTimes(1);
expect(Role.FetchAllByServerId).toHaveBeenCalledWith("guildId");
expect(interaction.guild?.roles.cache.find).toHaveBeenCalledTimes(1);
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("Roles");
expect(embed.data.description).toBe("Roles: 1\n\nroleName");
});
}); });

View file

@ -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", () => { 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', () => { 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", () => { 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", () => { 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", () => { 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", () => { 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("");
});
}); });