Backstop.jsにおいて、スクロールアニメーションなどを実施したうえで、キャプチャを取る手法

Backstop.jsにおいて、キャプチャをとってテストする際に、スクロールアニメーションなどがあると、初期設定ではうまくキャプチャが取れません。その際には、キャプチャが実行される前に動作するonReady.jsにおいて、スクロールしてからキャプチャするように設定します。

  • backstop_data/engine_scripts/puppet/onReady.js を編集する
module.exports = async (page, scenario, vp) => {
  console.log('SCENARIO > ' + scenario.label);
  await require('./clickAndHoverHelper')(page, scenario);

  // add more ready handlers here...

  // スクロールアニメーションを3秒かけて実行
  await page.evaluate(async () => {
    const scrollTop = document.body.scrollHeight;

    // 1秒かけてスクロールを実行
    await window.scrollTo({
      top: scrollTop,
      behavior: 'smooth',
      duration: 1000 // ミリ秒単位で時間を指定 (1000ミリ秒 = 1秒)
    });

    // 3秒待つ
    await new Promise((resolve) => setTimeout(resolve, 3000));
  });
};

最後まで1秒かけてスクロールして、それから3秒まってキャプチャを取ります。画像が読み込まれるまで遅い場合にも有効。

下記は、何かしらスクロールアニメーションにおいてテストをしたいときのサンプル

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		.div {
			width: 800px;
			margin-inline: auto;
			background-color: #ccc;
			padding: 320px 20px;
			margin-bottom: 20px;
		}
		/* ulはscrollのタイミングで消えている状態からふわっと表示される */
		.div ul {
			opacity: 0;
			transform: translateY(20px);
			transition: all 2s;
		}
		/* scrollのタイミングでulが表示される */
		.div.in-view ul {
			opacity: 1;
			transform: translateY(0);
		}
	</style>
</head>
<body>
	<div class="div">
		<ul>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
		</ul>
	</div>
	<div class="div">
		<ul>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
		</ul>
	</div>
	<div class="div">
		<ul>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
		</ul>
	</div>
	<div class="div">
		<ul>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
			<li>aaaa</li>
		</ul>
	</div>

	<script>
		document.addEventListener('DOMContentLoaded', function () {
			const divs = document.querySelectorAll('.div');

			function checkSlide() {
				divs.forEach(div => {
					// divの上下の位置を取得
					const slideInAt = (window.scrollY + window.innerHeight) - div.clientHeight / 2;
					// divの下の位置を取得
					const divBottom = div.offsetTop + div.clientHeight;
					// divが半分以上表示されたらin-viewクラスを付与
					const isHalfShown = slideInAt > div.offsetTop;
					const isNotScrolledPast = window.scrollY < divBottom;
					if (isHalfShown && isNotScrolledPast) {
						div.classList.add('in-view');
					}
				});
			}

			window.addEventListener('scroll', checkSlide);
			checkSlide(); // 初期状態でチェックを行う
		});
	</script>
</body>
</html>