📑

【jest-puppeteer】テストでよく使うカスタムフック一覧

2022/05/02に公開

はじめに

Vue.jsでのブラウザテストとしてjest-puppeteerを採用しています。

https://qiita.com/rh_taro/items/32bb6851303cbc613124

上の記事に追記するような形でなぜ必要で、どういう時に使うのかの具体例を添えて紹介していきます。主にこちらの記事を参考に作ったものと引用したコード(リンクを載せています)に関しましては動作確認済みとなっています。

要素があるかをbool値で判定させる

waitForSelectorで指定した要素が見えるようになるまで待つ実装をすることができますが、もし要素が見えない場合はエラーになりテストが止まってしまいます。

要素がある時(true)はAの処理を、要素が見えない場合(false)はBの処理をする分岐が必要だったので実装しました。

export const isElementVisible = async (page, selector) => {
  let visible = true;
  await page.waitForSelector(selector, { visible: true, timeout: 1000 })
  .catch(() => {
    visible = false;
  });
  return visible;
};

class名を取得する

動的にclassを変更する仕様の場合に役立ちます。具体的にはテスト中にボタンの活性・非活性が機能しているかの判定をする時に使います。

export const getClassName = async (selector) => {
  return await page.$eval(selector, (element) => {
    return element.className;
  });
};

テキストを取得する

これは言わずもがな必須な関数です。input系の入力値の確認や遷移後のタイトルを取得したりと非常に汎用性が高く一番頻度が高いかもしれません。

export const getTextContent = async (selector) => {
  return await page.$eval(selector, (element) => {
    return element.textContent;
  });
};

inputフィールドをクリアする

編集機能のテストを使用する際やバリデーションテストとして何回もinputフィールドに値を入力する場合このクリアの関数が役に立ちます。

export const resetInputValue = async (selector) => {
  await page.$eval(selector, (element) => (element.value = ''));
};

ページの最下部までスクロールする

z-indexで要素の上にオーバーレイが被っている場合値の入力や要素の取得をすることができませんでした。

被っている要素を無視して操作することもできるような気がしますが、一旦スクロールした方が後々テストを進めるにあたって都合がよかったのでスクロールの実装を選択しました。

export const autoScrollToBottom = async (page) => {
  await page.evaluate(async () => {
    await new Promise((resolve) => {
      let totalHeight = 0;
      const distance = 100;
      const timer = setInterval(() => {
        /* eslint-disable */
        const scrollHeight = document.body.scrollHeight;
        /* eslint-enable */
        window.scrollBy(0, distance);
        totalHeight += distance;
        if (totalHeight >= scrollHeight) {
          clearInterval(timer);
          resolve();
        }
      }, 100);
    });
  });
};

ラジオボタンを押下する

labelと連動している場合のみに限りますが、押下する>押下した要素がcheckedになっているかをまとめて確認するように実装しています。

export const fillInputRadio = async (customAttribute) => {
  await page.click(`[data-jp="label-${customAttribute}"]`);
  const inputRadio = await page.$(`[data-jp="input-${customAttribute}"]`);
  const isRadioSelected = await (
    await inputRadio.getProperty('checked')
  ).jsonValue();
  expect(isRadioSelected).toEqual(true);
};

最後に

個人的にe2eテストは使う関数が決まっている気がするので使いまわせるように実装しておくと後半になって実装が楽になると思います。(そのためモジュール化を前提としたコードっぽく紹介しています。)

特にシナリオが長くなってしまうとコードが冗長になりがちなので意識的に切り出しをしてコードの品質・安全性を保つ必要があると思いました。

Discussion