반응형
react test library를 통해 모달 컴포넌트 테스트를 작성하였다.
요구사항
버튼을 누르면 모달이 열린다.
모달 외부를 누르면 모달이 닫힌다.
모달을 클릭했을때는 모달이 닫히면 안된다.
테스트코드
import { render, screen } from '@testing-library/react';
import Test from '..';
import userEvent from '@testing-library/user-event';
test('default : modal is not visible', () => {
render(<Test />);
// 특정 텍스트를 통해 모달이 처음에는 안보이는 상태임을 확인한다.(=dom에 없는지)
const modalText = 'This is a modal. Click outside to close.';
expect(screen.queryByText(modalText)).not.toBeInTheDocument();
});
test('clicking button opens the modal', () => {
render(<Test />);
// 버튼을 눌러 모달을 연다.
const openModalButton = screen.getByRole('button', { name: '모달 열기' });
userEvent.click(openModalButton);
// 특정 텍스트를 통해 모달이 열렸는지(=dom에 있는지) 본다.
const modalText = 'This is a modal. Click outside to close.';
expect(screen.getByText(modalText)).toBeInTheDocument();
});
test('clicking outside the modal closes it', () => {
render(<Test />);
// 일단 모달을 연다
const openModalButton = screen.getByRole('button', { name: '모달 열기' });
userEvent.click(openModalButton);
// 모달 백드롭을 잡는다.
const modalBackground = screen.getByTestId('modal-background');
userEvent.click(modalBackground);
// 모달이 닫혔는지(=dom에 없는지) 본다
const modalText = 'This is a modal. Click outside to close.';
expect(screen.queryByText(modalText)).not.toBeInTheDocument();
});
모달이 열렸는지 닫혔는지 여부
모달이 열렸는지 닫혔는지 여부는 toBeInTheDocument()를 이용했다.
모달 백드롭을 잡는 방법은 document.body가 아닌 data-testid를 이용했다.
<Backdrop data-testid='modal-background' onClick={() => setOpen(false)}>
...
</Backdrop>
document.body는 모달 자체도 포함하는데, 요구사항을 보았을 때 모달을 클릭했을때는 모달이 닫히면 안되기 때문이다.
다른 사람들은 모달 테스트 코드를 작성할 때 어떻게 작성하는지 궁금하다. data-testid 말고 다른 방법이 있을까.
클릭 테스트
fireEvent대신 userEvent를 사용했다.
fireEvent는 click이벤트만 dom을 통해 테스트하는 반면, userEvent는 클릭할때 일어나는 모든 이벤트를 테스트하기 때문이다.(사용자관점)
https://wnsdufdl.tistory.com/545
실제 컴포넌트 코드
// Page
import { useState } from 'react';
import Modal from './Modal';
const Test = () => {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>모달 열기</button>
<Modal open={open} setOpen={setOpen} />
</>
);
};
export default Test;
// Modal.tsx
import React from 'react';
import styled from 'styled-components';
const Modal = ({
open,
setOpen,
}: {
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
}) => {
if (!open) return <></>;
return (
<Backdrop data-testid='modal-background' onClick={() => setOpen(false)}>
{
<div data-testid='modal' onClick={(e) => e.stopPropagation()}>
<Span>This is a modal. Click outside to close.</Span>
</div>
}
</Backdrop>
);
};
export default Modal;
const Backdrop = styled.div`
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
right: 0;
background: rgba(255, 255, 255, 0.8);
display: flex;
align-items: center;
justify-content: center;
`;
const Span = styled.span`
padding: 30px;
border: 1px solid skyblue;
border-radius: 30px;
`;
반응형
'개발 > 테스트코드' 카테고리의 다른 글
MSW(Mock Service Worker) : 비동기로 테스트하기 (0) | 2023.09.01 |
---|---|
queryByText와 getByText (0) | 2023.08.28 |
fireEvent와 userEvent 차이 (0) | 2023.08.26 |
Jest로 비동기 테스트하기(done) (0) | 2022.04.08 |
Jest로 큰지 작은지, truthy인지 falsy인지 테스트하기 (0) | 2022.04.07 |