From 4bfe8bc511cf8ecfc362a9ea5bd4bca68b8a01a0 Mon Sep 17 00:00:00 2001 From: JinJung0101 Date: Fri, 16 Feb 2024 15:47:36 +0900 Subject: [PATCH 1/3] =?UTF-8?q?test=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/auth/auth_test.http | 29 ----------------------------- src/books/books-test.http | 13 ------------- 2 files changed, 42 deletions(-) delete mode 100644 src/auth/auth_test.http delete mode 100644 src/books/books-test.http diff --git a/src/auth/auth_test.http b/src/auth/auth_test.http deleted file mode 100644 index b2156e8..0000000 --- a/src/auth/auth_test.http +++ /dev/null @@ -1,29 +0,0 @@ -### - -POST http://localhost:3000/auth/login -Content-Type: application/json - -{ - "userId": "jinhwan", - "password": "qwer" -} - -### -POST http://localhost:3000/auth/register -Content-Type: application/json - -{ - "userId": "jinhwan", - "password": "qwer", - "email": "test1@test1.com" -} - -### -PATCH http://localhost:3000/auth/password -Content-Type: application/json -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2NWE3MzEwYmRhNGUxOWI2OTQxY2RkNDgiLCJlbWFpbCI6InRlc3QxQHRlc3QxLmNvbSIsImlhdCI6MTcwNTQ1NjI0OCwiZXhwIjoxNzA1NTQyNjQ4fQ.Wa0VxJj0NaShwMn4v8ZVVbvW0sD5cydjNrqRypJnI94 - -{ - "oldPassword": "qwer", - "newPassword": "1234" -} \ No newline at end of file diff --git a/src/books/books-test.http b/src/books/books-test.http deleted file mode 100644 index a8e8cfb..0000000 --- a/src/books/books-test.http +++ /dev/null @@ -1,13 +0,0 @@ -@host = http://localhost:3000/api - -### - -POST {{host}}/books/image HTTP/1.1 -Content-Type: multipart/form-data; boundary=MyBoundary - ---MyBoundary -Content-Disposition: form-data; name="file"; filename="test.png" -Content-Type: image/png - - ---MyBoundary-- From 7e5e55d4eeb6422fa43807598050ab89ad9501fa Mon Sep 17 00:00:00 2001 From: JinJung0101 Date: Sat, 17 Feb 2024 21:09:07 +0900 Subject: [PATCH 2/3] =?UTF-8?q?user=20=EA=B0=80=EC=9E=85=20=EC=8B=9C=20?= =?UTF-8?q?=EA=B8=80=EC=9E=90=20=EC=88=98=20=EC=A0=9C=ED=95=9C=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20-=20userId,=20password=20=EA=B8=80=EC=9E=90=20?= =?UTF-8?q?=EC=88=98=20=EC=A0=9C=ED=95=9C=20-=20users.controller=20?= =?UTF-8?q?=EA=B0=84=EB=8B=A8=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/auth/auth.controller.ts | 3 +- src/filter/GlobalExceptionFilter.ts | 8 +++- src/users/__test__/users.controller.spec.ts | 48 +++++++++++++++++++++ src/users/dto/create-user.dto.ts | 19 ++++---- src/users/users.controller.ts | 5 ++- 5 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 src/users/__test__/users.controller.spec.ts diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index 6b7ed00..9dc9300 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -7,6 +7,7 @@ import { UseGuards, Patch, Res, + ValidationPipe, } from '@nestjs/common'; import { Response } from 'express'; import { CreateUserDto } from 'src/users/dto/create-user.dto'; @@ -25,7 +26,7 @@ export class AuthController { constructor(private authService: AuthService) {} @Post('register') - async register(@Body() createUserDto: CreateUserDto) { + async register(@Body(new ValidationPipe()) createUserDto: CreateUserDto) { return await this.authService.register(createUserDto); } diff --git a/src/filter/GlobalExceptionFilter.ts b/src/filter/GlobalExceptionFilter.ts index fc18430..da4478e 100644 --- a/src/filter/GlobalExceptionFilter.ts +++ b/src/filter/GlobalExceptionFilter.ts @@ -21,7 +21,13 @@ export class GlobalExceptionFilter implements ExceptionFilter { if (exception instanceof HttpException) { status = exception.getStatus(); - userMessage = 'A request error occurred'; + const exceptionResponse = exception.getResponse(); + userMessage = + typeof exceptionResponse === 'string' + ? exceptionResponse + : Array.isArray((exceptionResponse as any).message) + ? (exceptionResponse as any).message[0] + : (exceptionResponse as any).message || 'A request error occurred'; } else if (exception.name === 'CastError') { status = HttpStatus.BAD_REQUEST; this.logger.error(`CastError: ${exception.message}`); diff --git a/src/users/__test__/users.controller.spec.ts b/src/users/__test__/users.controller.spec.ts new file mode 100644 index 0000000..e65cd5d --- /dev/null +++ b/src/users/__test__/users.controller.spec.ts @@ -0,0 +1,48 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { UsersController } from '../users.controller'; +import { UsersService } from '../users.service'; +import { CreateUserDto } from '../dto/create-user.dto'; + +describe('UsersController', () => { + let controller: UsersController; + let service: UsersService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [UsersController], + providers: [ + { + provide: UsersService, + useValue: { + createUser: jest + .fn() + .mockResolvedValue({ id: '1', userId: 'test', password: 'test' }), + }, + }, + ], + }).compile(); + + controller = module.get(UsersController); + service = module.get(UsersService); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); + + describe('createUser', () => { + it('should return a user', async () => { + const createUserDto: CreateUserDto = { + userId: 'test', + password: 'test', + }; + expect(await controller.createUser(createUserDto)).toEqual({ + id: '1', + userId: 'test', + password: 'test', + }); + expect(service.createUser).toHaveBeenCalledWith(createUserDto); + }); + }); +}); diff --git a/src/users/dto/create-user.dto.ts b/src/users/dto/create-user.dto.ts index 06b463f..b66ea17 100644 --- a/src/users/dto/create-user.dto.ts +++ b/src/users/dto/create-user.dto.ts @@ -1,22 +1,23 @@ -import { IsNotEmpty, IsString, Matches } from 'class-validator'; +import { + IsNotEmpty, + IsString, + Matches, + MaxLength, + MinLength, +} from 'class-validator'; export class CreateUserDto { @IsString() @IsNotEmpty() + @MinLength(3, { message: '3글자 이상 입력해 주세요.' }) + @MaxLength(10, { message: '10글자 이내로 입력해 주세요.' }) @Matches(/^[A-Za-z0-9]*$/, { message: 'userId should not contain spaces or special characters', }) userId: string; @IsString() + @MinLength(4, { message: '4글자 이상 입력해 주세요.' }) @IsNotEmpty() password: string; - - // @IsString() - // @IsEmail() - // @IsOptional() - // email: string; - - // @IsOptional() - // refreshToken?: string | null; } diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index cf54aae..02d575c 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -10,6 +10,7 @@ import { Req, UseInterceptors, UploadedFile, + ValidationPipe, } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { UsersService } from './users.service'; @@ -32,7 +33,9 @@ export class UsersController { constructor(private readonly usersService: UsersService) {} @Post() - createUser(@Body() createUserDto: CreateUserDto): Promise { + createUser( + @Body(new ValidationPipe()) createUserDto: CreateUserDto, + ): Promise { return this.usersService.createUser(createUserDto); } From e316b4db9645a00f76872e141b0f284586a1172d Mon Sep 17 00:00:00 2001 From: JinJung0101 Date: Sat, 17 Feb 2024 22:45:14 +0900 Subject: [PATCH 3/3] =?UTF-8?q?create-user.dto=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/users/dto/create-user.dto.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/users/dto/create-user.dto.ts b/src/users/dto/create-user.dto.ts index b66ea17..d478949 100644 --- a/src/users/dto/create-user.dto.ts +++ b/src/users/dto/create-user.dto.ts @@ -9,15 +9,15 @@ import { export class CreateUserDto { @IsString() @IsNotEmpty() - @MinLength(3, { message: '3글자 이상 입력해 주세요.' }) - @MaxLength(10, { message: '10글자 이내로 입력해 주세요.' }) + @MinLength(3, { message: '아이디를 3글자 이상 입력해 주세요.' }) + @MaxLength(10, { message: '아이디를 10글자 이내로 입력해 주세요.' }) @Matches(/^[A-Za-z0-9]*$/, { message: 'userId should not contain spaces or special characters', }) userId: string; @IsString() - @MinLength(4, { message: '4글자 이상 입력해 주세요.' }) + @MinLength(4, { message: '비밀번호를 4글자 이상 입력해 주세요.' }) @IsNotEmpty() password: string; }