State 테스트
App.tsx
return (
<Container>
<Contents>
<ToDoListContainer data-testid='toDoList'>
{
toDoList.map((item, index) => (
<ToDoItem key={item} label={item} onDelete={()=>deleteToDo(index)}/>
))
}
</ToDoListContainer>
<InputContainer>
<Input placeholder="할 일을 입력해 주세요" value={toDo} onChange={(text => setToDo(text))}/>
<Button label="추가" onClick={addToDo}/>
</InputContainer>
</Contents>
</Container>
);
}
App.test.tsx
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import App from './App';
import 'jest-styled-components';
describe('<App />', () => {
it('renders component correctly', () => {
const {container} = render(<App />);
const toDoList = screen.getByTestId('toDoList');
expect(toDoList).toBeInTheDocument();
expect(toDoList.firstChild).toBeNull();
const input = screen.getByPlaceholderText('할 일을 입력해 주세요');
expect(input).toBeInTheDocument();
const label = screen.getByText('추가');
expect(label).toBeInTheDocument();
//expect(container).toMatchSnapshot();
});
it('adds and deletes ToDo items', () => {
render(<App />);
const input = screen.getByPlaceholderText('할 일을 입력해 주세요');
const button = screen.getByText('추가');
fireEvent.change(input, { target: { value: 'study react 1' } });
fireEvent.click(button);
const todoItem = screen.getByText('study react 1');
expect(todoItem).toBeInTheDocument();
const deleteButton = screen.getByText('삭제');
expect(deleteButton).toBeInTheDocument();
const toDoList = screen.getByTestId('toDoList');
expect(toDoList.childElementCount).toBe(1);
fireEvent.change(input, { target: { value: 'study react 2' } });
fireEvent.click(button);
const todoItem2 = screen.getByText('study react 2');
expect(todoItem2).toBeInTheDocument();
expect(toDoList.childElementCount).toBe(2);
const deleteButtons = screen.getAllByText('삭제');
fireEvent.click(deleteButtons[0]);
expect(todoItem).not.toBeInTheDocument();
expect(toDoList.childElementCount).toBe(1);
});
/*
it('does not add emtpy ToDo', () => {
render(<App />);
const button = screen.getByText('추가');
fireEvent.click(button);
const toDoList = screen.getByTestId('toDoList');
expect(toDoList.firstChild).toBeNull();
});
*/
});
사용자가 입력한 할 일 목록 데이터는 styled-components로 만든 ToDoListContainer 컴포넌트 안에 표시되게 된다. 테스트 명세에서는이 할 일 목록 데이터가 화면에 표시되엇는지, 표시되지 않았는지 확인하기 위해 ToDoListContainer 컴포넌트를 찾을 수 있어야 하지만 id, class 등 어떠한 속성도 가지고 있지 않아 테스트 진행이 불가능하다. 그러므로 대안 방법이 data-testid 이다.
data-testid는 다른 동작에 영향을 주지 않고 테스트 명세에서 컴포넌트를 쉽게 찾을 수 있게 도와주는 속성이다.
<ToDoListContainer data-testid='toDoList'>
{
toDoList.map((item, index) => (
<ToDoItem key={item} label={item} onDelete={()=>deleteToDo(index)}/>
))
}
</ToDoListContainer>
const toDoList = screen.getByTestId('toDoList');
npm run test -- --coverage 로 옵션을 붙여서 테스트하면 아래와같이 결과가 농ㄴ다.
* index.tsx와 reportWebVitals.ts 는 무시
App.tsx 40번째줄이 테스트 되어있지않다고 나온다.
코드를 열어보면 할 일을 입력하지 않은 상태에서 "추가" 버튼을 눌러서 할 일을 추가하려고 했을 때 빈 할 일이 추가되지 않도록 코드가 작성되어있는데 이 코드와 관련된 테스트 명세가 추가되지 않았음을 알 수 있다.
해당 코드를 App.test.tsx 에 추가하면
it('does not add emtpy ToDo', () => {
render(<App />);
const button = screen.getByText('추가');
fireEvent.click(button);
const toDoList = screen.getByTestId('toDoList');
expect(toDoList.firstChild).toBeNull();
});
아래와같이 App.tsx 100으로 완료된것을 볼 수 있다.
반응형
'2022 > 리액트+TDD(完)' 카테고리의 다른 글
클래스 컴포넌트 라이프 사이클 (0) | 2022.01.13 |
---|---|
함수 컴포넌트에서 클래스 컴포넌트 변환 (0) | 2022.01.12 |
Props/ State - 6 (0) | 2022.01.09 |
Props/ State - 5 (0) | 2022.01.09 |
Props / State - 4 (0) | 2022.01.08 |