- Added comprehensive unit tests for `MessagesService`, `CommentsService`, `EventsGateway`, and enhancements in `UsersService`. - Ensured proper mocking and test coverage for newly introduced dependencies like `EventsGateway` and `RBACService`.
242 lines
6.6 KiB
TypeScript
242 lines
6.6 KiB
TypeScript
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(),
|
|
jwtVerify: jest.fn(),
|
|
}));
|
|
|
|
import { CACHE_MANAGER } from "@nestjs/cache-manager";
|
|
import { ConfigService } from "@nestjs/config";
|
|
import { Test, TestingModule } from "@nestjs/testing";
|
|
import { RbacService } from "../auth/rbac.service";
|
|
import { MediaService } from "../media/media.service";
|
|
import { S3Service } from "../s3/s3.service";
|
|
import { UsersRepository } from "./repositories/users.repository";
|
|
import { UsersService } from "./users.service";
|
|
|
|
describe("UsersService", () => {
|
|
let service: UsersService;
|
|
let repository: UsersRepository;
|
|
|
|
const mockUsersRepository = {
|
|
create: jest.fn(),
|
|
findOne: jest.fn(),
|
|
findByEmailHash: jest.fn(),
|
|
findOneWithPrivateData: jest.fn(),
|
|
countAll: jest.fn(),
|
|
findAll: jest.fn(),
|
|
findByUsername: jest.fn(),
|
|
update: jest.fn(),
|
|
getTwoFactorSecret: jest.fn(),
|
|
getUserContents: jest.fn(),
|
|
getUserFavorites: jest.fn(),
|
|
softDeleteUserAndContents: jest.fn(),
|
|
};
|
|
|
|
const mockCacheManager = {
|
|
del: jest.fn(),
|
|
};
|
|
|
|
const mockRbacService = {
|
|
getUserRoles: jest.fn(),
|
|
};
|
|
|
|
const mockMediaService = {
|
|
scanFile: jest.fn(),
|
|
processImage: jest.fn(),
|
|
};
|
|
|
|
const mockS3Service = {
|
|
uploadFile: jest.fn(),
|
|
getPublicUrl: jest.fn(),
|
|
};
|
|
|
|
const mockConfigService = {
|
|
get: jest.fn(),
|
|
};
|
|
|
|
beforeEach(async () => {
|
|
jest.clearAllMocks();
|
|
|
|
const module: TestingModule = await Test.createTestingModule({
|
|
providers: [
|
|
UsersService,
|
|
{ provide: UsersRepository, useValue: mockUsersRepository },
|
|
{ provide: CACHE_MANAGER, useValue: mockCacheManager },
|
|
{ provide: RbacService, useValue: mockRbacService },
|
|
{ provide: MediaService, useValue: mockMediaService },
|
|
{ provide: S3Service, useValue: mockS3Service },
|
|
{ provide: ConfigService, useValue: mockConfigService },
|
|
],
|
|
}).compile();
|
|
|
|
service = module.get<UsersService>(UsersService);
|
|
repository = module.get<UsersRepository>(UsersRepository);
|
|
});
|
|
|
|
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",
|
|
};
|
|
mockUsersRepository.create.mockResolvedValue({ uuid: "uuid1", ...data });
|
|
|
|
const result = await service.create(data);
|
|
|
|
expect(result.uuid).toBe("uuid1");
|
|
expect(repository.create).toHaveBeenCalledWith(data);
|
|
});
|
|
});
|
|
|
|
describe("findOne", () => {
|
|
it("should find a user", async () => {
|
|
mockUsersRepository.findOne.mockResolvedValue({ uuid: "uuid1" });
|
|
mockRbacService.getUserRoles.mockResolvedValue([]);
|
|
const result = await service.findOne("uuid1");
|
|
expect(result.uuid).toBe("uuid1");
|
|
});
|
|
|
|
it("should return null if not found", async () => {
|
|
mockUsersRepository.findOne.mockResolvedValue(null);
|
|
const result = await service.findOne("uuid1");
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("update", () => {
|
|
it("should update a user", async () => {
|
|
mockUsersRepository.update.mockResolvedValue([
|
|
{ uuid: "uuid1", displayName: "New" },
|
|
]);
|
|
const result = await service.update("uuid1", { displayName: "New" });
|
|
expect(result[0].displayName).toBe("New");
|
|
});
|
|
});
|
|
|
|
describe("clearUserCache", () => {
|
|
it("should delete cache", async () => {
|
|
await service.clearUserCache("u1");
|
|
expect(mockCacheManager.del).toHaveBeenCalledWith("users/profile/u1");
|
|
});
|
|
});
|
|
|
|
describe("findByEmailHash", () => {
|
|
it("should call repository.findByEmailHash", async () => {
|
|
mockUsersRepository.findByEmailHash.mockResolvedValue({ uuid: "u1" });
|
|
mockRbacService.getUserRoles.mockResolvedValue([]);
|
|
const result = await service.findByEmailHash("hash");
|
|
expect(result.uuid).toBe("u1");
|
|
expect(mockUsersRepository.findByEmailHash).toHaveBeenCalledWith("hash");
|
|
});
|
|
});
|
|
|
|
describe("findOneWithPrivateData", () => {
|
|
it("should return user with roles", async () => {
|
|
mockUsersRepository.findOneWithPrivateData.mockResolvedValue({ uuid: "u1" });
|
|
mockRbacService.getUserRoles.mockResolvedValue(["admin"]);
|
|
const result = await service.findOneWithPrivateData("u1");
|
|
expect(result.roles).toEqual(["admin"]);
|
|
});
|
|
});
|
|
|
|
describe("findAll", () => {
|
|
it("should return all users", async () => {
|
|
mockUsersRepository.findAll.mockResolvedValue([{ uuid: "u1" }]);
|
|
mockUsersRepository.countAll.mockResolvedValue(1);
|
|
|
|
const result = await service.findAll(10, 0);
|
|
|
|
expect(result.totalCount).toBe(1);
|
|
expect(result.data[0].uuid).toBe("u1");
|
|
});
|
|
});
|
|
|
|
describe("findPublicProfile", () => {
|
|
it("should return public profile", async () => {
|
|
mockUsersRepository.findByUsername.mockResolvedValue({
|
|
uuid: "u1",
|
|
username: "u1",
|
|
});
|
|
const result = await service.findPublicProfile("u1");
|
|
expect(result.username).toBe("u1");
|
|
});
|
|
});
|
|
|
|
describe("updateConsent", () => {
|
|
it("should update consent", async () => {
|
|
await service.updateConsent("u1", "v1", "v2");
|
|
expect(mockUsersRepository.update).toHaveBeenCalledWith("u1", {
|
|
termsVersion: "v1",
|
|
privacyVersion: "v2",
|
|
gdprAcceptedAt: expect.any(Date),
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("setTwoFactorSecret", () => {
|
|
it("should set 2fa secret", async () => {
|
|
await service.setTwoFactorSecret("u1", "secret");
|
|
expect(mockUsersRepository.update).toHaveBeenCalledWith("u1", {
|
|
twoFactorSecret: "secret",
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("toggleTwoFactor", () => {
|
|
it("should toggle 2fa", async () => {
|
|
await service.toggleTwoFactor("u1", true);
|
|
expect(mockUsersRepository.update).toHaveBeenCalledWith("u1", {
|
|
isTwoFactorEnabled: true,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("getTwoFactorSecret", () => {
|
|
it("should return 2fa secret", async () => {
|
|
mockUsersRepository.getTwoFactorSecret.mockResolvedValue("secret");
|
|
const result = await service.getTwoFactorSecret("u1");
|
|
expect(result).toBe("secret");
|
|
});
|
|
});
|
|
|
|
describe("exportUserData", () => {
|
|
it("should return all user data", async () => {
|
|
mockUsersRepository.findOneWithPrivateData.mockResolvedValue({ uuid: "u1" });
|
|
mockUsersRepository.getUserContents.mockResolvedValue([]);
|
|
mockUsersRepository.getUserFavorites.mockResolvedValue([]);
|
|
|
|
const result = await service.exportUserData("u1");
|
|
|
|
expect(result.profile).toBeDefined();
|
|
expect(result.contents).toBeDefined();
|
|
expect(result.favorites).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe("remove", () => {
|
|
it("should soft delete user", async () => {
|
|
await service.remove("u1");
|
|
expect(mockUsersRepository.softDeleteUserAndContents).toHaveBeenCalledWith(
|
|
"u1",
|
|
);
|
|
});
|
|
});
|
|
});
|