- Added `ContentsRepository` as a dependency to `CommentsService` and updated tests for mock setup. - Adjusted import order in relevant files to align with project standards.
152 lines
4.8 KiB
TypeScript
152 lines
4.8 KiB
TypeScript
import { ForbiddenException, NotFoundException } from "@nestjs/common";
|
|
import { Test, TestingModule } from "@nestjs/testing";
|
|
import { ContentsRepository } from "../contents/repositories/contents.repository";
|
|
import { EventsGateway } from "../realtime/events.gateway";
|
|
import { S3Service } from "../s3/s3.service";
|
|
import { CommentsService } from "./comments.service";
|
|
import { CommentLikesRepository } from "./repositories/comment-likes.repository";
|
|
import { CommentsRepository } from "./repositories/comments.repository";
|
|
|
|
describe("CommentsService", () => {
|
|
let service: CommentsService;
|
|
let repository: CommentsRepository;
|
|
|
|
const mockCommentsRepository = {
|
|
create: jest.fn(),
|
|
findAllByContentId: jest.fn(),
|
|
findOne: jest.fn(),
|
|
findOneEnriched: jest.fn(),
|
|
delete: jest.fn(),
|
|
};
|
|
|
|
const mockCommentLikesRepository = {
|
|
addLike: jest.fn(),
|
|
removeLike: jest.fn(),
|
|
countByCommentId: jest.fn(),
|
|
isLikedByUser: jest.fn(),
|
|
};
|
|
|
|
const mockContentsRepository = {
|
|
findOne: jest.fn(),
|
|
};
|
|
|
|
const mockS3Service = {
|
|
getPublicUrl: jest.fn(),
|
|
};
|
|
|
|
const mockEventsGateway = {
|
|
sendToContent: jest.fn(),
|
|
sendToUser: jest.fn(),
|
|
};
|
|
|
|
beforeEach(async () => {
|
|
jest.clearAllMocks();
|
|
const module: TestingModule = await Test.createTestingModule({
|
|
providers: [
|
|
CommentsService,
|
|
{ provide: CommentsRepository, useValue: mockCommentsRepository },
|
|
{ provide: CommentLikesRepository, useValue: mockCommentLikesRepository },
|
|
{ provide: ContentsRepository, useValue: mockContentsRepository },
|
|
{ provide: S3Service, useValue: mockS3Service },
|
|
{ provide: EventsGateway, useValue: mockEventsGateway },
|
|
],
|
|
}).compile();
|
|
|
|
service = module.get<CommentsService>(CommentsService);
|
|
repository = module.get<CommentsRepository>(CommentsRepository);
|
|
});
|
|
|
|
it("should be defined", () => {
|
|
expect(service).toBeDefined();
|
|
});
|
|
|
|
describe("create", () => {
|
|
it("should create a comment", async () => {
|
|
const userId = "user1";
|
|
const contentId = "content1";
|
|
const dto = { text: "Nice meme", parentId: undefined };
|
|
const createdComment = { id: "c1", ...dto, user: { username: "u1" } };
|
|
mockCommentsRepository.create.mockResolvedValue(createdComment);
|
|
mockCommentsRepository.findOneEnriched.mockResolvedValue(createdComment);
|
|
mockCommentLikesRepository.countByCommentId.mockResolvedValue(0);
|
|
mockCommentLikesRepository.isLikedByUser.mockResolvedValue(false);
|
|
|
|
const result = await service.create(userId, contentId, dto);
|
|
expect(result.id).toBe("c1");
|
|
expect(repository.create).toHaveBeenCalledWith({
|
|
userId,
|
|
contentId,
|
|
text: dto.text,
|
|
parentId: undefined,
|
|
});
|
|
expect(mockEventsGateway.sendToContent).toHaveBeenCalledWith(
|
|
contentId,
|
|
"new_comment",
|
|
expect.any(Object),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("findAllByContentId", () => {
|
|
it("should return comments for a content", async () => {
|
|
mockCommentsRepository.findAllByContentId.mockResolvedValue([
|
|
{ id: "c1", user: { avatarUrl: "path" } },
|
|
]);
|
|
mockCommentLikesRepository.countByCommentId.mockResolvedValue(5);
|
|
mockCommentLikesRepository.isLikedByUser.mockResolvedValue(true);
|
|
mockS3Service.getPublicUrl.mockReturnValue("url");
|
|
|
|
const result = await service.findAllByContentId("content1", "u1");
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].likesCount).toBe(5);
|
|
expect(result[0].isLiked).toBe(true);
|
|
expect(result[0].user.avatarUrl).toBe("url");
|
|
});
|
|
});
|
|
|
|
describe("remove", () => {
|
|
it("should remove comment if owner", async () => {
|
|
mockCommentsRepository.findOne.mockResolvedValue({ userId: "u1" });
|
|
await service.remove("u1", "c1");
|
|
expect(repository.delete).toHaveBeenCalledWith("c1");
|
|
});
|
|
|
|
it("should remove comment if admin", async () => {
|
|
mockCommentsRepository.findOne.mockResolvedValue({ userId: "u1" });
|
|
await service.remove("other", "c1", true);
|
|
expect(repository.delete).toHaveBeenCalledWith("c1");
|
|
});
|
|
|
|
it("should throw NotFoundException if comment does not exist", async () => {
|
|
mockCommentsRepository.findOne.mockResolvedValue(null);
|
|
await expect(service.remove("u1", "c1")).rejects.toThrow(NotFoundException);
|
|
});
|
|
|
|
it("should throw ForbiddenException if not owner and not admin", async () => {
|
|
mockCommentsRepository.findOne.mockResolvedValue({ userId: "u1" });
|
|
await expect(service.remove("other", "c1")).rejects.toThrow(
|
|
ForbiddenException,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("like", () => {
|
|
it("should add like", async () => {
|
|
mockCommentsRepository.findOne.mockResolvedValue({ id: "c1" });
|
|
await service.like("u1", "c1");
|
|
expect(mockCommentLikesRepository.addLike).toHaveBeenCalledWith("c1", "u1");
|
|
});
|
|
});
|
|
|
|
describe("unlike", () => {
|
|
it("should remove like", async () => {
|
|
mockCommentsRepository.findOne.mockResolvedValue({ id: "c1" });
|
|
await service.unlike("u1", "c1");
|
|
expect(mockCommentLikesRepository.removeLike).toHaveBeenCalledWith(
|
|
"c1",
|
|
"u1",
|
|
);
|
|
});
|
|
});
|
|
});
|