Skip to content

Commit

Permalink
Merge pull request #228 from boostcampwm-2024/test/admin-api
Browse files Browse the repository at this point in the history
✅ test:  admin 로그인, admin 회원가입, sessionId 확인 API 테스트 코드 작성
  • Loading branch information
CodeVac513 authored Dec 3, 2024
2 parents ade223f + 9e0f5be commit aa76657
Show file tree
Hide file tree
Showing 8 changed files with 337 additions and 5 deletions.
2 changes: 1 addition & 1 deletion server/src/admin/admin.api-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function ApiPostRegisterAdmin() {
ApiConflictResponse({
description: 'Conflict',
example: {
message: '이미 존재하는 계정입니다.',
message: '이미 존재하는 아이디입니다.',
},
}),
ApiUnauthorizedResponse({
Expand Down
8 changes: 4 additions & 4 deletions server/src/admin/admin.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class AdminService {
private readonly SESSION_TTL = 60 * 60 * 12;

constructor(
private readonly loginRepository: AdminRepository,
private readonly adminRepository: AdminRepository,
private readonly redisService: RedisService,
) {}

Expand All @@ -30,7 +30,7 @@ export class AdminService {
const cookie = request.cookies['sessionId'];
const { loginId, password } = loginAdminDto;

const admin = await this.loginRepository.findOne({
const admin = await this.adminRepository.findOne({
where: { loginId },
});

Expand Down Expand Up @@ -95,7 +95,7 @@ export class AdminService {
async registerAdmin(registerAdminDto: RegisterAdminDto) {
let { loginId, password } = registerAdminDto;

const existingAdmin = await this.loginRepository.findOne({
const existingAdmin = await this.adminRepository.findOne({
where: { loginId },
});

Expand All @@ -106,6 +106,6 @@ export class AdminService {
const saltRounds = 10;
password = await bcrypt.hash(password, saltRounds);

return this.loginRepository.registerAdmin({ loginId, password });
return this.adminRepository.registerAdmin({ loginId, password });
}
}
37 changes: 37 additions & 0 deletions server/test/admin/dto/login-admin.dto.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { LoginAdminDto } from '../../../src/admin/dto/login-admin.dto';
import { validate } from 'class-validator';

describe('LoginAdminDto Test', () => {
let loginAdminDto: LoginAdminDto;

beforeEach(() => {
loginAdminDto = new LoginAdminDto();
});

it('ID에 null이 입력되면 유효성 검사에 실패한다.', async () => {
//given
loginAdminDto.loginId = null;
loginAdminDto.password = 'testAdminPassword';

//when
const errors = await validate(loginAdminDto);

//then
expect(errors).toHaveLength(1);
expect(errors[0].constraints).toHaveProperty('isNotEmpty');
expect(errors[0].constraints).toHaveProperty('isString');
});
it('패스워드에 null이 입력되면 유효성 검사에 실패한다.', async () => {
//given
loginAdminDto.loginId = 'testAdminId';
loginAdminDto.password = null;

//when
const errors = await validate(loginAdminDto);

//then
expect(errors).toHaveLength(1);
expect(errors[0].constraints).toHaveProperty('isNotEmpty');
expect(errors[0].constraints).toHaveProperty('isString');
});
});
76 changes: 76 additions & 0 deletions server/test/admin/dto/register-admin.dto.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { RegisterAdminDto } from '../../../src/admin/dto/register-admin.dto';
import { validate } from 'class-validator';

describe('LoginAdminDto Test', () => {
let registerAdminDto: RegisterAdminDto;

beforeEach(() => {
registerAdminDto = new RegisterAdminDto();
});

it('ID의 길이가 6 이상, 255 이하가 아니라면 유효성 검사에 실패한다.', async () => {
//given
registerAdminDto.loginId = 'test';
registerAdminDto.password = 'testAdminPassword!';

//when
const errors = await validate(registerAdminDto);

//then
expect(errors).toHaveLength(1);
expect(errors[0].constraints).toHaveProperty('isLength');
});

it('패스워드의 길이가 6 이상, 60 이하가 아니라면 유효성 검사에 실패한다.', async () => {
//given
registerAdminDto.loginId = 'testId';
registerAdminDto.password = 'test';

//when
const errors = await validate(registerAdminDto);

//then
expect(errors).toHaveLength(1);
expect(errors[0].constraints).toHaveProperty('isLength');
});

it('패스워드에 특수문자가 하나 이상 없다면 유효성 검사에 실패한다.', async () => {
//given
registerAdminDto.loginId = 'testAdminId';
registerAdminDto.password = 'testAdminPassword';

//when
const errors = await validate(registerAdminDto);

//then
expect(errors).toHaveLength(1);
expect(errors[0].constraints).toHaveProperty('matches');
});

it('ID에 null이 입력되면 유효성 검사에 실패한다.', async () => {
//given
registerAdminDto.loginId = null;
registerAdminDto.password = 'testAdminPassword!';

//when
const errors = await validate(registerAdminDto);

//then
expect(errors).toHaveLength(1);
expect(errors[0].constraints).toHaveProperty('isString');
});

it('패스워드에 null이 입력되면 유효성 검사에 실패한다.', async () => {
//given
registerAdminDto.loginId = 'testAdminId';
registerAdminDto.password = null;

//when
const errors = await validate(registerAdminDto);

//then
expect(errors).toHaveLength(1);
expect(errors[0].constraints).toHaveProperty('isString');
expect(errors[0].constraints).toHaveProperty('matches');
});
});
66 changes: 66 additions & 0 deletions server/test/admin/login.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { INestApplication } from '@nestjs/common';
import { AdminService } from '../../src/admin/admin.service';
import { LoginAdminDto } from '../../src/admin/dto/login-admin.dto';
import * as request from 'supertest';
import { RegisterAdminDto } from '../../src/admin/dto/register-admin.dto';
describe('POST api/admin/login E2E Test', () => {
let app: INestApplication;
let adminService: AdminService;
const registerAdminDto: RegisterAdminDto = {
loginId: 'testAdminId',
password: 'testAdminPassword!',
};

beforeAll(async () => {
app = global.testApp;
adminService = app.get(AdminService);
await adminService.registerAdmin(registerAdminDto);
});
it('등록된 계정이면 정상적으로 로그인할 수 있다.', async () => {
//given
const loginAdminDto: LoginAdminDto = {
loginId: 'testAdminId',
password: 'testAdminPassword!',
};

//when
const response = await request(app.getHttpServer())
.post('/api/admin/login')
.send(loginAdminDto);

//then
expect(response.status).toBe(200);
expect(response.headers['set-cookie'][0]).toContain('sessionId=');
});

it('등록되지 않은 ID로 로그인을 시도하면 401 UnAuthorized 예외가 발생한다.', async () => {
//given
const loginWrongAdminIdDto: LoginAdminDto = {
loginId: 'testWrongAdminId',
password: 'testAdminPassword!',
};

//when
const response = await request(app.getHttpServer())
.post('/api/admin/login')
.send(loginWrongAdminIdDto);

//then
expect(response.status).toBe(401);
});

it('비밀번호가 다르다면 401 UnAuthorized 예외가 발생한다.', async () => {
//given
const loginWrongAdminPasswordDto: LoginAdminDto = {
loginId: 'testAdminId',
password: 'testWrongAdminPassword!',
};
//when
const response = await request(app.getHttpServer())
.post('/api/admin/login')
.send(loginWrongAdminPasswordDto);

//then
expect(response.status).toBe(401);
});
});
73 changes: 73 additions & 0 deletions server/test/admin/register.e2e.spect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { INestApplication } from '@nestjs/common';
import { AdminService } from '../../src/admin/admin.service';
import { LoginAdminDto } from '../../src/admin/dto/login-admin.dto';
import { RegisterAdminDto } from '../../src/admin/dto/register-admin.dto';
import * as request from 'supertest';

describe('POST api/admin/register E2E Test', () => {
let app: INestApplication;
let adminService: AdminService;

//given
const loginAdminDto: LoginAdminDto = {
loginId: 'testAdminId',
password: 'testAdminPassword!',
};
const registerAdminDto: RegisterAdminDto = {
loginId: 'testNewAdminId',
password: 'testNewAdminPassword!',
};

beforeAll(async () => {
app = global.testApp;
adminService = app.get(AdminService);

await adminService.registerAdmin(loginAdminDto);
});

it('관리자가 로그인되어 있으면 다른 관리자 계정 회원가입을 할 수 있다.', async () => {
//given
const agent = request.agent(app.getHttpServer());

//when
await agent.post('/api/admin/login').send(loginAdminDto);
const response = await agent
.post('/api/admin/register')
.send(registerAdminDto);

//then
expect(response.status).toBe(201);
});

it('이미 가입한 ID를 입력하면 관리자 계정을 생성할 수 없다.', async () => {
//given
const agent = request.agent(app.getHttpServer());

//when
await agent.post('/api/admin/login').send(loginAdminDto);
const response = await agent
.post('/api/admin/register')
.send(registerAdminDto);

//then
expect(response.status).toBe(409);
});

it('관리자가 로그아웃 상태면 401 UnAuthorized 예외가 발생한다.', async () => {
//given
const registerAdminDto: RegisterAdminDto = {
loginId: 'testNewAdminId',
password: 'testNewAdminPassword!',
};

const agent = request.agent(app.getHttpServer());

//when
const response = await agent
.post('/api/admin/register')
.send(registerAdminDto);

//then
expect(response.status).toBe(401);
});
});
58 changes: 58 additions & 0 deletions server/test/admin/sessionId.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { INestApplication } from '@nestjs/common';
import { AdminService } from '../../src/admin/admin.service';
import { LoginAdminDto } from '../../src/admin/dto/login-admin.dto';
import * as request from 'supertest';
import { v4 as uuidv4 } from 'uuid';

describe('GET api/admin/sessionId E2E Test', () => {
let app: INestApplication;
let adminService: AdminService;

//given
const loginAdminDto: LoginAdminDto = {
loginId: 'testAdminId',
password: 'testAdminPassword!',
};

beforeAll(async () => {
app = global.testApp;
adminService = app.get(AdminService);

await adminService.registerAdmin(loginAdminDto);
});

it('쿠키의 session id가 유효하다면 관리자를 로그인 상태로 취급한다.', async () => {
//given
const agent = request.agent(app.getHttpServer());

//when
await agent.post('/api/admin/login').send(loginAdminDto);
const response = await agent.get('/api/admin/sessionId');

//then
expect(response.status).toBe(200);
});

it('session id가 일치하지 않는다면 401 UnAuthorized 예외가 발생한다.', async () => {
//given
const randomUUID = uuidv4();

//when
const response = await request(app.getHttpServer())
.get('/api/admin/sessionId')
.set('Cookie', [`sessionId=${randomUUID}`]);

//then
expect(response.status).toBe(401);
});

it('session id가 없다면 401 UnAuthorized 예외가 발생한다.', async () => {
//when
const response = await request(app.getHttpServer())
.get('/api/admin/sessionId')
.set('Cookie', [`sessionId=`]);

//then
expect(response.status).toBe(401);
});
});
22 changes: 22 additions & 0 deletions server/test/feed/fixture/feedFixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Feed } from '../../../src/feed/feed.entity';
import { RssAccept } from '../../../src/rss/rss.entity';

export class FeedFixture {
static readonly GENERAL_FEED = {
title: `Test Feed `,
createdAt: new Date(),
path: `http://test.com/post/`,
thumbnail: `http://test.com/thumbnail/`,
viewCount: 0,
};

static createFeedFixture(
blog: RssAccept,
overwrites: Partial<Feed> = {},
): Feed {
const feed = new Feed();
Object.assign(feed, { ...this.GENERAL_FEED, blog });
Object.assign(feed, overwrites);
return feed;
}
}

0 comments on commit aa76657

Please sign in to comment.