Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

사고쳤어요

[React / ts] Book Store 만들기 - ④ 컴포넌트 제작과 테스트파일 만들기 본문

웹 풀스택

[React / ts] Book Store 만들기 - ④ 컴포넌트 제작과 테스트파일 만들기

kevinmj12 2025. 4. 20. 21:46

Button Component 만들기

Button

const Button: React.FC<ButtonProps> = ({
  children,
  size,
  scheme,
  disabled,
}) => {
  return (
    <ButtonStyle size={size} scheme={scheme} disabled={disabled}>
      {children}
    </ButtonStyle>
  );
};

styled 컴포넌트의 ButtonStyle을 가져오고 Props를 전달받아 기본적인 Button을 구현하였다.

 

ButtonStyle

const ButtonStyle = styled.button<Omit<ButtonProps, "children">>`
  font-size: ${({ theme, size }) => theme.button[size].fontSize};
  padding: ${({ theme, size }) => theme.button[size].padding};
  color: ${({ theme, scheme }) => theme.buttonScheme[scheme].color};
  background-color: ${({ theme, scheme }) =>
    theme.buttonScheme[scheme].backgroundColor};
  border: 0;
  border-radius: ${({ theme }) => theme.borderRadius.default};

  opacity: ${({ disabled }) => (disabled ? 0.5 : 1.0)};
  pointer-events: ${({ disabled }) => (disabled ? "none" : "auto")};
  cursor: ${({ disabled }) => (disabled ? "none" : "pointer")};
`;

 

size, scheme을 이용해 theme에서 스타일을 동적으로 가져오도록 하였고

disabled값에 따라 투명도, 클릭 여부, 커서 모양 등을 설정해주었다.

 

그리고 styled.button에서 Omit<ButtonProps, "children">이 사용되었는데

Omit<T, K>는 타입스크립트에서 타입 T에서 키 K를 제외한 타입을 만든다는 뜻이다.

 

즉 ButtonProps가 다음과 같이 정의되어 있을 때

interface ButtonProps {
  children: React.ReactNode;
  size: ButtonSize;
  scheme: ButtonScheme;
  disabled?: boolean;
  isLoading?: boolean;
};

 

Omit<buttonprops, "children"="">은 다음과 같이 children을 제외한 ButtonProps를 의미한다.

{
  size: ButtonSize;
  scheme: ButtonScheme;
  disabled?: boolean;
  isLoading?: boolean;
}

 

 

전체 코드

import styled from "styled-components";
import { ButtonScheme, ButtonSize } from "../../style/theme";

interface ButtonProps {
  children: React.ReactNode;
  size: ButtonSize;
  scheme: ButtonScheme;
  disabled?: boolean;
  isLoading?: boolean;
}

const Button: React.FC<ButtonProps> = ({
  children,
  size,
  scheme,
  disabled,
}) => {
  return (
    <ButtonStyle size={size} scheme={scheme} disabled={disabled}>
      {children}
    </ButtonStyle>
  );
};

const ButtonStyle = styled.button<Omit<ButtonProps, "children">>`
  font-size: ${({ theme, size }) => theme.button[size].fontSize};
  padding: ${({ theme, size }) => theme.button[size].padding};
  color: ${({ theme, scheme }) => theme.buttonScheme[scheme].color};
  background-color: ${({ theme, scheme }) =>
    theme.buttonScheme[scheme].backgroundColor};
  border: 0;
  border-radius: ${({ theme }) => theme.borderRadius.default};
  opacity: ${({ disabled }) => (disabled ? 0.5 : 1.0)};
  pointer-events: ${({ disabled }) => (disabled ? "none" : "auto")};
  cursor: ${({ disabled }) => (disabled ? "none" : "pointer")};
`;

export default Button;

 

 

테스트 코드 작성

react에서는 @testing-library/react를 활용하여 단위 테스트를 진행할 수 있다.

// Button.spec.tsx

import { render, screen } from "@testing-library/react";
import { BookStoreThemeProvider } from "../context/ThemeContext";
import Button from "./Button";

describe("Button 컴포넌트 테스트", () => {
  it("렌더 확인", () => {
    // 1. 렌더
    // React 컴포넌트를 테스트 환경에 렌더링
    render(
      <BookStoreThemeProvider>
        <Button size="large" scheme="primary">
          버튼
        </Button>
      </BookStoreThemeProvider>
    );
    // 2. 확인
    // 요소가 DOM에 존재하는지 검사
    expect(screen.getByText("버튼")).toBeInTheDocument();
  });

  it("size props 적용", () => {
    const { container } = render(
      <BookStoreThemeProvider>
        <Button size="large" scheme="primary">
          제목
        </Button>
      </BookStoreThemeProvider>
    );

    // 인라인 스타일이 제대로 적용되었는지 검사
    expect(screen.getByRole("button")).toHaveStyle({
      fontSize: "1.5rem",
    });
  });
});

expect...toBeInTheDocument()로 요소가 DOM에 존재하는지를 검사할 수 있고

expect...toHaveStyle()로 스타일이 제대로 적용되었는지를 검사할 수 있다.

이외에도 다양한 검사 함수가 있어 필요한 요소들을 테스트해볼 수 있다.

 

테스트는 npm test 명령어로 모든 테스트 파일에 대해 테스트를 수행할 수 있으며,

npm test Button과 같이 Button.spec.tsx에 해당되는 테스트만을 진행할 수도 있다.

 

테스트가 성공적으로 진행된 경우 다음과 같이 콘솔창이 나타난다.