Blog
written by 70_10

Playwrightでブラウザの時刻を操作する

現在 Playwright にはブラウザ内の時刻を操作する機能がありません。
この機能について Issue が上がっていますが、まだ対応するまでには至っていません。
[Feature] Time/Date emulation via e.g. a clock() primitive · Issue #6347 · microsoft/playwright

この Issue ではワークアラウンドとして Sinon.js を使った方法が提案されています。
今回はその方法でブラウザの時刻を操作します。

流れ

  1. Playwright のプロジェクトを用意
  2. Sinon.js のインストール
  3. 時刻操作をするサンプルテストを作成

0. Playwright のプロジェクトを用意

まずは Playwright のプロジェクトを用意します。

Terminal
npm init playwright@latest

1. Sinon.js のインストール

Sinon.js をインストールします。TypeScript を使用するので @types/sinon もインストールします。

Terminal
npm install -D sinon @types/sinon

2. 時刻操作をするサンプルテストを作成

tests/fake-timer.test.ts
import test, { expect } from "@playwright/test";
import path from "node:path";
import { SinonFakeTimers, SinonStatic } from "sinon";

declare global {
  interface Window {
    __clock: SinonFakeTimers;
    sinon: SinonStatic;
  }
}

test.beforeEach(async ({ context }) => {
  await context.addInitScript({
    path: path.join(__dirname, "..", "./node_modules/sinon/pkg/sinon.js"),
  });

  await context.addInitScript(() => {
    window.__clock = window.sinon.useFakeTimers();
  });
});

test("fake timer test", async ({ page }) => {
  await page.setContent(`
    <h1>UTC Time: <x-time></x-time></h1>
    <script>
      const time = document.querySelector('x-time');
      (function renderLoop() {
        const date = new Date();
        time.textContent = [date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()]
          .map(number => String(number).padStart(2, '0'))
          .join(':');
        setTimeout(renderLoop, 1000);
      })();
    </script>
  `);

  await expect(page.locator("x-time")).toHaveText("00:00:00");
  await page.evaluate(() => window.__clock.tick(60 * 60 * 1000));
  await expect(page.locator("x-time")).toHaveText("01:00:00");
});

最初に Window へ **clock と sinon を定義しています。
Window.**clock から時刻を操作します。

beforeEach内では Sinon.js をブラウザに追加し、 Window.__clock を初期化しています。
時刻を操作するには以下のように page.evaluete を使います。

時刻を1時間進める
await page.evaluate(() => window.__clock.tick(60 * 60 * 1000));

テストのサンプル

playwright-samples/fake-timer.spec.ts at main · 70-10/playwright-samples

参考記事