ReactHookForm Submit 테스트 이슈

이짜젠·2021년 10월 17일
0

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",
        })
      );
    });
  });
profile
오늘 먹은 음식도 기억이 안납니다. 그래서 모든걸 기록합니다.

0개의 댓글