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 <commits@nhcarrigan.com>
Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
This commit is contained in:
Naomi Carrigan 2024-09-30 03:51:49 +00:00 committed by Naomi the Technomancer
parent 30a5c0c0c6
commit 2bc2f81bbd
2 changed files with 126 additions and 22 deletions

View File

@ -20,6 +20,7 @@ export const view: Command = {
setMinValue(1). setMinValue(1).
setRequired(true); setRequired(true);
}), }),
// eslint-disable-next-line max-lines-per-function
run: async(bot, interaction) => { run: async(bot, interaction) => {
try { try {
await interaction.deferReply({ ephemeral: true }); await interaction.deferReply({ ephemeral: true });
@ -28,34 +29,66 @@ export const view: Command = {
where: { numericalId }, where: { numericalId },
}); });
if (!task) { if (!task) {
await interaction.editReply({ content: `Task ${String(numericalId)} not found.` }); await interaction.editReply({
content: `Task ${String(numericalId)} not found.`,
});
return; return;
} }
if (task.deleted) { if (task.deleted) {
await interaction.editReply({ content: `Task ${String(numericalId)} has been deleted.` }); await interaction.editReply({
content: `Task ${String(numericalId)} has been deleted.`,
});
return; return;
} }
await interaction.editReply({ embeds: [ await interaction.editReply({
{ embeds: [
description: task.description, {
fields: [ description: task.description,
{ inline: true, name: "Priority", value: task.priority }, fields: [
{ inline: true, name: "Completed", value: task.completed { inline: true, name: "Priority", value: task.priority },
? "Yes" {
: "No" }, inline: true,
{ name: "Tag", value: task.tags.join(", ") }, name: "Completed",
{ name: "Assignee", value: task.assignees.map((id) => { value: task.completed
return `<@${id}>`; ? "Yes"
}).join(", ") }, : "No",
},
], {
title: `Task ${String(task.numericalId)}`, 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) { } catch (error) {
await errorHandler(bot, "view command", error, interaction.replied await errorHandler(
? interaction.editReply.bind(interaction) bot,
: interaction.reply.bind(interaction)); "view command",
error,
interaction.replied
? interaction.editReply.bind(interaction)
: interaction.reply.bind(interaction),
);
} }
}, },
}; };

View File

@ -103,6 +103,11 @@ describe("view command", () => {
fields: [ fields: [
{ inline: true, name: "Priority", value: "critical" }, { inline: true, name: "Priority", value: "critical" },
{ inline: true, name: "Completed", value: "No" }, { 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: "Tag", value: "discord" },
{ name: "Assignee", value: "<@123>" }, { 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() => { it("should execute correctly with a completed task", async() => {
expect.assertions(3); expect.assertions(3);
const mockBot = { const mockBot = {
@ -159,6 +225,11 @@ describe("view command", () => {
fields: [ fields: [
{ inline: true, name: "Priority", value: "critical" }, { inline: true, name: "Priority", value: "critical" },
{ inline: true, name: "Completed", value: "Yes" }, { 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: "Tag", value: "discord" },
{ name: "Assignee", value: "<@123>" }, { name: "Assignee", value: "<@123>" },
], ],