← スキル一覧に戻る

playwright-fixtures-implementation
by teocrafters
⭐ 0🍴 0📅 2026年1月25日
SKILL.md
name: playwright-fixtures-implementation description: Guide for creating and using Playwright fixtures for E2E testing. Use when implementing test utilities or Page Object Models.
Playwright Fixtures Implementation Skill
Guide for creating and using Playwright fixtures for E2E testing with Nuxt hydration handling.
Purpose
USE this skill when:
- Creating reusable test utilities
- Implementing Page Object Models
- Setting up test fixtures for features
- Need Nuxt-specific testing patterns
Core Principles
- USE Playwright's
test.extend()API for reusable utilities - IMPLEMENT Page Object Models as fixtures, not standalone classes
- ALWAYS import
testandexpectfromtests/fixtures/index.ts - ADD data-testid attributes during component development
Fixture Organization
tests/
├── fixtures/
│ ├── index.ts # Merged fixtures (import from here)
│ ├── auth-fixtures.ts # Authentication utilities
│ ├── speakers-fixtures.ts # Feature utilities
│ └── test-accounts.json # Test data
├── e2e/
│ └── speakers.spec.ts # Import from "../fixtures"
Import Pattern (CRITICAL)
// ✅ Correct: Import from merged fixtures
import { test, expect } from "../fixtures"
// ❌ Wrong: Direct import bypasses custom fixtures
import { test, expect } from "@playwright/test"
Creating Fixtures
Basic Fixture
// tests/fixtures/speakers-fixtures.ts
import { test as base } from "@playwright/test"
export const test = base.extend({
speakersPage: async ({ page }, use) => {
await page.goto("http://localhost:3000/speakers")
await page.waitForLoadState("networkidle")
await use(page)
},
})
export { expect } from "@playwright/test"
Page Object Model Fixture
// tests/fixtures/speakers-fixtures.ts
class SpeakersPage {
constructor(public readonly page: Page) {}
async goto() {
await this.page.goto("http://localhost:3000/speakers")
await this.page.waitForLoadState("networkidle")
}
async createSpeaker(data: { firstName: string; lastName: string }) {
await this.page.getByTestId("speakers-create-button").click()
await this.page.getByTestId("speaker-first-name-input").fill(data.firstName)
await this.page.getByTestId("speaker-last-name-input").fill(data.lastName)
await this.page.getByTestId("speaker-submit-button").click()
}
async getSpeakerCard(name: string) {
return this.page.getByTestId("speaker-card").filter({ hasText: name })
}
}
export const test = base.extend<{ speakersPage: SpeakersPage }>({
speakersPage: async ({ page }, use) => {
const speakersPage = new SpeakersPage(page)
await speakersPage.goto()
await use(speakersPage)
},
})
Merging Fixtures
index.ts Pattern
// tests/fixtures/index.ts
import { mergeTests, mergeExpects } from "@playwright/test"
import { test as authTest, expect as authExpect } from "./auth-fixtures"
import { test as speakersTest, expect as speakersExpect } from "./speakers-fixtures"
export const test = mergeTests(authTest, speakersTest)
export const expect = mergeExpects(authExpect, speakersExpect)
Nuxt Hydration Handling
Auto-Wait Fixture
// tests/fixtures/nuxt-fixtures.ts
import { test as base } from "@playwright/test"
export const test = base.extend({
page: async ({ page }, use) => {
// Extend page with Nuxt-aware navigation
const originalGoto = page.goto.bind(page)
page.goto = async (url, options) => {
const response = await originalGoto(url, options)
await page.waitForLoadState("networkidle")
await page.waitForFunction(() => window.__NUXT__?.isHydrating === false)
return response
}
await use(page)
},
})
Test Selector Strategy
data-testid Requirements
<!-- Component -->
<template>
<UCard data-testid="speaker-card">
<UButton
data-testid="speaker-edit-button"
@click="handleEdit" />
<UButton
data-testid="speaker-delete-button"
@click="handleDelete" />
</UCard>
</template>
Using in Tests
// tests/e2e/speakers.spec.ts
import { test, expect } from "../fixtures"
test("edit speaker", async ({ speakersPage }) => {
await speakersPage.page.getByTestId("speaker-edit-button").first().click()
await speakersPage.page.getByTestId("speaker-first-name-input").fill("Updated")
await speakersPage.page.getByTestId("speaker-submit-button").click()
await expect(
speakersPage.page.getByTestId("speaker-card")
).toContainText("Updated")
})
Naming Convention
- USE kebab-case:
{feature}-{element}-{type} - EXAMPLES:
speakers-create-buttonspeaker-first-name-inputspeaker-cardtalk-schedule-dialog
Anti-Patterns
❌ Importing from @playwright/test directly ❌ Using CSS classes or text as selectors ❌ Not waiting for Nuxt hydration ❌ Creating standalone Page Object classes (use fixtures) ❌ Forgetting data-testid attributes
References
- Full patterns:
.agents/e2e-testing-patterns.md - Test checklist:
.agents/test-ready-component-checklist.md
スコア
総合スコア
50/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
レビュー
💬
レビュー機能は近日公開予定です