From 6f241ab34930c94d73023018e079edd2d279fb76 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Tue, 31 Dec 2024 16:59:57 +0000 Subject: [PATCH 1/2] Update tests --- src/buttonEvents/Effects.ts | 8 +- tests/buttonEvents/Effects.test.ts | 135 +++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 tests/buttonEvents/Effects.test.ts diff --git a/src/buttonEvents/Effects.ts b/src/buttonEvents/Effects.ts index d7c9ef3..f481733 100644 --- a/src/buttonEvents/Effects.ts +++ b/src/buttonEvents/Effects.ts @@ -19,7 +19,7 @@ export default class Effects extends ButtonEvent { } } - private async List(interaction: ButtonInteraction) { + public async List(interaction: ButtonInteraction) { const pageOption = interaction.customId.split(" ")[2]; const page = Number(pageOption); @@ -37,7 +37,7 @@ export default class Effects extends ButtonEvent { }); } - private async Use(interaction: ButtonInteraction) { + public async Use(interaction: ButtonInteraction) { const subaction = interaction.customId.split(" ")[2]; switch (subaction) { @@ -50,7 +50,7 @@ export default class Effects extends ButtonEvent { } } - private async UseConfirm(interaction: ButtonInteraction) { + public async UseConfirm(interaction: ButtonInteraction) { const id = interaction.customId.split(" ")[3]; const effectDetail = EffectDetails.get(id); @@ -108,7 +108,7 @@ export default class Effects extends ButtonEvent { await interaction.reply("Unable to use effect! Please make sure you have it in your inventory and is not on cooldown"); } - private async UseCancel(interaction: ButtonInteraction) { + public async UseCancel(interaction: ButtonInteraction) { const id = interaction.customId.split(" ")[3]; const effectDetail = EffectDetails.get(id); diff --git a/tests/buttonEvents/Effects.test.ts b/tests/buttonEvents/Effects.test.ts new file mode 100644 index 0000000..b500491 --- /dev/null +++ b/tests/buttonEvents/Effects.test.ts @@ -0,0 +1,135 @@ +import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, EmbedBuilder } from "discord.js"; +import Effects from "../../src/buttonEvents/Effects"; +import EffectHelper from "../../src/helpers/EffectHelper"; +import { EffectDetails } from "../../src/constants/EffectDetails"; +import TimeLengthInput from "../../src/helpers/TimeLengthInput"; + +describe("Effects", () => { + let interaction: ButtonInteraction; + let effects: Effects; + + beforeEach(() => { + interaction = { + customId: "effects list 1", + user: { id: "123" }, + reply: jest.fn(), + update: jest.fn(), + } as unknown as ButtonInteraction; + effects = new Effects(); + }); + + it("should call List method when action is 'list'", async () => { + const listSpy = jest.spyOn(effects, "List").mockImplementation(async () => {}); + + await effects.execute(interaction); + + expect(listSpy).toHaveBeenCalledWith(interaction); + }); + + it("should call Use method when action is 'use'", async () => { + interaction.customId = "effects use confirm 1"; + const useSpy = jest.spyOn(effects, "Use").mockImplementation(async () => {}); + + await effects.execute(interaction); + + expect(useSpy).toHaveBeenCalledWith(interaction); + }); + + it("should reply with error message when page option is not a valid number", async () => { + interaction.customId = "effects list invalid"; + await effects.execute(interaction); + + expect(interaction.reply).toHaveBeenCalledWith("Page option is not a valid number"); + }); + + it("should update interaction with generated embed and row", async () => { + const mockEmbed = { + embed: new EmbedBuilder(), + row: new ActionRowBuilder() + }; + + jest.spyOn(EffectHelper, "GenerateEffectEmbed").mockResolvedValue(mockEmbed); + + await effects.List(interaction); + + expect(interaction.update).toHaveBeenCalledWith({ + embeds: [mockEmbed.embed], + components: [mockEmbed.row], + }); + }); + + it("should call UseConfirm method when subaction is 'confirm'", async () => { + interaction.customId = "effects use confirm 1"; + const useConfirmSpy = jest.spyOn(effects, "UseConfirm").mockImplementation(async () => {}); + + await effects.Use(interaction); + + expect(useConfirmSpy).toHaveBeenCalledWith(interaction); + }); + + it("should call UseCancel method when subaction is 'cancel'", async () => { + interaction.customId = "effects use cancel 1"; + const useCancelSpy = jest.spyOn(effects, "UseCancel").mockImplementation(async () => {}); + + await effects.Use(interaction); + + expect(useCancelSpy).toHaveBeenCalledWith(interaction); + }); + + it("should reply with error message when effect detail is not found in UseConfirm", async () => { + interaction.customId = "effects use confirm invalid"; + await effects.UseConfirm(interaction); + + expect(interaction.reply).toHaveBeenCalledWith("Unable to find effect!"); + }); + + it("should reply with error message when effect detail is not found in UseCancel", async () => { + interaction.customId = "effects use cancel invalid"; + await effects.UseCancel(interaction); + + expect(interaction.reply).toHaveBeenCalledWith("Unable to find effect!"); + }); + + it("should update interaction with embed and row when effect is used successfully", async () => { + const mockEffectDetail = { id: "1", friendlyName: "Test Effect", duration: 1000, cost: 10, cooldown: 5000 }; + const mockResult = true; + + jest.spyOn(EffectDetails, "get").mockReturnValue(mockEffectDetail); + jest.spyOn(EffectHelper, "UseEffect").mockResolvedValue(mockResult); + + await effects.UseConfirm(interaction); + + expect(interaction.update).toHaveBeenCalledWith(expect.objectContaining({ + embeds: expect.any(Array), + components: expect.any(Array), + })); + }); + + it("should reply with error message when effect is not used successfully", async () => { + const mockEffectDetail = { id: "1", friendlyName: "Test Effect", duration: 1000, cost: 0, cooldown: 0 }; + const mockResult = false; + + jest.spyOn(EffectDetails, "get").mockReturnValue(mockEffectDetail); + jest.spyOn(EffectHelper, "UseEffect").mockResolvedValue(mockResult); + + await effects.UseConfirm(interaction); + + expect(interaction.reply).toHaveBeenCalledWith("Unable to use effect! Please make sure you have it in your inventory and is not on cooldown"); + }); + + it("should update interaction with embed and row when effect use is cancelled", async () => { + const mockEffectDetail = { id: "1", friendlyName: "Test Effect", duration: 1000, cost: 0, cooldown: 0 }; + + jest.spyOn(EffectDetails, "get").mockReturnValue(mockEffectDetail); + jest.spyOn(TimeLengthInput, "ConvertFromMilliseconds").mockReturnValue({ + GetLengthShort: () => "1s", + } as TimeLengthInput); + + await effects.UseCancel(interaction); + + expect(interaction.update).toHaveBeenCalledWith(expect.objectContaining({ + embeds: expect.any(Array), + components: expect.any(Array), + })); + }); +}); \ No newline at end of file From 222d990a315bfc0494efc50ff70405d42376f738 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Tue, 31 Dec 2024 17:00:36 +0000 Subject: [PATCH 2/2] Fix linting issues --- src/buttonEvents/Effects.ts | 2 +- src/commands/effects.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/buttonEvents/Effects.ts b/src/buttonEvents/Effects.ts index f481733..a09ffaa 100644 --- a/src/buttonEvents/Effects.ts +++ b/src/buttonEvents/Effects.ts @@ -1,4 +1,4 @@ -import {ActionRowBuilder, ButtonBuilder, ButtonInteraction,ButtonStyle,Embed,EmbedBuilder} from "discord.js"; +import {ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, EmbedBuilder} from "discord.js"; import {ButtonEvent} from "../type/buttonEvent"; import EffectHelper from "../helpers/EffectHelper"; import { EffectDetails } from "../constants/EffectDetails"; diff --git a/src/commands/effects.ts b/src/commands/effects.ts index 55f0da9..bc4f743 100644 --- a/src/commands/effects.ts +++ b/src/commands/effects.ts @@ -2,7 +2,6 @@ import {ActionRowBuilder, ButtonBuilder, ButtonStyle, CommandInteraction, EmbedB import {Command} from "../type/command"; import EffectHelper from "../helpers/EffectHelper"; import {EffectDetails} from "../constants/EffectDetails"; -import UserEffect from "../database/entities/app/UserEffect"; import TimeLengthInput from "../helpers/TimeLengthInput"; import EmbedColours from "../constants/EmbedColours";