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(), jwtVerify: jest.fn(), })); import { Test, TestingModule } from "@nestjs/testing"; import { CryptoService } from "../crypto/crypto.service"; import { DatabaseService } from "../database/database.service"; import { UsersService } from "./users.service"; describe("UsersService", () => { let service: UsersService; const mockDb = { insert: jest.fn(), select: jest.fn(), update: jest.fn(), transaction: jest.fn().mockImplementation((cb) => cb(mockDb)), }; const mockCryptoService = { getPgpEncryptionKey: jest.fn().mockReturnValue("mock-pgp-key"), }; 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(), where: jest.fn().mockReturnThis(), limit: jest.fn().mockReturnThis(), offset: jest.fn().mockReturnThis(), update: jest.fn().mockReturnThis(), set: jest.fn().mockReturnThis(), // biome-ignore lint/suspicious/noThenProperty: Fine for testing purposes then: jest.fn().mockImplementation(function (cb) { return Promise.resolve(this).then(cb); }), }; const mockImplementation = () => Object.assign(Promise.resolve([]), chain); for (const mock of Object.values(chain)) { if (mock !== chain.then) { mock.mockImplementation(mockImplementation); } } Object.assign(mockDb, chain); const module: TestingModule = await Test.createTestingModule({ providers: [ UsersService, { provide: DatabaseService, useValue: { db: mockDb } }, { provide: CryptoService, useValue: mockCryptoService }, ], }).compile(); service = module.get(UsersService); }); it("should be defined", () => { expect(service).toBeDefined(); }); describe("create", () => { it("should create a user", async () => { const data = { username: "u1", email: "e1", passwordHash: "p1", emailHash: "eh1", }; mockDb.returning.mockResolvedValue([{ uuid: "uuid1", ...data }]); const result = await service.create(data); expect(result.uuid).toBe("uuid1"); expect(mockDb.insert).toHaveBeenCalled(); }); }); describe("findOne", () => { it("should find a user", async () => { mockDb.limit.mockResolvedValue([{ uuid: "uuid1" }]); const result = await service.findOne("uuid1"); expect(result.uuid).toBe("uuid1"); }); it("should return null if not found", async () => { mockDb.limit.mockResolvedValue([]); const result = await service.findOne("uuid1"); expect(result).toBeNull(); }); }); describe("update", () => { it("should update a user", async () => { mockDb.returning.mockResolvedValue([{ uuid: "uuid1", displayName: "New" }]); const result = await service.update("uuid1", { displayName: "New" }); expect(result[0].displayName).toBe("New"); }); }); });