Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[13팀 김보영] [Chapter 2-2] 디자인 패턴과 함수형 프로그래밍 #31

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
26e2948
:recycle: refactor: cartUtils 분리
BoYoung00 Jan 12, 2025
b8e06ea
♻ refactor: useProducts 분리
BoYoung00 Jan 12, 2025
2be6772
♻ refactor: useCoupons 분리
BoYoung00 Jan 12, 2025
cad67a4
♻ refactor: useCart 분리
BoYoung00 Jan 12, 2025
aca5b45
:sparkles: feat: localStorage로 장바구니 관리 기능 추가
BoYoung00 Jan 13, 2025
df45ebf
♻ refactor: useDiscountCalculator 분리
BoYoung00 Jan 13, 2025
cda7c8e
:white_check_mark: useDiscountCalculator에 맞게 test 수정
BoYoung00 Jan 13, 2025
7ca3745
♻ refactor: 상품 추가 컴포넌트 분리
BoYoung00 Jan 14, 2025
505c04f
♻ refactor: ProductToggleButton 분리
BoYoung00 Jan 15, 2025
e6cd1dc
♻ refactor: 폴더 구조 수정
BoYoung00 Jan 15, 2025
0ad7261
♻ refactor: InputField 분리
BoYoung00 Jan 15, 2025
5ffef0f
♻ refactor: UpdateProductForm 분리
BoYoung00 Jan 15, 2025
720ce66
♻ refactor: ProductDetails 분리
BoYoung00 Jan 15, 2025
943462d
♻ refactor: ProductToggleButton 구조 개선 (자식 컴포넌트 분리 및 사용)
BoYoung00 Jan 15, 2025
9ed385a
♻ refactor: 파일 위치 수정
BoYoung00 Jan 15, 2025
a52970e
♻ refactor: AddNewProduct 구조 개선 (InputField 사용)
BoYoung00 Jan 15, 2025
eead67c
♻ refactor: ProductToggleButton 훅 분리
BoYoung00 Jan 15, 2025
ff1373d
♻ refactor: 쿠폰 관리 컴포넌트 분리
BoYoung00 Jan 16, 2025
84046e0
♻ refactor: cart 유틸 함수 분리
BoYoung00 Jan 16, 2025
96276e2
♻ refactor: CartPage 구조 개선 (유틸 함수 사용)
BoYoung00 Jan 16, 2025
8488861
♻ refactor: ProductList 분리
BoYoung00 Jan 16, 2025
b309519
♻ refactor: CartSummary 분리
BoYoung00 Jan 16, 2025
1038e27
♻ refactor: CartPage 구조 개선 (자식 컴포넌트 분리 및 사용)
BoYoung00 Jan 16, 2025
27da60d
Merge branch 'hanghae-plus:main' into main
BoYoung00 Jan 16, 2025
0d30ebc
🔧 chore: jsdom
BoYoung00 Jan 16, 2025
012bdf1
:bulb: docs: 주석 제거
BoYoung00 Jan 16, 2025
d3b4f4e
:white_check_mark: test: useCart, 유틸 함수 테스트 추가
BoYoung00 Jan 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"eslint": "^9.12.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.12",
"jsdom": "^26.0.0",
"typescript": "^5.6.3",
"vite": "^5.4.9",
"vitest": "^2.1.3"
Expand Down
95 changes: 86 additions & 9 deletions src/advanced/__tests__/advanced.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useState } from "react";
import { describe, expect, test } from 'vitest';
import { act, fireEvent, render, screen, within } from '@testing-library/react';
import { CartPage } from '../../refactoring/components/CartPage';
import { AdminPage } from "../../refactoring/components/AdminPage";
import { act, fireEvent, render, renderHook, screen, within } from '@testing-library/react';
import { Coupon, Product } from '../../types';
import { AdminPage } from "../../origin/components/AdminPage";
import { CartPage } from "../../origin/components/CartPage";
import { useCart } from "../../refactoring/pages/cart/hooks/useCart";
import { getAppliedDiscount, getMaxDiscount, getRemainingStock } from "../../refactoring/pages/cart/models/cart";

const mockProducts: Product[] = [
{
Expand Down Expand Up @@ -232,13 +234,88 @@ describe('advanced > ', () => {
})

describe('자유롭게 작성해보세요.', () => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

직접 테스트 코드 작성하는 거 좋네요bb

test('새로운 유틸 함수를 만든 후에 테스트 코드를 작성해서 실행해보세요', () => {
expect(true).toBe(false);
})
test('useCart hook 테스트: 로컬 스토리지 사용', () => {
const mockProduct: Product = {
id: 'p1',
name: '상품1',
price: 10000,
stock: 10,
discounts: [],
};

const { result } = renderHook(() => useCart({ useLocalStorage: true }));

// 장바구니에 아이템 추가
act(() => {
result.current.addToCart(mockProduct);
});

let cart = result.current.cart;
expect(cart).toHaveLength(1);
expect(cart[0].product.id).toBe('p1');
expect(cart[0].quantity).toBe(1);

// 수량 업데이트
act(() => {
result.current.updateQuantity('p1', 5);
});

cart = result.current.cart;
expect(cart[0].quantity).toBe(5);

// 로컬 스토리지 확인
const storedCart = JSON.parse(localStorage.getItem('cart') || '[]');
expect(storedCart).toHaveLength(1);
expect(storedCart[0].product.id).toBe('p1');
expect(storedCart[0].quantity).toBe(5);

// 아이템 삭제
act(() => {
result.current.removeFromCart('p1');
});

cart = result.current.cart;
expect(cart).toHaveLength(0);

// 로컬 스토리지 확인
const updatedStoredCart = JSON.parse(localStorage.getItem('cart') || '[]');
expect(updatedStoredCart).toHaveLength(0);
});

test('새로운 hook 함수르 만든 후에 테스트 코드를 작성해서 실행해보세요', () => {
expect(true).toBe(false);
})
test("getMaxDiscount: 최대 할인율 반환", () => {
const discounts = [
{ quantity: 5, rate: 0.05 },
{ quantity: 10, rate: 0.1 },
{ quantity: 15, rate: 0.2 },
];

expect(getMaxDiscount(discounts)).toBe(0.2);
});

test("getAppliedDiscount: 적용 가능한 할인율 반환", () => {
const item = {
product: {
id: "p1",
name: "상품 1",
price: 100,
stock: 10,
discounts: [
{ quantity: 5, rate: 0.05 },
{ quantity: 10, rate: 0.1 },
],
},
quantity: 7,
};

expect(getAppliedDiscount(item)).toBe(0.05);
});

test("getRemainingStock: 남은 재고 계산", () => {
const product = { id: "p1", name: "상품 1", price: 100, stock: 10, discounts: [] };
const cart = [{ product, quantity: 3 }];

expect(getRemainingStock(product, cart)).toBe(7);
});
})
})

32 changes: 17 additions & 15 deletions src/basic/__tests__/basic.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import {
screen,
within,
} from "@testing-library/react";
import { CartPage } from "../../refactoring/components/CartPage";
import { AdminPage } from "../../refactoring/components/AdminPage";
import { CartItem, Coupon, Product } from "../../types";
import { useCart, useCoupons, useProducts } from "../../refactoring/hooks";
import * as cartUtils from "../../refactoring/models/cart";
import { useCoupons, useProducts } from "../../refactoring/hooks";
import { AdminPage } from "../../origin/components/AdminPage";
import { CartPage } from "../../origin/components/CartPage";
import { useDiscountCalculator } from "../../refactoring/pages/cart/hooks/useDiscountCalculator";
import { useCart } from "../../refactoring/pages/cart/hooks/useCart";
import * as cartUtils from "../../refactoring/pages/cart/models/cart";

const mockProducts: Product[] = [
{
Expand Down Expand Up @@ -383,10 +385,10 @@ describe("basic > ", () => {
];

test("쿠폰 없이 총액을 올바르게 계산해야 합니다.", () => {
const result = cartUtils.calculateCartTotal(cart, null);
expect(result.totalBeforeDiscount).toBe(400);
expect(result.totalAfterDiscount).toBe(380);
expect(result.totalDiscount).toBe(20);
const { result } = renderHook(() => useDiscountCalculator(cart, null));
expect(result.current.totalBeforeDiscount).toBe(400);
expect(result.current.totalAfterDiscount).toBe(380);
expect(result.current.totalDiscount).toBe(20);
});

test("금액쿠폰을 올바르게 적용해야 합니다.", () => {
Expand All @@ -396,9 +398,9 @@ describe("basic > ", () => {
discountType: "amount",
discountValue: 50,
};
const result = cartUtils.calculateCartTotal(cart, coupon);
expect(result.totalAfterDiscount).toBe(330);
expect(result.totalDiscount).toBe(70);
const { result } = renderHook(() => useDiscountCalculator(cart, coupon));
expect(result.current.totalAfterDiscount).toBe(330);
expect(result.current.totalDiscount).toBe(70);
});

test("퍼센트 쿠폰을 올바르게 적용해야 합니다", () => {
Expand All @@ -408,9 +410,9 @@ describe("basic > ", () => {
discountType: "percentage",
discountValue: 10,
};
const result = cartUtils.calculateCartTotal(cart, coupon);
expect(result.totalAfterDiscount).toBe(342);
expect(result.totalDiscount).toBe(58);
const { result } = renderHook(() =>useDiscountCalculator(cart, coupon));
expect(result.current.totalAfterDiscount).toBe(342);
expect(result.current.totalDiscount).toBe(58);
});
});

Expand Down Expand Up @@ -509,7 +511,7 @@ describe("basic > ", () => {
result.current.applyCoupon(testCoupon);
});

const total = result.current.calculateTotal();
const total = result.current.calculateTotal;
expect(total.totalBeforeDiscount).toBe(200);
expect(total.totalAfterDiscount).toBe(180);
expect(total.totalDiscount).toBe(20);
Expand Down
4 changes: 2 additions & 2 deletions src/refactoring/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useState } from 'react';
import { CartPage } from './components/CartPage.tsx';
import { AdminPage } from './components/AdminPage.tsx';
import { AdminPage } from './pages/admin/AdminPage.tsx';
import { Coupon, Product } from '../types.ts';
import { useCoupons, useProducts } from "./hooks";
import { CartPage } from '../origin/components/CartPage.tsx';

const initialProducts: Product[] = [
{
Expand Down
Loading
Loading