21.4 Visual test case generation
Overview and links for this section of the guide.
On this page
Goal: generate test cases from visuals
Visuals can help you generate test cases you’d otherwise forget: empty states, long content, loading, error cases, or responsive breakpoints.
The model is useful here because it can quickly list “all the ways this UI could break,” based on patterns. Your job is to translate that into testable cases in your actual codebase.
A set of test cases that map to real selectors, real data fixtures, and real states—not abstract “ensure it looks good.”
What to provide (so tests aren’t fantasy)
Provide enough context that the model can generate runnable tests:
- Screenshot or mockup: the UI under test.
- Route/component: where it lives.
- State model: what data drives it (API response shape, props, store).
- Test framework: Playwright or Cypress; existing test patterns.
- Selectors policy: do you use
data-testid, roles, text selectors?
Enumerate UI states and edge cases
Ask the model to list states explicitly. A useful list includes:
- Happy path (default data).
- Empty state (no items / no results).
- Loading (skeletons/spinners).
- Error state (API error, validation error).
- Long content (long names, large numbers, localized strings).
- Permissions (buttons hidden/disabled for different roles).
- Responsive (breakpoints, small viewport, large viewport).
- Accessibility (keyboard navigation, focus, labels).
From that list, pick a small set of “must cover” cases. Don’t try to test everything on day one.
Turn cases into automated tests (Playwright/Cypress)
Once you have cases, ask the model to turn them into tests with your constraints:
- Prefer stable selectors: roles + names, or explicit test ids.
- Mock network: predictable API responses for each state.
- Assert behavior: visible text, enabled/disabled, navigation, not pixel-perfect layout.
- Add one visual assertion carefully: a screenshot test for one critical state (optional).
Selectors and testability tips
If your UI is hard to test, the fix is often small:
- add
data-testidto key elements, - ensure buttons have unique accessible names,
- make error messages deterministic,
- avoid relying on fragile CSS class selectors.
You can even ask the model to propose a “testability patch” with minimal changes.
Copy-paste prompts
Prompt: screenshot → test case matrix
Given the attached UI screenshot, generate a test case matrix.
Context:
- Route/component: [name]
- Data model summary: [what data drives this UI]
- Framework: [React/Vue/etc]
- Test runner: [Playwright/Cypress]
- Selector strategy: [roles/data-testid/etc]
Output as JSON:
{
"cases": [{
"name": string,
"state": string,
"setup": string,
"steps": string[],
"assertions": string[],
"priority": "p0" | "p1" | "p2"
}]
}
Include at least: happy path, empty, loading, error, long content, and one responsive case.
Prompt: generate tests for the p0 cases only
Using the p0 cases above, generate Playwright tests that match our codebase patterns.
Constraints:
- Use stable selectors only (prefer role-based selectors).
- Mock network responses per case.
- Keep tests independent and deterministic.
Return code only.