From 76e61cf1071d0db6b999d482a2ae8020f96e58f3 Mon Sep 17 00:00:00 2001 From: koomin1227 Date: Thu, 14 Dec 2023 15:34:40 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[BE]=20Test=20:=20users-block.service.spec.?= =?UTF-8?q?ts=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../users-block/users-block.service.spec.ts | 136 ++++++++++++++++++ BE/src/users-block/users-block.service.ts | 4 +- 2 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 BE/src/users-block/users-block.service.spec.ts diff --git a/BE/src/users-block/users-block.service.spec.ts b/BE/src/users-block/users-block.service.spec.ts new file mode 100644 index 0000000..5437116 --- /dev/null +++ b/BE/src/users-block/users-block.service.spec.ts @@ -0,0 +1,136 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { HttpException } from '@nestjs/common'; +import { UsersBlockService } from './users-block.service'; +import { BlockUserEntity } from '../entities/blockUser.entity'; +import { UserEntity } from '../entities/user.entity'; +import { ConfigService } from '@nestjs/config'; + +const mockBlockUserRepository = () => ({ + save: jest.fn(), + find: jest.fn(), + findOne: jest.fn(), + softDelete: jest.fn(), +}); + +const mockUserRepository = () => ({ + findOne: jest.fn(), +}); +type MockRepository = Partial, jest.Mock>>; +describe('PostsBlockService', () => { + let service: UsersBlockService; + let blockUserRepository: MockRepository; + let userRepository: MockRepository; + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + UsersBlockService, + { + provide: getRepositoryToken(BlockUserEntity), + useValue: mockBlockUserRepository(), + }, + { + provide: getRepositoryToken(UserEntity), + useValue: mockUserRepository(), + }, + { + provide: ConfigService, + useValue: { get: jest.fn((key: string) => 'mocked-value') }, + }, + ], + }).compile(); + + service = module.get(UsersBlockService); + blockUserRepository = module.get>( + getRepositoryToken(BlockUserEntity), + ); + userRepository = module.get>( + getRepositoryToken(UserEntity), + ); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + describe('addBlockUser()', function () { + it('should not found', function () { + userRepository.findOne.mockResolvedValue(null); + expect(async () => { + await service.addBlockUser('user', 'blocker'); + }).rejects.toThrowError( + new HttpException('존재하지 않는 유저입니다', 404), + ); + }); + it('should bad request', function () { + userRepository.findOne.mockResolvedValue(new UserEntity()); + blockUserRepository.findOne.mockResolvedValue({ delete_date: null }); + expect(async () => { + await service.addBlockUser('user', 'blocker'); + }).rejects.toThrowError(new HttpException('이미 차단된 유저입니다', 400)); + }); + it('should save', async function () { + userRepository.findOne.mockResolvedValue(new UserEntity()); + blockUserRepository.findOne.mockResolvedValue(null); + blockUserRepository.save.mockResolvedValue(new BlockUserEntity()); + await service.addBlockUser('user', 'blocker'); + expect(blockUserRepository.save).toHaveBeenCalledTimes(1); + }); + }); + + describe('getBlockUser', function () { + it('should be user who has profile_img', async function () { + const blockUsers = []; + const blockUser = new BlockUserEntity(); + blockUser.blocked_user = 'user'; + blockUser.blockedUser = new UserEntity(); + blockUser.blockedUser.nickname = 'test'; + blockUser.blockedUser.profile_img = 'image_url'; + blockUsers.push(blockUser); + blockUserRepository.find.mockResolvedValue(blockUsers); + const users = await service.getBlockUser('user'); + expect(users[0].profile_img).toEqual('image_url'); + }); + + it('should be user who has no profile_img', async function () { + const blockUsers = []; + const blockUser = new BlockUserEntity(); + blockUser.blocked_user = 'user'; + blockUser.blockedUser = new UserEntity(); + blockUser.blockedUser.nickname = 'test'; + blockUser.blockedUser.profile_img = null; + blockUsers.push(blockUser); + blockUserRepository.find.mockResolvedValue(blockUsers); + const users = await service.getBlockUser('user'); + expect(users[0].profile_img).toEqual('mocked-value'); + }); + + it('should be user who leave', async function () { + const blockUsers = []; + const blockUser = new BlockUserEntity(); + blockUser.blocked_user = 'user'; + blockUser.blockedUser = null; + blockUsers.push(blockUser); + blockUserRepository.find.mockResolvedValue(blockUsers); + const users = await service.getBlockUser('user'); + expect(users[0].profile_img).toEqual(null); + expect(users[0].nickname).toEqual(null); + expect(users[0].user_id).toEqual('user'); + }); + }); + + describe('removeBlockUser', function () { + it('should not found', function () { + blockUserRepository.findOne.mockResolvedValue(null); + expect(async () => { + await service.removeBlockUser('user', 'blocker'); + }).rejects.toThrowError(new HttpException('없는 사용자 입니다.', 404)); + }); + + it('should delete', async function () { + blockUserRepository.findOne.mockResolvedValue(new BlockUserEntity()); + await service.removeBlockUser('user', 'blocker'); + expect(blockUserRepository.softDelete).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/BE/src/users-block/users-block.service.ts b/BE/src/users-block/users-block.service.ts index 84835a5..f588828 100644 --- a/BE/src/users-block/users-block.service.ts +++ b/BE/src/users-block/users-block.service.ts @@ -1,8 +1,8 @@ import { HttpException, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { BlockUserEntity } from 'src/entities/blockUser.entity'; +import { BlockUserEntity } from '../entities/blockUser.entity'; import { Repository } from 'typeorm'; -import { UserEntity } from 'src/entities/user.entity'; +import { UserEntity } from '../entities/user.entity'; import { ConfigService } from '@nestjs/config'; interface BlockedUser { From 9c59f1698cf239ca1ec4d08808c1f005f880e989 Mon Sep 17 00:00:00 2001 From: koomin1227 Date: Thu, 14 Dec 2023 16:39:32 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[BE]=20Rename=20:=20posts-block.service.spe?= =?UTF-8?q?c.ts=20=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{users-block.service.spec.ts => posts-block.service.spec.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename BE/src/posts-block/{users-block.service.spec.ts => posts-block.service.spec.ts} (100%) diff --git a/BE/src/posts-block/users-block.service.spec.ts b/BE/src/posts-block/posts-block.service.spec.ts similarity index 100% rename from BE/src/posts-block/users-block.service.spec.ts rename to BE/src/posts-block/posts-block.service.spec.ts From 1fe54967a445849e0c0e240558237ba58f13694a Mon Sep 17 00:00:00 2001 From: koomin1227 Date: Thu, 14 Dec 2023 16:47:21 +0900 Subject: [PATCH 3/5] =?UTF-8?q?[BE]=20Feat=20:=20report=20API=20=EA=B0=80?= =?UTF-8?q?=EB=93=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BE/src/login/login.controller.ts | 2 +- BE/src/report/report.module.ts | 3 ++- BE/src/report/report.service.ts | 16 ++++------------ 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/BE/src/login/login.controller.ts b/BE/src/login/login.controller.ts index 6f07779..f0c0ffa 100644 --- a/BE/src/login/login.controller.ts +++ b/BE/src/login/login.controller.ts @@ -12,8 +12,8 @@ import { LoginService, SocialProperties } from './login.service'; import { AppleLoginDto } from './dto/appleLogin.dto'; import { AuthGuard } from '../common/guard/auth.guard'; - @Controller() +@UseGuards(AuthGuard) export class LoginController { constructor(private readonly loginService: LoginService) {} diff --git a/BE/src/report/report.module.ts b/BE/src/report/report.module.ts index c76f593..45c45ff 100644 --- a/BE/src/report/report.module.ts +++ b/BE/src/report/report.module.ts @@ -5,10 +5,11 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { ReportEntity } from '../entities/report.entity'; import { PostEntity } from '../entities/post.entity'; import { UserEntity } from '../entities/user.entity'; +import { AuthGuard } from '../common/guard/auth.guard'; @Module({ imports: [TypeOrmModule.forFeature([ReportEntity, PostEntity, UserEntity])], controllers: [ReportController], - providers: [ReportService], + providers: [ReportService, AuthGuard], }) export class ReportModule {} diff --git a/BE/src/report/report.service.ts b/BE/src/report/report.service.ts index 398c1fd..b7d6c89 100644 --- a/BE/src/report/report.service.ts +++ b/BE/src/report/report.service.ts @@ -4,8 +4,6 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { ReportEntity } from '../entities/report.entity'; import { PostEntity } from '../entities/post.entity'; -import { UserEntity } from '../entities/user.entity'; - @Injectable() export class ReportService { constructor( @@ -13,15 +11,15 @@ export class ReportService { private reportRepository: Repository, @InjectRepository(PostEntity) private postRepository: Repository, - @InjectRepository(UserEntity) - private userRepository: Repository, ) {} async createReport(body: CreateReportDto, userId: string) { - const isAllExist = await this.isExist(body.post_id); + const isExist = await this.postRepository.exist({ + where: { id: body.post_id }, + }); if (body.user_id === userId) { throw new HttpException('자신의 게시글은 신고 할 수 없습니다.', 400); } - if (!isAllExist) { + if (!isExist) { throw new HttpException('신고할 대상이 존재 하지 않습니다.', 404); } const reportEntity = new ReportEntity(); @@ -31,10 +29,4 @@ export class ReportService { reportEntity.reporter = userId; await this.reportRepository.save(reportEntity); } - async isExist(postId) { - const isPostExist: boolean = await this.postRepository.exist({ - where: { id: postId }, - }); - return !!isPostExist; - } } From 92bf1ed722a4b236d9c6bad2d80992bc5847d27b Mon Sep 17 00:00:00 2001 From: koomin1227 Date: Thu, 14 Dec 2023 17:11:45 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[BE]=20Feat=20:=20report=20API=20=EA=B0=80?= =?UTF-8?q?=EB=93=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BE/src/report/report.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BE/src/report/report.service.ts b/BE/src/report/report.service.ts index b7d6c89..50c8f5f 100644 --- a/BE/src/report/report.service.ts +++ b/BE/src/report/report.service.ts @@ -13,12 +13,12 @@ export class ReportService { private postRepository: Repository, ) {} async createReport(body: CreateReportDto, userId: string) { - const isExist = await this.postRepository.exist({ - where: { id: body.post_id }, - }); if (body.user_id === userId) { throw new HttpException('자신의 게시글은 신고 할 수 없습니다.', 400); } + const isExist = await this.postRepository.exist({ + where: { id: body.post_id }, + }); if (!isExist) { throw new HttpException('신고할 대상이 존재 하지 않습니다.', 404); } From 5caf16e3a783280cf28bfcbe86f68802d0e82bc1 Mon Sep 17 00:00:00 2001 From: koomin1227 Date: Thu, 14 Dec 2023 17:26:34 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[BE]=20Test=20:=20report.service.spec.ts=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BE/src/report/report.service.spec.ts | 83 ++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 BE/src/report/report.service.spec.ts diff --git a/BE/src/report/report.service.spec.ts b/BE/src/report/report.service.spec.ts new file mode 100644 index 0000000..4b0e053 --- /dev/null +++ b/BE/src/report/report.service.spec.ts @@ -0,0 +1,83 @@ +import { Repository } from 'typeorm'; +import { ReportService } from './report.service'; +import { ReportEntity } from '../entities/report.entity'; +import { PostEntity } from '../entities/post.entity'; +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; +import { CreateReportDto } from './dto/createReport.dto'; +import { HttpException } from '@nestjs/common'; + +const mockReportRepository = () => ({ + save: jest.fn(), + find: jest.fn(), + findOne: jest.fn(), + softDelete: jest.fn(), +}); + +const mockPostRepository = () => ({ + findOne: jest.fn(), + exist: jest.fn(), +}); + +type MockRepository = Partial, jest.Mock>>; + +describe('ReportService', function () { + let service: ReportService; + let reportRepository: MockRepository; + let postRepository: MockRepository; + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + ReportService, + { + provide: getRepositoryToken(ReportEntity), + useValue: mockReportRepository(), + }, + { + provide: getRepositoryToken(PostEntity), + useValue: mockPostRepository(), + }, + ], + }).compile(); + + service = module.get(ReportService); + reportRepository = module.get>( + getRepositoryToken(ReportEntity), + ); + postRepository = module.get>( + getRepositoryToken(PostEntity), + ); + }); + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('createReport()', function () { + const body = new CreateReportDto(); + body.post_id = 123; + body.user_id = 'user'; + body.description = 'test'; + it('should bad request', function () { + expect(async () => { + await service.createReport(body, 'user'); + }).rejects.toThrowError( + new HttpException('자신의 게시글은 신고 할 수 없습니다.', 400), + ); + }); + + it('should not found', function () { + postRepository.exist.mockResolvedValue(false); + expect(async () => { + await service.createReport(body, 'user1'); + }).rejects.toThrowError( + new HttpException('신고할 대상이 존재 하지 않습니다.', 404), + ); + }); + + it('should save', async function () { + postRepository.exist.mockResolvedValue(true); + await service.createReport(body, 'user1'); + expect(reportRepository.save).toHaveBeenCalledTimes(1); + }); + }); +});