feat: add modular services and repositories for improved code organization

Introduce repository pattern across multiple services, including `favorites`, `tags`, `sessions`, `reports`, `auth`, and more. Decouple crypto functionalities into modular services like `HashingService`, `JwtService`, and `EncryptionService`. Improve testability and maintainability by simplifying dependencies and consolidating utility logic.
This commit is contained in:
Mathis HERRIOT
2026-01-14 12:11:39 +01:00
parent 9c45bf11e4
commit 514bd354bf
64 changed files with 1801 additions and 1295 deletions

View File

@@ -1,56 +1,29 @@
import { Test, TestingModule } from "@nestjs/testing";
import { DatabaseService } from "../database/database.service";
import { CreateReportDto } from "./dto/create-report.dto";
import { ReportsService } from "./reports.service";
import { ReportsRepository } from "./repositories/reports.repository";
describe("ReportsService", () => {
let service: ReportsService;
let repository: ReportsRepository;
const mockDb = {
insert: jest.fn(),
values: jest.fn(),
returning: jest.fn(),
select: jest.fn(),
from: jest.fn(),
orderBy: jest.fn(),
limit: jest.fn(),
offset: jest.fn(),
update: jest.fn(),
set: jest.fn(),
where: jest.fn(),
const mockReportsRepository = {
create: jest.fn(),
findAll: jest.fn(),
updateStatus: jest.fn(),
};
beforeEach(async () => {
jest.clearAllMocks();
const chain = {
insert: jest.fn().mockReturnThis(),
values: jest.fn().mockReturnThis(),
returning: jest.fn().mockReturnThis(),
select: jest.fn().mockReturnThis(),
from: jest.fn().mockReturnThis(),
orderBy: jest.fn().mockReturnThis(),
limit: jest.fn().mockReturnThis(),
offset: jest.fn().mockReturnThis(),
update: jest.fn().mockReturnThis(),
set: jest.fn().mockReturnThis(),
where: jest.fn().mockReturnThis(),
};
const mockImplementation = () => Object.assign(Promise.resolve([]), chain);
for (const mock of Object.values(chain)) {
mock.mockImplementation(mockImplementation);
}
Object.assign(mockDb, chain);
const module: TestingModule = await Test.createTestingModule({
providers: [
ReportsService,
{ provide: DatabaseService, useValue: { db: mockDb } },
{ provide: ReportsRepository, useValue: mockReportsRepository },
],
}).compile();
service = module.get<ReportsService>(ReportsService);
repository = module.get<ReportsRepository>(ReportsRepository);
});
it("should be defined", () => {
@@ -60,29 +33,31 @@ describe("ReportsService", () => {
describe("create", () => {
it("should create a report", async () => {
const reporterId = "u1";
const data: CreateReportDto = { contentId: "c1", reason: "spam" };
mockDb.returning.mockResolvedValue([{ id: "r1", ...data, reporterId }]);
const data = { contentId: "c1", reason: "spam" };
mockReportsRepository.create.mockResolvedValue({ id: "r1", ...data, reporterId });
const result = await service.create(reporterId, data);
expect(result.id).toBe("r1");
expect(mockDb.insert).toHaveBeenCalled();
expect(repository.create).toHaveBeenCalled();
});
});
describe("findAll", () => {
it("should return reports", async () => {
mockDb.offset.mockResolvedValue([{ id: "r1" }]);
mockReportsRepository.findAll.mockResolvedValue([{ id: "r1" }]);
const result = await service.findAll(10, 0);
expect(result).toHaveLength(1);
expect(repository.findAll).toHaveBeenCalledWith(10, 0);
});
});
describe("updateStatus", () => {
it("should update report status", async () => {
mockDb.returning.mockResolvedValue([{ id: "r1", status: "resolved" }]);
mockReportsRepository.updateStatus.mockResolvedValue([{ id: "r1", status: "resolved" }]);
const result = await service.updateStatus("r1", "resolved");
expect(result[0].status).toBe("resolved");
expect(repository.updateStatus).toHaveBeenCalledWith("r1", "resolved");
});
});
});