TodoForm 만들기
새로운 할 일 항목을 등록 할 수 있는 TodoForm 이라는 컴포넌트를 만들 것입니다.
먼저 비이었는 함수형 컴포넌트를 하나 만들어줍시다.
TodoForm.js
import React from 'react';
const TodoForm = () => {
return (
<div>
</div>
);
};
export default TodoForm;
그 다음에는 실패하는 테스트 케이스를 하나 작성해봅시다.
TodoForm.test.js
import React from 'react';
import { render } from 'react-testing-library';
import TodoForm from './TodoForm';
describe('TodoForm', () => {
it('has input and button', () => {
const { getByText, getByPlaceholderText } = render(<TodoForm />);
getByPlaceholderText('할 일을 입력하세요');
getByText('등록'); // 버튼이 있는지 확인
});
});
테스트 코드를 작성하고 나면 당연히 실패 할 것입니다. 우리가 아직 구현을 안해줬으니까요. 구현을 해봅시다!
TodoForm.js
import React from 'react';
const TodoForm = () => {
return (
<form>
<input placeholder="할 일을 입력하세요" />
<button type="submit">등록</button>
</form>
);
};
export default TodoForm;
인풋과 버튼을 만들어주었으니, 테스트 케이스가 통과 할 것입니다.
이제 이 컴포넌트의 기능들을 위한 테스트 코드를 작성해봅시다.
TodoForm.test.js
import React from 'react';
import { render, fireEvent } from 'react-testing-library';
import TodoForm from './TodoForm';
describe('TodoForm', () => {
it('has input and button', () => {
const { getByText, getByPlaceholderText } = render(<TodoForm />);
getByPlaceholderText('할 일을 입력하세요');
getByText('등록'); // 버튼이 있는지 확인
});
it('changes input', () => {
const { getByPlaceholderText } = render(<TodoForm />);
const input = getByPlaceholderText('할 일을 입력하세요');
fireEvent.change(input, {
target: {
value: 'TDD 배우기'
}
});
expect(input.value).toBe('TDD 배우기');
});
});
이 테스트는 우리가 컴포넌트에 기능을 구현하기 전에도 통과 할 것입니다. 왜냐하면 input 에 우리가 onChange 및 value 값을 설정하지 않았기 때문이죠. 우선 기능을 구현해보고, 테스트가 여전히 통과하는지 확인해보세요.
TodoForm.js
import React, { useState, useCallback } from 'react';
const TodoForm = () => {
const [value, setValue] = useState('');
const onChange = useCallback(e => {
setValue(e.target.value);
}, []);
return (
<form>
<input
placeholder="할 일을 입력하세요"
value={value}
onChange={onChange}
/>
<button type="submit">등록</button>
</form>
);
};
export default TodoForm;
테스트 코드가 정말 잘 작동하는지 검증하는 좋은 방법은 일부러 틀려보는 것 입니다.
TodoForm 컴포넌트의 onChange 함수 내부에서 setValue 함수를 호출하는 부분을 주석처리해보세요.
const onChange = useCallback(e => {
// setValue(e.target.value);
}, []);
FAIL src/TodoForm.test.js
● TodoForm › changes input
expect(received).toBe(expected) // Object.is equality
Expected: "TDD 배우기"
Received: ""
19 | }
20 | });
> 21 | expect(input.value).toBe('TDD 배우기');
| ^
22 | });
23 | });
24 |
at Object.toBe (src/TodoForm.test.js:21:25)
위와 같이 실패하는것을 확인했다면 다시 원상복구 하세요.
그 다음에는 등록 버튼을 누르는 기능을 위한 테스트 코드를 작성하겠습니다. 이번에는 Mock 함수라는 것을 사용합니다. Mock 함수는 Jest 에서 제공하는 가짜 함수를 만들어주는 기능이며 이 가짜 함수를 사용하면 함수가 몇번 호출이 되었는지, 그리고 함수의 파라미터에는 무엇이 전달 되었는지 알아낼 수 있습니다.
import React from 'react';
import { render, fireEvent } from 'react-testing-library';
import TodoForm from './TodoForm';
describe('TodoForm', () => {
it('has input and button', () => {
const { getByText, getByPlaceholderText } = render(<TodoForm />);
getByPlaceholderText('할 일을 입력하세요');
getByText('등록'); // 버튼이 있는지 확인
});
it('changes input', () => {
// 인풋 값이 잘 바뀌는지 확인
const { getByPlaceholderText } = render(<TodoForm />);
const input = getByPlaceholderText('할 일을 입력하세요');
fireEvent.change(input, {
target: {
value: 'TDD 배우기'
}
});
expect(input.value).toBe('TDD 배우기');
});
it('submits form', () => {
// 등록 기능을 확인
const onInsert = jest.fn(); // Mock 함수를 만듭니다
const { getByPlaceholderText, getByText } = render(
<TodoForm onInsert={onInsert} />
);
const button = getByText('등록');
const input = getByPlaceholderText('할 일을 입력하세요');
// 인풋에 입력하고
fireEvent.change(input, {
target: {
value: 'TDD 배우기'
}
});
// 버튼을 클릭했을 때
fireEvent.click(button);
expect(input.value).toBe(''); // 인풋 값이 비워져야함
expect(onInsert).toBeCalled(); // 함수가 호출 됐어야함
expect(onInsert).toBeCalledWith('TDD 배우기'); // 함수가 'TDD 배우기' 라는 파라미터로 호출돼썽야함
});
});
이제 위 테스트 케이스를 통과시키기 위하여 기능을 구현해봅시다.
TodoForm.js
import React, { useState, useCallback } from 'react';
const TodoForm = ({ onInsert }) => {
const [value, setValue] = useState('');
const onChange = useCallback(e => {
setValue(e.target.value);
}, []);
const onSubmit = useCallback(e => {
e.preventDefault();
onInsert(value);
setValue('');
});
return (
<form onSubmit={onSubmit}>
<input
placeholder="할 일을 입력하세요"
value={value}
onChange={onChange}
/>
<button type="submit">등록</button>
</form>
);
};
export default TodoForm;
이제 TodoForm 을 모두 구현하셨습니다!