Skip to content

Commit

Permalink
Merge pull request #75 from LocalMingle/dev
Browse files Browse the repository at this point in the history
[완료] 이미지 업로드 사이즈, 확장자 유효성 검사 + [작업 중] unit, integration test 작업들
  • Loading branch information
erickimme authored Oct 24, 2023
2 parents bd2b5aa + 23d3bc7 commit 05c9db9
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 6 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"jest": "^29.7.0",
"prettier": "^3.0.0",
"prisma": "^5.4.2",
"source-map-support": "^0.5.21",
Expand Down
166 changes: 163 additions & 3 deletions src/users/users.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,180 @@
// users.controller.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
// import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { UsersModule } from './users.module';
import { PrismaService } from '../prisma/prisma.service';

describe('UsersController', () => {
describe('UsersController unit test', () => {
// let app: INestApplication;
let controller: UsersController;

beforeEach(async () => {
// const userServiceTest = { findAll: () => ['test1', 'test2'] };
// console.log('userServiceTest:', userServiceTest);

let requestMock = {};
let responseMock = {};

beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [UsersController],
imports: [UsersModule],
providers: [UsersService],
}).compile();
})
// .overrideProvider(UsersService)
// .useValue(userServiceTest)
.compile();

controller = module.get<UsersController>(UsersController);
// app = module.createNestApplication();
// await app.init();
});

// jest test
it('should be defined', () => {
expect(controller).toBeDefined();
});

describe('Unit Tests', () => {

// 3. userId를 통한 유저 조회
// @Get(':id')
// @UseGuards(JwtAccessAuthGuard) // passport를 사용하여 인증 확인
// @ApiBearerAuth() // Swagger 문서에 Bearer 토큰 인증 추가
// @ApiOperation({ summary: 'ID로 회원 조회' })
// @ApiResponse({ status: 200, description: '유저 정보 조회 성공' })
// async findOne(@Param('id') id: string) {
// const user = this.usersService.findOne(+id);
// if (!user) {
// throw new NotFoundException('User does not exist');
// }
// return user;
// }
it('should return a status of 200', () => {
controller.findOne('1');
expect(controller.findOne('1')).toBe('1');
});
});

});

/*
// supertest
describe('User Signup Tests', () => {
const validUser = {
email: '[email protected]',
password: 'password',
confirmPassword: 'password',
nickname: 'nicknameDTO',
intro: 'introDTO',
};
// TestCase 01: 회원가입 테스트 - 유효한 CreateUserDto
it('should create a user if CreateUserDto is valid', async () => {
await request(app.getHttpServer())
.post('/users/signup')
.send(validUser)
.expect(201);
});
// TestCase 02: 회원가입 테스트 - 비밀번호와 비밀번호 확인이 일치하지 않을 때
it('should not create a user if password and confirmPassword do not match', async () => {
const invalidUser = { ...validUser, confirmPassword: 'wrongPassword' };
await request(app.getHttpServer())
.post('/users/signup')
.send(invalidUser)
.expect(400);
});
// TestCase 03: 회원가입 테스트 - 이메일 중복 테스트
it('should not create a user if email is invalid', async () => {
const invalidUser = { ...validUser, email: 'invalidEmail' };
await request(app.getHttpServer())
.post('/users/signup')
.send(invalidUser)
.expect(400);
});
// TestCase 04: 회원가입 테스트 - 닉네임 중복 테스트
it('should not create a user if nickname is already taken', async () => {
const invalidUser = { ...validUser, nickname: 'existingNickname' };
await request(app.getHttpServer())
.post('/users/signup')
.send(invalidUser)
.expect(400);
});
// TestCase 05: 회원가입 테스트 - 회원가입 성공 테스트 create(createUserDto: CreateUserDto)
it('should successfully create a user', async () => {
const newUser = {
email: '[email protected]',
password: 'newPassword',
confirmPassword: 'newPassword',
nickname: 'newNickname',
intro: 'newIntro',
};
await request(app.getHttpServer())
.post('/users/signup')
.send(newUser)
.expect(201);
});
});
describe('User Operations Tests', () => {
// TestCase 06: 사용자 ID로 사용자 조회 테스트 findOne(id: number)
it('should find a user by ID', async () => {
const userId = 1; // 예시 ID
await request(app.getHttpServer()).get(`/users/${userId}`).expect(200);
});
// TestCase 07: 유저 본인 조회 테스트 (users/me) findMe
it('should find the current user', async () => {
await request(app.getHttpServer()).get('/users/me').expect(200);
});
// TestCase 08: 유저 정보 수정 테스트 update(id: number, updateUserDto: UpdateUserDto)
it('should update user information', async () => {
const userId = 1; // 예시 ID
const updateUserDto = {
nickname: 'newNickname',
intro: 'newIntro',
};
await request(app.getHttpServer())
.put(`/users/${userId}`)
.send(updateUserDto)
.expect(200);
});
// TestCase 09: 회원 탈퇴 테스트 remove(userId: number, password: string)
it('should remove a user', async () => {
const userId = 1; // 예시 ID
const password = 'password'; // 예시 비밀번호
await request(app.getHttpServer())
.delete(`/users/${userId}`)
.send({ password })
.expect(200);
});
// TestCase 10: 사용자가 생성한 모임(Event) 리스트를 조회한다. findHostedEvents(id: number)
it('should find hosted events by user ID', async () => {
const userId = 1; // 예시 ID
await request(app.getHttpServer())
.get(`/users/${userId}/hosted-events`)
.expect(200);
});
// TestCase 11: 사용자가 참여한 모임(Event) 리스트를 조회한다. findJoinedEvents(id: number)
it('should find joined events by user ID', async () => {
const userId = 1; // 예시 ID
await request(app.getHttpServer())
.get(`/users/${userId}/joined-events`)
.expect(200);
});
});
afterAll(async () => {
await app.close();
});
*/
16 changes: 15 additions & 1 deletion src/users/users.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import { DeleteUserDto } from './dto/delete-user.dto';
import { ApiBearerAuth, ApiCreatedResponse, ApiOkResponse, ApiOperation, ApiResponse, ApiTags, ApiBody, ApiConsumes, ApiProperty } from '@nestjs/swagger';
import { UserEntity } from './entities/user.entity';
import { JwtAccessAuthGuard } from 'src/auth/guards/jwt-auth.guard';
// import { JwtAccessAuthGuard } from '../auth/guards/jwt-auth.guard';
import { User } from '@prisma/client';
import { AwsS3Service } from 'src/aws/aws.s3';
// import { AwsS3Service } from '../aws/aws.s3';
import { UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';

Expand Down Expand Up @@ -118,7 +120,6 @@ export class UsersController {
@ApiResponse({ status: 400, description: '중복된 닉네임입니다' })
@ApiResponse({ status: 401, description: '패스워드가 일치하지 않습니다' })
@ApiResponse({ status: 404, description: '유저 정보가 존재하지 않습니다' })

async update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
const user = await this.usersService.findOne(+id);
if (!user) {
Expand Down Expand Up @@ -197,6 +198,19 @@ export class UsersController {
throw new NotFoundException('User does not exist');
}

// 이미지 파일 Validation 체크
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
const SUPPORTED_FILE_TYPES = ["image/jpeg", "image/png", "image/gif"];
if (!file) {
throw new NotFoundException('이미지 파일을 선택해주세요.');
}
if (file.size > MAX_FILE_SIZE) {
throw new NotFoundException('파일 크기는 5MB를 초과할 수 없습니다.');
}
if (!SUPPORTED_FILE_TYPES.includes(file.mimetype)) {
throw new NotFoundException('지원되는 파일 형식은 JPEG, PNG, GIF 뿐입니다.');
}

// 이미지를 s3에 업로드한다.
const uploadedFile = await this.awsS3Service.uploadFile(file) as { Location: string };

Expand Down
3 changes: 3 additions & 0 deletions src/users/users.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { PrismaModule } from 'src/prisma/prisma.module';
// import { PrismaModule } from '../prisma/prisma.module';
import { AwsModule } from 'src/aws/aws.module';
import { AwsS3Service } from 'src/aws/aws.s3';
// import { AwsModule } from '../aws/aws.module';
// import { AwsS3Service } from '../aws/aws.s3';

@Module({
controllers: [UsersController],
Expand Down
13 changes: 13 additions & 0 deletions src/users/users.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,17 @@ describe('UsersService', () => {
it('should be defined', () => {
expect(service).toBeDefined();
});

it('TC06: should not create a user if email is invalid', async () => {
const createUserDto = { email: 'invalidEmail' };
await expect(service.create(createUserDto)).rejects.toThrow();
});

it('TC06: should not create a user if password and confirmPassword do not match', async () => {
const createUserDto = {
password: 'password1',
confirmPassword: 'password2' /* ... */,
};
await expect(service.create(createUserDto)).rejects.toThrow();
});
});
1 change: 1 addition & 0 deletions src/users/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { PrismaService } from 'src/prisma/prisma.service';
import * as bcrypt from 'bcrypt';
import { User, UserDetail } from '@prisma/client';
import { IUsersServiceFindByEmail, IUsersServiceFindByNickname } from './interfaces/users-service.interface';
// import { PrismaService } from '../prisma/prisma.service';



Expand Down

0 comments on commit 05c9db9

Please sign in to comment.