From 2bc2f81bbd74fb5ab03bc8563eee2e0d0752ab09 Mon Sep 17 00:00:00 2001 From: Naomi Carrigan Date: Mon, 30 Sep 2024 03:51:49 +0000 Subject: [PATCH] fix: fallback empty arrays in view embed (#4) ### Explanation The view embed was sending empty fields if the `tags` or `assignees` arrays were empty. Adding a fallback value provides a better UX. ### Issue _No response_ ### Attestations - [x] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/) - [x] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). - [x] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/). ### Dependencies - [ ] I have pinned the dependencies to a specific patch version. ### Style - [x] I have run the linter and resolved any errors. - [x] My pull request uses an appropriate title, matching the conventional commit standards. - [x] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request. ### Tests - [ ] My contribution adds new code, and I have added tests to cover it. - [x] My contribution modifies existing code, and I have updated the tests to reflect these changes. - [x] All new and existing tests pass locally with my changes. - [x] Code coverage remains at or above the configured threshold. ### Documentation _No response_ ### Versioning Patch - My pull request introduces bug fixes ONLY. Reviewed-on: https://codeberg.org/nhcarrigan/rig-task-bot/pulls/4 Co-authored-by: Naomi Carrigan Co-committed-by: Naomi Carrigan --- src/commands/view.ts | 77 +++++++++++++++++++++++++++----------- test/commands/view.spec.ts | 71 +++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 22 deletions(-) diff --git a/src/commands/view.ts b/src/commands/view.ts index 03fb337..5f3f6fc 100644 --- a/src/commands/view.ts +++ b/src/commands/view.ts @@ -20,6 +20,7 @@ export const view: Command = { setMinValue(1). setRequired(true); }), + // eslint-disable-next-line max-lines-per-function run: async(bot, interaction) => { try { await interaction.deferReply({ ephemeral: true }); @@ -28,34 +29,66 @@ export const view: Command = { where: { numericalId }, }); if (!task) { - await interaction.editReply({ content: `Task ${String(numericalId)} not found.` }); + await interaction.editReply({ + content: `Task ${String(numericalId)} not found.`, + }); return; } if (task.deleted) { - await interaction.editReply({ content: `Task ${String(numericalId)} has been deleted.` }); + await interaction.editReply({ + content: `Task ${String(numericalId)} has been deleted.`, + }); return; } - await interaction.editReply({ embeds: [ - { - description: task.description, - fields: [ - { inline: true, name: "Priority", value: task.priority }, - { inline: true, name: "Completed", value: task.completed - ? "Yes" - : "No" }, - { name: "Tag", value: task.tags.join(", ") }, - { name: "Assignee", value: task.assignees.map((id) => { - return `<@${id}>`; - }).join(", ") }, - - ], - title: `Task ${String(task.numericalId)}`, - }, - ] }); + await interaction.editReply({ + embeds: [ + { + description: task.description, + fields: [ + { inline: true, name: "Priority", value: task.priority }, + { + inline: true, + name: "Completed", + value: task.completed + ? "Yes" + : "No", + }, + { + inline: true, + name: "Due Date", + value: task.dueAt.toLocaleDateString("en-US"), + }, + { + name: "Tag", + value: task.tags.length > 0 + ? task.tags.join(", ") + : "No tags.", + }, + { + name: "Assignee", + value: + task.assignees.length > 0 + ? task.assignees. + map((id) => { + return `<@${id}>`; + }). + join(", ") + : "No assignees.", + }, + ], + title: `Task ${String(task.numericalId)}`, + }, + ], + }); } catch (error) { - await errorHandler(bot, "view command", error, interaction.replied - ? interaction.editReply.bind(interaction) - : interaction.reply.bind(interaction)); + await errorHandler( + bot, + "view command", + error, + interaction.replied + ? interaction.editReply.bind(interaction) + : interaction.reply.bind(interaction), + ); } }, }; diff --git a/test/commands/view.spec.ts b/test/commands/view.spec.ts index 2cb43c6..5c1c212 100644 --- a/test/commands/view.spec.ts +++ b/test/commands/view.spec.ts @@ -103,6 +103,11 @@ describe("view command", () => { fields: [ { inline: true, name: "Priority", value: "critical" }, { inline: true, name: "Completed", value: "No" }, + { + inline: true, + name: "Due Date", + value: new Date("2021-10-10").toLocaleDateString("en-US"), + }, { name: "Tag", value: "discord" }, { name: "Assignee", value: "<@123>" }, ], @@ -112,6 +117,67 @@ describe("view command", () => { }); }); + it("should execute correctly with fallback values", async() => { + expect.assertions(3); + const mockBot = { + database: { + tasks: { + findUnique: vi.fn().mockReturnValue({ + assignees: [ ], + completed: false, + deleted: false, + description: "Task 1 description", + dueAt: new Date("2021-10-10"), + numericalId: 1, + priority: "critical", + tags: [ ], + title: "Task 1", + }), + }, + }, + } as never; + const mockInteraction = { + deferReply: vi.fn(), + editReply: vi.fn(), + options: { getInteger: vi.fn().mockReturnValue(1) }, + } as never; + await view.run(mockBot, mockInteraction); + expect( + mockInteraction.deferReply, + "should defer the reply", + ).toHaveBeenCalledWith({ ephemeral: true }); + expect( + mockBot.database.tasks.findUnique, + "should query database", + ).toHaveBeenCalledWith({ + where: { + numericalId: 1, + }, + }); + expect( + mockInteraction.editReply, + "should call editReply", + ).toHaveBeenCalledWith({ + embeds: [ + { + description: "Task 1 description", + fields: [ + { inline: true, name: "Priority", value: "critical" }, + { inline: true, name: "Completed", value: "No" }, + { + inline: true, + name: "Due Date", + value: new Date("2021-10-10").toLocaleDateString("en-US"), + }, + { name: "Tag", value: "No tags." }, + { name: "Assignee", value: "No assignees." }, + ], + title: "Task 1", + }, + ], + }); + }); + it("should execute correctly with a completed task", async() => { expect.assertions(3); const mockBot = { @@ -159,6 +225,11 @@ describe("view command", () => { fields: [ { inline: true, name: "Priority", value: "critical" }, { inline: true, name: "Completed", value: "Yes" }, + { + inline: true, + name: "Due Date", + value: new Date("2021-10-10").toLocaleDateString("en-US"), + }, { name: "Tag", value: "discord" }, { name: "Assignee", value: "<@123>" }, ],