Compare commits
2 commits
d0a8db718e
...
39231ddc16
Author | SHA1 | Date | |
---|---|---|---|
39231ddc16 | |||
91bc444e71 |
4 changed files with 605 additions and 31 deletions
|
@ -61,13 +61,13 @@ export default class Kick extends Command {
|
||||||
|
|
||||||
const channelName = await SettingsHelper.GetSetting('channels.logs.mod', interaction.guildId);
|
const channelName = await SettingsHelper.GetSetting('channels.logs.mod', interaction.guildId);
|
||||||
|
|
||||||
if (!channelName) return;
|
if (channelName) {
|
||||||
|
|
||||||
const channel = interaction.guild.channels.cache.find(x => x.name == channelName) as TextChannel;
|
const channel = interaction.guild.channels.cache.find(x => x.name == channelName) as TextChannel;
|
||||||
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
await channel.send({ embeds: [ logEmbed ]});
|
await channel.send({ embeds: [ logEmbed ]});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const audit = new Audit(targetUser.user!.id, AuditType.Kick, reason, interaction.user.id, interaction.guildId);
|
const audit = new Audit(targetUser.user!.id, AuditType.Kick, reason, interaction.user.id, interaction.guildId);
|
||||||
await audit.Save(Audit, audit);
|
await audit.Save(Audit, audit);
|
||||||
|
|
|
@ -40,15 +40,13 @@ export default class Poll extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async execute(interaction: CommandInteraction) {
|
public override async execute(interaction: CommandInteraction) {
|
||||||
const title = interaction.options.get('title');
|
const title = interaction.options.get('title', true);
|
||||||
const option1 = interaction.options.get('option1');
|
const option1 = interaction.options.get('option1', true);
|
||||||
const option2 = interaction.options.get('option2');
|
const option2 = interaction.options.get('option2', true);
|
||||||
const option3 = interaction.options.get('option3');
|
const option3 = interaction.options.get('option3');
|
||||||
const option4 = interaction.options.get('option4');
|
const option4 = interaction.options.get('option4');
|
||||||
const option5 = interaction.options.get('option5');
|
const option5 = interaction.options.get('option5');
|
||||||
|
|
||||||
if (!title || !option1 || !option2) return;
|
|
||||||
|
|
||||||
const description = [
|
const description = [
|
||||||
option1.value as string,
|
option1.value as string,
|
||||||
option2.value as string,
|
option2.value as string,
|
||||||
|
@ -58,15 +56,7 @@ export default class Poll extends Command {
|
||||||
]
|
]
|
||||||
.filter(x => x != null);
|
.filter(x => x != null);
|
||||||
|
|
||||||
const arrayOfNumbers = [
|
const reactionEmojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣"];
|
||||||
':one:',
|
|
||||||
':two:',
|
|
||||||
':three:',
|
|
||||||
':four:',
|
|
||||||
':five:',
|
|
||||||
];
|
|
||||||
|
|
||||||
const reactionEmojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣"];
|
|
||||||
|
|
||||||
description.forEach((value, index) => {
|
description.forEach((value, index) => {
|
||||||
description[index] = `${reactionEmojis[index]} ${description[index]}`;
|
description[index] = `${reactionEmojis[index]} ${description[index]}`;
|
||||||
|
@ -82,10 +72,11 @@ export default class Poll extends Command {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const message = await interaction.reply({ embeds: [ embed ]});
|
const messageResponse = await interaction.reply({ embeds: [ embed ]});
|
||||||
|
const message = await messageResponse.fetch();
|
||||||
|
|
||||||
description.forEach(async (value, index) => {
|
description.forEach(async (value, index) => {
|
||||||
await (await message.fetch()).react(reactionEmojis[index]);
|
await message.react(reactionEmojis[index]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -141,19 +141,490 @@ describe('Execute', () => {
|
||||||
expect(savedAudit?.ServerId).toBe("guildId");
|
expect(savedAudit?.ServerId).toBe("guildId");
|
||||||
});
|
});
|
||||||
|
|
||||||
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 () => {
|
||||||
|
let sentEmbed: EmbedBuilder | undefined;
|
||||||
|
let savedAudit: Audit | undefined;
|
||||||
|
|
||||||
test.todo("GIVEN interaction.guildId is null, EXPECT nothing to happen");
|
// Arrange
|
||||||
|
const targetUser = {
|
||||||
|
member: {
|
||||||
|
kickable: true,
|
||||||
|
kick: jest.fn(),
|
||||||
|
} as unknown as GuildMember,
|
||||||
|
user: {
|
||||||
|
tag: "userTag",
|
||||||
|
id: "userId",
|
||||||
|
avatarURL: jest.fn().mockReturnValue("https://avatarurl.com/user.png"),
|
||||||
|
} as unknown as User,
|
||||||
|
};
|
||||||
|
|
||||||
test.todo("GIVEN interaction.guild is null, EXPECT nothing to happen");
|
const reason = {
|
||||||
|
value: "Test reason",
|
||||||
|
};
|
||||||
|
|
||||||
test.todo("GIVEN reasonInput is null, EXPECT reason to be defaulted");
|
const channel = {
|
||||||
|
name: "mod-logs",
|
||||||
|
send: jest.fn().mockImplementation((options: any) => {
|
||||||
|
sentEmbed = options.embeds[0];
|
||||||
|
}),
|
||||||
|
} as unknown as TextChannel;
|
||||||
|
|
||||||
test.todo("GIVEN reasonInput.value is undefined, EXPECT reason to be defaulted");
|
const interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(false),
|
||||||
|
guildId: "guildId",
|
||||||
|
guild: {
|
||||||
|
channels: {
|
||||||
|
cache: [ channel ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValueOnce(targetUser)
|
||||||
|
.mockReturnValue(reason),
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
user: {
|
||||||
|
id: "moderatorId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
test.todo("GIVEN user is not kickable, EXPECT insufficient permissions error");
|
SettingsHelper.GetSetting = jest.fn().mockResolvedValue("mod-logs");
|
||||||
|
|
||||||
test.todo("GIVEN channels.logs.mod setting can not be found, EXPECT command to return");
|
Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => {
|
||||||
|
savedAudit = audit;
|
||||||
|
});
|
||||||
|
|
||||||
test.todo("GIVEN channel can not be found, EXPECT logEmbed not to be sent");
|
// Act
|
||||||
|
const command = new Command();
|
||||||
|
await command.execute(interaction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(interaction.isChatInputCommand).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
expect(interaction.reply).not.toHaveBeenCalled();
|
||||||
|
expect(targetUser.member.kick).not.toHaveBeenCalled();
|
||||||
|
expect(Audit.prototype.Save).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("GIVEN interaction.guildId is null, EXPECT nothing to happen", async () => {
|
||||||
|
let sentEmbed: EmbedBuilder | undefined;
|
||||||
|
let savedAudit: Audit | undefined;
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const targetUser = {
|
||||||
|
member: {
|
||||||
|
kickable: true,
|
||||||
|
kick: jest.fn(),
|
||||||
|
} as unknown as GuildMember,
|
||||||
|
user: {
|
||||||
|
tag: "userTag",
|
||||||
|
id: "userId",
|
||||||
|
avatarURL: jest.fn().mockReturnValue("https://avatarurl.com/user.png"),
|
||||||
|
} as unknown as User,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reason = {
|
||||||
|
value: "Test reason",
|
||||||
|
};
|
||||||
|
|
||||||
|
const channel = {
|
||||||
|
name: "mod-logs",
|
||||||
|
send: jest.fn().mockImplementation((options: any) => {
|
||||||
|
sentEmbed = options.embeds[0];
|
||||||
|
}),
|
||||||
|
} as unknown as TextChannel;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(true),
|
||||||
|
guildId: null,
|
||||||
|
guild: {
|
||||||
|
channels: {
|
||||||
|
cache: [ channel ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValueOnce(targetUser)
|
||||||
|
.mockReturnValue(reason),
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
user: {
|
||||||
|
id: "moderatorId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
SettingsHelper.GetSetting = jest.fn().mockResolvedValue("mod-logs");
|
||||||
|
|
||||||
|
Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => {
|
||||||
|
savedAudit = audit;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const command = new Command();
|
||||||
|
await command.execute(interaction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(interaction.reply).not.toHaveBeenCalled();
|
||||||
|
expect(targetUser.member.kick).not.toHaveBeenCalled();
|
||||||
|
expect(Audit.prototype.Save).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("GIVEN interaction.guild is null, EXPECT nothing to happen", async () => {
|
||||||
|
let sentEmbed: EmbedBuilder | undefined;
|
||||||
|
let savedAudit: Audit | undefined;
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const targetUser = {
|
||||||
|
member: {
|
||||||
|
kickable: true,
|
||||||
|
kick: jest.fn(),
|
||||||
|
} as unknown as GuildMember,
|
||||||
|
user: {
|
||||||
|
tag: "userTag",
|
||||||
|
id: "userId",
|
||||||
|
avatarURL: jest.fn().mockReturnValue("https://avatarurl.com/user.png"),
|
||||||
|
} as unknown as User,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reason = {
|
||||||
|
value: "Test reason",
|
||||||
|
};
|
||||||
|
|
||||||
|
const channel = {
|
||||||
|
name: "mod-logs",
|
||||||
|
send: jest.fn().mockImplementation((options: any) => {
|
||||||
|
sentEmbed = options.embeds[0];
|
||||||
|
}),
|
||||||
|
} as unknown as TextChannel;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(true),
|
||||||
|
guildId: "guildId",
|
||||||
|
guild: null,
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValueOnce(targetUser)
|
||||||
|
.mockReturnValue(reason),
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
user: {
|
||||||
|
id: "moderatorId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
SettingsHelper.GetSetting = jest.fn().mockResolvedValue("mod-logs");
|
||||||
|
|
||||||
|
Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => {
|
||||||
|
savedAudit = audit;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const command = new Command();
|
||||||
|
await command.execute(interaction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(interaction.reply).not.toHaveBeenCalled();
|
||||||
|
expect(targetUser.member.kick).not.toHaveBeenCalled();
|
||||||
|
expect(Audit.prototype.Save).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("GIVEN reasonInput is null, EXPECT reason to be defaulted", async () => {
|
||||||
|
let sentEmbed: EmbedBuilder | undefined;
|
||||||
|
let savedAudit: Audit | undefined;
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const targetUser = {
|
||||||
|
member: {
|
||||||
|
kickable: true,
|
||||||
|
kick: jest.fn(),
|
||||||
|
} as unknown as GuildMember,
|
||||||
|
user: {
|
||||||
|
tag: "userTag",
|
||||||
|
id: "userId",
|
||||||
|
avatarURL: jest.fn().mockReturnValue("https://avatarurl.com/user.png"),
|
||||||
|
} as unknown as User,
|
||||||
|
};
|
||||||
|
|
||||||
|
const channel = {
|
||||||
|
name: "mod-logs",
|
||||||
|
send: jest.fn().mockImplementation((options: any) => {
|
||||||
|
sentEmbed = options.embeds[0];
|
||||||
|
}),
|
||||||
|
} as unknown as TextChannel;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(true),
|
||||||
|
guildId: "guildId",
|
||||||
|
guild: {
|
||||||
|
channels: {
|
||||||
|
cache: [ channel ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValueOnce(targetUser)
|
||||||
|
.mockReturnValue(null),
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
user: {
|
||||||
|
id: "moderatorId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
SettingsHelper.GetSetting = jest.fn().mockResolvedValue("mod-logs");
|
||||||
|
|
||||||
|
Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => {
|
||||||
|
savedAudit = audit;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const command = new Command();
|
||||||
|
await command.execute(interaction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const sentEmbedReasonField = sentEmbed!.data.fields!.find(x => x.name == "Reason");
|
||||||
|
|
||||||
|
expect(sentEmbedReasonField!.value).toBe("*none*");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("GIVEN reasonInput.value is undefined, EXPECT reason to be defaulted", async () => {
|
||||||
|
let sentEmbed: EmbedBuilder | undefined;
|
||||||
|
let savedAudit: Audit | undefined;
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const targetUser = {
|
||||||
|
member: {
|
||||||
|
kickable: true,
|
||||||
|
kick: jest.fn(),
|
||||||
|
} as unknown as GuildMember,
|
||||||
|
user: {
|
||||||
|
tag: "userTag",
|
||||||
|
id: "userId",
|
||||||
|
avatarURL: jest.fn().mockReturnValue("https://avatarurl.com/user.png"),
|
||||||
|
} as unknown as User,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reason = {
|
||||||
|
value: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const channel = {
|
||||||
|
name: "mod-logs",
|
||||||
|
send: jest.fn().mockImplementation((options: any) => {
|
||||||
|
sentEmbed = options.embeds[0];
|
||||||
|
}),
|
||||||
|
} as unknown as TextChannel;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(true),
|
||||||
|
guildId: "guildId",
|
||||||
|
guild: {
|
||||||
|
channels: {
|
||||||
|
cache: [ channel ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValueOnce(targetUser)
|
||||||
|
.mockReturnValue(reason),
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
user: {
|
||||||
|
id: "moderatorId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
SettingsHelper.GetSetting = jest.fn().mockResolvedValue("mod-logs");
|
||||||
|
|
||||||
|
Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => {
|
||||||
|
savedAudit = audit;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const command = new Command();
|
||||||
|
await command.execute(interaction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const sentEmbedReasonField = sentEmbed!.data.fields!.find(x => x.name == "Reason");
|
||||||
|
|
||||||
|
expect(sentEmbedReasonField!.value).toBe("*none*");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("GIVEN user is not kickable, EXPECT insufficient permissions error", async () => {
|
||||||
|
let sentEmbed: EmbedBuilder | undefined;
|
||||||
|
let savedAudit: Audit | undefined;
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const targetUser = {
|
||||||
|
member: {
|
||||||
|
kickable: false,
|
||||||
|
kick: jest.fn(),
|
||||||
|
} as unknown as GuildMember,
|
||||||
|
user: {
|
||||||
|
tag: "userTag",
|
||||||
|
id: "userId",
|
||||||
|
avatarURL: jest.fn().mockReturnValue("https://avatarurl.com/user.png"),
|
||||||
|
} as unknown as User,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reason = {
|
||||||
|
value: "Test reason",
|
||||||
|
};
|
||||||
|
|
||||||
|
const channel = {
|
||||||
|
name: "mod-logs",
|
||||||
|
send: jest.fn().mockImplementation((options: any) => {
|
||||||
|
sentEmbed = options.embeds[0];
|
||||||
|
}),
|
||||||
|
} as unknown as TextChannel;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(true),
|
||||||
|
guildId: "guildId",
|
||||||
|
guild: {
|
||||||
|
channels: {
|
||||||
|
cache: [ channel ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValueOnce(targetUser)
|
||||||
|
.mockReturnValue(reason),
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
user: {
|
||||||
|
id: "moderatorId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
SettingsHelper.GetSetting = jest.fn().mockResolvedValue("mod-logs");
|
||||||
|
|
||||||
|
Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => {
|
||||||
|
savedAudit = audit;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const command = new Command();
|
||||||
|
await command.execute(interaction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
expect(interaction.reply).toHaveBeenCalledWith("Insufficient permissions. Please contact a moderator.");
|
||||||
|
|
||||||
|
expect(targetUser.member.kick).not.toHaveBeenCalled();
|
||||||
|
expect(Audit.prototype.Save).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("GIVEN channels.logs.mod setting can not be found, EXPECT command to return", async () => {
|
||||||
|
let sentEmbed: EmbedBuilder | undefined;
|
||||||
|
let savedAudit: Audit | undefined;
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const targetUser = {
|
||||||
|
member: {
|
||||||
|
kickable: true,
|
||||||
|
kick: jest.fn(),
|
||||||
|
} as unknown as GuildMember,
|
||||||
|
user: {
|
||||||
|
tag: "userTag",
|
||||||
|
id: "userId",
|
||||||
|
avatarURL: jest.fn().mockReturnValue("https://avatarurl.com/user.png"),
|
||||||
|
} as unknown as User,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reason = {
|
||||||
|
value: "Test reason",
|
||||||
|
};
|
||||||
|
|
||||||
|
const channel = {
|
||||||
|
name: "mod-logs",
|
||||||
|
send: jest.fn().mockImplementation((options: any) => {
|
||||||
|
sentEmbed = options.embeds[0];
|
||||||
|
}),
|
||||||
|
} as unknown as TextChannel;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(true),
|
||||||
|
guildId: "guildId",
|
||||||
|
guild: {
|
||||||
|
channels: {
|
||||||
|
cache: [ channel ],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValueOnce(targetUser)
|
||||||
|
.mockReturnValue(reason),
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
user: {
|
||||||
|
id: "moderatorId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
SettingsHelper.GetSetting = jest.fn().mockResolvedValue(undefined);
|
||||||
|
|
||||||
|
Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => {
|
||||||
|
savedAudit = audit;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const command = new Command();
|
||||||
|
await command.execute(interaction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(channel.send).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
expect(Audit.prototype.Save).toHaveBeenCalledTimes(1);
|
||||||
|
expect(targetUser.member.kick).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("GIVEN channel can not be found, EXPECT logEmbed not to be sent", async () => {
|
||||||
|
let sentEmbed: EmbedBuilder | undefined;
|
||||||
|
let savedAudit: Audit | undefined;
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const targetUser = {
|
||||||
|
member: {
|
||||||
|
kickable: true,
|
||||||
|
kick: jest.fn(),
|
||||||
|
} as unknown as GuildMember,
|
||||||
|
user: {
|
||||||
|
tag: "userTag",
|
||||||
|
id: "userId",
|
||||||
|
avatarURL: jest.fn().mockReturnValue("https://avatarurl.com/user.png"),
|
||||||
|
} as unknown as User,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reason = {
|
||||||
|
value: "Test reason",
|
||||||
|
};
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
isChatInputCommand: jest.fn().mockReturnValue(true),
|
||||||
|
guildId: "guildId",
|
||||||
|
guild: {
|
||||||
|
channels: {
|
||||||
|
cache: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValueOnce(targetUser)
|
||||||
|
.mockReturnValue(reason),
|
||||||
|
},
|
||||||
|
reply: jest.fn(),
|
||||||
|
user: {
|
||||||
|
id: "moderatorId",
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
SettingsHelper.GetSetting = jest.fn().mockResolvedValue("mod-logs");
|
||||||
|
|
||||||
|
Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => {
|
||||||
|
savedAudit = audit;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const command = new Command();
|
||||||
|
await command.execute(interaction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
expect(Audit.prototype.Save).toHaveBeenCalledTimes(1);
|
||||||
|
expect(targetUser.member.kick).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
});
|
});
|
|
@ -1,9 +1,121 @@
|
||||||
|
import { CommandInteraction, EmbedBuilder, InteractionResponse, Message, SlashCommandBuilder, SlashCommandStringOption } from "discord.js";
|
||||||
|
import Command from "../../src/commands/poll";
|
||||||
|
import EmbedColours from "../../src/constants/EmbedColours";
|
||||||
|
|
||||||
describe('Constructor', () => {
|
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("poll");
|
||||||
|
expect(commandBuilder.description).toBe("Run a poll, automatically adding reaction emojis as options");
|
||||||
|
expect(commandBuilder.options.length).toBe(6);
|
||||||
|
|
||||||
|
const commandBuilderTitleOption = commandBuilder.options[0] as SlashCommandStringOption;
|
||||||
|
|
||||||
|
expect(commandBuilderTitleOption.name).toBe("title");
|
||||||
|
expect(commandBuilderTitleOption.description).toBe("Title of the poll");
|
||||||
|
expect(commandBuilderTitleOption.required).toBe(true);
|
||||||
|
|
||||||
|
const commandBuilderOption1Option = commandBuilder.options[1] as SlashCommandStringOption;
|
||||||
|
|
||||||
|
expect(commandBuilderOption1Option.name).toBe("option1");
|
||||||
|
expect(commandBuilderOption1Option.description).toBe("Option 1");
|
||||||
|
expect(commandBuilderOption1Option.required).toBe(true);
|
||||||
|
|
||||||
|
const commandBuilderOption2Option = commandBuilder.options[2] as SlashCommandStringOption;
|
||||||
|
|
||||||
|
expect(commandBuilderOption2Option.name).toBe("option2");
|
||||||
|
expect(commandBuilderOption2Option.description).toBe("Option 2");
|
||||||
|
expect(commandBuilderOption2Option.required).toBe(true);
|
||||||
|
|
||||||
|
const commandBuilderOption3Option = commandBuilder.options[3] as SlashCommandStringOption;
|
||||||
|
|
||||||
|
expect(commandBuilderOption3Option.name).toBe("option3");
|
||||||
|
expect(commandBuilderOption3Option.description).toBe("Option 3");
|
||||||
|
|
||||||
|
const commandBuilderOption4Option = commandBuilder.options[4] as SlashCommandStringOption;
|
||||||
|
|
||||||
|
expect(commandBuilderOption4Option.name).toBe("option4");
|
||||||
|
expect(commandBuilderOption4Option.description).toBe("Option 4");
|
||||||
|
|
||||||
|
const commandBuilderOption5Option = commandBuilder.options[5] as SlashCommandStringOption;
|
||||||
|
|
||||||
|
expect(commandBuilderOption5Option.name).toBe("option5");
|
||||||
|
expect(commandBuilderOption5Option.description).toBe("Option 5");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Execute', () => {
|
describe('Execute', () => {
|
||||||
test.todo("EXPECT a poll to be created");
|
test("EXPECT a poll to be created", async () => {
|
||||||
|
let sentEmbed: EmbedBuilder | undefined;
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const message = {
|
||||||
|
react: jest.fn(),
|
||||||
|
} as unknown as Message<boolean>;
|
||||||
|
|
||||||
|
const response = {
|
||||||
|
fetch: jest.fn().mockResolvedValue(message),
|
||||||
|
} as unknown as InteractionResponse<boolean>;
|
||||||
|
|
||||||
|
const interaction = {
|
||||||
|
options: {
|
||||||
|
get: jest.fn().mockReturnValueOnce({ value: "Title" })
|
||||||
|
.mockReturnValueOnce({ value: "Option 1" })
|
||||||
|
.mockReturnValueOnce({ value: "Option 2" })
|
||||||
|
.mockReturnValueOnce({ value: "Option 3" })
|
||||||
|
.mockReturnValueOnce({ value: "Option 4" })
|
||||||
|
.mockReturnValue({ value: "Option 5" }),
|
||||||
|
},
|
||||||
|
reply: jest.fn().mockImplementation((options: any) => {
|
||||||
|
sentEmbed = options.embeds[0];
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}),
|
||||||
|
user: {
|
||||||
|
username: "username",
|
||||||
|
avatarURL: jest.fn().mockReturnValue("https://avatarurl.com/user.png"),
|
||||||
|
},
|
||||||
|
} as unknown as CommandInteraction;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const command = new Command();
|
||||||
|
await command.execute(interaction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(interaction.options.get).toHaveBeenCalledTimes(6);
|
||||||
|
expect(interaction.options.get).toHaveBeenCalledWith("title", true);
|
||||||
|
expect(interaction.options.get).toHaveBeenCalledWith("option1", true);
|
||||||
|
expect(interaction.options.get).toHaveBeenCalledWith("option2", true);
|
||||||
|
expect(interaction.options.get).toHaveBeenCalledWith("option3");
|
||||||
|
expect(interaction.options.get).toHaveBeenCalledWith("option4");
|
||||||
|
expect(interaction.options.get).toHaveBeenCalledWith("option5");
|
||||||
|
|
||||||
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
expect(sentEmbed).toBeDefined();
|
||||||
|
expect(sentEmbed!.data.color).toBe(EmbedColours.Ok);
|
||||||
|
expect(sentEmbed!.data.title).toBe("Title");
|
||||||
|
expect(sentEmbed!.data.description).toBe("1️⃣ Option 1\n2️⃣ Option 2\n3️⃣ Option 3\n4️⃣ Option 4\n5️⃣ Option 5");
|
||||||
|
expect(sentEmbed!.data.footer).toBeDefined();
|
||||||
|
expect(sentEmbed!.data.footer!.text).toBe("Poll by username");
|
||||||
|
expect(sentEmbed!.data.footer!.icon_url).toBe("https://avatarurl.com/user.png");
|
||||||
|
|
||||||
|
expect(interaction.user.avatarURL).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
expect(response.fetch).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
expect(message.react).toHaveBeenCalledTimes(5);
|
||||||
|
expect(message.react).toHaveBeenCalledWith("1️⃣");
|
||||||
|
expect(message.react).toHaveBeenCalledWith("2️⃣");
|
||||||
|
expect(message.react).toHaveBeenCalledWith("3️⃣");
|
||||||
|
expect(message.react).toHaveBeenCalledWith("4️⃣");
|
||||||
|
expect(message.react).toHaveBeenCalledWith("5️⃣");
|
||||||
|
});
|
||||||
|
|
||||||
test.todo("GIVEN title is not supplied, EXPECT nothing to happen");
|
test.todo("GIVEN title is not supplied, EXPECT nothing to happen");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue