ワンクリックで
e2e-testing
End-to-end testing patterns and best practices. Trigger: When writing or reviewing E2E tests for any layer.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
End-to-end testing patterns and best practices. Trigger: When writing or reviewing E2E tests for any layer.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Paste-ready session summary for context transfer to a new chat. Trigger: User says 'context handoff', 'start fresh', or session needs to continue.
One-at-a-time questioning to fully profile a goal before acting. Trigger: User says 'grill me', goal is vague, or clarification is needed first.
Batch execution with checkpoints. Trigger: When executing plans with batched tasks.
Universal coding principles: DRY, security by default, null guards, and YAGNI. Trigger: When writing or reviewing code in any language or technology.
Accessibility guide (WCAG 2.1/2.2, Level A–AAA). Trigger: When building UI components, interactive elements, or auditing accessibility compliance.
Astro quality patterns: island philosophy, SEO by page type, and Core Web Vitals. Trigger: When reviewing Astro site quality or hydration decisions.
| name | e2e-testing |
| description | End-to-end testing patterns and best practices. Trigger: When writing or reviewing E2E tests for any layer. |
| license | Apache 2.0 |
| metadata | {"version":"1.1","type":"domain"} |
Orchestrates E2E testing strategy and architecture -- delegates to playwright and stagehand skills.
Each test should walk through a real user scenario rather than verifying internal state.
// CORRECT: tests the outcome the user sees
test('customer completes purchase', async ({ page }) => {
await page.goto('/products');
await page.getByRole('button', { name: 'Add to cart' }).first().click();
await page.getByRole('link', { name: 'Cart' }).click();
await page.getByRole('button', { name: 'Checkout' }).click();
await expect(page.getByText('Order confirmed')).toBeVisible();
});
// WRONG: testing internal state
expect(store.getState().cart.items).toHaveLength(1);
Use selectors that survive refactors -- data-testid for complex components, ARIA roles for standard elements.
// CORRECT: resilient selectors
await page.getByTestId('product-card').first().click();
await page.getByRole('navigation').getByRole('link', { name: 'Cart' }).click();
// WRONG: structural selectors that break on layout changes
await page.locator('div > div:nth-child(3) > a.link-blue').click();
Never sleep -- rely on auto-wait or explicit conditions tied to visible DOM changes.
// CORRECT: wait for a real DOM condition
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.getByRole('alert')).toHaveText('Saved');
// WRONG: arbitrary delay
await page.waitForTimeout(2000);
Each test creates its own data and cleans up -- no shared mutable state.
test.beforeEach(async ({ request }) => {
await request.post('/api/test/seed', {
data: { user: 'e2e-user-' + Date.now(), role: 'customer' },
});
});
test.afterEach(async ({ request }) => {
await request.post('/api/test/cleanup');
});
Each user flow has a success path and failure paths. Assert both visible outcomes and absent states — an E2E test that only checks success misses half the contract.
// ✅ POSITIVE: success outcome is visible
await expect(page.getByText('Order confirmed')).toBeVisible();
await expect(page.getByRole('link', { name: 'My orders' })).toBeVisible();
// ✅ NEGATIVE: error state appears on invalid input; success state absent
await page.getByLabel('Email').fill('not-an-email');
await page.getByRole('button', { name: 'Place order' }).click();
await expect(page.getByText('Invalid email')).toBeVisible();
await expect(page.getByText('Order confirmed')).not.toBeVisible();
await expect(page.getByRole('button', { name: 'Place order' })).toBeDisabled();
Playwright assertion matchers — see playwright skill for toBeVisible, toBeDisabled, not.*.
Run E2E as a dedicated CI stage after unit tests; upload artifacts on failure.
e2e-tests:
needs: [unit-tests, build]
steps:
- run: npx playwright install --with-deps
- run: npx playwright test --retries=1 --reporter=html
- uses: actions/upload-artifact@v4
if: failure()
with: { name: playwright-report, path: playwright-report/ }
Browser UI flow?
→ Delegate to the playwright skill
AI-driven automation?
→ Delegate to the stagehand skill
Need test data?
→ Seed via API in beforeEach, clean up in afterEach
Flaky in CI?
→ Add --retries=1, mock external services, upload traces
Testing auth flows?
→ Store storageState and reuse across tests
API-only flow?
→ Use Playwright request fixture or HTTP client
Slow suite?
→ Shard across CI workers with --shard=N/M
import { test, expect } from '@playwright/test';
test.describe('Checkout flow', () => {
test.beforeEach(async ({ request }) => {
await request.post('/api/test/seed', {
data: { products: ['widget-a'], user: 'checkout-user' },
});
});
test('guest completes checkout', async ({ page }) => {
await page.goto('/products');
await page.getByTestId('product-card').first().click();
await page.getByRole('button', { name: 'Add to cart' }).click();
await page.getByRole('link', { name: 'Cart (1)' }).click();
await page.getByRole('button', { name: 'Checkout' }).click();
await page.getByLabel('Email').fill('guest@example.com');
await page.getByRole('button', { name: 'Place order' }).click();
await expect(page.getByText('Order confirmed')).toBeVisible();
});
});
page.route() in CIplaywright install --with-deps--shard=1/4)getByRole, getByTestId, or getByLabelwaitForTimeout or manual sleeps