Skip to content

Commit

Permalink
add taskTitle field to /task/update API (#227)
Browse files Browse the repository at this point in the history
* add taskTitle field to /task/update API

* feat:add test case for sendTaskUpdate util

* feat: add test cases to taskUpdateHandler

* refactor: add message in constant responses

* remove: extra line
  • Loading branch information
tejaskh3 authored May 5, 2024
1 parent bdbb0c6 commit adcc1d2
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 22 deletions.
2 changes: 2 additions & 0 deletions src/constants/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,5 @@ export const INVALID_TOKEN_FORMAT =
"Invalid Authentication header format. Expected 'Bearer <token>'";

export const AUTHENTICATION_ERROR = "Invalid Authentication token";
export const TASK_UPDATE_SENT_MESSAGE =
"Task update sent on Discord's tracking-updates channel.";
15 changes: 11 additions & 4 deletions src/controllers/taskUpdatesHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@ export const sendTaskUpdatesHandler = async (request: IRequest, env: env) => {
try {
await verifyNodejsBackendAuthToken(authHeader, env);
const updates: TaskUpdates = await request.json();
const { completed, planned, blockers, userName, taskId } = updates.content;
await sendTaskUpdate(completed, planned, blockers, userName, taskId, env);
return new JSONResponse(
"Task update sent on Discord's tracking-updates channel."
const { completed, planned, blockers, userName, taskId, taskTitle } =
updates.content;
await sendTaskUpdate(
completed,
planned,
blockers,
userName,
taskId,
taskTitle,
env
);
return new JSONResponse(response.TASK_UPDATE_SENT_MESSAGE);
} catch (error: any) {
return new JSONResponse({
res: response.INTERNAL_SERVER_ERROR,
Expand Down
1 change: 1 addition & 0 deletions src/typeDefinitions/taskUpdate.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export interface TaskUpdates {
blockers: string;
userName: string;
taskId: string;
taskTitle: string;
};
}
3 changes: 2 additions & 1 deletion src/utils/sendTaskUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ export async function sendTaskUpdate(
blockers: string,
userName: string,
taskId: string,
taskTitle: string,
env: env
): Promise<void> {
const taskUrl = config(env).RDS_STATUS_SITE_URL + `/tasks/${taskId}`;
const formattedString =
`${userName} added an update to their task: <${taskUrl}>\n` +
`**${userName}** added an update to their task: [${taskTitle}](<${taskUrl}>)\n` +
`\n**Completed**\n${completed}\n\n` +
`**Planned**\n${planned}\n\n` +
`**Blockers**\n${blockers}`;
Expand Down
26 changes: 22 additions & 4 deletions tests/unit/handlers/taskUpdateHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { sendTaskUpdatesHandler } from "../../../src/controllers/taskUpdatesHand
import JSONResponse from "../../../src/utils/JsonResponse";
import * as response from "../../../src/constants/responses";
import { sendTaskUpdate } from "../../../src/utils/sendTaskUpdates";

import { generateDummyRequestObject } from "../../fixtures/fixture";

jest.mock("../../../src/utils/verifyAuthToken", () => ({
Expand All @@ -11,7 +10,6 @@ jest.mock("../../../src/utils/verifyAuthToken", () => ({
jest.mock("../../../src/utils/sendTaskUpdates", () => ({
sendTaskUpdate: jest.fn().mockResolvedValue(undefined),
}));

describe("sendTaskUpdatesHandler", () => {
const mockEnv = { DISCORD_TOKEN: "mockToken" };
const mockData = {
Expand All @@ -21,20 +19,22 @@ describe("sendTaskUpdatesHandler", () => {
blockers: "NA",
userName: "12345678910",
taskId: "79wMEIek990",
taskTitle: "Hyperlink as task Title",
},
};
afterEach(() => {
jest.clearAllMocks();
});

it("sendTaskUpdate function should return undefined after successfully sending the message", async () => {
const { completed, planned, blockers, userName, taskId } = mockData.content;
const { completed, planned, blockers, userName, taskId, taskTitle } =
mockData.content;
const response = await sendTaskUpdate(
completed,
planned,
blockers,
userName,
taskId,
taskTitle,
mockEnv
);
expect(response).toBe(undefined);
Expand All @@ -50,4 +50,22 @@ describe("sendTaskUpdatesHandler", () => {
expect(result.status).toBe(401);
expect(jsonResponse).toEqual(response.UNAUTHORIZED);
});
it("should return success response if task update is sent successfully", async () => {
const mockRequest = generateDummyRequestObject({
url: "/task/update",
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer dummyToken",
},
});
mockRequest.json = jest.fn().mockResolvedValue(mockData);
const result: JSONResponse = await sendTaskUpdatesHandler(
mockRequest,
mockEnv
);
expect(result.status).toBe(200);
const res: JSONResponse = await result.json();
expect(res).toBe(response.TASK_UPDATE_SENT_MESSAGE);
});
});
99 changes: 86 additions & 13 deletions tests/unit/utils/sendTasksUpdates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ describe("sendTaskUpdate function", () => {
const blockers = "No blockers";
const userName = "Tejas";
const taskId = "69nduIn210";
const taskTitle = "Hyperlink as task title";
const taskUrl = config(mockEnv).RDS_STATUS_SITE_URL + `/tasks/${taskId}`;
const assertFetchCall = (url: string, bodyObj: any, mockEnv: any) => {
expect(global.fetch).toHaveBeenCalledWith(url, {
Expand All @@ -24,11 +25,42 @@ describe("sendTaskUpdate function", () => {
afterEach(() => {
jest.clearAllMocks();
});
test("should throw an error if response status is not OK", async () => {
const url = config(mockEnv).TRACKING_CHANNEL_URL;
const formattedString =
`**${userName}** added an update to their task: [${taskTitle}](<${taskUrl}>)\n` +
`\n**Completed**\n${completed}\n\n` +
`**Planned**\n${planned}\n\n` +
`**Blockers**\n${blockers}`;
const bodyObj = {
content: formattedString,
};

jest
.spyOn(global, "fetch")
.mockResolvedValueOnce(
new JSONResponse("", { status: 400, statusText: "Bad Request" })
);

await expect(
sendTaskUpdate(
completed,
planned,
blockers,
userName,
taskId,
taskTitle,
mockEnv
)
).rejects.toThrowError("Failed to send task update: 400 - Bad Request");

assertFetchCall(url, bodyObj, mockEnv);
});

test("should send the task update to discord tracking channel when all fields are present", async () => {
const url = config(mockEnv).TRACKING_CHANNEL_URL;
const formattedString =
`${userName} added an update to their task: <${taskUrl}>\n` +
`**${userName}** added an update to their task: [${taskTitle}](<${taskUrl}>)\n` +
`\n**Completed**\n${completed}\n\n` +
`**Planned**\n${planned}\n\n` +
`**Blockers**\n${blockers}`;
Expand All @@ -46,6 +78,7 @@ describe("sendTaskUpdate function", () => {
blockers,
userName,
taskId,
taskTitle,
mockEnv
);

Expand All @@ -55,7 +88,7 @@ describe("sendTaskUpdate function", () => {
test("should send the task update to discord tracking channel when only completed is present", async () => {
const url = config(mockEnv).TRACKING_CHANNEL_URL;
const formattedString =
`${userName} added an update to their task: <${taskUrl}>\n` +
`**${userName}** added an update to their task: [${taskTitle}](<${taskUrl}>)\n` +
`\n**Completed**\n${completed}\n\n` +
`**Planned**\n\n\n` +
`**Blockers**\n`;
Expand All @@ -67,15 +100,23 @@ describe("sendTaskUpdate function", () => {
.spyOn(global, "fetch")
.mockImplementation(() => Promise.resolve(new JSONResponse("")));

await sendTaskUpdate(completed, "", "", userName, taskId, mockEnv);
await sendTaskUpdate(
completed,
"",
"",
userName,
taskId,
taskTitle,
mockEnv
);

assertFetchCall(url, bodyObj, mockEnv);
});

test("should send the task update to discord tracking channel when only planned is present", async () => {
const url = config(mockEnv).TRACKING_CHANNEL_URL;
const formattedString =
`${userName} added an update to their task: <${taskUrl}>\n` +
`**${userName}** added an update to their task: [${taskTitle}](<${taskUrl}>)\n` +
`\n**Completed**\n\n\n` +
`**Planned**\n${planned}\n\n` +
`**Blockers**\n`;
Expand All @@ -87,15 +128,15 @@ describe("sendTaskUpdate function", () => {
.spyOn(global, "fetch")
.mockImplementation(() => Promise.resolve(new JSONResponse("")));

await sendTaskUpdate("", planned, "", userName, taskId, mockEnv);
await sendTaskUpdate("", planned, "", userName, taskId, taskTitle, mockEnv);

assertFetchCall(url, bodyObj, mockEnv);
});

test("should send the task update to discord tracking channel when only blockers is present", async () => {
const url = config(mockEnv).TRACKING_CHANNEL_URL;
const formattedString =
`${userName} added an update to their task: <${taskUrl}>\n` +
`**${userName}** added an update to their task: [${taskTitle}](<${taskUrl}>)\n` +
`\n**Completed**\n\n\n` +
`**Planned**\n\n\n` +
`**Blockers**\n${blockers}`;
Expand All @@ -107,15 +148,23 @@ describe("sendTaskUpdate function", () => {
.spyOn(global, "fetch")
.mockImplementation(() => Promise.resolve(new JSONResponse("")));

await sendTaskUpdate("", "", blockers, userName, taskId, mockEnv);
await sendTaskUpdate(
"",
"",
blockers,
userName,
taskId,
taskTitle,
mockEnv
);

assertFetchCall(url, bodyObj, mockEnv);
});

test("should send the task update to discord tracking channel when only completed and planned are present", async () => {
const url = config(mockEnv).TRACKING_CHANNEL_URL;
const formattedString =
`${userName} added an update to their task: <${taskUrl}>\n` +
`**${userName}** added an update to their task: [${taskTitle}](<${taskUrl}>)\n` +
`\n**Completed**\n${completed}\n\n` +
`**Planned**\n${planned}\n\n` +
`**Blockers**\n`;
Expand All @@ -127,15 +176,23 @@ describe("sendTaskUpdate function", () => {
.spyOn(global, "fetch")
.mockImplementation(() => Promise.resolve(new JSONResponse("")));

await sendTaskUpdate(completed, planned, "", userName, taskId, mockEnv);
await sendTaskUpdate(
completed,
planned,
"",
userName,
taskId,
taskTitle,
mockEnv
);

assertFetchCall(url, bodyObj, mockEnv);
});

test("should send the task update to discord tracking channel when only completed and blockers are present", async () => {
const url = config(mockEnv).TRACKING_CHANNEL_URL;
const formattedString =
`${userName} added an update to their task: <${taskUrl}>\n` +
`**${userName}** added an update to their task: [${taskTitle}](<${taskUrl}>)\n` +
`\n**Completed**\n${completed}\n\n` +
`**Planned**\n\n\n` +
`**Blockers**\n${blockers}`;
Expand All @@ -147,15 +204,23 @@ describe("sendTaskUpdate function", () => {
.spyOn(global, "fetch")
.mockImplementation(() => Promise.resolve(new JSONResponse("")));

await sendTaskUpdate(completed, "", blockers, userName, taskId, mockEnv);
await sendTaskUpdate(
completed,
"",
blockers,
userName,
taskId,
taskTitle,
mockEnv
);

assertFetchCall(url, bodyObj, mockEnv);
});

test("should send the task update to discord tracking channel when only planned and blockers are present", async () => {
const url = config(mockEnv).TRACKING_CHANNEL_URL;
const formattedString =
`${userName} added an update to their task: <${taskUrl}>\n` +
`**${userName}** added an update to their task: [${taskTitle}](<${taskUrl}>)\n` +
`\n**Completed**\n\n\n` +
`**Planned**\n${planned}\n\n` +
`**Blockers**\n${blockers}`;
Expand All @@ -167,7 +232,15 @@ describe("sendTaskUpdate function", () => {
.spyOn(global, "fetch")
.mockImplementation(() => Promise.resolve(new JSONResponse("")));

await sendTaskUpdate("", planned, blockers, userName, taskId, mockEnv);
await sendTaskUpdate(
"",
planned,
blockers,
userName,
taskId,
taskTitle,
mockEnv
);

assertFetchCall(url, bodyObj, mockEnv);
});
Expand Down

0 comments on commit adcc1d2

Please sign in to comment.