Capstone: Testing a Real Feature
One feature, one complete test suite, every chapter's tool making an appearance: rendering, real user interaction, async mocking, conditional rendering, and an accessibility check.
The Feature Under Test
LoginForm: an email field and a password field, both required. Submitting calls POST /api/login. While the request is pending, the button reads "Signing in...". A failed login (401) shows an error message. A successful login shows a welcome message.
Setting Up MSW for the Capstone
The Full Test Suite
What This Capstone Demonstrates
| Test | Chapter's Tool Applied |
|---|---|
| Labeled fields render | Ch.3 — query by role/label |
| Empty-submission validation | Ch.4 — userEvent + conditional rendering |
| Pending → success flow | Ch.5 + Ch.6 — findBy/async + MSW |
| Failed-login error | Ch.6 — server.use() error override |
| Accessibility check | Ch.8 — jest-axe |
Chapter 2's runner mechanics (describe/it/expect) sit underneath every single one of these, and Chapter 7's point stands too — this exact same suite, translated to @testing-library/vue or @testing-library/svelte, would look nearly identical.
LoginForm's actual implementation — and know exactly what it's supposed to do: labeled fields, required-field validation, a pending state, a success path, a failure path, and an accessibility baseline. That's the real, practical payoff of everything this course has built toward: tests that document behavior, not just verify it.
LoginForm in relative isolation — no real routing, no real backend, no verification that a successful login actually navigates to a dashboard page. That's Chapter 1's E2E layer, deliberately out of this course's scope from the very first chapter. A real production app would layer Playwright/Cypress tests on top of exactly this kind of component-level suite, not instead of it.
Coding Challenges
Add a sixth test to this suite: confirm that the "Log In" button is disabled while the login request is pending, to prevent a double-submit, using the same MSW setup as the success-path test.
📄 View solutionThis suite's empty-submission test doesn't use MSW at all. Explain why that's correct — what makes that specific behavior different from the login-success and login-failure tests that do need it.
📄 View solutionWrite a short reflection: pick one habit from this course (e.g. query priority, queryBy for absence, resetting MSW handlers, coverage skepticism) that you think you'd have gotten wrong without this course, and explain what would have gone wrong in practice.
📄 View solutionChapter 9 Quick Reference
- A complete feature test suite combines: rendering + query priority (Ch.3), userEvent + conditional rendering (Ch.4), async findBy (Ch.5), MSW + error simulation (Ch.6), and jest-axe (Ch.8)
- Ch.2's describe/it/expect mechanics underpin every test regardless of what's being tested
- Ch.7's cross-framework convergence means this same suite structure transfers to Vue/Svelte with minimal changes
- A well-named test suite documents behavior — readable as a spec, not just a pass/fail gate
- This suite is intentionally not an E2E test — Chapter 1 scoped that layer out from day one
✅ Frontend Testing Complete — 9 / 9 chapters
From the testing pyramid through Jest/Vitest mechanics, the Testing Library philosophy, real component and hook testing, mocking, cross-framework testing, coverage honesty, and accessibility — to a complete, realistic feature test suite. Every habit this course built is meant to transfer directly to real code, in React or otherwise.