e2e-playwright-testing について
Web 開発者やコーディングエージェント向けの Playwright E2E テストスキルです。プロジェクトの構成に応じて、ロケーターや認証から CI 設定までのテスト規約を示します。
主な機能
- 01プロジェクト構成と認証方式の検出
- 02アクセシブルなロケーターの指針
- 03認証状態の再利用
- 04フォームとアサーションのパターン
- 05テスト構成と信頼性の規約
- 06CI 設定のガイド
活用シーン
- 01Playwright E2E テストの作成やレビュー
- 02不安定なブラウザテストの調査
- 03フォームや認証フローのテスト
- 04Playwright の CI 設定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ asyrafhussin/ agent-skills --skill e2e-playwright-testingインストール後、Claude Code で/e2e-playwright-testingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
AGENTS.mdmetadata.jsonREADME.mdrules/_sections.md_template.mdassert-web-first.mdauth-storage-state.mdform-custom-checkboxes.mdform-react-date-inputs.mdloc-prefer-role-locators.mdloc-strict-mode.mdorg-mirror-routes.mdrel-no-wait-for-timeout.md詳細
E2E Playwright テスト
Playwright を使った信頼性の高いエンドツーエンドのブラウザーテストのパターンと規約です。
Web アプリケーション向けの包括的な E2E テストガイドです。ロケーター戦略、認証の再利用、フォームテスト(React/SPA 固有の注意点を含む)、アサーション、テストの整理、信頼性、CI/CD の設定を扱う、6 つのカテゴリにわたる 8 つのルールを掲載しています。
スタックの検出
E2E テストの作成またはレビューを行う前に、プロジェクトのスタックを検出してください。
手順 1 — Playwright の確認
# Look in package.json devDependencies:
# "@playwright/test" → Playwright is installed
# Check for playwright.config.js or playwright.config.ts
@playwright/testが存在する場合 → このスキルの Playwright パターンを使用してくださいcypressが存在する場合 → このスキルは適用されません
手順 2 — フロントエンドフレームワークの検出
# Check package.json dependencies:
# "react" + "@inertiajs/react" → React + Inertia.js (SPA with server routing)
# "react" + "react-router" → React SPA
# "vue" → Vue.js
# "next" → Next.js
これが重要な理由:
- React + Inertia.js:Inertia は
history.pushStateを使用するため、waitForLoadState('networkidle')ではなくwaitForURLを使用します - React の制御された入力:テキストには
fill()が使えますが、日付/時刻にはkeyboard.type()が必要です - SPA ナビゲーション:ページ全体は再読み込みされないため、アサーションではネットワークのアイドル状態ではなく、コンテンツを待つ必要があります
手順 3 — 認証パターンの検出
# Check for session-based (Laravel Sanctum) or token-based (JWT) auth
# Session: storageState saves cookies
# Token: may need to save tokens to localStorage
手順 4 — レート制限の検出
# Check routes for throttle middleware
# If present in dev, tests will hit 429 after ~5 login attempts
# Solution: production-only throttle or increase limits in test env
メタデータ
- バージョン: 1.0.0
- ルール数: 6 つのカテゴリにわたる 8 つのルール
- ライセンス: MIT
適用する場面
- Playwright の E2E テストを作成またはレビューするとき
- 新しいプロジェクトで E2E テストをセットアップするとき
- 不安定なブラウザーテストをデバッグするとき
- フォーム送信、認証フロー、ユーザー操作をテストするとき
- 要素のロケーター戦略を選ぶとき
- CI/CD 向けに Playwright を設定するとき
優先度別のルールカテゴリ
| 優先度 | カテゴリ | 影響度 | 接頭辞 |
|---|---|---|---|
| 1 | ロケーター | CRITICAL | loc |
| 2 | 認証 | CRITICAL | auth |
| 3 | アサーション | HIGH | assert |
| 4 | フォームと入力 | HIGH | form |
| 5 | テストの整理 | MEDIUM | org |
| 6 | 信頼性 | MEDIUM | rel |
クイックリファレンス
1. ロケーター(CRITICAL)
loc-prefer-role-locators- CSS セレクターよりgetByRole/getByLabelを使用するloc-strict-mode-exact/first/スコープ指定を使って strict モード違反に対処する
2. 認証(CRITICAL)
auth-storage-state- セットアッププロジェクトのパターンを使ってログイン状態を再利用する
3. アサーション(HIGH)
assert-web-first- 自動再試行するexpect(locator)アサーションを使用する
4. フォームと入力(HIGH)
form-react-date-inputs- React アプリの日付/時刻にはkeyboard.type()を使用するform-custom-checkboxes- sr-only チェックボックスコンポーネントに対処する
5. テストの整理(MEDIUM)
org-mirror-routes- ディレクトリ構造をルートグループに対応させる
6. 信頼性(MEDIUM)
rel-no-wait-for-timeout- 任意のwaitForTimeoutは使用しない
基本パターン
ロケーターの優先順位
// 1st: Role (best — mirrors accessibility)
page.getByRole('button', { name: 'Submit' })
page.getByRole('tab', { name: 'Network' })
page.getByRole('heading', { name: 'Dashboard' })
// 2nd: Label (for form fields)
page.getByLabel('Email')
// 3rd: Text (for static content, use exact when ambiguous)
page.getByText('Welcome', { exact: true })
// 4th: ID (for inputs without proper labels)
page.locator('#password')
// Last resort: CSS selector
page.locator('button.submit-btn')
認証のセットアップパターン
// Setup project logs in once per role, all tests reuse the state
// 3 logins for 90+ tests (not 90 logins)
// In test files:
test.use({ role: 'customer' });
test('shows dashboard', async ({ authedPage: page }) => {
await page.goto('/dashboard');
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
});
React の日付入力に関する注意点
// fill() doesn't trigger React onChange for date/time inputs
// Use keyboard.type() instead:
await dateInput.click();
await page.keyboard.type('16042026'); // DDMMYYYY
await timeInput.click();
await page.keyboard.type('1000AM'); // 10:00 AM
Strict モードの修正
// Bad: matches "Verified" AND "Unverified"
page.getByRole('button', { name: 'Verified' })
// Good: exact match
page.getByRole('button', { name: 'Verified', exact: true })
// Bad: matches heading AND breadcrumb
page.getByText('POS Demo')
// Good: use role to disambiguate
page.getByRole('heading', { name: 'POS Demo' })
並列実行の判断
// Default Playwright: fullyParallel: true
// Use this when: tests are independent, each test creates its own data
// Override to sequential: workers: 1
// Use this when: tests share a seeded database with mutable state
// Without this, one test's buy transaction changes the balance another test expects
設定テンプレート
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './specs',
fullyParallel: false, // true if tests are independent
workers: 1, // increase if no shared mutable state
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
reporter: [['html', { open: 'never' }], ['list']],
use: {
baseURL: process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:8000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{ name: 'auth-setup', testMatch: /auth\.setup\.js$/, testDir: './auth' },
{ name: 'chrome', use: { ...devices['Desktop Chrome'] }, dependencies: ['auth-setup'] },
{ name: 'mobile', use: { ...devices['iPhone 14'] }, dependencies: ['auth-setup'], testMatch: /responsive/ },
],
});
参考資料
完全版ドキュメント
すべてのルールを詳しく記載した完全版ガイド:AGENTS.md
コメント
Markdown 対応