ReactHookForm Submitテストホットスポット


テスト学習のために、簡単なtodo-listアプリケーションを作成してテストしています.
サンプルコードを見ると簡単に覚えられます.
formの場合、react-form-hookを使用すると、submitイベントが呼び出されてもjestが正常に検出できないホットスポットがあります.もう3時間近くになったようです.
原因は大体二つある.

検証に失敗しました


react-form-hookの場合、submitは検証に合格してこそ最終的に呼び出されます.
私はそれをrequire: trueと決めて、手ぶらで提出しました.
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",
        })
      );
    });
  });