WHEN testing any front-end UI with DOM Testing Library; behavior-first queries, userEvent flows, async patterns.
View on GitHubplugins/web/skills/frontend-testing/SKILL.md
February 1, 2026
Select agents to install to:
npx add-skill https://github.com/mintuz/claude-plugins/blob/main/plugins/web/skills/frontend-testing/SKILL.md -a claude-code --skill frontend-testingInstallation paths:
.claude/skills/frontend-testing/# Front-End Testing with DOM Testing Library
Framework-agnostic DOM Testing Library patterns for behavior-driven testing. For React-specific patterns (renderHook, context, components), load the `react-testing` skill. For TDD workflow (RED-GREEN-REFACTOR), load the `tdd` skill.
## Core Philosophy
**Test behavior users see, not implementation details.**
Testing Library exists to solve a fundamental problem: tests that break when you refactor (false negatives) and tests that pass when bugs exist (false positives).
### Two Types of Users
Your UI components have two users:
1. **End-users**: Interact through the DOM (clicks, typing, reading text)
2. **Developers**: You, refactoring implementation
**Kent C. Dodds principle**: "The more your tests resemble the way your software is used, the more confidence they can give you."
### Why This Matters
**False negatives** (tests break on refactor):
```typescript
// ❌ WRONG - Testing implementation (will break on refactor)
it("should update internal state", () => {
const component = new CounterComponent();
component.setState({ count: 5 }); // Coupled to state implementation
expect(component.state.count).toBe(5);
});
```
**Correct approach** (behavior-driven):
```typescript
// ✅ CORRECT - Testing user-visible behavior
it("should submit form when user clicks submit", async () => {
const handleSubmit = vi.fn();
const user = userEvent.setup();
render(`
<form id="login-form">
<label>Email: <input name="email" /></label>
<button type="submit">Submit</button>
</form>
`);
await user.type(screen.getByLabelText(/email/i), "test@example.com");
await user.click(screen.getByRole("button", { name: /submit/i }));
expect(handleSubmit).toHaveBeenCalled();
});
```
## Quick Reference
| Topic | Guide |
| -------------------------------------- | ------------------------------------------------