Skip to main content
ASoc
Comparison

Cypress vs. Storybook: A Test Runner and a Workshop, Not Rivals

They overlap on one thing and solve different problems. What each catches, what browser binaries cost every CI install, and four defects here that neither would have found.

The ASoc Team9 min read

Cypress and Storybook are not alternatives to each other. Cypress is a test runner that drives a real browser and asserts behaviour; Storybook is a component workshop that renders components in isolation so you can build, document and review them. They overlap on exactly one capability — rendering a single component in a browser — and teams that run both use Cypress to verify and Storybook to build.

So "Cypress vs Storybook" is usually the wrong question. The useful one is: which class of defect am I buying coverage for, and what does that coverage cost to install and keep? This post answers that, and then gives the honest third data point — this storefront runs neither, and the defects it actually shipped say something about why.

The short answer

CypressStorybook
Primary jobRun tests against a browserBuild and document components in isolation
CatchesBroken user flows, wrong behaviour, regressionsVisual and API drift, unclear component contracts
ScopeWhole app (E2E) or one componentOne component, one state at a time
AssertionsCore featureVia addons (interaction, visual regression)
Produces docsNoYes — a browsable component catalogue
Runs in CIYes, headlessYes, via its test runner or a visual-diff service
Needs the app to bootYes for E2E, no for component testsNo
Dev dependency weightHeavy (browser binaries)Heavy (its own build pipeline)
Best fitApps with flows worth regression-testingDesign systems and shared component libraries

Pick Cypress if your risk is "the checkout broke and nobody noticed." Pick Storybook if your risk is "nobody knows this component has eleven props and three of them conflict." Pick both if you maintain a component library that an app depends on — that is the case where their jobs genuinely stack, and Cypress's Storybook integration lets you reuse stories as test fixtures.

Where the overlap actually is

Cypress component testing was the feature that made this comparison a real question. It renders a single component in a real browser, without routing or booting the rest of the app, which is substantially what Storybook does — and it is faster and less flaky than an E2E test of the same component, because there is no page load or navigation in the way.

What it does not give you is the artefact. Cypress component tests leave behind a pass/fail result; Storybook leaves behind a browsable catalogue that a designer, a PM, or a new engineer can open. If the reason you were considering Storybook is "our components are undocumented," Cypress does not solve it, and the reverse is also true: Storybook's interaction testing addon writes assertions, but you would not build an E2E suite in it.

Running them together is supported and costs setup. Reusing stories as Cypress fixtures means the test runner, the story and the component all participate in the render, and some Storybook features (controls, knobs) have historically not carried over. It is worth it when the stories already exist; it is not a reason to create them.

The third option, with numbers

This storefront is a Next.js 16 marketplace: 772 prerendered pages, 92 component files, 111 products. It runs no Cypress, no Storybook, and no component tests of any kind. That is not a recommendation — it is a data point about what kind of codebase can skip both, and what it needs instead.

What it does run, measured on the current tree:

npm test
# Test Files  31 passed (31)
#      Tests  391 passed (391)
#   Duration  7.44s  (transform 4.50s, tests 2.85s)

391 assertions in 2.85 seconds of actual test time, with one dev dependency (vitest) and no browser. The suite grew from 273 tests at an earlier quality gate to 391, and it has not needed a browser yet, because of what it asserts: data and logic invariants, not rendered output. src/data/__tests__/blog.test.ts is representative — 18 assertions covering whether slugs are unique and URL-safe, whether every post has a registered loader and every loader a post, whether dates are real calendar dates, whether internal link targets resolve to products and pages that exist.

The reason that is enough here is the shape of the codebase: 92 components, of which 68 are Server Components with no interactivity at all, rendering content that comes from typed arrays. The defect that actually hurts is not "the button does not open" — it is "the button links to a product that was retired," and no component test finds that.

The defects it did ship, and what caught them

Four real ones, each caught by something that is neither Cypress nor Storybook:

  1. /blog had no <h1> at all. Caught by a Lighthouse accessibility audit, after the page had been live.
  2. /docs skipped from h1 to h3. Same audit.
  3. BlogTag missed AA contrast by a hundredth — text-primary (#465fff) on bg-primary-25 (#f2f7ff) at 12px measures 4.49:1 against a 4.5:1 requirement.
  4. The "Keep reading" rail concentrated every internal link on 12 posts out of 178 — three of them collecting 111 inbound links each — leaving 166 posts with none. Caught by writing a data invariant, after Search Console reported 35 uncrawled posts.

That list is the argument of this whole post. Numbers 1–3 are rendering defects, exactly the category Storybook is for — and a story would have rendered all three without complaint, because a story shows you a component, and all three are properties of the page the component lands on, or of a contrast ratio no human eye catches at 0.01. What found them was an automated audit against real built pages. Number 4 is a property of a data structure across 178 items, which no browser-based tool of either kind would surface; what found it was 20 lines of arithmetic over an array, and it is now a permanent assertion:

✓ spreads inbound rail links evenly instead of concentrating them

npm test now fails if any post drops to zero inbound rail links or one collects more than six. That assertion is cheap, instant, and guards a defect that cost real indexing.

The install cost nobody budgets for

The axis most comparisons skip, and the one that decided it here. Playwright is used in this repo — for screenshot capture, not testing — and it is deliberately not a dependency:

// scripts/release/capture-gallery.mjs
//
// playwright is NOT a dependency of the storefront (it would cost every CI
// install for a script that runs a few times a year) -- install it ad hoc:
//   npm install --no-save playwright
import { chromium } from "playwright";

A browser-driving tool means browser binaries in every CI install, on every pull request, forever. For a script that runs a few times a year, --no-save is the right trade. For a test suite that must run on every push, you cannot dodge it that way — the cost is permanent, and it is the real price of both Cypress and Storybook. Worth pricing explicitly before adopting either, because it is paid by every contributor and every CI minute, not just by the person who set it up.

Which to choose, by what you are building

Your situationReach forWhy
Shared component library, several consumersStorybookThe catalogue is the deliverable, not a side effect
App with a checkout, auth, or multi-step flowCypressThose flows break silently and cost money
Design system plus the app that consumes itBothStories as fixtures; Cypress asserts the behaviour
Content/data-driven site, mostly Server ComponentsNeither yetYour defects are in the data — assert the invariants first
Deciding between component tests and E2ECypress component tests firstFaster, less flaky, no routing or app boot

The row to argue with is the fourth, so here is the condition on it: it holds while your interactive surface is small and your content surface is large. The moment this storefront gained a checkout, a download authorisation path and an account dashboard, it gained flows worth E2E coverage — and that is the point at which Cypress starts earning its install cost here. The logic underneath those flows is currently covered by unit tests instead (entitlements, download authorisation, webhook signature verification, refund eligibility), which is cheaper and catches a different, narrower set of bugs. That is a deliberate position with a known gap, not a claim that browser tests are unnecessary.

Mistakes and troubleshooting

SymptomCauseFix
Storybook adopted, bugs still shipStories render components; they do not assert behaviourAdd the interaction/visual-diff addons, or a test runner
Cypress suite is slow and flakyE2E-testing things that are component-levelMove those to Cypress component tests — no routing, no app boot
Stories drift from the real appStory props are maintained separately from the call sitesImport the real data/types into the story instead of inlining props
CI install time doubled after adopting eitherBrowser binaries now download on every installCache the browser path in CI; audit whether the tool must run on every push
Reused stories fail inside CypressControls/knobs and decorators do not all carry overKeep fixture stories plain, without addon-dependent features
Both tools green, accessibility still brokenNeither audits a real built page by defaultAdd an automated a11y audit against built routes
Both tools green, links point nowhereRendered output is correct; the data is wrongAssert data invariants in a plain unit test

Frequently asked questions

Is Storybook a testing tool? Not by itself. It renders components in isolation and documents them; assertions come from addons (interaction testing, visual regression) or from an external runner. If you need pass/fail in CI, that is a decision on top of Storybook, not something it gives you.

Can Cypress replace Storybook? For verifying a component's behaviour, largely yes — its component tests render in a real browser without booting the app. For documenting a component so other people can discover it, no. Cypress produces results; Storybook produces a catalogue.

Do I need either for a static marketing site? Usually not. On a content-driven site most defects are in the data and the markup semantics, which plain unit tests and an automated accessibility audit catch faster and for a fraction of the install cost.

What about Playwright instead of Cypress? Playwright covers the same E2E ground with multi-browser support and a different API, and it carries the same browser-binary install cost. This repo uses it, but for screenshot automation rather than testing — see Playwright automated screenshots, and Playwright vs Vitest for the testing comparison.

Templates in this post

ASoc Amplify is a social-media-management SaaS marketing site with services, results stats and a journal. ASoc Atelier is a designer's portfolio and studio site with selected work, services and a booking funnel. ASoc Axiom is a neural-networks AI-consultancy landing page with four services, an FAQ and project-based pricing.

Browse the full sets: Next.js landing page templates, Tailwind landing page templates.

Keep reading

Comparison8 min read

esbuild vs. Vite: What This Repo's Own Lockfile Says

Neither is a dependency here — but the Vite version vitest pulls in has already dropped esbuild for Rolldown, proven straight from the lockfile.

Read more
Comparison9 min read

Fathom vs. Vercel Analytics: Portability, Priced

Both are cookieless with a one-line install. The difference is what happens when you leave your host, measured against this site's live CSP, event wrapper and Lighthouse run.

Read more