상품 목록 페이지

상품 목록 보기 기능

상품 목록을 얻어서 표시하는 화면

  1. 상품 목록 패칭

  2. 상품 목록 리스팅

User Scenario

  • 카테고리 별로 상품 목록이 보여져야 한다.

  • 카테고리를 선택하지 않으면 전체 상품이 노출된다.

  • 각 상품은 상품명과 가격이 노출된다.

  • 상품을 클릭하면 상품 상세 페이지로 넘어간다.

circle-info

Null Object Patternarrow-up-right

  • 객체지향 디자인패턴 중 하나로 객체가 null 값을 반환할 때 생길 수 있는 문제를 해결하기 위해 사용됨

  • NullPointerException 같은 예외를 피하기 위해 null 대신 객체의 인터페이스를 충족하지만 값이 없는 객체를 반환한다.

circle-info

Intl Objectarrow-up-right 다양한 나라의 언어에 맞는 문자열, 숫자, 시간, 날짜 비교와 관련된 포맷팅 기능을 제공한다.

chevron-rightUnit Testhashtag

ProductList.test.tsx

import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Route, useParams } from "react-router-dom";

import { products } from "@/fixtures";
import { withAllContexts, withRouter } from "@/tests/utils";

import ProductList from "./ProductList";

const context = describe;

describe("ProductList", () => {
  it("render correctly", async () => {
    render(
      withAllContexts(withRouter(<Route path="/" element={<ProductList />} />))
    );

    await Promise.all(
      products.map(async (product) => {
        await waitFor(() =>
          expect(screen.getByText(product.name)).toBeInTheDocument()
        );
        await waitFor(() =>
          expect(screen.getByText(product.price)).toBeInTheDocument()
        );
      })
    );

    await waitFor(() => expect(screen.getAllByRole("link")).toHaveLength(2));
  });

  context("when product item is clicked", () => {
    const product = products[0];

    it("navigate to the product detail page", async () => {
      function DetailPage() {
        const params = useParams();
        return <pre>{JSON.stringify(params)}</pre>;
      }

      render(
        withAllContexts(
          withRouter(
            <>
              <Route path="/" element={<ProductList />} />
              <Route path="/:id" element={<DetailPage />} />
            </>
          )
        )
      );

      await waitFor(() => screen.getByText(product.name));
      const linkBtn = screen.getAllByRole("link")[0];

      userEvent.click(linkBtn);

      await waitFor(() =>
        expect(screen.getByText(new RegExp(product.id))).toBeInTheDocument()
      );
    });
  });
});

Product.test.tsx

import { render, screen } from "@testing-library/react";

import { products } from "@/fixtures";
import { withAllContexts } from "@/tests/utils";

import Product from "./Product";

describe("Product", () => {
  const product = products[0];
  it("render correctly", () => {
    render(withAllContexts(<Product product={product} />));

    expect(screen.getByRole("img")).toHaveAttribute(
      "src",
      product.thumbnail.url
    );

    expect(screen.getByText(product.name)).toBeInTheDocument();
    expect(screen.getByText(product.price)).toBeInTheDocument();
  });
})
chevron-rightE2E Testhashtag

상품 카테고리 목록

외부에서 상품 카테고리를 주입받아(API Fetching) 헤더에 표시

해당 데이터 관리를 어디서 하느냐에 따라 외부(API)에서 주입받는 데이터, 내부에서 관리하는 데이터로 구분할 수 있다.

즉, 어드민 페이지에서 상품 카테고리를 관리한다면 외부에서 데이터를 주입받아 표시하는 형태로 진행한다.

circle-info

자주 바뀌지 않고 클라이언트에서 즉시 수정하는게 편한 데이터는 클라이언트 내부에서 관리하는 것이 좋다.

User Scenario

  • 어드민에서 지정한 카테고리 목록들이 표시된다.

  • 카테고리 버튼을 클릭하면 해당하는 상품 목록 페이지로 넘어간다.

chevron-rightUnit Testhashtag
chevron-rightE2E Testhashtag

Last updated