Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:COS301-SE-2024/The-Republic into…
Browse files Browse the repository at this point in the history
… feature/minor_updates
  • Loading branch information
IRIA7 committed Sep 30, 2024
2 parents cc2d616 + a5d48c6 commit 12911ee
Show file tree
Hide file tree
Showing 26 changed files with 376 additions and 258 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ The documentation provides different versions and progress for each demo, guidin
<b style="font-size: 18px;">HLOKOMANI KHONDLO</b>
</h2>
<b style="font-size: 16px;">Integration Engineer</b>
<br> I am an integration engineer driven by the desire to understand and optimize how systems work. My passion for software engineering allows me to create seamless integrations that enhance product functionality and user experience. I specialize in using various tools and technologies to connect different systems and ensure they work together efficiently.
<br> I'm an integration engineer who’s driven by building solutions that make a difference. I focus on creating systems that connect seamlessly and actually improve how things work. My goal is to deliver efficient and resilient solutions that have a real, lasting impact.
<br><br>
<b style="font-size: 16px;">Profile Links</b>
<br><br>
Expand All @@ -251,13 +251,13 @@ The documentation provides different versions and progress for each demo, guidin
<img src="https://skillicons.dev/icons?i=express">
</a>
<a href="#" style="text-decoration: none; margin-right: 10px; display: inline-block; vertical-align: middle;">
<img src="https://skillicons.dev/icons?i=supabase">
<img src="https://skillicons.dev/icons?i=react">
</a>
<a href="#" style="text-decoration: none; margin-right: 10px; display: inline-block; vertical-align: middle;">
<img src="https://skillicons.dev/icons?i=aws">
<img src="https://skillicons.dev/icons?i=azure">
</a>
<a href="#" style="text-decoration: none; margin-right: 10px; display: inline-block; vertical-align: middle;">
<img src="https://skillicons.dev/icons?i=nodejs">
<img src="https://skillicons.dev/icons?i=supabase">
</a>
<a href="#" style="text-decoration: none; margin-right: 10px; display: inline-block; vertical-align: middle;">
<img src="https://skillicons.dev/icons?i=nextjs">
Expand Down
14 changes: 12 additions & 2 deletions backend/src/__tests__/controllers/commentController.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Request, Response } from "express";
import { Request, Response, NextFunction } from "express";
import { CommentService } from "@/modules/comments/services/commentService";
import { sendResponse } from "@/utilities/response";
import * as commentController from "@/modules/comments/controllers/commentController";
Expand All @@ -19,11 +19,13 @@ jest.mock("@/modules/shared/services/redisClient", () => ({
describe("Comment Controller", () => {
let mockRequest: Partial<Request>;
let mockResponse: Partial<Response>;
let mockNext: NextFunction;
let mockCommentService: jest.Mocked<CommentService>;

beforeEach(() => {
mockRequest = { body: {} };
mockResponse = { json: jest.fn() } as Partial<Response>;
mockNext = jest.fn();
mockCommentService = {
getNumComments: jest.fn(),
getComments: jest.fn(),
Expand All @@ -44,7 +46,15 @@ describe("Comment Controller", () => {

testCases.forEach(({ name, method }) => {
it(`should call sendResponse for ${name}`, async () => {
await method(mockRequest as Request, mockResponse as Response);
if (Array.isArray(method)) {
// If the method is an array (middleware + controller), call each function in the array
for (const fn of method) {
await fn(mockRequest as Request, mockResponse as Response, mockNext);
}
} else {
// If it's a regular function, call it directly
await method(mockRequest as Request, mockResponse as Response);
}
expect(sendResponse).toHaveBeenCalled();
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Request, Response } from "express";
import { Request, Response, NextFunction } from "express";
import { sendResponse } from "@/utilities/response";
import SubscriptionsService from "@/modules/subscriptions/services/subscriptionsService";
import * as subscriptionsController from "@/modules/subscriptions/controllers/subscriptionsController";
Expand Down Expand Up @@ -176,9 +176,11 @@ describe("Subscriptions Controller", () => {
mockResponse,
);

await subscriptionsController.getSubscriptions(
// Call the last function in the getSubscriptions array
await subscriptionsController.getSubscriptions[subscriptionsController.getSubscriptions.length - 1](
req as Request,
res as Response,
jest.fn() as NextFunction
);

expect(
Expand All @@ -193,9 +195,11 @@ describe("Subscriptions Controller", () => {
mockError,
);

await subscriptionsController.getSubscriptions(
// Call the last function in the getSubscriptions array
await subscriptionsController.getSubscriptions[subscriptionsController.getSubscriptions.length - 1](
req as Request,
res as Response,
jest.fn() as NextFunction
);

expect(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Request, Response } from "express";
import { Request, Response, NextFunction } from "express";
import { VisualizationService } from "@/modules/visualizations/services/visualizationService";
import { sendResponse } from "@/utilities/response";
import * as visualizationController from "@/modules/visualizations/controllers/visualizationController";
Expand Down Expand Up @@ -37,9 +37,10 @@ describe("Visualization Controller", () => {
});

it("should call sendResponse for getVizData", async () => {
await visualizationController.getVizData(
await visualizationController.getVizData[visualizationController.getVizData.length - 1](
mockRequest as Request,
mockResponse as Response,
jest.fn() as NextFunction
);
expect(sendResponse).toHaveBeenCalled();
});
Expand All @@ -48,9 +49,10 @@ describe("Visualization Controller", () => {
const error = new Error("Test error");
mockVisualizationService.getVizData.mockRejectedValue(error);

await visualizationController.getVizData(
await visualizationController.getVizData[visualizationController.getVizData.length - 1](
mockRequest as Request,
mockResponse as Response,
jest.fn() as NextFunction
);
expect(sendResponse).toHaveBeenCalledWith(mockResponse, expect.any(Error));
});
Expand Down
32 changes: 0 additions & 32 deletions backend/src/__tests__/routes/commentRoutes.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,38 +29,6 @@ describe("Comments Routes", () => {
jest.clearAllMocks();
});

describe("POST /comments/", () => {
it("should call getComments controller", async () => {
(verifyAndGetUser as jest.Mock).mockImplementation((req, res, next) =>
next(),
);
(commentController.getComments as jest.Mock).mockImplementation(
(req, res) => res.status(200).json({}),
);

const response = await request(app).post("/comments/").send();

expect(response.status).toBe(200);
expect(commentController.getComments).toHaveBeenCalled();
});
});

describe("POST /comments/count", () => {
it("should call getNumComments controller", async () => {
(verifyAndGetUser as jest.Mock).mockImplementation((req, res, next) =>
next(),
);
(commentController.getNumComments as jest.Mock).mockImplementation(
(req, res) => res.status(200).json({}),
);

const response = await request(app).post("/comments/count").send();

expect(response.status).toBe(200);
expect(commentController.getNumComments).toHaveBeenCalled();
});
});

describe("POST /comments/add", () => {
it("should call addComment controller", async () => {
(verifyAndGetUser as jest.Mock).mockImplementation((req, res, next) =>
Expand Down
21 changes: 0 additions & 21 deletions backend/src/__tests__/routes/subscriptionsRoutes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,4 @@ describe("Subscription Routes", () => {
expect(subscriptionsController.locationSubscriptions).toHaveBeenCalled();
});
});

describe("POST /subscriptions/subscriptions", () => {
it("should call getSubscriptions controller", async () => {
(verifyAndGetUser as jest.Mock).mockImplementation((req, res, next) =>
next(),
);
(
subscriptionsController.getSubscriptions as jest.Mock
).mockImplementation((req, res) =>
res.status(200).json({ message: "Get subscriptions successful" }),
);

const response = await request(app)
.post("/subscriptions/subscriptions")
.send();

expect(response.status).toBe(200);
expect(response.body.message).toBe("Get subscriptions successful");
expect(subscriptionsController.getSubscriptions).toHaveBeenCalled();
});
});
});
22 changes: 13 additions & 9 deletions backend/src/__tests__/routes/visualizationRoutes.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import request from "supertest";
import express from "express";
import express, { Request, Response, NextFunction } from "express";
import visualizationRouter from "@/modules/visualizations/routes/visualizationRoutes";

import * as visualizationController from "@/modules/visualizations/controllers/visualizationController";

jest.mock("@/middleware/cacheMiddleware");
jest.mock("@/middleware/cacheMiddleware", () => ({
cacheMiddleware: jest.fn().mockImplementation(() => (req: Request, res: Response, next: NextFunction) => next()),
}));
jest.mock("@/utilities/cacheUtils");

jest.mock("@/modules/shared/services/redisClient", () => ({
Expand All @@ -17,24 +20,25 @@ jest.mock("@/modules/shared/services/redisClient", () => ({
},
}));

jest.mock("@/modules/visualizations/controllers/visualizationController");
jest.mock("@/modules/visualizations/controllers/visualizationController", () => ({
getVizData: jest.fn().mockImplementation((req: Request, res: Response) => {
return res.status(200).json({});
}),
}));

const app = express();
app.use(express.json());
app.use("/visualizations", visualizationRouter);


describe("Visualization Routes", () => {
beforeEach(() => {
jest.clearAllMocks();
});

describe("POST /visualizations/", () => {
describe("POST /visualizations", () => {
it("should call getVizData controller", async () => {
(visualizationController.getVizData as jest.Mock).mockImplementation(
(req, res) => res.status(200).json({}),
);

const response = await request(app).post("/visualizations/").send();
const response = await request(app).post("/visualizations").send();

expect(response.status).toBe(200);
expect(visualizationController.getVizData).toHaveBeenCalled();
Expand Down
4 changes: 3 additions & 1 deletion backend/src/middleware/cacheMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ export const cacheMiddleware = (duration: number) => {
} else {
const originalJson = res.json;
res.json = function (body: unknown) {
redisClient?.setex(key, duration, JSON.stringify(body));
if (res.statusCode >= 200 && res.statusCode < 300) {
redisClient?.setex(key, duration, JSON.stringify(body));
}
return originalJson.call(this, body);
};
next();
Expand Down
52 changes: 31 additions & 21 deletions backend/src/modules/comments/controllers/commentController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,44 @@ import { Request, Response } from "express";
import { CommentService } from "@/modules/comments/services/commentService";
import { sendResponse } from "@/utilities/response";
import { APIResponse } from "@/types/response";
import { cacheMiddleware } from "@/middleware/cacheMiddleware";
import { clearCachePattern } from "@/utilities/cacheUtils";

const commentService = new CommentService();

export async function getNumComments(req: Request, res: Response) {
try {
const { itemId, itemType, parent_id } = req.body;
const response = await commentService.getNumComments({
itemId,
itemType,
parent_id,
});
sendResponse(res, response);
} catch (error) {
sendResponse(res, error as APIResponse);
}
}
export const getNumComments = [
cacheMiddleware(300),
async (req: Request, res: Response) => {
try {
const { itemId, itemType, parent_id } = req.body;
const response = await commentService.getNumComments({
itemId,
itemType,
parent_id,
});
sendResponse(res, response);
} catch (error) {
sendResponse(res, error as APIResponse);
}
},
];

export async function getComments(req: Request, res: Response) {
try {
const response = await commentService.getComments(req.body);
sendResponse(res, response);
} catch (error) {
sendResponse(res, error as APIResponse);
}
}
export const getComments = [
cacheMiddleware(300),
async (req: Request, res: Response) => {
try {
const response = await commentService.getComments(req.body);
sendResponse(res, response);
} catch (error) {
sendResponse(res, error as APIResponse);
}
},
];

export async function addComment(req: Request, res: Response) {
try {
const response = await commentService.addComment(req.body);
clearCachePattern("__express__/api/comments*");
sendResponse(res, response);
} catch (error) {
sendResponse(res, error as APIResponse);
Expand All @@ -40,6 +49,7 @@ export async function addComment(req: Request, res: Response) {
export async function deleteComment(req: Request, res: Response) {
try {
const response = await commentService.deleteComment(req.body);
clearCachePattern("__express__/api/comments*");
sendResponse(res, response);
} catch (error) {
sendResponse(res, error as APIResponse);
Expand Down
Loading

0 comments on commit 12911ee

Please sign in to comment.