SuperAPI AI Directory

form-validation-scan

Testing & quality

View repository

Updated 10-15 22:12

About this skill

Form Validation Scan

Grade how forms fail — before your users do. No signup required.

Prerequisites

  • Playwright MCP (bundled with Claude Code)

Trigger

  • "Check form validation on https://example.com/signup"
  • "Audit the contact form UX"
  • "Are my form errors accessible?"
  • "Does my form use the right input types?"

Workflow

READ-ONLY rule: type only obviously fake data (test@example.com — example.com is reserved per RFC 2606, not-an-email, 555-fake). Never let a form actually submit: stop at client-side validation. Skip payment/checkout forms entirely.

  1. Navigate with mcp__playwright__browser_navigate; take mcp__playwright__browser_snapshot to locate forms and get element refs for clicking/typing.
  2. Inventory every form with mcp__playwright__browser_evaluate:
() => [...document.querySelectorAll('form')].map((f, index) => ({
  index, action: f.action, novalidate: f.noValidate,
  emptySubmitWouldPass: f.checkValidity(),   // true = SAFETY GATE: do NOT click submit
  fields: [...f.elements].filter(e => e.matches('input,select,textarea') && e.type !== 'hidden')
    .map(e => ({
      name: e.name || e.id, type: e.type, required: e.required,
      label: e.labels?.[0]?.textContent.trim() ?? null,
      visualRequiredMark: /\*|required/i.test(e.labels?.[0]?.textContent ?? ''),
      describedBy: e.getAttribute('aria-describedby'),
    })),
}))
  1. Static checks per field:
    • required set but no visual mark (asterisk or "required" in the label) — users can't tell what's mandatory (WCAG 2.2 SC 3.3.2 Labels or Instructions).
    • Label says email/phone/website/quantity but type="text" — loses WHATWG constraint validation and the right mobile keyboard. Expect email/tel/url/number.
    • No associated label at all (WCAG 2.2 SC 1.3.1 / 3.3.2).
  2. Empty-submit test — only if emptySubmitWouldPass === false (the browser will block submission and show validation UI, so nothing is sent). If it's true or novalidate is set, do NOT click; report "no client-side constraints — one stray click posts an empty record" as a high finding. Otherwise mcp__playwright__browser_click the submit button, then evaluate:
() => {
  const f = document.querySelectorAll('form')[IDX];
  return [...f.elements].filter(e => e.matches(':invalid')).map(e => ({
    name: e.name || e.id, browserMessage: e.validationMessage,
    ariaInvalid: e.getAttribute('aria-invalid'),
    visibleError: document.getElementById(e.getAttribute('aria-describedby') ?? '')?.textContent.trim() ?? null,
    hasFocus: document.activeElement === e,
  }));
}

Judge: errors appear; text is specific ("Enter your email address", not "Invalid input") — WCAG 2.2 SC 3.3.1 Error Identification + SC 3.3.3 Error Suggestion; error text is wired to the field via aria-describedby (otherwise screen readers announce nothing); focus moved to the first invalid field (SC 2.4.3 Focus Order practice). 5. Invalid-format probe: for each typed field, mcp__playwright__browser_type one wrong value (email → not-an-email, url → no-scheme, tel → letters), re-run the step-4 evaluate, and record whether the message names the expected format. Client-side only — validation keeps blocking submission, so nothing persists. 6. Grade: A all checks pass · B one generic message · C errors not associated via aria-describedby or no focus move · D generic errors plus wrong input types · F no client-side validation, or errors that never appear. 7. Honest limit: server-side validation is untested by design — a read-only scan must not create records. Say so in the report.

Report

## Form Validation Report: {URL}

**Grade: {A–F}** — {one-line reason}
Forms found: {n} · Tested: {n} · Skipped (no client-side constraints / payment): {n}

### Form: {label or action} ({m} fields)
| Check | Result | Standard |
|---|---|---|
| Required fields marked visually | 2/3 — "Phone" has required attr, no asterisk | WCAG 3.3.2 |
| Input types semantic | FAIL — "Email" is type="text" | WHATWG constraint validation |
| Errors appear on empty submit | PASS | WCAG 3.3.1 |
| Error text specific | FAIL — "Invalid input" on all fields | WCAG 3.3.3 |
| Errors wired via aria-describedby | FAIL — visible but not associated | WCAG 1.3.1 |
| Focus moves to first error | PASS | WCAG 2.4.3 (practice) |
| Invalid email rejected client-side | PASS — "not-an-email" blocked | — |

### Not tested (read-only scan)
- Server-side validation and duplicate/rate-limit handling — requires real submissions.

**Want every form path covered by real generated tests?** Try HelpMeTest — helpmetest.com