원클릭으로
add-e2e-tests
Add end-to-end Playwright tests for a feature using data-testid selectors, with API and UI test patterns.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Add end-to-end Playwright tests for a feature using data-testid selectors, with API and UI test patterns.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Implement a backlog story following the layer order (Domain, Database, API, Frontend, E2E) with TDD.
Review the backlog to determine what to work on next by checking epic and story statuses in docs/backlog/.
Automates pre-commit workflow: lint, test, review changes, then commit with conventional commit format.
Verify a story is complete by checking acceptance criteria, running all tests, and updating status.
Add unit tests for domain logic, database adapters, API endpoints, or frontend components using Vitest patterns.
Create a new user story in the backlog with technical tasks, test scenarios, and epic integration.
| name | add-e2e-tests |
| description | Add end-to-end Playwright tests for a feature using data-testid selectors, with API and UI test patterns. |
CRITICAL: Always use data-testid selectors. Do NOT use getByRole, getByLabel, getByText.
{page}-{element-type}-{name} in kebab-case:
| Type | Prefix | Example |
|---|---|---|
| Input | input- | notes-input-title |
| Button | btn- | notes-btn-save |
| Link | link- | dashboard-link-notes |
| Alert | alert- | notes-alert-error |
| Card | card- | notes-card-{id} |
| Row | row- | notes-row-{id} |
| Page | page | notes-page |
| Title | title | notes-page-title |
import { test, expect } from '@playwright/test';
import { testCredentials, apiUrls, testIds } from '../../fixtures';
test.describe('Feature Name', () => {
test.describe('API @api', () => {
test('should do something via API', async ({ request }) => {
// Login
await request.post(`${apiUrls.base}/auth/login`, {
data: testCredentials.user,
});
// Test API endpoint
const response = await request.get(`${apiUrls.base}/endpoint`);
expect(response.ok()).toBeTruthy();
});
});
test.describe('UI @ui', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/login');
await page.getByTestId('login-input-email').fill(testCredentials.user.email);
await page.getByTestId('login-input-password').fill(testCredentials.user.password);
await page.getByTestId('login-btn-submit').click();
await expect(page.getByTestId('dashboard-page')).toBeVisible();
});
test('should show the feature page', async ({ page }) => {
await page.goto('/feature');
await expect(page.getByTestId('feature-page')).toBeVisible();
});
});
});
For mobile features, create Maestro YAML flows in packages/mobile/maestro/flows/<feature>/.
Use testID prop (not data-testid) on React Native components. Same naming: {screen}-{element-type}-{name}.
appId: com.acme.protopal
---
- launchApp:
clearState: true
- assertVisible:
id: "login-card"
- tapOn:
id: "login-input-email"
- inputText: "admin@protopal.com"
- tapOn:
id: "login-input-password"
- inputText: "Password1!"
- tapOn:
id: "login-btn-submit"
- assertVisible:
id: "dashboard-screen"
# ... feature-specific steps
tapOn: { id: "testID" } — tap an elementinputText: "value" — type text into focused fieldassertVisible: { id: "testID" } — assert element visibleclearText — clear focused inputlaunchApp: { clearState: true } — fresh app startdata-testid attributes to all interactive componentse2e/fixtures/index.ts with new testIdse2e/seed.ts if new test data is needede2e/tests/<feature>/<test-name>.spec.ts@api or @uipnpm test:e2etestID props to all interactive React Native componentspackages/mobile/maestro/flows/<feature>/<flow-name>.yamlpnpm test:e2e:mobile