diff --git a/server/src/cartItems/web/cartItem-remove.controller.test.ts b/server/src/cartItems/web/cartItem-remove.controller.test.ts index 6b6beab..5271444 100644 --- a/server/src/cartItems/web/cartItem-remove.controller.test.ts +++ b/server/src/cartItems/web/cartItem-remove.controller.test.ts @@ -19,7 +19,7 @@ describe('cartItemSave Controller', () => { context('사용자가 장바구니에 카트 id 입력하면', () => { it('200 상태코드를 반환한다.', async () => { - const { status, body } = await request(app).delete(`/cart/${existingCartItem.id}`); + const { status, body } = await request(app).delete(`/carts/${existingCartItem.id}`); expect(status).toBe(200); expect(body).toEqual(true); @@ -34,7 +34,7 @@ describe('cartItemSave Controller', () => { }); it('400 상태코드와 에러 메세지를 반환한다.', async () => { - const { status, body } = await request(app).delete(`/cart/${nonExistingCartItem.id}`); + const { status, body } = await request(app).delete(`/carts/${nonExistingCartItem.id}`); expect(status).toBe(400); expect(body).toEqual({ diff --git a/server/src/cartItems/web/cartItem-save.controller.test.ts b/server/src/cartItems/web/cartItem-save.controller.test.ts index 099aef0..6773dbc 100644 --- a/server/src/cartItems/web/cartItem-save.controller.test.ts +++ b/server/src/cartItems/web/cartItem-save.controller.test.ts @@ -12,14 +12,14 @@ import { addToCart } from '../application/cartItem-save.service'; jest.mock('../application/cartItem-save.service.ts'); describe('cartItemSave Controller', () => { - describe('POST /cart', () => { + describe('POST /carts', () => { beforeEach(() => { (addToCart as jest.Mock).mockResolvedValue(true); }); context('사용자가 장바구니에 도서와 수량을 추가하면', () => { it('201 상태코드를 반환한다.', async () => { - const { status, body } = await request(app).post('/cart').send({ + const { status, body } = await request(app).post('/carts').send({ userId: existingCartItem.userId, bookId: existingCartItem.bookId, count: existingCartItem.count, @@ -38,7 +38,7 @@ describe('cartItemSave Controller', () => { }); it('400 상태코드와 에러 메세지를 반환한다.', async () => { - const { status, body } = await request(app).post('/cart').send({ + const { status, body } = await request(app).post('/carts').send({ userId: nonExistingCartItem.userId, bookId: nonExistingCartItem.bookId, count: nonExistingCartItem.count, diff --git a/server/src/fixture/jwt.fixture.ts b/server/src/fixture/jwt.fixture.ts new file mode 100644 index 0000000..24d1c19 --- /dev/null +++ b/server/src/fixture/jwt.fixture.ts @@ -0,0 +1,2 @@ +export const ACCESS_TOKEN = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjMsImVtYWlsIjoiYWJjZGVAZ21haWwuY29tIiwiaWF0IjoxNzEwNDIzODUxLCJleHAiOjE3MTA0MjQxNTF9.m1GUUsCHpMtaX3jScLJ-GACfZ_BEUQUnyMxrq_bg5FQ'; diff --git a/server/src/likes/application/add-like.service.test.ts b/server/src/likes/application/add-like.service.test.ts index 7c2f85d..9b8ac4a 100644 --- a/server/src/likes/application/add-like.service.test.ts +++ b/server/src/likes/application/add-like.service.test.ts @@ -6,34 +6,36 @@ import { existingLike, nonExistingLike } from 'src/fixture/likes.fixture'; import { when } from 'jest-when'; -import Like from '../domain/like'; +import { validateToken } from 'src/users/jwt/jwt.provider'; + +import { ACCESS_TOKEN } from 'src/fixture/jwt.fixture'; + import { save } from '../domain/likes.repository'; import { addLike } from './add-like.service'; jest.mock('../domain/likes.repository.ts'); +jest.mock('../../users/jwt/jwt.provider.ts'); describe('addLike Service', () => { beforeEach(() => { - when(save as jest.Mock) - .calledWith( - new Like({ - userId: existingLike.userId, - likedBookId: existingLike.likedBookId, - }), - ) - .mockResolvedValue(true); + when(validateToken as jest.Mock).mockResolvedValue({ userId: existingLike.userId }); + when(save as jest.Mock).mockResolvedValue(true); }); + context('사용자 id와 도서 정보 id가 좋아요 추가에 성공하면', () => { it('true를 반환한다.', async () => { - const savedLike = await addLike(existingLike.userId, existingLike.likedBookId); + const savedLike = await addLike(ACCESS_TOKEN, existingLike.likedBookId); expect(savedLike).toBe(true); }); }); context('사용자 id와 도서 정보 id가 좋아요 추가에 실패하면', () => { + beforeEach(() => { + when(save as jest.Mock).mockResolvedValue(false); + }); it('error를 던져야 한다.', async () => { - await expect(addLike(nonExistingLike.userId, nonExistingLike.likedBookId)).rejects.toThrow( + await expect(addLike(ACCESS_TOKEN, nonExistingLike.likedBookId)).rejects.toThrow( new HttpException('좋아요 추가에 실패했습니다.', StatusCodes.BAD_REQUEST), ); }); diff --git a/server/src/likes/application/add-like.service.ts b/server/src/likes/application/add-like.service.ts index 730f7fb..a62ff3d 100644 --- a/server/src/likes/application/add-like.service.ts +++ b/server/src/likes/application/add-like.service.ts @@ -1,17 +1,15 @@ -import { StatusCodes } from 'http-status-codes'; +import { validateToken } from 'src/users/jwt/jwt.provider'; + import HttpException from 'src/utils/httpException'; -import { validateToken } from 'src/users/jwt/jwt.provider'; +import { StatusCodes } from 'http-status-codes'; -import Like from '../domain/like'; import { save } from '../domain/likes.repository'; export const addLike = async (accessToken: any, likedBookId: number): Promise => { const { userId } = validateToken(accessToken); - const like = new Like({ userId, likedBookId }); - const likeData = like.getDataOfLike(); - const savedLike = await save(likeData); + const savedLike = await save({ userId, likedBookId }); if (!savedLike) { throw new HttpException('좋아요 추가에 실패했습니다.', StatusCodes.BAD_REQUEST); } diff --git a/server/src/likes/application/cancel-like.service.test.ts b/server/src/likes/application/cancel-like.service.test.ts index 19e9944..542a7f1 100644 --- a/server/src/likes/application/cancel-like.service.test.ts +++ b/server/src/likes/application/cancel-like.service.test.ts @@ -6,28 +6,35 @@ import { existingLike, nonExistingLike } from 'src/fixture/likes.fixture'; import { when } from 'jest-when'; +import { ACCESS_TOKEN } from 'src/fixture/jwt.fixture'; + +import { validateToken } from 'src/users/jwt/jwt.provider'; + import { deleteByUserIdAndLikedBookId } from '../domain/likes.repository'; import { cancelLike } from './cancel-like.service'; jest.mock('../domain/likes.repository.ts'); +jest.mock('../../users/jwt/jwt.provider.ts'); describe('cancelLike Service', () => { beforeEach(() => { - when(deleteByUserIdAndLikedBookId as jest.Mock) - .calledWith(existingLike.userId, existingLike.likedBookId) - .mockResolvedValue(true); + when(validateToken as jest.Mock).mockResolvedValue({ userId: existingLike.userId }); + when(deleteByUserIdAndLikedBookId as jest.Mock).mockResolvedValue(true); }); context('사용자 id와 도서 정보 id가 좋아요 취소에 성공하면', () => { it('true를 반환한다.', async () => { - const canceledLike = await cancelLike(existingLike.userId, existingLike.likedBookId); + const canceledLike = await cancelLike(ACCESS_TOKEN, existingLike.likedBookId); expect(canceledLike).toBe(true); }); }); context('사용자 id와 도서 정보 id가 좋아요 취소에 실패하면', () => { + beforeEach(() => { + when(deleteByUserIdAndLikedBookId as jest.Mock).mockResolvedValue(false); + }); it('error를 던져야 한다.', async () => { - await expect(cancelLike(nonExistingLike.userId, nonExistingLike.likedBookId)).rejects.toThrow( + await expect(cancelLike(ACCESS_TOKEN, nonExistingLike.likedBookId)).rejects.toThrow( new HttpException('좋아요 취소에 실패했습니다.', StatusCodes.BAD_REQUEST), ); }); diff --git a/server/src/likes/application/cancel-like.service.ts b/server/src/likes/application/cancel-like.service.ts index 1eb73bb..287edc2 100644 --- a/server/src/likes/application/cancel-like.service.ts +++ b/server/src/likes/application/cancel-like.service.ts @@ -1,10 +1,14 @@ import { StatusCodes } from 'http-status-codes'; import HttpException from 'src/utils/httpException'; +import { validateToken } from 'src/users/jwt/jwt.provider'; + import { deleteByUserIdAndLikedBookId } from '../domain/likes.repository'; -export const cancelLike = async (userId: number, likedBookId: number): Promise => { +export const cancelLike = async (accessToken: any, likedBookId: number): Promise => { + const { userId } = validateToken(accessToken); const canceledLike = await deleteByUserIdAndLikedBookId(userId, likedBookId); + if (!canceledLike) { throw new HttpException('좋아요 취소에 실패했습니다.', StatusCodes.BAD_REQUEST); } diff --git a/server/src/likes/web/cancel-like.controller.test.ts b/server/src/likes/web/cancel-like.controller.test.ts index 0d755d2..aa79bc6 100644 --- a/server/src/likes/web/cancel-like.controller.test.ts +++ b/server/src/likes/web/cancel-like.controller.test.ts @@ -19,7 +19,10 @@ describe('cancelLike Controller', () => { it('200 상태코드를 반환한다.', async () => { const { statusCode, body } = await request(app) .delete(`/likes/${existingLike.likedBookId}`) - .send({ userId: existingLike.userId }); + .set( + 'Authorization', + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjMsImVtYWlsIjoiYWJjZGVAZ21haWwuY29tIiwiaWF0IjoxNzEwNDIzODUxLCJleHAiOjE3MTA0MjQxNTF9.m1GUUsCHpMtaX3jScLJ-GACfZ_BEUQUnyMxrq_bg5FQ', + ); expect(statusCode).toBe(200); expect(body).toBe(true); @@ -35,7 +38,10 @@ describe('cancelLike Controller', () => { it('400 상태코드와 에러 메세지를 반환한다.', async () => { const { statusCode, body } = await request(app) .delete(`/likes/${nonExistingLike.likedBookId}`) - .send({ userId: nonExistingLike.userId }); + .set( + 'Authorization', + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjMsImVtYWlsIjoiYWJjZGVAZ21haWwuY29tIiwiaWF0IjoxNzEwNDIzODUxLCJleHAiOjE3MTA0MjQxNTF9.m1GUUsCHpMtaX3jScLJ-GACfZ_BEUQUnyMxrq_bg5FQ', + ); expect(statusCode).toBe(400); expect(body).toEqual({ diff --git a/server/src/likes/web/cancel-like.controller.ts b/server/src/likes/web/cancel-like.controller.ts index ca39036..ed1c6b3 100644 --- a/server/src/likes/web/cancel-like.controller.ts +++ b/server/src/likes/web/cancel-like.controller.ts @@ -5,8 +5,9 @@ import { StatusCodes } from 'http-status-codes'; import { cancelLike } from '../application/cancel-like.service'; -const cancelLikeHandler = ({ params: { id }, body: { userId } }: Request, res: Response) => { - ResponseHandler(() => cancelLike(userId, Number(id)), StatusCodes.OK, res); +const cancelLikeHandler = ({ params: { id }, headers }: Request, res: Response) => { + const accessToken = headers.authorization; + ResponseHandler(() => cancelLike(accessToken, Number(id)), StatusCodes.OK, res); }; export default cancelLikeHandler; diff --git a/server/src/orders/web/orders-detail.controller.test.ts b/server/src/orders/web/orders-detail.controller.test.ts index 6ac5ef6..40232fa 100644 --- a/server/src/orders/web/orders-detail.controller.test.ts +++ b/server/src/orders/web/orders-detail.controller.test.ts @@ -6,31 +6,8 @@ describe('getOrdersDetailHandler', () => { context('주문 상세 상품 조회가 성공하면', () => { it('상태코드 200과 응답 정보를 반환한다.', async () => { const { status, body } = await request(app).get('/orders/1'); - expect(status).toBe(200); - expect(body).toEqual([ - { - bookId: 1, - bookTitle: '홍길동전', - author: '작가미상', - price: 8000, - count: 2, - }, - { - bookId: 2, - bookTitle: '러닝 리액트', - author: '알렉스 뱅크스', - price: 25000, - count: 1, - }, - { - bookId: 3, - bookTitle: '우아한 타입스크립트 with 리액트', - author: '우아한형제들 웹프론트그룹 지음', - price: 22500, - count: 10, - }, - ]); + expect(body).toEqual([{ author: '걍구두', bookId: 2, bookTitle: '신델렐라', price: 20000, quantity: 3 }]); }); }); }); diff --git a/server/src/orders/web/orders-list.controller.test.ts b/server/src/orders/web/orders-list.controller.test.ts index a076a3e..0769339 100644 --- a/server/src/orders/web/orders-list.controller.test.ts +++ b/server/src/orders/web/orders-list.controller.test.ts @@ -10,16 +10,22 @@ describe('getAllOrdersHandler Controller', () => { expect(status).toBe(200); expect(body).toEqual([ { + address: '강원도 춘천시 동내면 대룡산길 227-314 24408 한국', + bookTitle: '어린왕자', + contact: '010-1234-5667', orderId: 1, - createAt: expect.any(String), - delivery: { - address: '서울시 경인로', - receiver: '홍길동', - contact: '010-1234-5667', - }, - bookTitle: '홍길동전', - totalPrice: 25000, - totalCount: 5, + receiver: '홍길동', + totalPrice: 6000, + totalQuantity: 3, + }, + { + address: '강원도 춘천시 동내면 대룡산길 227-314 24408 한국', + bookTitle: '어린왕자', + contact: '010-1234-5667', + orderId: 2, + receiver: '홍길동', + totalPrice: 6000, + totalQuantity: 3, }, ]); }); diff --git a/server/src/orders/web/orders-save.controller.test.ts b/server/src/orders/web/orders-save.controller.test.ts index fb23d7d..58ee9eb 100644 --- a/server/src/orders/web/orders-save.controller.test.ts +++ b/server/src/orders/web/orders-save.controller.test.ts @@ -3,7 +3,7 @@ import request from 'supertest'; import { order } from '../application/orders-save.service'; -jest.mock('../application/order-save.service.ts'); +jest.mock('../application/orders-save.service.ts'); describe('saveOrdersHandler', () => { describe('POST /orders', () => { @@ -36,7 +36,7 @@ describe('saveOrdersHandler', () => { totalPrice: 50000, }); - expect(status).toBe(200); + expect(status).toBe(201); expect(body).toEqual('주문 등록 완료'); }); }); diff --git a/server/src/users/jwt/jwt.provider.ts b/server/src/users/jwt/jwt.provider.ts index 8c053a7..c2fd566 100644 --- a/server/src/users/jwt/jwt.provider.ts +++ b/server/src/users/jwt/jwt.provider.ts @@ -22,9 +22,11 @@ export const validateToken = (token: string) => { } try { - const decodedJwt = jwt.verify(token, process.env.JWT_SECRET as Secret) as jwt.JwtPayload; + const { userId } = jwt.verify(token, process.env.JWT_SECRET as Secret) as jwt.JwtPayload; - return decodedJwt; + return { + userId, + }; } catch (e) { throw new HttpException('인증 할 수 없는 token 입니다', StatusCodes.UNAUTHORIZED); } diff --git a/server/src/users/signin/web/signin.controller.test.ts b/server/src/users/signin/web/signin.controller.test.ts index 834a02f..2b4abc0 100644 --- a/server/src/users/signin/web/signin.controller.test.ts +++ b/server/src/users/signin/web/signin.controller.test.ts @@ -27,7 +27,9 @@ describe('signin Controller', () => { }); expect(statusCode).toBe(200); - expect(body).toBe(ACCESS_TOKEN); + expect(body).toEqual({ + token: ACCESS_TOKEN, + }); }); });