2024-05-11 14:03:05 +01:00
|
|
|
import { CommandInteraction, EmbedBuilder, GuildMember, PermissionsBitField, SlashCommandBuilder, SlashCommandStringOption, SlashCommandUserOption, TextChannel, User } from "discord.js";
|
|
|
|
import Command from "../../src/commands/kick";
|
|
|
|
import SettingsHelper from "../../src/helpers/SettingsHelper";
|
|
|
|
import Audit from "../../src/database/entities/Audit";
|
|
|
|
import EmbedColours from "../../src/constants/EmbedColours";
|
|
|
|
import { AuditType } from "../../src/constants/AuditType";
|
|
|
|
|
2022-04-24 14:46:37 +01:00
|
|
|
beforeEach(() => {
|
|
|
|
process.env = {};
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('Constructor', () => {
|
2024-05-11 14:03:05 +01:00
|
|
|
test('EXPECT properties to be set', () => {
|
|
|
|
const command = new Command();
|
|
|
|
|
|
|
|
expect(command.CommandBuilder).toBeDefined();
|
|
|
|
|
|
|
|
const commandBuilder = command.CommandBuilder as SlashCommandBuilder;
|
|
|
|
|
|
|
|
expect(commandBuilder.name).toBe("kick");
|
|
|
|
expect(commandBuilder.description).toBe("Kick a member from the server with an optional reason");
|
|
|
|
expect(commandBuilder.default_member_permissions).toBe(PermissionsBitField.Flags.KickMembers.toString());
|
|
|
|
expect(commandBuilder.options.length).toBe(2);
|
|
|
|
|
|
|
|
const commandBuilderTargetOption = commandBuilder.options[0] as SlashCommandUserOption;
|
|
|
|
|
|
|
|
expect(commandBuilderTargetOption.name).toBe("target");
|
|
|
|
expect(commandBuilderTargetOption.description).toBe("The user");
|
|
|
|
expect(commandBuilderTargetOption.required).toBe(true);
|
|
|
|
|
|
|
|
const commandBuilderReasonOption = commandBuilder.options[1] as SlashCommandStringOption;
|
|
|
|
|
|
|
|
expect(commandBuilderReasonOption.name).toBe("reason");
|
|
|
|
expect(commandBuilderReasonOption.description).toBe("The reason");
|
|
|
|
});
|
2022-04-24 14:46:37 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('Execute', () => {
|
2024-05-11 14:03:05 +01:00
|
|
|
test("GIVEN input is valid, EXPECT member to be kicked", async () => {
|
|
|
|
let sentEmbed: EmbedBuilder | undefined;
|
|
|
|
let savedAudit: Audit | undefined;
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-11 14:03:05 +01:00
|
|
|
// 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,
|
|
|
|
};
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-11 14:03:05 +01:00
|
|
|
const reason = {
|
|
|
|
value: "Test reason",
|
|
|
|
};
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-11 14:03:05 +01:00
|
|
|
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.isChatInputCommand).toHaveBeenCalledTimes(1);
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-11 14:03:05 +01:00
|
|
|
expect(interaction.options.get).toHaveBeenCalledTimes(2);
|
|
|
|
expect(interaction.options.get).toHaveBeenCalledWith("target", true);
|
|
|
|
expect(interaction.options.get).toHaveBeenCalledWith("reason");
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-11 14:03:05 +01:00
|
|
|
expect(targetUser.member.kick).toHaveBeenCalledTimes(1);
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-11 14:03:05 +01:00
|
|
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
|
|
|
expect(interaction.reply).toHaveBeenCalledWith("`userTag` has been kicked.");
|
|
|
|
|
|
|
|
expect(SettingsHelper.GetSetting).toHaveBeenCalledTimes(1);
|
|
|
|
expect(SettingsHelper.GetSetting).toHaveBeenCalledWith("channels.logs.mod", "guildId");
|
|
|
|
|
|
|
|
expect(channel.send).toHaveBeenCalledTimes(1);
|
|
|
|
expect(channel.send).toHaveBeenCalledWith({ embeds: [ expect.any(EmbedBuilder) ] });
|
|
|
|
|
|
|
|
expect(Audit.prototype.Save).toHaveBeenCalledTimes(1);
|
|
|
|
expect(Audit.prototype.Save).toHaveBeenCalledWith(Audit, expect.any(Audit));
|
|
|
|
|
|
|
|
expect(sentEmbed).toBeDefined();
|
|
|
|
expect(sentEmbed!.data.color).toBe(EmbedColours.Ok);
|
|
|
|
expect(sentEmbed!.data.title).toBe("Member Kicked");
|
|
|
|
expect(sentEmbed!.data.description).toBe("<@userId> `userTag`");
|
|
|
|
expect(sentEmbed!.data.thumbnail?.url).toBe("https://avatarurl.com/user.png");
|
|
|
|
expect(sentEmbed!.data.fields).toBeDefined();
|
|
|
|
expect(sentEmbed!.data.fields!.length).toBe(2);
|
|
|
|
|
|
|
|
const sentEmbedModeratorField = sentEmbed!.data.fields![0];
|
|
|
|
|
|
|
|
expect(sentEmbedModeratorField.name).toBe("Moderator");
|
|
|
|
expect(sentEmbedModeratorField.value).toBe("<@moderatorId>");
|
|
|
|
|
|
|
|
const sentEmbedReasonField = sentEmbed!.data.fields![1];
|
|
|
|
|
|
|
|
expect(sentEmbedReasonField.name).toBe("Reason");
|
|
|
|
expect(sentEmbedReasonField.value).toBe("Test reason");
|
|
|
|
|
|
|
|
expect(targetUser.user.avatarURL).toHaveBeenCalledTimes(1);
|
|
|
|
|
|
|
|
expect(savedAudit).toBeDefined();
|
|
|
|
expect(savedAudit?.UserId).toBe("userId");
|
|
|
|
expect(savedAudit?.AuditType).toBe(AuditType.Kick);
|
|
|
|
expect(savedAudit?.Reason).toBe("Test reason");
|
|
|
|
expect(savedAudit?.ModeratorId).toBe("moderatorId");
|
|
|
|
expect(savedAudit?.ServerId).toBe("guildId");
|
|
|
|
});
|
|
|
|
|
2024-05-13 15:58:14 +01:00
|
|
|
test("GIVEN interaction is NOT a chat input command, 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(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;
|
|
|
|
|
|
|
|
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.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;
|
2024-05-11 14:03:05 +01:00
|
|
|
|
2024-05-13 15:58:14 +01:00
|
|
|
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;
|
2024-05-11 14:03:05 +01:00
|
|
|
|
2024-05-13 15:58:14 +01:00
|
|
|
SettingsHelper.GetSetting = jest.fn().mockResolvedValue("mod-logs");
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-13 15:58:14 +01:00
|
|
|
Audit.prototype.Save = jest.fn().mockImplementation((_, audit: Audit) => {
|
|
|
|
savedAudit = audit;
|
|
|
|
});
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-13 15:58:14 +01:00
|
|
|
// Act
|
|
|
|
const command = new Command();
|
|
|
|
await command.execute(interaction);
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-13 15:58:14 +01:00
|
|
|
// Assert
|
|
|
|
expect(interaction.reply).toHaveBeenCalledTimes(1);
|
|
|
|
expect(interaction.reply).toHaveBeenCalledWith("Insufficient permissions. Please contact a moderator.");
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-13 15:58:14 +01:00
|
|
|
expect(targetUser.member.kick).not.toHaveBeenCalled();
|
|
|
|
expect(Audit.prototype.Save).not.toHaveBeenCalled();
|
|
|
|
});
|
2022-04-24 14:46:37 +01:00
|
|
|
|
2024-05-13 15:58:14 +01:00
|
|
|
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);
|
|
|
|
});
|
2022-04-24 14:46:37 +01:00
|
|
|
});
|