Skip to content

Commit

Permalink
Merge pull request #361 from boostcampwm2023/BE-feature/boards
Browse files Browse the repository at this point in the history
보드 모듈 리팩토링
  • Loading branch information
Conut-1 authored Nov 14, 2024
2 parents 82f9b01 + e7ff32f commit 605f8b7
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 168 deletions.
166 changes: 78 additions & 88 deletions nestjs-BE/server/src/boards/boards.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { HttpStatus, NotFoundException } from '@nestjs/common';
import { BoardsController } from './boards.controller';
import { BoardsService } from './boards.service';
import { UploadService } from '../upload/upload.service';
import { Board } from './schemas/board.schema';
import { CreateBoardDto } from './dto/create-board.dto';
import { HttpStatus, NotFoundException } from '@nestjs/common';
import { UpdateWriteOpResult } from 'mongoose';
import { ConfigModule, ConfigService } from '@nestjs/config';

describe('BoardsController', () => {
let controller: BoardsController;
let boardsService: BoardsService;
let uploadService: UploadService;
let configService: ConfigService;

beforeEach(async () => {
Expand All @@ -22,126 +18,120 @@ describe('BoardsController', () => {
{
provide: BoardsService,
useValue: {
create: jest.fn(),
createBoard: jest.fn(),
deleteBoard: jest.fn(),
restoreBoard: jest.fn(),
},
},
{
provide: UploadService,
useValue: {
uploadFile: jest.fn(),
},
},
],
}).compile();

controller = module.get<BoardsController>(BoardsController);
boardsService = module.get<BoardsService>(BoardsService);
uploadService = module.get<UploadService>(UploadService);
configService = module.get<ConfigService>(ConfigService);
});

it('createBoard created board', async () => {
describe('createBoard', () => {
const bodyMock = {
boardName: 'board name',
spaceId: 'space uuid',
} as CreateBoardDto;
const imageMock = { filename: 'image' } as Express.Multer.File;
jest.spyOn(uploadService, 'uploadFile').mockResolvedValue('image url');
jest.spyOn(boardsService, 'create').mockResolvedValue({
uuid: 'board uuid',
createdAt: 'created date' as unknown as Date,
} as Board);

const board = controller.createBoard(bodyMock, imageMock);

await expect(board).resolves.toEqual({
statusCode: HttpStatus.CREATED,
message: 'Board created.',
data: {
boardId: 'board uuid',
date: 'created date',

it('created board', async () => {
(boardsService.createBoard as jest.Mock).mockResolvedValue({
uuid: 'board uuid',
createdAt: 'created date',
imageUrl: 'image url',
},
});

const board = controller.createBoard(bodyMock, imageMock);

await expect(board).resolves.toEqual({
statusCode: HttpStatus.CREATED,
message: 'Board created.',
data: {
boardId: 'board uuid',
date: 'created date',
imageUrl: 'image url',
},
});
});
expect(uploadService.uploadFile).toHaveBeenCalled();
});

it('createBoard request does not have image file', async () => {
const bodyMock = {
boardName: 'board name',
spaceId: 'space uuid',
} as CreateBoardDto;
jest.spyOn(boardsService, 'create').mockResolvedValue({
uuid: 'board uuid',
createdAt: 'created date' as unknown as Date,
} as Board);

const response = controller.createBoard(
bodyMock,
null as unknown as Express.Multer.File,
);

await expect(response).resolves.toEqual({
statusCode: HttpStatus.CREATED,
message: 'Board created.',
data: {
boardId: 'board uuid',
date: 'created date',
imageUrl: configService.get<string>('APP_ICON_URL'),
},
it('request does not have image file', async () => {
(boardsService.createBoard as jest.Mock).mockResolvedValue({
uuid: 'board uuid',
createdAt: 'created date',
});

const response = controller.createBoard(
bodyMock,
undefined as Express.Multer.File,
);

await expect(response).resolves.toEqual({
statusCode: HttpStatus.CREATED,
message: 'Board created.',
data: {
boardId: 'board uuid',
date: 'created date',
imageUrl: configService.get<string>('APP_ICON_URL'),
},
});
});
expect(uploadService.uploadFile).not.toHaveBeenCalled();
});

it('deleteBoard success', async () => {
describe('deleteBoard', () => {
const bodyMock = { boardId: 'board uuid' };
jest.spyOn(boardsService, 'deleteBoard').mockResolvedValue({
matchedCount: 1,
} as UpdateWriteOpResult);

const response = controller.deleteBoard(bodyMock);
it('success', async () => {
(boardsService.deleteBoard as jest.Mock).mockResolvedValue({
matchedCount: 1,
});

const response = controller.deleteBoard(bodyMock);

await expect(response).resolves.toEqual({
statusCode: HttpStatus.OK,
message: 'Board deleted.',
await expect(response).resolves.toEqual({
statusCode: HttpStatus.OK,
message: 'Board deleted.',
});
});
});

it('deleteBoard fail', async () => {
const bodyMock = { boardId: 'board uuid' };
jest.spyOn(boardsService, 'deleteBoard').mockResolvedValue({
matchedCount: 0,
} as UpdateWriteOpResult);
it('fail', async () => {
(boardsService.deleteBoard as jest.Mock).mockRejectedValue(
new NotFoundException(),
);

const response = controller.deleteBoard(bodyMock);
const response = controller.deleteBoard(bodyMock);

await expect(response).rejects.toThrow(NotFoundException);
await expect(response).rejects.toThrow(NotFoundException);
});
});

it('restoreBoard success', async () => {
describe('restoreBoard', () => {
const bodyMock = { boardId: 'board uuid' };
jest.spyOn(boardsService, 'restoreBoard').mockResolvedValue({
matchedCount: 1,
} as UpdateWriteOpResult);

const response = controller.restoreBoard(bodyMock);
it('success', async () => {
(boardsService.restoreBoard as jest.Mock).mockResolvedValue({
matchedCount: 1,
});

const response = controller.restoreBoard(bodyMock);

await expect(response).resolves.toEqual({
statusCode: HttpStatus.OK,
message: 'Board restored.',
await expect(response).resolves.toEqual({
statusCode: HttpStatus.OK,
message: 'Board restored.',
});
});
});

it('restoreBoard fail', async () => {
const bodyMock = { boardId: 'board uuid' };
jest.spyOn(boardsService, 'restoreBoard').mockResolvedValue({
matchedCount: 0,
} as UpdateWriteOpResult);
it('fail', async () => {
(boardsService.restoreBoard as jest.Mock).mockRejectedValue(
new NotFoundException(),
);

const response = controller.restoreBoard(bodyMock);
const response = controller.restoreBoard(bodyMock);

await expect(response).rejects.toThrow(NotFoundException);
await expect(response).rejects.toThrow(NotFoundException);
});
});
});
67 changes: 13 additions & 54 deletions nestjs-BE/server/src/boards/boards.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@ import {
HttpStatus,
Query,
Patch,
NotFoundException,
UseInterceptors,
UploadedFile,
} from '@nestjs/common';
import { BoardsService } from './boards.service';
import { CreateBoardDto } from './dto/create-board.dto';
import {
ApiBody,
ApiConsumes,
Expand All @@ -23,7 +20,9 @@ import {
ApiQuery,
ApiTags,
} from '@nestjs/swagger';
import { Public } from '../auth/decorators/public.decorator';
import { FileInterceptor } from '@nestjs/platform-express';
import { BoardsService } from './boards.service';
import { CreateBoardDto } from './dto/create-board.dto';
import { DeleteBoardDto } from './dto/delete-board.dto';
import { RestoreBoardDto } from './dto/restore-board.dto';
import {
Expand All @@ -34,20 +33,12 @@ import {
RestoreBoardFailure,
RestoreBoardSuccess,
} from './swagger/boards.type';
import { FileInterceptor } from '@nestjs/platform-express';
import { UploadService } from '../upload/upload.service';
import { ConfigService } from '@nestjs/config';

const BOARD_EXPIRE_DAY = 7;
import { Public } from '../auth/decorators/public.decorator';

@Controller('boards')
@ApiTags('boards')
export class BoardsController {
constructor(
private boardsService: BoardsService,
private uploadService: UploadService,
private configService: ConfigService,
) {}
constructor(private boardsService: BoardsService) {}

@ApiOperation({
summary: '보드 생성',
Expand All @@ -67,14 +58,14 @@ export class BoardsController {
@Body() createBoardDto: CreateBoardDto,
@UploadedFile() image: Express.Multer.File,
) {
const imageUrl = image
? await this.uploadService.uploadFile(image)
: this.configService.get<string>('APP_ICON_URL');
const document = await this.boardsService.create(createBoardDto, imageUrl);
const document = await this.boardsService.createBoard(
createBoardDto,
image,
);
const responseData = {
boardId: document.uuid,
date: document.createdAt,
imageUrl,
imageUrl: document.imageUrl,
};
return {
statusCode: HttpStatus.CREATED,
Expand All @@ -100,32 +91,10 @@ export class BoardsController {
@Get('list')
async findBySpaceId(@Query('spaceId') spaceId: string) {
const boardList = await this.boardsService.findBySpaceId(spaceId);
const responseData = boardList.reduce<Array<any>>((list, board) => {
let isDeleted = false;

if (board.deletedAt && board.deletedAt > board.restoredAt) {
const expireDate = new Date(board.deletedAt);
expireDate.setDate(board.deletedAt.getDate() + BOARD_EXPIRE_DAY);
if (new Date() > expireDate) {
this.boardsService.deleteExpiredBoard(board.uuid);
return list;
}
isDeleted = true;
}

list.push({
boardId: board.uuid,
boardName: board.boardName,
createdAt: board.createdAt,
imageUrl: board.imageUrl,
isDeleted,
});
return list;
}, []);
return {
statusCode: HttpStatus.OK,
message: 'Retrieved board list.',
data: responseData,
data: boardList,
};
}

Expand All @@ -142,12 +111,7 @@ export class BoardsController {
@Public()
@Patch('delete')
async deleteBoard(@Body() deleteBoardDto: DeleteBoardDto) {
const updateResult = await this.boardsService.deleteBoard(
deleteBoardDto.boardId,
);
if (!updateResult.matchedCount) {
throw new NotFoundException('Target board not found.');
}
await this.boardsService.deleteBoard(deleteBoardDto.boardId);
return { statusCode: HttpStatus.OK, message: 'Board deleted.' };
}

Expand All @@ -164,12 +128,7 @@ export class BoardsController {
@Public()
@Patch('restore')
async restoreBoard(@Body() resotreBoardDto: RestoreBoardDto) {
const updateResult = await this.boardsService.restoreBoard(
resotreBoardDto.boardId,
);
if (!updateResult.matchedCount) {
throw new NotFoundException('Target board not found.');
}
await this.boardsService.restoreBoard(resotreBoardDto.boardId);
return { statusCode: HttpStatus.OK, message: 'Board restored.' };
}
}
2 changes: 1 addition & 1 deletion nestjs-BE/server/src/boards/boards.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { BoardsService } from './boards.service';
import { BoardsController } from './boards.controller';
import { MongooseModule } from '@nestjs/mongoose';
import { Board, BoardSchema } from './schemas/board.schema';
import { UploadModule } from '../upload/upload.module';

Expand Down
Loading

0 comments on commit 605f8b7

Please sign in to comment.