Skip to main content
Engineering

Two Kinds of Tests for a Modern Frontend

9 min read

Automated tests catch regressions before users do. But "testing" is not one thing — logic tests and UI tests catch different bugs and run at different speeds.

Vocabulary

Layer Tool Speed Catches
Unit / logic Vitest + jsdom Milliseconds Wrong output from pure functions
UI / interaction Storybook + Chromium Seconds Broken renders, dead click handlers

Steps

Step 1 — Configure Vitest with two projects

typescript

Step 2 — Write a unit test

Place it next to the module it tests:

typescript

Run: yarn test:unit

Step 3 — Write a server utility test

SEO builders and sitemap generators are perfect unit-test targets:

typescript

Step 4 — UI tests live in Storybook stories

No separate Button.test.tsx needed — the story's play() function IS the test:

typescript

Run: yarn test:storybook

Step 5 — Run coverage and wire CI

bash

Both projects gate merges in GitHub Actions.

When to use which

Question Use
Pure function, no DOM? Vitest unit test
Component renders correctly? Storybook story
Click handler fires? Storybook play()
DB row maps to display object? Vitest unit test

Common pitfalls

  • Testing JSX line-by-line with unit tests — slow and brittle. Use Storybook instead.
  • Skipping Storybook tests in CI — broken UI ships silently.
  • 100% coverage on components — aim coverage at logic modules.

Verify it works

Run yarn test. Both projects should pass. Break a mapper intentionally — unit test should fail. Break a button handler — Storybook test should fail.

Takeaway

Vitest for brains. Storybook for eyes. Two projects, one CI pipeline, zero excuses for regressions.