Skip to content

Commit

Permalink
Merge pull request #146 from Yanolza-Miniproject/feature/#137
Browse files Browse the repository at this point in the history
Feat: 로그인, capacity에 따른 버튼 비활성화
  • Loading branch information
mysdpy30s authored Nov 30, 2023
2 parents e8e4017 + ad185ab commit 9565320
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 79 deletions.
10 changes: 7 additions & 3 deletions src/components/Detail/ActionButtonGroup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { purchaseState } from "../../../store/purchaseAtom";
import * as Styled from "./ActionButtonGroup.styles";
import { ActionButtonGroupProps } from "./ActionButtonGroup.types";
import { formatDate } from "../../../utils/formatDate";
import { useRecoilValue } from "recoil";
import { userDataAtom } from "../../../store/userDataAtom";

const ActionButtonGroup = ({
checkInAt,
Expand All @@ -20,6 +22,9 @@ const ActionButtonGroup = ({
const queryParams = new URLSearchParams(location.search);
const roomId = parseInt(queryParams.get("room-id") || "0", 10);

const userData = useRecoilValue(userDataAtom);
const isLoggedIn = userData.memberId !== "";

const onAddToCart = () => {
const formattedCheckInAt = formatDate(new Date(checkInAt));
const formattedCheckOutAt = formatDate(new Date(checkOutAt));
Expand Down Expand Up @@ -60,7 +65,6 @@ const ActionButtonGroup = ({
},
{
onSuccess: (response) => {
// const orderId = Math.floor(Math.random() * 100000); // 이부분 삭제 예정
setPurchase((prev) => ({
...prev,
order_id: response.data.data,
Expand All @@ -77,10 +81,10 @@ const ActionButtonGroup = ({

return (
<Styled.ButtonGroupContainer>
<Styled.AddToCartButton onClick={onAddToCart}>
<Styled.AddToCartButton onClick={onAddToCart} disabled={!isLoggedIn}>
장바구니 담기
</Styled.AddToCartButton>
<Styled.BuyNowButton onClick={handleBuyNow}>
<Styled.BuyNowButton onClick={handleBuyNow} disabled={!isLoggedIn}>
바로 구매하기
</Styled.BuyNowButton>
</Styled.ButtonGroupContainer>
Expand Down
42 changes: 42 additions & 0 deletions src/components/Detail/PriceDisplay/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { render, screen } from "@testing-library/react";
import { RecoilRoot } from "recoil";
import PriceDisplay from "./";
import {
checkInDateState,
checkOutDateState,
} from "../../../store/checkinCheckOutAtom";
import calculateNightCount from "../../../utils/calculateNightCount";
import formatNumber from "../../../utils/formatNumber";

describe("PriceDisplay Component", () => {
const mockPricePerNight = 100000;
const mockCheckInDate = new Date("2023-01-01");
const mockCheckOutDate = new Date("2023-01-03");

const setup = () => {
render(
<RecoilRoot
initializeState={({ set }) => {
set(checkInDateState, mockCheckInDate);
set(checkOutDateState, mockCheckOutDate);
}}
>
<PriceDisplay pricePerNight={mockPricePerNight} />
</RecoilRoot>,
);
};

test("총합 가격이 올바르게 계산되어 표시되는지 테스트", () => {
setup();

const nightCount = calculateNightCount(
mockCheckInDate.toISOString(),
mockCheckOutDate.toISOString(),
);
const expectedTotalPrice = nightCount * mockPricePerNight;

expect(
screen.getByText(`₩ ${formatNumber(expectedTotalPrice)}`),
).toBeInTheDocument();
});
});
16 changes: 12 additions & 4 deletions src/components/Detail/QuantitySelector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const QuantitySelector: React.FC<QuantitySelectorProps> = ({
initialQuantity,
onQuantityChange,
price,
capacity,
}) => {
const [quantity, setQuantity] = useState(initialQuantity);

Expand All @@ -17,9 +18,11 @@ const QuantitySelector: React.FC<QuantitySelectorProps> = ({
};

const handleIncrease = () => {
const newQuantity = quantity + 1;
setQuantity(newQuantity);
onQuantityChange(newQuantity);
if (quantity < capacity) {
const newQuantity = quantity + 1;
setQuantity(newQuantity);
onQuantityChange(newQuantity);
}
};

return (
Expand All @@ -35,7 +38,12 @@ const QuantitySelector: React.FC<QuantitySelectorProps> = ({
-
</Styled.MinusButton>
<Styled.QuantityText>{quantity}</Styled.QuantityText>
<Styled.PlusButton onClick={handleIncrease}>+</Styled.PlusButton>
<Styled.PlusButton
onClick={handleIncrease}
disabled={quantity >= capacity}
>
+
</Styled.PlusButton>
</Styled.ControlContainer>
</Styled.SelectorContainer>
);
Expand Down
91 changes: 58 additions & 33 deletions src/components/DetailList/RoomItem/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,62 @@
// import "@testing-library/jest-dom";
// import { render, screen } from "@testing-library/react";
// import RoomItem from "./";
// import formatNumber from "../../../utils/formatNumber";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { createWrapper } from "../../../test/test.utils";
import RoomItem from "./";

// const testData = {
// id: 1,
// name: "디럭스룸",
// price: 200000,
// capacity: 2,
// roomImageUrl: "example-room-image.jpg",
// RoomInventory: [{ date: "2023-01-01", inventory: 5 }],
// checkInDate: new Date("2023-01-01"),
// checkOutDate: new Date("2023-01-02"),
// };
const testData = {
id: 1,
name: "그랜드하얏트",
price: 100000,
capacity: 2,
roomImageUrl: "test-room-image.jpg",
RoomInventory: [{ date: "2023-05-01", inventory: 5 }],
checkInDate: new Date("2023-05-01"),
checkOutDate: new Date("2023-05-02"),
roomImages: "test-room-image.jpg",
};

// describe("RoomItem", () => {
// test("아이템의 정보가 데이터에 맞게 표시되어야 한다.", () => {
// render(<RoomItem {...testData} />);
describe("RoomItem Test", () => {
test("객실 아이템이 렌더링되는지 테스트", () => {
if ("IntersectionObserver" in window) {
render(
<RoomItem
id={testData.id}
name={testData.name}
price={testData.price}
capacity={testData.capacity}
roomImages={testData.roomImages}
RoomInventory={testData.RoomInventory}
checkInDate={testData.checkInDate}
checkOutDate={testData.checkOutDate}
/>,
);
}
});

// const name = screen.getByText(testData.name);
// const capacity = screen.getByText(`최대 인원: ${testData.capacity}명`);
// const price = screen.getByText(`₩${formatNumber(testData.price)}`);
// const inventoryText = `남은 객실: ${testData.RoomInventory[0].inventory}개`;
// const inventory = screen.getByText((content) =>
// content.includes(inventoryText),
// );
// expect(inventory).toBeInTheDocument();
// const roomImage = screen.getByAltText(`${testData.name} 이미지`);
test("객실 리스트 아이템을 누르면 해당 객실 상세페이지로 이동.", () => {
if ("IntersectionObserver" in window) {
const router = jest.fn();
const user = userEvent.setup();
const wrapper = createWrapper();

// expect(name).toBeInTheDocument();
// expect(capacity).toBeInTheDocument();
// expect(price).toBeInTheDocument();
// expect(inventory).toBeInTheDocument();
// expect(roomImage).toHaveAttribute("src", testData.roomImageUrl);
// });
// });
render(
<RoomItem
id={testData.id}
name={testData.name}
price={testData.price}
capacity={testData.capacity}
roomImages={testData.roomImages}
RoomInventory={testData.RoomInventory}
checkInDate={testData.checkInDate}
checkOutDate={testData.checkOutDate}
/>,
{ wrapper },
);

const item = screen.getByTestId("individual-item");
user.click(item);

expect(router).toHaveBeenCalledWith(testData.id);
}
});
});
80 changes: 44 additions & 36 deletions src/components/DetailList/RoomList/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,47 @@
// import "@testing-library/jest-dom";
// import { render, screen } from "@testing-library/react";
// import { RecoilRoot } from "recoil";
// import {
// checkInDateState,
// checkOutDateState,
// } from "../../../store/checkinCheckOutAtom";
// import RoomList from ".";
import { render, screen } from "@testing-library/react";
import { RecoilRoot } from "recoil";
import RoomList from "./";
import isInventoryAvailable from "./RoomList.utils";
import { BrowserRouter } from "react-router-dom";

// // Recoil 상태를 모의 처리하기 위해 필요
// jest.mock("recoil", () => ({
// ...jest.requireActual("recoil"),
// useRecoilValue: jest.fn().mockImplementation((state) => {
// if (state === checkInDateState) {
// return new Date("2023-01-01"); // 예시 체크인 날짜
// } else if (state === checkOutDateState) {
// return new Date("2023-01-02"); // 예시 체크아웃 날짜
// }
// return null;
// }),
// }));
const accommodationDetail = {
rooms: [
{
id: 1,
name: "스탠다드 룸",
price: 150000,
capacity: 2,
roomImages: [
{ id: 101, imageUrl: "image1.jpg" },
{ id: 102, imageUrl: "image2.jpg" },
],
RoomInventory: [
{ date: "2023-01-01", inventory: 5 },
{ date: "2023-01-02", inventory: 4 },
],
roomImageUrl: "standard-room.jpg",
},
],
};
describe("RoomList Test", () => {
test("필터링된 룸 리스트가 렌더링되는지 테스트", () => {
const testCheckInDate = new Date("2023-01-01");
const testCheckOutDate = new Date("2023-01-02");

// describe("RoomList", () => {
// test("renders room list and filters rooms based on check-in and check-out dates", () => {
// render(
// <RecoilRoot>
// <RoomList />
// </RecoilRoot>,
// );
render(
<BrowserRouter>
<RecoilRoot>
<RoomList rooms={accommodationDetail.rooms} />
</RecoilRoot>
</BrowserRouter>,
);

// // 방 목록이 올바르게 렌더링되는지 확인
// expect(screen.getByTestId("room-list")).toBeInTheDocument();

// // 체크인 및 체크아웃 날짜에 따라 필터링된 방의 수를 검증 (방의 수는 mock 데이터에 따라 달라질 수 있음)
// // 예: expect(screen.getAllByTestId('room-item')).toHaveLength(예상되는 방의 수);
// });

// // 필요에 따라 추가적인 테스트 케이스를 작성할 수 있습니다.
// });
accommodationDetail.rooms.forEach((room) => {
if (isInventoryAvailable(room, testCheckInDate, testCheckOutDate)) {
expect(screen.getByText(room.name)).toBeInTheDocument();
} else {
expect(screen.queryByText(room.name)).toBeNull();
}
});
});
});
4 changes: 1 addition & 3 deletions src/pages/Detail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ const Detail = () => {
return <div></div>;
}

console.log("roomId", roomId);
console.log("데이터:", data.data);

if (error || !roomDetails) {
return <div>Error: {error ? error.message : "객실 정보가 없습니다."}</div>;
}
Expand Down Expand Up @@ -75,6 +72,7 @@ const Detail = () => {
initialQuantity={selectedGuests}
onQuantityChange={(newQuantity) => setSelectedGuests(newQuantity)}
price={roomDetails.data.price}
capacity={roomDetails.data.capacity}
/>
<PriceDisplay pricePerNight={roomDetails.data.price} />
<ActionButtonGroup
Expand Down

0 comments on commit 9565320

Please sign in to comment.