一键导入
angular-user-journey
Simulate full user journeys (signup -> login -> dashboard -> purchase) via MCP Playwright with screenshots and timing at each step
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Simulate full user journeys (signup -> login -> dashboard -> purchase) via MCP Playwright with screenshots and timing at each step
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Reusable MCP Playwright code snippets for testing this Angular + DaisyUI + Supabase app — auth helpers, form filling, toast checking, table extraction
Capture baseline screenshots of all app pages and pixel-diff on subsequent runs to detect unintended UI changes
Guide for exposing services via ASD tunnels — asd expose, asd.yaml network config, with/without Caddy, auth rules
| name | angular-user-journey |
| description | Simulate full user journeys (signup -> login -> dashboard -> purchase) via MCP Playwright with screenshots and timing at each step |
| user_invocable | true |
| arg_description | Journey name: full | signup | login | purchase | dashboard (default: full) |
Simulate end-to-end user journeys through the ASD Angular Supabase app using MCP Playwright. Each journey captures screenshots, checks for console errors, and reports timing.
http://localhost:4200
This skill file must be kept up to date by Claude. When you encounter selectors or journey steps that no longer work, or discover new reusable patterns for common user flows, update this SKILL.md immediately. Outdated skills waste time — fix them as you find them.
| Journey | Description |
|---|---|
full | Signup -> Login -> Dashboard -> Purchase -> Sign Out |
signup | Create account, verify confirmation message |
login | Sign in, verify redirect to dashboard |
purchase | Pricing -> Select plan -> Payment callback |
dashboard | Login -> Dashboard stats -> Orders -> Settings |
/)h1.text-5xl.hero-content a.btn.btn-primary (scoped — navbar also has btn-primary).hero-content a.btn.btn-outline[href="/dashboard"]/auth/login)h2.card-title (text: "Sign In")input#email[type="email"]input#password[type="password"]button.btn.btn-primary[type="submit"].alert.alert-errora[href="/auth/signup"]/auth/signup)h2.card-title (text: "Create Account")input#email[type="email"]input#password[type="password"] (minlength 8)button.btn.btn-primary[type="submit"].alert.alert-success (text: "Check your email for a confirmation link.").alert.alert-errora[href="/auth/login"]/pricing)h1 (text: "Pricing").card.bg-base-200 (3 cards: Starter/Pro/Enterprise)h2.card-title (text: "Starter", "Pro", "Enterprise")span.text-4xl.font-bold (text: "€9", "€29", "€99") — use exact match (getByText('€9', { exact: true })) to avoid €9 matching €99.card-actions button.btn.btn-primary (text: "Get Started").alert.alert-error/payment/callback)h1.card-title (text: "Payment Submitted")a.btn.btn-primary[href="/dashboard/orders"].card-body a.btn.btn-ghost:has-text("Back to Home") (scoped — navbar logo also has btn-ghost href="/")/dashboard)h1 (text: "Dashboard")a.btn[href="/dashboard/orders"] (text: "Orders")a.btn[href="/dashboard/settings"] (text: "Settings").stat-card (User, Status, Platform).stat-card .font-semibold/dashboard/orders)h2 (text: "Order History").loading.loading-spinnertable.tableth (Date, Description, Amount, Status)span.badge with .badge-success / .badge-warning / .badge-error / .badge-ghost/dashboard/settings)h2.card-title (text: "Account Settings").font-mono (user ID)button.btn.btn-error (text: "Sign Out").navbar a.btn.btn-ghost.text-xl (in .flex-1).navbar a.btn.btn-ghost.btn-sm:has-text("Pricing") (in .flex-none).navbar a.btn.btn-ghost.btn-sm:has-text("Dashboard") (authenticated only).navbar button.btn.btn-outline.btn-sm:has-text("Sign Out") (authenticated only).navbar a.btn.btn-primary.btn-sm:has-text("Sign In") (unauthenticated only)footer (text: "Built with ASD Platform")// MCP Playwright: init-browser
// Viewport: 1400x900, headless
await page.goto('http://localhost:4200')
await page.waitForLoadState('networkidle')
For each step:
await page.waitForLoadState('networkidle')/dashboard/**, /auth/callback, /payment/callback), also wait: await page.waitForSelector('[relevant-element]')page.on('console', msg => { if (msg.type() === 'error') ... })Output a summary table:
| Step | URL | Screenshot | Time (ms) | Console Errors |
|---|
full/, verify hero heading visible, screenshot/auth/login/dashboard, verify statssignupSteps 1-4 from the full journey.
loginSteps 5-7 from the full journey (requires existing account).
purchase/pricing, verify 3 plan cardsdashboardSteps 5-9 from the full journey (requires existing account).
DaisyUI button classes repeat across navbar and page content. Always scope with a parent container to avoid strict mode violations:
| Element | Wrong (ambiguous) | Correct (scoped) |
|---|---|---|
| Hero CTA | a.btn-primary[href="/auth/login"] | .hero-content a.btn-primary |
| Navbar Sign In | a.btn-primary[href="/auth/login"] | .navbar a.btn-primary.btn-sm |
| Back to Home | a.btn-ghost[href="/"] | .card-body a.btn-ghost:has-text("Back to Home") |
| Navbar logo | a.btn-ghost[href="/"] | .navbar a.btn-ghost.text-xl |
Supabase local includes Mailpit for capturing auth emails:
http://localhost:54324localhost:54325http://localhost:54324/api/v1/messagesUse after signup to verify confirmation emails are sent.
/), Pricing (/pricing) are prerendered. Dashboard (/dashboard/**), Auth Callback, Payment Callback are client-rendered. Client pages need explicit waits for content./dashboard without auth redirects to /auth/login. Test this behavior explicitly.networkidle wait state. For Angular signals/change detection, wait for specific elements rather than arbitrary timeouts..loading.loading-spinner and become disabled during async operations. Wait for spinner to disappear before asserting results.