بنقرة واحدة
test-ui
Visual regression testing with Playwright screenshots and AI-powered diff analysis
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Visual regression testing with Playwright screenshots and AI-powered diff analysis
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | test-ui |
| description | Visual regression testing with Playwright screenshots and AI-powered diff analysis |
| user-invocable | true |
/test-uiYou are performing visual regression testing on the Elenvo Next.js application. Your job is to capture screenshots of affected pages, compare them against baselines, identify regressions, fix CSS/layout issues, and update baselines for intentional changes.
The user may optionally pass specific routes as arguments (e.g., /test-ui /dashboard /settings). If provided, test ONLY those routes. Otherwise, auto-detect affected pages from git diff.
If the user provided specific routes as arguments, use those and skip detection.
Otherwise, run git diff --name-only (include both staged and unstaged changes) and map changed files to routes:
| Changed file pattern | Routes to test |
|---|---|
app/(app)/dashboard/* | /dashboard |
app/(app)/settings/* | /settings |
app/(app)/onboarding/* | /onboarding |
app/(app)/retirement/* | /retirement |
app/(app)/insurance/* | /insurance |
app/(app)/financial-overview/* | /financial-overview |
app/(app)/my-plans/* | /my-plans |
app/(app)/ai-advisor/* | /ai-advisor |
app/(app)/advisors/* | /advisors |
app/(public)/page.tsx or app/page.tsx | / |
app/(public)/sign-up/* | /sign-up |
components/layout/* | ALL major routes (layout change affects everything) |
components/ui/* | ALL major routes (shared component change) |
app/globals.css | ALL major routes (global style change) |
tailwind.config.ts | ALL major routes |
The full list of major routes for "ALL" cases: /, /dashboard, /settings, /onboarding, /retirement, /insurance, /financial-overview, /my-plans, /ai-advisor, /advisors
Public routes (no auth needed): /, /sign-up
Authenticated routes (login required): /dashboard, /settings, /onboarding, /retirement, /insurance, /financial-overview, /my-plans, /ai-advisor, /advisors
Print a summary: "Testing X pages: /route1, /route2, ..."
If no routes are affected (e.g., only test files or docs changed), report "No UI-affecting changes detected" and exit.
Check if localhost:3000 is already serving:
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 || true
If NOT running, start it in the background:
npm run dev &
Then wait for it to be ready (poll with curl, max 30 seconds).
mkdir -p .test-ui/current .test-ui/diff .test-ui/baseline
For EACH affected route, capture at two viewports:
Desktop (1280x720):
browser_resize to width=1280, height=720browser_navigate to http://localhost:3000<route>browser_evaluate to check:
document.readyState === 'complete'[data-loading="true"] or .animate-spin visiblebrowser_take_screenshot.test-ui/current/<route-name>-desktop.pngMobile (375x667):
browser_resize to width=375, height=667.test-ui/current/<route-name>-mobile.pngRoute name mapping for filenames: strip leading /, replace / with -. Root / becomes home.
Examples: /dashboard → dashboard, /financial-overview → financial-overview, / → home
Before capturing authenticated routes, you MUST log in first:
http://localhost:3000/sign-in (or the login page)SUPABASE_TEST_EMAIL env var, or fall back to zelin@vt.eduSUPABASE_TEST_PASSWORD env varIf login fails (no test password available), skip authenticated routes and report which routes were skipped due to auth.
If the Playwright MCP tools are not available, write a temporary Playwright script:
// .test-ui/capture.ts — temporary script, delete after use
import { chromium } from 'playwright'
const routes = [
/* detected routes */
]
const viewports = [
{ name: 'desktop', width: 1280, height: 720 },
{ name: 'mobile', width: 375, height: 667 },
]
async function capture() {
const browser = await chromium.launch()
const context = await browser.newContext()
const page = await context.newPage()
// Login if needed
// ... (fill in auth flow)
for (const route of routes) {
for (const vp of viewports) {
await page.setViewportSize({ width: vp.width, height: vp.height })
await page.goto(`http://localhost:3000${route}`, { waitUntil: 'networkidle' })
await page.waitForTimeout(1000) // settle animations
const safeName = route === '/' ? 'home' : route.slice(1).replace(/\//g, '-')
await page.screenshot({
path: `.test-ui/current/${safeName}-${vp.name}.png`,
fullPage: false,
})
}
}
await browser.close()
}
capture()
Run with: npx playwright test .test-ui/capture.ts or npx tsx .test-ui/capture.ts
Delete the script after use.
Check if .test-ui/baseline/ has any .png files.
.test-ui/current/ to .test-ui/baseline//test-ui again after future changes to compare.".test-ui/current/ and .test-ui/diff/ are in .gitignore (baselines are committed)For each screenshot in .test-ui/current/, find its matching baseline in .test-ui/baseline/.
Pixel comparison approach — write and run a small Node script using pixelmatch:
// .test-ui/compare.mjs — temporary, delete after use
import { readFileSync, writeFileSync, readdirSync } from 'fs'
import { PNG } from 'pngjs'
import pixelmatch from 'pixelmatch'
const currentDir = '.test-ui/current'
const baselineDir = '.test-ui/baseline'
const diffDir = '.test-ui/diff'
const files = readdirSync(currentDir).filter((f) => f.endsWith('.png'))
const results = []
for (const file of files) {
const baselinePath = `${baselineDir}/${file}`
const currentPath = `${currentDir}/${file}`
try {
const baseline = PNG.sync.read(readFileSync(baselinePath))
const current = PNG.sync.read(readFileSync(currentPath))
const { width, height } = baseline
const diff = new PNG({ width, height })
const numDiffPixels = pixelmatch(baseline.data, current.data, diff.data, width, height, {
threshold: 0.1,
})
const totalPixels = width * height
const diffPercent = ((numDiffPixels / totalPixels) * 100).toFixed(2)
writeFileSync(`${diffDir}/${file}`, PNG.sync.write(diff))
results.push({ file, diffPercent: parseFloat(diffPercent), numDiffPixels, totalPixels })
} catch (e) {
results.push({ file, error: e.message })
}
}
console.log(JSON.stringify(results, null, 2))
First ensure dependencies are available: npm list pixelmatch pngjs 2>/dev/null || npm install --no-save pixelmatch pngjs
Run: node .test-ui/compare.mjs
Parse the results. For each screenshot:
Delete the temporary comparison script after use.
For each screenshot with diff > 0.5%, visually analyze the changes:
.test-ui/baseline/<name>.png) using the Read tool.test-ui/current/<name>.png) using the Read tool.test-ui/diff/<name>.png) using the Read toolCompare all three images carefully. Categorize the change:
The visual diff matches the code change. Examples:
Action: Mark this baseline for update (Step 6).
An unintended visual change. Examples:
Action: Fix in Step 5.
Minor rendering differences not caused by code changes:
Action: Ignore (treat as PASS).
For EACH analyzed screenshot, print:
📸 <filename>: <CATEGORY> — <brief description of what changed>
For each regression identified:
Identify the root cause: Read the component and CSS files related to the affected page. Look at what changed in the git diff that could have caused this.
Make a targeted fix: Edit ONLY the CSS/layout properties needed. Common fixes:
overflow-hidden or overflow-auto for overflow issuesflex / grid properties for layout shiftsz-index for stacking issuessm:, md:, lg:) for mobile regressionsw-full, min-h-0, shrink-0 for sizing issuesRe-capture: Take new screenshots of ONLY the affected pages/viewports.
Re-compare: Run pixel comparison again on the fixed screenshots.
Verify: If diff is now <= 0.5% or categorized as intentional/acceptable, the fix worked.
Maximum 3 iterations. If a regression persists after 3 fix attempts, report it as needing user attention — it's likely a design-level decision, not a simple CSS bug.
After all analysis and fixes are complete, collect all screenshots that need baseline updates:
IMPORTANT: Do NOT silently update baselines. Present the full list to the user:
🔄 Baseline updates needed:
1. dashboard-desktop.png — INTENTIONAL: new stats card added to header
2. dashboard-mobile.png — INTENTIONAL: new stats card added to header
3. settings-desktop.png — FIXED REGRESSION: sidebar overlap corrected
4. home-desktop.png — NEW: first baseline capture
Confirm baseline updates? (These will be committed to .test-ui/baseline/)
Wait for user confirmation before copying current screenshots to baseline.
Print a final summary table:
╔══════════════════════════════════╤═════════╤═════════╗
║ Page │ Desktop │ Mobile ║
╠══════════════════════════════════╪═════════╪═════════╣
║ / (home) │ ✅ PASS │ ✅ PASS ║
║ /dashboard │ 🔄 UPD │ 🔄 UPD ║
║ /settings │ 🔧 FIX │ ✅ PASS ║
╚══════════════════════════════════╧═════════╧═════════╝
Legend:
Then summarize:
Final status line:
✅ VISUAL TEST PASSED — all pages pass, no action needed🔄 BASELINES UPDATED — intentional changes captured (user confirmed)❌ NEEDS ATTENTION — unresolved regressions requiring user decisionAfter the skill completes:
.test-ui/compare.mjs, .test-ui/capture.ts).test-ui/current/ (useful for manual inspection) but these are gitignored.test-ui/diff/ (useful for manual inspection) but these are gitignored.test-ui/baseline/ are the only committed artifactsEnsure these entries exist in the project .gitignore:
# visual regression testing
.test-ui/current/
.test-ui/diff/
Do NOT gitignore .test-ui/baseline/ — baselines should be committed so the team shares the same visual reference.
Quick unit + property-based test run with AI auto-fix loop
Complete test suite — unit, property, integration, e2e, mutation, and coverage audit
Lighthouse performance/SEO/a11y/best-practices optimization with AI self-loop to push all scores to 90+
Unit + property tests verified by mutation testing with AI self-improvement loop
Implement changes to align code with UX design files (product-ia.md, product-flows.md, product-interactions.md). Reads design specs and modifies code to match.
Product UX review from the user's perspective. Analyzes IA, user flows, and interactions for any web application.