Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions cypress/tests/api/api-comments.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ describe("Comments API", function () {
cy.request("GET", `${apiComments}/${transactionId}`).then((response) => {
expect(response.status).to.eq(200);
expect(response.body.comments).to.be.an("array").that.has.length(1);

const comment = response.body.comments[0];
expect(comment).to.have.property("id");
expect(comment).to.have.property("uuid");
expect(comment).to.have.property("content");
expect(comment).to.have.property("userId");
expect(comment).to.have.property("transactionId");
expect(comment).to.have.property("createdAt");
expect(comment).to.have.property("modifiedAt");
});
});

it("errors when invalid transactionId", function () {
cy.request({
method: "GET",
url: `${apiComments}/1234`,
failOnStatusCode: false,
}).then((response) => {
expect(response.status).to.eq(422);
expect(response.body.errors).to.be.an("array").that.has.length(1);
});
});
});
Expand All @@ -50,6 +70,62 @@ describe("Comments API", function () {
}).then((response) => {
expect(response.status).to.eq(200);
});

// Verify persistence
cy.request("GET", `${apiComments}/${ctx.transactionId}`).then((response) => {
expect(response.status).to.eq(200);
const contents = response.body.comments.map((c: Comment) => c.content);
expect(contents).to.include("This is my comment");
});
});

it("errors when content is missing from POST body", function () {
cy.request({
method: "POST",
url: `${apiComments}/${ctx.transactionId}`,
failOnStatusCode: false,
body: {},
}).then((response) => {
expect(response.status).to.eq(422);
expect(response.body.errors).to.be.an("array");
});
});

it("errors when invalid transactionId on POST", function () {
cy.request({
method: "POST",
url: `${apiComments}/1234`,
failOnStatusCode: false,
body: { content: "test" },
}).then((response) => {
expect(response.status).to.eq(422);
expect(response.body.errors).to.be.an("array");
});
});
});

context("Unauthenticated", function () {
it("is unauthorized to GET comments without login", function () {
cy.clearCookies();
cy.request({
method: "GET",
url: `${apiComments}/${ctx.transactionId}`,
failOnStatusCode: false,
}).then((response) => {
expect(response.status).to.eq(401);
});
});

it("is unauthorized to POST comments without login", function () {
cy.clearCookies();
cy.request({
method: "POST",
url: `${apiComments}/${ctx.transactionId}`,
failOnStatusCode: false,
body: { content: "This is my comment" },
}).then((response) => {
expect(response.status).to.eq(401);
});
});
});
});
60 changes: 60 additions & 0 deletions src/__tests__/comments.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import {
getAllUsers,
getTransactionsByUserId,
createComment,
createComments,
getCommentsByTransactionId,
getTransactionById,
getNotificationsByUserId,
} from "../../backend/database";

import { User, Transaction } from "../../src/models";
Expand All @@ -24,6 +27,14 @@ describe("Comments", () => {

expect(comment.transactionId).toBe(transactions[0].id);
expect(comment.content).toBe(content);

expect(comment).toHaveProperty("id");
expect(comment).toHaveProperty("uuid");
expect(comment).toHaveProperty("content");
expect(comment).toHaveProperty("userId");
expect(comment).toHaveProperty("transactionId");
expect(comment).toHaveProperty("createdAt");
expect(comment).toHaveProperty("modifiedAt");
});

it("should get a list of comments for a transaction", () => {
Expand All @@ -37,4 +48,53 @@ describe("Comments", () => {

expect(comments[0].transactionId).toBe(transaction.id);
});

it("should create a comment and generate notifications for sender and receiver", () => {
const users = getAllUsers();
const transactions: Transaction[] = getTransactionsByUserId(users[0].id);
const transaction = transactions[0];
const { senderId, receiverId } = getTransactionById(transaction.id);

// Pick a user who is NOT the sender or receiver to exercise the branch at line 675
const thirdPartyUser = users.find(
(u: User) => u.id !== senderId && u.id !== receiverId
)!;

const senderNotificationsBefore = getNotificationsByUserId(senderId);
const receiverNotificationsBefore = getNotificationsByUserId(receiverId);

createComments(thirdPartyUser.id, transaction.id, "Third-party comment");

const comments = getCommentsByTransactionId(transaction.id);
const createdComment = comments.find(
(c) => c.content === "Third-party comment"
);
expect(createdComment).toBeDefined();
expect(createdComment!.userId).toBe(thirdPartyUser.id);
expect(createdComment!.transactionId).toBe(transaction.id);

const senderNotificationsAfter = getNotificationsByUserId(senderId);
const receiverNotificationsAfter = getNotificationsByUserId(receiverId);

expect(senderNotificationsAfter.length).toBeGreaterThan(
senderNotificationsBefore.length
);
expect(receiverNotificationsAfter.length).toBeGreaterThan(
receiverNotificationsBefore.length
);
});

it("should return an empty array for a transaction with no comments", () => {
const user: User = getAllUsers()[0];
const transactions: Transaction[] = getTransactionsByUserId(user.id);

// Find a transaction that has no comments
const transactionWithNoComments = transactions.find(
(t) => getCommentsByTransactionId(t.id).length === 0
);
expect(transactionWithNoComments).toBeDefined();

const comments = getCommentsByTransactionId(transactionWithNoComments!.id);
expect(comments).toEqual([]);
});
});