From b177bee75c0060bcaed38fde5652f97a31ec32f2 Mon Sep 17 00:00:00 2001 From: Mathis HERRIOT <197931332+0x485254@users.noreply.github.com> Date: Tue, 20 Jan 2026 13:46:42 +0100 Subject: [PATCH] test(favorites): add unit tests for FavoritesController and FavoritesRepository with mocked dependencies --- .../favorites/favorites.controller.spec.ts | 82 +++++++++++++++++++ .../repositories/favorites.repository.spec.ts | 68 +++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 backend/src/favorites/favorites.controller.spec.ts create mode 100644 backend/src/favorites/repositories/favorites.repository.spec.ts diff --git a/backend/src/favorites/favorites.controller.spec.ts b/backend/src/favorites/favorites.controller.spec.ts new file mode 100644 index 0000000..a930dc2 --- /dev/null +++ b/backend/src/favorites/favorites.controller.spec.ts @@ -0,0 +1,82 @@ +jest.mock("uuid", () => ({ + v4: jest.fn(() => "mocked-uuid"), +})); + +jest.mock("@noble/post-quantum/ml-kem.js", () => ({ + ml_kem768: { + keygen: jest.fn(), + encapsulate: jest.fn(), + decapsulate: jest.fn(), + }, +})); + +jest.mock("jose", () => ({ + SignJWT: jest.fn().mockReturnValue({ + setProtectedHeader: jest.fn().mockReturnThis(), + setIssuedAt: jest.fn().mockReturnThis(), + setExpirationTime: jest.fn().mockReturnThis(), + sign: jest.fn().mockResolvedValue("mocked-jwt"), + }), + jwtVerify: jest.fn(), +})); + +import { Test, TestingModule } from "@nestjs/testing"; +import { AuthGuard } from "../auth/guards/auth.guard"; +import { AuthenticatedRequest } from "../common/interfaces/request.interface"; +import { FavoritesController } from "./favorites.controller"; +import { FavoritesService } from "./favorites.service"; + +describe("FavoritesController", () => { + let controller: FavoritesController; + let service: FavoritesService; + + const mockFavoritesService = { + addFavorite: jest.fn(), + removeFavorite: jest.fn(), + getUserFavorites: jest.fn(), + }; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [FavoritesController], + providers: [{ provide: FavoritesService, useValue: mockFavoritesService }], + }) + .overrideGuard(AuthGuard) + .useValue({ canActivate: () => true }) + .compile(); + + controller = module.get(FavoritesController); + service = module.get(FavoritesService); + }); + + it("should be defined", () => { + expect(controller).toBeDefined(); + }); + + describe("add", () => { + it("should call service.addFavorite", async () => { + const req = { user: { sub: "user-uuid" } } as AuthenticatedRequest; + await controller.add(req, "content-1"); + expect(service.addFavorite).toHaveBeenCalledWith("user-uuid", "content-1"); + }); + }); + + describe("remove", () => { + it("should call service.removeFavorite", async () => { + const req = { user: { sub: "user-uuid" } } as AuthenticatedRequest; + await controller.remove(req, "content-1"); + expect(service.removeFavorite).toHaveBeenCalledWith( + "user-uuid", + "content-1", + ); + }); + }); + + describe("list", () => { + it("should call service.getUserFavorites", async () => { + const req = { user: { sub: "user-uuid" } } as AuthenticatedRequest; + await controller.list(req, 10, 0); + expect(service.getUserFavorites).toHaveBeenCalledWith("user-uuid", 10, 0); + }); + }); +}); diff --git a/backend/src/favorites/repositories/favorites.repository.spec.ts b/backend/src/favorites/repositories/favorites.repository.spec.ts new file mode 100644 index 0000000..3d051fa --- /dev/null +++ b/backend/src/favorites/repositories/favorites.repository.spec.ts @@ -0,0 +1,68 @@ +import { Test, TestingModule } from "@nestjs/testing"; +import { DatabaseService } from "../../database/database.service"; +import { FavoritesRepository } from "./favorites.repository"; + +describe("FavoritesRepository", () => { + let repository: FavoritesRepository; + + const mockDb = { + select: jest.fn().mockReturnThis(), + from: jest.fn().mockReturnThis(), + innerJoin: jest.fn().mockReturnThis(), + where: jest.fn().mockReturnThis(), + limit: jest.fn().mockReturnThis(), + offset: jest.fn().mockReturnThis(), + insert: jest.fn().mockReturnThis(), + values: jest.fn().mockReturnThis(), + delete: jest.fn().mockReturnThis(), + returning: jest.fn().mockReturnThis(), + execute: jest.fn(), + }; + + const wrapWithThen = (obj: any) => { + obj.then = function (onFulfilled: any) { + const result = this.execute(); + return Promise.resolve(result).then(onFulfilled); + }; + return obj; + }; + wrapWithThen(mockDb); + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + FavoritesRepository, + { provide: DatabaseService, useValue: { db: mockDb } }, + ], + }).compile(); + + repository = module.get(FavoritesRepository); + }); + + it("should find content by id", async () => { + (mockDb.execute as jest.Mock).mockResolvedValue([{ id: "1" }]); + const result = await repository.findContentById("1"); + expect(result.id).toBe("1"); + }); + + it("should add favorite", async () => { + (mockDb.execute as jest.Mock).mockResolvedValue([ + { userId: "u", contentId: "c" }, + ]); + await repository.add("u", "c"); + expect(mockDb.insert).toHaveBeenCalled(); + }); + + it("should remove favorite", async () => { + (mockDb.execute as jest.Mock).mockResolvedValue([{ id: "1" }]); + await repository.remove("u", "c"); + expect(mockDb.delete).toHaveBeenCalled(); + }); + + it("should find by user id", async () => { + (mockDb.execute as jest.Mock).mockResolvedValue([{ content: { id: "c1" } }]); + const result = await repository.findByUserId("u1", 10, 0); + expect(result).toHaveLength(1); + expect(result[0].id).toBe("c1"); + }); +});