사고쳤어요
[React / ts] Book Store 만들기 - ④ 컴포넌트 제작과 테스트파일 만들기 본문
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에 해당되는 테스트만을 진행할 수도 있다.
테스트가 성공적으로 진행된 경우 다음과 같이 콘솔창이 나타난다.
'웹 풀스택' 카테고리의 다른 글
[React / ts] Book Store 만들기 - ⑥ Axios 사용과 웹서버 연결 (1) | 2025.04.21 |
---|---|
[React / ts] Book Store 만들기 - ⑤ 라우터 만들기 (0) | 2025.04.21 |
[React / ts] Book Store 만들기 - ③ ThemeSwitcher 만들기 (0) | 2025.04.19 |
[React / ts] Book Store 만들기 - ② 레이아웃 구성, 글로벌 스타일 적용 (0) | 2025.04.18 |
[React / ts] Book Store 만들기 - ① 프로젝트 생성과 폴더 구조 설정 (0) | 2025.04.17 |