🐣
reCAPTCHAを使用した新規登録画面のIntegration Test
概要
Integration Testの導入を以下の記事を参考に実装しました。
しかし、実際にサービスとしてユーザーのアカウントを作成する新規登録画面には、reCAPTCHAを追加で実装する必要が出てきます。reCAPTCHAとは、登録画面などでよく見られる以下の画像のようなもので、botによる不正なアクセスを防ぐために用いられます。(詳しくはこちら)
そうした中で、reCAPTCHAを追加した状態だと、テストがうまく通らない問題が発生しました。そのため、その解決方法を記事として残しておこうと思います。
使用技術
- Next.js
- Jest
- React Testing Library
- react-google-recaptcha
reCAPTCHAの実装
npm install --save react-google-recaptcha
実装方法はライブラリにそのまま乗っかっただけなのであまり詳しく説明はしません。今回のテストで使用した形だけざっくり記載しておきます。
import ReCAPTCHA from 'react-google-recaptcha';
import { useCallback, useRef } from 'react';
const Signup = () => {
const recaptchaRef = useRef<ReCAPTCHA | null>(null);
const onSubmit = useCallback(async (e: ChangeEvent<HTMLFormElement>) => {
e.preventDefault();
// reCAPTCHAのtokenを取得
const token = await recaptchaRef.current?.executeAsync();
if (!token) { return; }
// ここで新規登録の処理
router.push('/');
}, [router]);
return (
<>
<form onSubmit={ onSubmit }>
{/* メールアドレスやパスワードの入力項目 */}
</form>
<ReCAPTCHA
ref={ recaptchaRef }
sitekey={ recaptchaKey } // 各自googleから作成してください
size="invisible"
badge='inline'
/>
<>
)
}
課題と解決
上記した実装方法でテストを実行した場合、reCAPTCHAから取得しているtokenが取得できず、新規登録の処理まで辿り着けないことでテストが失敗で返されてしまいます。
そのため、この課題を解決するためには、tokenをrecaptchaRefに格納しているReCAPTCHAコンポーネントをモックする必要があります。
そして、その方法が以下のようになります。
import { forwardRef, useImperativeHandle } from 'react';
// react-google-recaptcha の mock
jest.mock('react-google-recaptcha', () => {
const ReCAPTCHA = forwardRef(function Components(props, ref) {
useImperativeHandle(ref, () => ({
executeAsync: jest.fn(() => 'token'),
}));
return null;
});
return ReCAPTCHA;
});
参考にした記事と同じように、jest.mockでモックを生成し、tokenを取得しているexecuteAsyncという関数に対して、tokenに値する文字列を返しています。このように、reCAPTCHAに対してもモックを実装してあげることで、テストを問題なく通すことができます。
Discussion