Compare commits
6 Commits
v1.7.5
...
46ffdd809c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46ffdd809c
|
||
|
|
2dcd277347
|
||
|
|
9486803aeb
|
||
|
|
1e0bb03182
|
||
|
|
f1d1359dcb
|
||
|
|
7b76942795
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@memegoat/backend",
|
"name": "@memegoat/backend",
|
||||||
"version": "1.7.5",
|
"version": "1.8.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
84
backend/src/comments/comments.service.spec.ts
Normal file
84
backend/src/comments/comments.service.spec.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import { ForbiddenException, NotFoundException } from "@nestjs/common";
|
||||||
|
import { Test, TestingModule } from "@nestjs/testing";
|
||||||
|
import { CommentsService } from "./comments.service";
|
||||||
|
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(),
|
||||||
|
delete: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
CommentsService,
|
||||||
|
{ provide: CommentsRepository, useValue: mockCommentsRepository },
|
||||||
|
],
|
||||||
|
}).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" };
|
||||||
|
mockCommentsRepository.create.mockResolvedValue({ id: "c1", ...dto });
|
||||||
|
|
||||||
|
const result = await service.create(userId, contentId, dto);
|
||||||
|
expect(result.id).toBe("c1");
|
||||||
|
expect(repository.create).toHaveBeenCalledWith({
|
||||||
|
userId,
|
||||||
|
contentId,
|
||||||
|
text: dto.text,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("findAllByContentId", () => {
|
||||||
|
it("should return comments for a content", async () => {
|
||||||
|
mockCommentsRepository.findAllByContentId.mockResolvedValue([{ id: "c1" }]);
|
||||||
|
const result = await service.findAllByContentId("content1");
|
||||||
|
expect(result).toHaveLength(1);
|
||||||
|
expect(repository.findAllByContentId).toHaveBeenCalledWith("content1");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -7,6 +7,7 @@ import { BadRequestException } from "@nestjs/common";
|
|||||||
import { ConfigService } from "@nestjs/config";
|
import { ConfigService } from "@nestjs/config";
|
||||||
import { Test, TestingModule } from "@nestjs/testing";
|
import { Test, TestingModule } from "@nestjs/testing";
|
||||||
import { MediaService } from "../media/media.service";
|
import { MediaService } from "../media/media.service";
|
||||||
|
import { EventsGateway } from "../realtime/events.gateway";
|
||||||
import { S3Service } from "../s3/s3.service";
|
import { S3Service } from "../s3/s3.service";
|
||||||
import { ContentsService } from "./contents.service";
|
import { ContentsService } from "./contents.service";
|
||||||
import { ContentsRepository } from "./repositories/contents.repository";
|
import { ContentsRepository } from "./repositories/contents.repository";
|
||||||
@@ -49,6 +50,10 @@ describe("ContentsService", () => {
|
|||||||
del: jest.fn(),
|
del: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockEventsGateway = {
|
||||||
|
sendToUser: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
|
||||||
@@ -60,6 +65,7 @@ describe("ContentsService", () => {
|
|||||||
{ provide: MediaService, useValue: mockMediaService },
|
{ provide: MediaService, useValue: mockMediaService },
|
||||||
{ provide: ConfigService, useValue: mockConfigService },
|
{ provide: ConfigService, useValue: mockConfigService },
|
||||||
{ provide: CACHE_MANAGER, useValue: mockCacheManager },
|
{ provide: CACHE_MANAGER, useValue: mockCacheManager },
|
||||||
|
{ provide: EventsGateway, useValue: mockEventsGateway },
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
|
|||||||
96
backend/src/messages/messages.service.spec.ts
Normal file
96
backend/src/messages/messages.service.spec.ts
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import { ForbiddenException } from "@nestjs/common";
|
||||||
|
import { Test, TestingModule } from "@nestjs/testing";
|
||||||
|
import { EventsGateway } from "../realtime/events.gateway";
|
||||||
|
import { MessagesService } from "./messages.service";
|
||||||
|
import { MessagesRepository } from "./repositories/messages.repository";
|
||||||
|
|
||||||
|
describe("MessagesService", () => {
|
||||||
|
let service: MessagesService;
|
||||||
|
let _repository: MessagesRepository;
|
||||||
|
let _eventsGateway: EventsGateway;
|
||||||
|
|
||||||
|
const mockMessagesRepository = {
|
||||||
|
findConversationBetweenUsers: jest.fn(),
|
||||||
|
createConversation: jest.fn(),
|
||||||
|
addParticipant: jest.fn(),
|
||||||
|
createMessage: jest.fn(),
|
||||||
|
findAllConversations: jest.fn(),
|
||||||
|
isParticipant: jest.fn(),
|
||||||
|
findMessagesByConversationId: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockEventsGateway = {
|
||||||
|
sendToUser: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
MessagesService,
|
||||||
|
{ provide: MessagesRepository, useValue: mockMessagesRepository },
|
||||||
|
{ provide: EventsGateway, useValue: mockEventsGateway },
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<MessagesService>(MessagesService);
|
||||||
|
_repository = module.get<MessagesRepository>(MessagesRepository);
|
||||||
|
_eventsGateway = module.get<EventsGateway>(EventsGateway);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("sendMessage", () => {
|
||||||
|
it("should send message to existing conversation", async () => {
|
||||||
|
const senderId = "s1";
|
||||||
|
const dto = { recipientId: "r1", text: "hello" };
|
||||||
|
mockMessagesRepository.findConversationBetweenUsers.mockResolvedValue({
|
||||||
|
id: "conv1",
|
||||||
|
});
|
||||||
|
mockMessagesRepository.createMessage.mockResolvedValue({
|
||||||
|
id: "m1",
|
||||||
|
text: "hello",
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await service.sendMessage(senderId, dto);
|
||||||
|
|
||||||
|
expect(result.id).toBe("m1");
|
||||||
|
expect(mockEventsGateway.sendToUser).toHaveBeenCalledWith(
|
||||||
|
"r1",
|
||||||
|
"new_message",
|
||||||
|
expect.anything(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create new conversation if not exists", async () => {
|
||||||
|
const senderId = "s1";
|
||||||
|
const dto = { recipientId: "r1", text: "hello" };
|
||||||
|
mockMessagesRepository.findConversationBetweenUsers.mockResolvedValue(null);
|
||||||
|
mockMessagesRepository.createConversation.mockResolvedValue({
|
||||||
|
id: "new_conv",
|
||||||
|
});
|
||||||
|
mockMessagesRepository.createMessage.mockResolvedValue({ id: "m1" });
|
||||||
|
|
||||||
|
await service.sendMessage(senderId, dto);
|
||||||
|
|
||||||
|
expect(mockMessagesRepository.createConversation).toHaveBeenCalled();
|
||||||
|
expect(mockMessagesRepository.addParticipant).toHaveBeenCalledTimes(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getMessages", () => {
|
||||||
|
it("should return messages if user is participant", async () => {
|
||||||
|
mockMessagesRepository.isParticipant.mockResolvedValue(true);
|
||||||
|
mockMessagesRepository.findMessagesByConversationId.mockResolvedValue([
|
||||||
|
{ id: "m1" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = await service.getMessages("u1", "conv1");
|
||||||
|
expect(result).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw ForbiddenException if user is not participant", async () => {
|
||||||
|
mockMessagesRepository.isParticipant.mockResolvedValue(false);
|
||||||
|
await expect(service.getMessages("u1", "conv1")).rejects.toThrow(
|
||||||
|
ForbiddenException,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
54
backend/src/realtime/events.gateway.spec.ts
Normal file
54
backend/src/realtime/events.gateway.spec.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { ConfigService } from "@nestjs/config";
|
||||||
|
import { Test, TestingModule } from "@nestjs/testing";
|
||||||
|
import { JwtService } from "../crypto/services/jwt.service";
|
||||||
|
import { EventsGateway } from "./events.gateway";
|
||||||
|
|
||||||
|
describe("EventsGateway", () => {
|
||||||
|
let gateway: EventsGateway;
|
||||||
|
let _jwtService: JwtService;
|
||||||
|
|
||||||
|
const mockJwtService = {
|
||||||
|
verifyJwt: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockConfigService = {
|
||||||
|
get: jest.fn().mockReturnValue("secret-password-32-chars-long-!!!"),
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
EventsGateway,
|
||||||
|
{ provide: JwtService, useValue: mockJwtService },
|
||||||
|
{ provide: ConfigService, useValue: mockConfigService },
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
gateway = module.get<EventsGateway>(EventsGateway);
|
||||||
|
_jwtService = module.get<JwtService>(JwtService);
|
||||||
|
gateway.server = {
|
||||||
|
to: jest.fn().mockReturnThis(),
|
||||||
|
emit: jest.fn(),
|
||||||
|
} as any;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be defined", () => {
|
||||||
|
expect(gateway).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("sendToUser", () => {
|
||||||
|
it("should emit event to user room", () => {
|
||||||
|
const userId = "user123";
|
||||||
|
const event = "test_event";
|
||||||
|
const data = { foo: "bar" };
|
||||||
|
|
||||||
|
gateway.sendToUser(userId, event, data);
|
||||||
|
|
||||||
|
expect(gateway.server.to).toHaveBeenCalledWith(`user:${userId}`);
|
||||||
|
expect(gateway.server.to(`user:${userId}`).emit).toHaveBeenCalledWith(
|
||||||
|
event,
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -108,6 +108,7 @@ describe("UsersService", () => {
|
|||||||
describe("findOne", () => {
|
describe("findOne", () => {
|
||||||
it("should find a user", async () => {
|
it("should find a user", async () => {
|
||||||
mockUsersRepository.findOne.mockResolvedValue({ uuid: "uuid1" });
|
mockUsersRepository.findOne.mockResolvedValue({ uuid: "uuid1" });
|
||||||
|
mockRbacService.getUserRoles.mockResolvedValue([]);
|
||||||
const result = await service.findOne("uuid1");
|
const result = await service.findOne("uuid1");
|
||||||
expect(result.uuid).toBe("uuid1");
|
expect(result.uuid).toBe("uuid1");
|
||||||
});
|
});
|
||||||
@@ -139,6 +140,7 @@ describe("UsersService", () => {
|
|||||||
describe("findByEmailHash", () => {
|
describe("findByEmailHash", () => {
|
||||||
it("should call repository.findByEmailHash", async () => {
|
it("should call repository.findByEmailHash", async () => {
|
||||||
mockUsersRepository.findByEmailHash.mockResolvedValue({ uuid: "u1" });
|
mockUsersRepository.findByEmailHash.mockResolvedValue({ uuid: "u1" });
|
||||||
|
mockRbacService.getUserRoles.mockResolvedValue([]);
|
||||||
const result = await service.findByEmailHash("hash");
|
const result = await service.findByEmailHash("hash");
|
||||||
expect(result.uuid).toBe("u1");
|
expect(result.uuid).toBe("u1");
|
||||||
expect(mockUsersRepository.findByEmailHash).toHaveBeenCalledWith("hash");
|
expect(mockUsersRepository.findByEmailHash).toHaveBeenCalledWith("hash");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@memegoat/frontend",
|
"name": "@memegoat/frontend",
|
||||||
"version": "1.7.5",
|
"version": "1.8.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@memegoat/source",
|
"name": "@memegoat/source",
|
||||||
"version": "1.7.5",
|
"version": "1.8.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"version:get": "cmake -P version.cmake GET",
|
"version:get": "cmake -P version.cmake GET",
|
||||||
|
|||||||
Reference in New Issue
Block a user