← Back to list

write-e2e-test
by agentconfig
Elevate your AI assistants by configuring them for any role or workflow. Explore the primitives that unlock their full potential.
⭐ 2🍴 1📅 Jan 24, 2026
SKILL.md
name: write-e2e-test description: Write Playwright E2E tests following project patterns for components and user interactions. Use when adding tests for new features, testing accessibility, or validating responsive behavior.
Write E2E Test
Create Playwright E2E tests for agentconfig.org following project patterns.
Test File Location
All E2E tests live in site/tests/e2e/:
site/tests/e2e/
├── app.spec.ts
├── comparison.spec.ts
├── fileTree.spec.ts
├── navigation.spec.ts
├── primitiveCards.spec.ts
└── theme.spec.ts
Test File Structure
import { test, expect } from '@playwright/test'
test.describe('Feature Name', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/')
})
test('should do something specific', async ({ page }) => {
// Arrange
const element = page.getByRole('button', { name: 'Click me' })
// Act
await element.click()
// Assert
await expect(page.getByText('Success')).toBeVisible()
})
})
Locator Strategy (Priority Order)
Use the most resilient locators, in this order of preference:
1. Role + Name (most resilient)
page.getByRole('button', { name: 'Submit' })
page.getByRole('heading', { name: 'Welcome' })
page.getByRole('navigation')
2. Label/Placeholder (for form elements)
page.getByLabel('Email address')
page.getByPlaceholder('Enter your email')
3. Text content (for static text)
page.getByText('Learn more')
page.getByText(/welcome/i) // regex for flexible matching
4. Test ID (when others don't work)
page.getByTestId('file-tree-node')
5. CSS selectors (last resort)
page.locator('.custom-component')
Common Test Patterns
Navigation
test('should scroll to section when nav link is clicked', async ({ page }) => {
const navLink = page.getByRole('link', { name: 'File Tree' })
const section = page.getByRole('region', { name: 'File Tree' })
await navLink.click()
await expect(section).toBeInViewport()
})
Theme Toggle
test('should toggle between light and dark mode', async ({ page }) => {
const toggle = page.getByRole('button', { name: /theme/i })
await expect(page.locator('html')).toHaveAttribute('data-theme', 'light')
await toggle.click()
await expect(page.locator('html')).toHaveAttribute('data-theme', 'dark')
})
Expandable Content
test('should expand tree node on click', async ({ page }) => {
const treeNode = page.getByRole('button', { name: '.github/' })
const childNode = page.getByRole('button', { name: 'copilot-instructions.md' })
await expect(childNode).not.toBeVisible()
await treeNode.click()
await expect(childNode).toBeVisible()
})
Copy to Clipboard
test('should copy template to clipboard', async ({ page, context }) => {
await context.grantPermissions(['clipboard-read', 'clipboard-write'])
const copyButton = page.getByRole('button', { name: 'Copy template' })
await copyButton.click()
const clipboardText = await page.evaluate(() => navigator.clipboard.readText())
expect(clipboardText).toContain('expected content')
})
Responsive Testing
Test at multiple viewport sizes:
test.describe('Mobile viewport', () => {
test.use({ viewport: { width: 375, height: 667 } })
test('should show mobile navigation', async ({ page }) => {
await expect(page.getByRole('button', { name: 'Menu' })).toBeVisible()
})
})
test.describe('Desktop viewport', () => {
test.use({ viewport: { width: 1280, height: 720 } })
test('should show full navigation', async ({ page }) => {
await expect(page.getByRole('navigation')).toBeVisible()
})
})
Theme Testing
Test both light and dark modes:
test.describe('Dark mode', () => {
test.use({ colorScheme: 'dark' })
test('should render with dark theme colors', async ({ page }) => {
// Verify dark mode specific styling
})
})
test.describe('Light mode', () => {
test.use({ colorScheme: 'light' })
test('should render with light theme colors', async ({ page }) => {
// Verify light mode specific styling
})
})
Test Independence
Each test must be independent:
- Don't rely on state from previous tests
- Use
beforeEachfor common setup - Clean up any side effects
Assertions
Use Playwright's built-in assertions (auto-waiting):
// Good - auto-waits for element
await expect(page.getByText('Hello')).toBeVisible()
await expect(page.getByRole('button')).toBeEnabled()
await expect(page.locator('.item')).toHaveCount(3)
await expect(page.getByRole('link')).toHaveAttribute('href', '/about')
// Bad - doesn't auto-wait
const text = await page.textContent('.item')
expect(text).toBe('Hello')
Test Naming
Use descriptive names that explain the expected behavior:
// Good
test('should expand tree node when clicked', ...)
test('should scroll to File Tree section when nav link is clicked', ...)
test('should display error message when copy fails', ...)
// Bad
test('click test', ...)
test('tree works', ...)
test('test 1', ...)
Running Tests
cd site
bun run test # Run all tests
bun run test:ui # Interactive test UI
Checklist
Before considering tests complete:
- Uses resilient locators (role > text > testid > css)
- Each test is independent
- Test name describes expected behavior
- Uses Playwright auto-waiting assertions
- Covers happy path and edge cases
- Tests responsive behavior if relevant
- Tests both themes if relevant
- No hardcoded waits (
page.waitForTimeout)
Score
Total Score
75/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
✓LICENSE
ライセンスが設定されている
+10
✓説明文
100文字以上の説明がある
+10
○人気
GitHub Stars 100以上
0/15
✓最近の活動
1ヶ月以内に更新
+10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
✓タグ
1つ以上のタグが設定されている
+5
Reviews
💬
Reviews coming soon
