Testing 공부를 위해 간단한 todo-list 앱을 만들어 테스트중에있다.
예제코드를 보면 쉽게 따라할 수 있다.
form의 경우 react-form-hook을 사용하는데, submit 이벤트를 호출해도 jest에서 제대로 감지못하는 이슈가있었다. 3시간 가까이 해맸던 것 같다.
원인은 크게 2가지였다.
react-form-hook의 경우 validation이 통과해야 최종적으로 submit이 호출이됐다.
나는 require: true
로 해놓고 빈값으로 놔둔채 주구장창 submit을 하고있었다.
TodoInput.tsx
//...
type TProps = {
onSubmit?: any;
};
const TodoInput: React.FC<TProps> = ({ onSubmit = () => {} }) => {
//...
const addTodo = useCallback((data) => {
const { title, content } = data;
dispatch(
actions.todos.add({
title,
content,
})
);
onSubmit();
reset();
}, []);
return (
<div>
<div>
<form onSubmit={handleSubmit(addTodo)} data-testid="todo-form">
<input
type="text"
{...register("title", { required: true })}
placeholder="제목"
data-testid="todo-title-input"
/>
<input
type="textarea"
{...register("content", { required: true })}
placeholder="내용"
data-testid="todo-content-input"
/>
<button type="submit" data-testid="todo-submit-btn">
추가
</button>
</form>
</div>
</div>
);
};
export default React.memo(TodoInput);
TodoInput.test.tsx
// ...
const createStore = configureStore<TRootState>([]);
let rootStore!: MockStoreEnhanced<TRootState>;
let todosState!: TState;
describe("organisms/TodoInput", () => {
beforeEach(async () => {
rootStore = createStore({
todos: getInitialState(),
});
todosState = rootStore.getState().todos;
rootStore.dispatch = jest.fn();
await act(async () => {
render(
<Provider store={rootStore}>
<TodoInput />
</Provider>
);
});
});
test("추가버튼 클릭시 add 이벤트를 dispatch 합니다.", async () => {
/*
==========================================
값을 넣어줘야 합니다.
*/
const todoExample = {
title: 'test title',
vlaue: 'test value'
},
const submitEl = screen.getByTestId("todo-submit-btn");
fireEvent.input(screen.getByTestId("todo-title-input"), {
target: {
value: todoExample.title,
},
});
fireEvent.input(screen.getByTestId("todo-content-input"), {
target: {
value: todoExample.value,
},
});
/*
==========================================
*/
fireEvent.submit(submitEl);
await waitFor(() => {
expect(rootStore.dispatch).toBeCalledWith(
actions.todos.add({
title: todoExample.title,
content: todoExample.value,
})
);
});
});
});
react-form-hook의 submit 처리는 비동기로 이루어진다.
submit이 일어나고 나서 그 결과가 ui에 반영될 때 까지 기다려주어야 한다는 뜻이다.
react-form-hook 테스팅가이드에도 아래와같은 문구가 있다.
waitFor 및 find* 메소드를 사용하여 폼이 제출되는 것을 감지합니다.
handleSubmit 메서드는 비동기적으로 실행되기 때문입니다.
waitfor
를 이용해 submit의 결과가 ui에 반영될때까지 기다려주자
//...
test("추가버튼 클릭시 add 이벤트를 dispatch 합니다.", async () => {
//...
fireEvent.submit(submitEl);
await waitFor(() => {
expect(rootStore.dispatch).toBeCalledWith(
actions.todos.add({
title: "test title",
content: "test content",
})
);
});
});