| name | smoke-test |
| description | Smoke test the running frontend and API by navigating key routes with Playwright, checking for console errors and broken pages. Use after /run-local or to verify the app works before creating a PR. |
| allowed-tools | Bash, Read, Glob, Grep, mcp__playwright__browser_navigate, mcp__playwright__browser_snapshot, mcp__playwright__browser_take_screenshot, mcp__playwright__browser_console_messages, mcp__playwright__browser_wait_for, mcp__playwright__browser_network_requests, mcp__playwright__browser_close, mcp__playwright__browser_click, mcp__playwright__browser_fill_form, mcp__playwright__browser_evaluate |
| user-invocable | true |
Smoke Test
Navigate key application routes using Playwright and verify they render without errors.
Arguments
--frontend-only — Only test frontend routes (skip API health checks)
--api-only — Only test API health endpoints
--interactive — Run interactive CRUD flows after route testing (creates test data)
--screenshot — Take screenshots of each page (saved to /tmp/smoke-test/)
{url} — Test a specific URL instead of the default routes
Prerequisites
The local environment must be running. If not, suggest running /run-local first.
Process
Step 1: Verify Services Are Up
Check that the expected ports are responding before running browser tests:
curl -sf http://localhost:5000/health/live > /dev/null 2>&1 && echo "API: UP" || echo "API: DOWN"
curl -sf http://localhost:5173 > /dev/null 2>&1 && echo "Frontend: UP" || echo "Frontend: DOWN"
curl -sf https://localhost:15888 -k > /dev/null 2>&1 && echo "Aspire: UP" || echo "Aspire: DOWN"
If services are down, STOP and suggest /run-local.
Step 2: API Health Checks (unless --frontend-only)
curl -sf http://localhost:5000/health/ready | python3 -m json.tool 2>/dev/null || echo "Health check failed"
Step 2.5: Authenticate (Frontend only)
Before testing frontend routes, log in using the API key form flow:
browser_navigate to http://localhost:5173/login
browser_fill_form with apiKey: "dev-api-key-1"
browser_click on the Continue/Sign In button
browser_wait_for redirect away from /login
If login fails (stays on /login after 5 seconds), fall back to localStorage injection:
browser_evaluate to set auth state:
localStorage.setItem('auth-storage', JSON.stringify({
state: { isAuthenticated: true, apiKey: 'dev-api-key-1', tenantId: 'dev-tenant' },
version: 0
}))
browser_navigate to http://localhost:5173/ to reload with auth
Step 3: Frontend Smoke Test (unless --api-only)
Navigate to each key route and verify it loads:
Routes to test:
/ — Landing/dashboard page
/devices — Device list
/bundles — Bundle list
/groups — Device groups (if exists)
For each route:
- Navigate using
mcp__playwright__browser_navigate
- Wait for the page to settle using
mcp__playwright__browser_wait_for (wait for network idle or a known element)
- Snapshot the page using
mcp__playwright__browser_snapshot to check the accessibility tree for content
- Check console using
mcp__playwright__browser_console_messages for errors
- Screenshot (if
--screenshot) using mcp__playwright__browser_take_screenshot
Step 3.5: Interactive CRUD Flows (only when --interactive)
Skip this step unless --interactive was passed.
Create Bundle flow:
browser_navigate to http://localhost:5173/bundles
browser_snapshot to find the "Create Bundle" button
browser_click on the Create Bundle button
browser_wait_for the dialog/form to appear
browser_fill_form with test data: name smoke-test-{timestamp}, version 1.0.0
browser_click on the submit button
browser_network_requests — verify POST to /api/bundles returned 2xx
browser_take_screenshot to capture the result
browser_snapshot to verify the new bundle appears in the list
Device detail flow:
browser_navigate to http://localhost:5173/devices
browser_snapshot to check if device rows exist
- If rows exist:
browser_click on the first device row
browser_wait_for the detail page to load
browser_snapshot to verify detail page has expected content (tabs, status, info)
Step 4: Check for Problems
Flag issues:
- Console errors — any
error level messages in the browser console
- Network failures — check
mcp__playwright__browser_network_requests for failed requests (4xx/5xx)
- Empty pages — snapshot shows no meaningful content
- Auth redirects — unexpected redirects to /login
Step 5: Cleanup
Close the browser session:
mcp__playwright__browser_close
Output Format
## Smoke Test Results
### API Health
| Endpoint | Status |
|----------|--------|
| /health/live | PASS |
| /health/ready | PASS |
### Frontend Routes
| Route | Status | Console Errors | Notes |
|-------|--------|---------------|-------|
| / | PASS | 0 | Dashboard rendered |
| /devices | PASS | 0 | Device table loaded |
| /bundles | FAIL | 2 | "TypeError: Cannot read property..." |
### Interactive Flows (if --interactive)
| Flow | Status | Notes |
|------|--------|-------|
| Create Bundle | PASS | Created "smoke-test-1710345600", visible in list |
| Device Detail | SKIP | No devices registered |
### Console Errors
- `/bundles`: `TypeError: Cannot read property 'map' of undefined` at bundles-overview.tsx:42
### Network Failures
- None
### Summary: {PASS / FAIL}
{N routes tested, M passed, K failed}
Guidelines
- This is a fast smoke test, not a comprehensive E2E suite
- Check for obvious breakage, not pixel-perfect rendering
- Console errors are the most valuable signal
- If auth is required and no credentials are available, note which routes redirected to login
- Don't fail on warnings, only on errors
Error Handling
- Services not running: STOP and suggest
/run-local before retrying.
- Playwright not available: Suggest installing with
npx playwright install or skip browser tests and fall back to curl-based health checks only.
- Auth required: Note which routes redirected to login and report as "SKIPPED (auth required)" rather than "FAIL".
Related Skills
/run-local to start the environment first
/add-feature to scaffold the feature, then smoke test it
/diagnose if smoke test reveals issues