Agent skill
e2e-test
Writes and runs end-to-end tests using Playwright. Use when user asks to "write E2E tests", "add end-to-end tests", "test this user flow", "fix flaky tests", "debug test failures", or "add Playwright tests". Also use when validating user-facing workflows or creating page object models.
Stars
1
Forks
1
Install this agent skill to your Project
npx add-skill https://github.com/jiyeol-lee/dotfiles/tree/main/.opencode/skills/e2e-test
SKILL.md
Workflow
- Discover test setup — Read
playwright.config.ts(or.js) for base URL, test directory, browser config, and timeouts - Identify target flow — Determine which user flow to test from the request
- Check for existing patterns — Glob
**/e2e/**/*.spec.tsor**/tests/**/*.spec.tsto follow existing test structure and naming conventions - Write the test — Follow selector priority, use page object models for complex flows
- Run and verify — Execute with
npx playwright test <file>and report results
Selector Priority
Read references/selectors.md when choosing selectors for test elements or when tests fail due to selector issues.
Quick reference (use in this order):
getByRole— buttons, links, inputs (preferred)getByLabel— form fieldsgetByPlaceholder— inputs with placeholdergetByText— static text contentgetByTestId— last resort, requiresdata-testidattribute
Error Handling
| Error Type | Action |
|---|---|
| Test failures | Document with error message and screenshot |
| Flaky tests | Add retry logic or fix root cause |
| Selector not found | Check selector strategy, suggest data-testid |
| Timeout errors | Increase timeout or fix async handling |
| Missing test deps | Report which dependencies are needed |
| Browser launch failure | Report environment setup issues |
Example
User request: "Write an E2E test for the login flow"
typescript
import { test, expect } from '@playwright/test';
test.describe('Login Flow', () => {
test('should login with valid credentials', async ({ page }) => {
await page.goto('/login');
// Fill login form using semantic selectors
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('securepassword');
await page.getByRole('button', { name: 'Sign in' }).click();
// Verify successful login
await expect(page).toHaveURL('/dashboard');
await expect(page.getByRole('heading', { name: 'Welcome' })).toBeVisible();
});
test('should show error for invalid credentials', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('wrongpassword');
await page.getByRole('button', { name: 'Sign in' }).click();
// Verify error message appears
await expect(page.getByText('Invalid email or password')).toBeVisible();
await expect(page).toHaveURL('/login');
});
});
Key patterns demonstrated:
getByLabelfor form fields (priority 2 — semantic and resilient)getByRolefor buttons (priority 1 — most preferred)getByTextfor error messages (priority 4 — appropriate for dynamic content)expectassertions for URL and element visibility- Happy path AND error path in the same describe block
Constraints
- NEVER hardcode credentials or secrets in test files — use environment variables or test fixtures
- NEVER skip tests without a documented reason (comment explaining why)
- NEVER use
locatorwith raw CSS/XPath when a semantic selector is available - NEVER write tests that depend on execution order between
test()blocks - ALWAYS clean up test data created during tests (use
test.afterEachortest.afterAll) - ALWAYS report flaky test patterns to the orchestrator for investigation
Didn't find tool you were looking for?