Reviewing Frontend QA
Given a frontend change (PR, deployed URL, or component), run through the checklist below and report findings as: Severity | Location | Issue | Expected vs Actual | Suggested fix.
Example finding:
[High] LoginForm.tsx:42 - Submit button remains enabled during pending request
Expected: disabled + loading spinner while awaiting response
Actual: button clickable, allows duplicate submissions
Fix: bind disabled={isSubmitting} and show spinner icon
Progress:
- Step 1: Understand intended behavior (spec, design file, ticket, or inferred from context)
- Step 2: Static review of code/markup for obvious defects
- Step 3: Visual review — compare rendered UI to design/spec
- Step 4: Responsive check — test at mobile, tablet, desktop breakpoints
- Step 5: Interaction check — hover, focus, click, keyboard nav, form states
- Step 6: Accessibility audit — semantics, contrast, ARIA, focus order
- Step 7: Edge cases — empty states, long text, error states, slow network
- Step 8: Compile findings by severity, write report
Step 1: Understand intended behavior
Read the ticket/design/spec first. If none exists, infer intent from similar patterns in the codebase and flag ambiguity rather than guessing silently.
Step 2: Static review
Scan for:
- Hardcoded values that should be dynamic (copy, colors, dimensions)
- Missing loading/error/empty states
- Unhandled null/undefined data
- Inline styles that bypass the design system
- Console errors/warnings in dev tools
Step 3: Visual review
Compare against design mockup pixel-by-pixel where possible:
- Spacing, alignment, typography (size/weight/line-height)
- Color values match tokens/theme
- Icons and imagery correct resolution, not stretched/cropped
Step 4: Responsive check
Test at minimum: 320px, 768px, 1024px, 1440px widths.
- No horizontal scroll unless intended
- Text doesn't overflow containers
- Touch targets ≥44px on mobile
- Nav/menu collapses appropriately
Step 5: Interaction check
- All interactive elements have hover/focus/active states
- Keyboard: Tab order logical, Enter/Space activate buttons, Esc closes modals
- Forms: validation messages appear/clear correctly, disabled state during submit
- Loading states don't cause layout shift
Step 6: Accessibility audit
- Semantic HTML (button vs div, proper heading hierarchy)
- Color contrast ≥4.5:1 for text (use WCAG AA as baseline)
- All images have meaningful alt text (or empty alt if decorative)
- Focus visible and follows DOM/tab order
- ARIA used only when native semantics insufficient
Step 7: Edge cases
- Empty state (no data) renders gracefully, not blank/broken
- Very long strings don't break layout (truncate or wrap)
- Error state shown when API fails
- Slow/offline network doesn't hang UI indefinitely
Step 8: Report
Group findings by severity: Blocker / High / Medium / Low / Nit. Blocker = breaks core flow or is inaccessible; Nit = cosmetic polish.
Example 1: Input: PR adds a "Save profile" button with a loading state. Output:
[Medium] ProfileForm.tsx:88 - No error state if save fails
Expected: toast/inline message on API error
Actual: button returns to idle silently, user unaware save failed
Fix: catch error, show inline message "Failed to save. Try again."
[Low] ProfileForm.tsx:12 - Save button uses #2563eb, design spec says #1D4ED8
Fix: update to token `color-primary-600`
Example 2: Input: New pricing page at /pricing, check responsiveness. Output:
[High] Pricing cards overflow viewport at 375px width, causing horizontal scroll
Expected: cards stack vertically below 768px
Fix: add grid-template-columns: 1fr media query at <768px
[Nit] CTA button text wraps awkwardly to two lines on tablet (768px)
Fix: reduce font-size or increase button padding at md breakpoint
- Always state expected vs actual — vague "this looks off" findings aren't actionable.
- Test with real/realistic data, not just happy-path lorem ipsum.
- Check keyboard-only navigation, not just mouse.
- Verify fixes don't regress other breakpoints/states.
- Prioritize ruthlessly — a long list of nits buried with one blocker gets ignored.
- Don't only check desktop at one resolution — most bugs hide at breakpoint edges.
- Don't skip empty/error/loading states — they're often untested but frequently broken.
- Don't rely solely on visual diffing — interaction and a11y bugs are invisible in screenshots.
- Don't report style nitpicks as blockers — reserve severity labels for functional/accessibility impact.
- Don't assume design intent — flag ambiguity instead of silently deciding what's "right."