💨

PlayWrightを用いたフロントエンドE2Eテスト(React, Next.js)

2024/11/12に公開

PlaywrightでのE2EテストをReactで実践したので、
その方法を解説します。
Playwright
https://playwright.dev/
Playwightを利用すれば、比較的簡単にE2Eテストを実装することができます。

導入

npm init playwright@latest

or

yarn create playwright

実行

npx playwright test --ui

--uiのオプションをつけることで、実際の画面でE2Eテストの様子を見ることができます

1. 認証(ログイン、ログアウト)

/register に遷移して、
emailとpasswordを入力して、
ボタンを押すという処理です。

  //新規登録
  await page.goto(localhost + '/register/')
  await page.fill('#email', testUser.email)
  await page.fill('#password', testUser.password)
  await page.fill('#confirmPassword', testUser.password)
  await page.locator('#signUp').click()
  await page.waitForTimeout(2000)


  await page.waitForTimeout(2000)
  await page.locator('#humbuger-menu').click()
  await page.waitForTimeout(1000)
  await page.locator('#logout').click()
  await page.waitForURL(localhost + '/login/')
  await page.waitForTimeout(3000)

今回だとボタンをクリックしています。
https://playwright.dev/docs/input

公式サイトを見ると、ダブルクリックや右クリックなど色々なクリックを選べるようです。

// Double click
await page.getByText('Item').dblclick();

// Right click
await page.getByText('Item').click({ button: 'right' });

// Shift + click
await page.getByText('Item').click({ modifiers: ['Shift'] });

2. 投稿処理

記事の内容を入力して、投稿するテストをしています。

  // 投稿
  await page.locator('#thumbnail-input').setInputFiles(editTestProfile.image)
  await page.waitForTimeout(3000)
  await page.fill('#title', 'test title')
  await page.check('input[name="categori"][value="ONEPIECE"]')
  await page.waitForTimeout(1000)
  await page.check('input[name="netabare"][value="ネタバレ有"]')
  await page.waitForTimeout(1000)
  await page.check('input[name="display"][value="true"]')
  await page.waitForTimeout(1000)
  await page.locator('#submit').click()
  await page.waitForTimeout(2000)
  await page.waitForURL(localhost)
  • setInputFiles
    これをすることで、inputに対して写真ファイルをアップすることができます。
    ファイルのパスを指定できます。
    複数ファイルもできるようです。
// Select one file
await page.getByLabel('Upload file').setInputFiles(path.join(__dirname, 'myfile.pdf'));

// Select multiple files
await page.getByLabel('Upload files').setInputFiles([
  path.join(__dirname, 'file1.txt'),
  path.join(__dirname, 'file2.txt'),
]);

// Select a directory
await page.getByLabel('Upload directory').setInputFiles(path.join(__dirname, 'mydir'));

  • check
    inputのチェックボックスに対して、実際にチェックすることができます。
    https://playwright.dev/docs/input
    これだとnameとvalueを指定して、どのnameに追加するかを選べます。

公式サイトを見ると、getByLabelでチェックする方が、より良い書き方かもしれません。

// Check the checkbox
await page.getByLabel('I agree to the terms above').check();

https://playwright.dev/docs/input

まとめ

Playwrightを使った簡単なE2Eテストの作り方でした。
しかし、今回紹介したテストコードだと検証しきれていない不完全な部分があるので、
その部分を今後テストしていきたいと思います。
あくまで一例を紹介します。

  • Assertions
    何かの処理が終わった時に、どのような文字や状態を返しているかをテストできます。
    下記だと'Submitted'という文章を返ってくるのを期待しているテストです。
    今回だとまだテストに入れられていないので、導入したいです。
await expect(page.getByTestId('status')).toHaveText('Submitted');

https://playwright.dev/docs/test-assertions

  • 他のブラウザでのテスト
    Playwightだとほとんどのブラウザでテストができるようです。
    今回の例だとchromium、firefox、webkitの3種類のブラウザでテスト検証しています。
    色んなブラウザを開く手間が減って、とても便利ですね。
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});
  • 認証状態のままテストできる

まだ詳しく読めているわけではありませんですが、
認証されたブラウザの状態を作るものを作成し、(tests/auth.setup.ts)

import { test as setup, expect } from '@playwright/test';
import path from 'path';

const authFile = path.join(__dirname, '../playwright/.auth/user.json');

setup('authenticate', async ({ page }) => {
  // Perform authentication steps. Replace these actions with your own.
  await page.goto('https://github.com/login');
  await page.getByLabel('Username or email address').fill('username');
  await page.getByLabel('Password').fill('password');
  await page.getByRole('button', { name: 'Sign in' }).click();
  // Wait until the page receives the cookies.
  //
  // Sometimes login flow sets cookies in the process of several redirects.
  // Wait for the final URL to ensure that the cookies are actually set.
  await page.waitForURL('https://github.com/');
  // Alternatively, you can wait until the page reaches a state where all cookies are set.
  await expect(page.getByRole('button', { name: 'View profile and more' })).toBeVisible();

  // End of authentication steps.

  await page.context().storageState({ path: authFile });
});

playwright.config.tsで読み込めば、最初から認証状態でテストできるようです。

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  projects: [
    // Setup project
    { name: 'setup', testMatch: /.*\.setup\.ts/ },

    {
      name: 'chromium',
      use: {
        ...devices['Desktop Chrome'],
        // Use prepared auth state.
        storageState: 'playwright/.auth/user.json',
      },
      dependencies: ['setup'],
    },

    {
      name: 'firefox',
      use: {
        ...devices['Desktop Firefox'],
        // Use prepared auth state.
        storageState: 'playwright/.auth/user.json',
      },
      dependencies: ['setup'],
    },
  ],
});

https://playwright.dev/docs/auth

今の時点ではいちいち認証を挟んでいるので、
これだと手間を減らせて、良いですね。

Discussion