基本的には順番に実行することを想定しています。
toHaveScreenshot
メソッドにはオブジェクト形式でオプションを渡すことができます。
以下のようにfullPage
プロパティにtrue
を渡すことでページ全体のスナップショットを取得、比較できます。
await expect(page).toHaveScreenshot({ fullPage: true });
jirei2.spec.tsファイルのコメントアウトを解除しテストを追加してみましょう。
Warning
画像の遅延ロードを行う場合、ページ下部の画像がロードされない場合があります。
Next.jsなどのImage
コンポーネントを利用する場合など、注意しないと意図しない画像になることがあります。
playwright.config.ts
のprojects
プロパティのコメントアウトを外して、様々な環境でテストを実行できるようにしましょう。
後続の課題では特にiOSデバイスを有効にする必要があります。
Tip
Playwrightのプロジェクトは以下のシェア率を見ながら、デフォルトで提供されているデバイスを選択するのがおすすめです。
https://gs.statcounter.com/screen-resolution-stats https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/deviceDescriptorsSource.json
これまで課題で様々な画面全体のスナップショットを取得しました。しかし、iOSのスナップショットでは一部の画像が読み込まれていないません。PlaywrightのE2Eテストの向けの機能を利用し、画像の遅延読み込みを無効にした上でページ全体のスナップショットを実行してみましょう。
Note
page.evaluate
関数にコールバック関数を渡すとブラウザのDOMを操作するできる- documentなどのブラウザのAPIも利用できます
- 遅延読み込みの無効化は以下のような対応が可能です
- 非同期エンコーディング、遅延読み込みの属性を削除してから読み込み完了まで待機する
- 少しずつスクロールし画像を全てロードしてからトップまで戻る
1.の答え
await page.evaluate(() => {
document.querySelectorAll("img").forEach((e) => {
e.removeAttribute("loading");
e.removeAttribute("decoding");
});
});
await page.waitForFunction(() => {
const selectors = Array.from(document.getElementsByTagName("img"));
return selectors.map((img) => img.complete).reduce((a, b) => a && b);
});
トップページは一部にアニメーションが用いられています。 そのため、テストの再現性が下がってしまっています(あえてスナップショットの撮影タイミングをずらすため、sleep関数を利用しています)。 複数回テストを実行すると画像の切り替わりにより、てテストに失敗するでしょう。
index.spec.tsを編集し、テストの安定性を向上させましょう
以下のようにmask
プロパティにlocator
オブジェクトの配列を渡すことで、該当箇所を塗りつぶし差分を無視することができます。
const locator = page.locator("セレクタ")
await expect(page).toHaveScreenshot({ mask: [locator] });
Warning
maskはスナップショットの取得後、その上から塗りつぶすため、マスク対象に重ねられている要素もmaskされます。 iframeや動画にも有効な手段ですが、乱用はVRTの信頼性を下げてしまうため、利用は最小限に抑えましょう。
本課題はSPも含めると実装が少しややこしいため、index.spec.tsに既に実装しています。
テストの速度、安定性を踏まえるとなるべく操作は減らしたほうがいいですが、ダイアログなどインタラクションの必要なコンポーネントやページは存在するため、適度に利用していきましょう。