PlaywrightとJest + TypeScriptでE2Eテスト

PlaywrightはMicrosoftのOSSでpuppeteer互換なクロスブラウザテストが書けるツールです。

Install

使用するには、Jestのpresetなどと一緒にインストールが必要です。

$ yarn add -D jest jest-playwright-preset playwright ts-jest

Create files

Jestの設定と、Playwrightの設定ファイル、そしてテストコードを書くファイルを用意します。

$ mkdir e2e
$ touch e2e/jest-playwright.config.js e2e/jest.config.js index.e2e.ts

e2e/jest-playwright.confg.js

playwrightの設定では、テスト用のサーバーを立ち上げる設定を書きます。下のコードでは、CirclCI上ではビルドされたアプリの方にE2Eテストを実行するようにしています。

module.exports = {
  serverOptions: {
    command: process.env.CI ? 'npx serve build -p 3000' : 'BROWSER=none npm start',
    port: 3000,
    launchTimeout: 200000,
    debug: true,
  },
};

e2e/jest.config.js

Jestの設定です。playwrightとts-jestが動く必要がありますので、設定しましょう。

module.exports = {
    preset: 'jest-playwright-preset',
    testEnvironment: 'jsdom',
    moduleFileExtensions: [
      'ts',
      'js'
    ],
    "testMatch": ["/**/*.e2e.js", "/**/*.e2e.ts"],
    globals: {
      "ts-jest": {
        "tsConfig": "tsconfig.json"
      }
    },
    transform: {
      "^.+\.(ts|tsx)$": "ts-jest"
    },
  };
  

e2e/index.e2e.ts

あとはTypeScriptでE2Eテストを書くだけです。型定義も同梱されているあたりさすがMicrosoftですね。

import {
  webkit,
  firefox,
  chromium,
  Browser,
  Page,
} from 'playwright';

const browserTypes = [chromium, firefox, webkit];

const shouldMatchOuterHTMLSnapshot = async (selector, page) => {
  const elementHandle = await page.$(selector);
  const jsHandle = await elementHandle.getProperty('outerHTML');
  const json = await jsHandle.jsonValue();
  expect(json).toMatchSnapshot();
};

describe.each([
  [chromium.name(), chromium],
  [firefox.name(), firefox],
  [webkit.name(), webkit],
])('test on %p', (_browserName, browserType) => {
  let browser: Browser
  let page: Page
  beforeAll(async () => {
    browser = await browserType.launch();
    const context = await browser.newContext();
    page = await context.newPage();
    await page.goto('http://localhost:3000');
  });

  afterAll(async () => {
    await browser.close();
  });

  it('should match snapshot [body]', async () => {
    await shouldMatchOuterHTMLSnapshot('[data-test="app.root"]', page);
  });

  it('should match snapshot', async () => {
    await shouldMatchOuterHTMLSnapshot('[data-test="login.form"]', page);
  });
});

Resources

Comment