원클릭으로
write-e2e
Write a Playwright E2E test for a specified flow using the project's auth setup pattern
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Write a Playwright E2E test for a specified flow using the project's auth setup pattern
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Implement a numbered testing strategy phase from docs/testing_strategy_phases/phase_$ARGUMENTS_*.md step by step
Implement a numbered phase from docs/phases/phase-$ARGUMENTS.md step by step
Review changed code for correctness, security, and project conventions. Invoke this skill automatically whenever a complete unit of work is done — a full implementation phase, a complete feature (repository + service + route + component all connected), or just before creating a PR. Do NOT invoke after editing a single file or mid-way through a feature. If the user says "done", "finished", "phase complete", "ready to commit", or similar, trigger this review immediately.
Run prisma migrate dev, regenerate client to the correct output path, and verify import paths
Scaffold a Prisma-backed repository for a given Prisma model
Scaffold a service class for a given domain following project conventions
| name | write-e2e |
| description | Write a Playwright E2E test for a specified flow using the project's auth setup pattern |
| disable-model-invocation | true |
| argument-hint | [flow-description] |
Write a Playwright E2E test for: $ARGUMENTS
Read docs/TESTING_STRATEGY.md Phase 4 before writing.
Auth is established ONCE by tests/e2e/auth.setup.ts. Individual tests do NOT perform login.
The storageState: 'playwright/.auth/user.json' is set globally in playwright.config.ts — do NOT add test.use({ storageState }) in your test file unless you need a DIFFERENT auth state.
import { test, expect } from '@playwright/test'
// storageState already loaded — user is pre-authenticated
test.describe('$ARGUMENTS', () => {
test('happy path', async ({ page }) => {
await page.goto('/dashboard')
// ...
})
})
Unauthenticated test (exception):
test('unauthenticated user redirects to login', async ({ page, context }) => {
await context.clearCookies()
await page.goto('/dashboard')
await expect(page).toHaveURL('/login')
})
All E2E tests live in tests/e2e/. Name the file after the flow:
invoices-upload.spec.tsauth-guard.spec.ts// Redirect assertion
await expect(page).toHaveURL('/dashboard')
// Visible element (auto-waits)
await expect(page.getByRole('heading', { name: 'Invoices' })).toBeVisible()
// File upload
await page.locator('input[type="file"]').setInputFiles({
name: 'test.pdf',
mimeType: 'application/pdf',
buffer: Buffer.from('%PDF-1.4 test'),
})
// Network error simulation
await page.route('**/api/invoices', route => route.abort('failed'))
When testing that user A cannot access user B's data, use a SEPARATE browser context for user B:
test('cannot access another user\'s invoice', async ({ page, context }) => {
// page is user A (pre-authenticated via storageState)
// Create a fully isolated context for user B
const secondCtx = await context.browser()!.newContext()
const secondPage = await secondCtx.newPage()
// ... register/login second user, try to access first user's resource
await secondCtx.close()
})
process.env['TEST_USER_EMAIL'] // bracket notation required (TS strict)
process.env['TEST_USER_PASSWORD']
process.env['TEST_BASE_URL'] // default: http://localhost:3000
page.route() to simulate server errors)# If playwright/.auth/user.json is missing:
npx playwright test --project=setup
# Run the new test
npx playwright test tests/e2e/<your-file>.spec.ts --project=chromium