Testing shared Vue components: unit, a11y, visuals?
ability to architect comprehensive component testing.
unit tests (Vitest/Jest) for logic, accessibility tests (axe, Pa11y) for ARIA/keyboard, visual regression (Percy, Chromatic) for rendering.
WHY IT EXISTS: Shared component libraries are high-leverage; a bug in one component breaks 10+ consumer apps. Testing must cover behavior (props, events, state), accessibility (blind and keyboard-only users), and appearance (no unintended styling drift). Manual testing alone is slow and unreliable.
THE MENTAL MODEL: Testing layers. Layer 1 (unit): does the component logic work? Does it handle props, emit events, manage internal state? Layer 2 (accessibility): does the DOM include required ARIA attributes? Can keyboard users navigate? Do screen readers announce content correctly? Layer 3 (visual): do CSS changes unexpectedly break layout, colors, or typography? Each layer catches different issues.
HOW IT WORKS: Use Vitest for unit tests: mount the component, pass props, trigger events, assert output. Use axe-core (or Pa11y) to audit the rendered DOM for accessibility violations (missing labels, invalid ARIA, keyboard traps). Use Percy or Chromatic to capture screenshots on each PR, compare against baseline, and flag pixel-level changes. Integrate all three into CI: unit tests must pass, a11y audit must have zero violations (or a documented allowlist), visual regression must be approved before merge. Storybook is a common hub: write one .stories.vue file per component, run unit tests against it, run a11y audit on the story, and Percy compares each story across browsers and screen sizes.
WHEN IT MATTERS: Public component libraries (Material UI, Chakra) do all three rigorously. Internal libraries benefit too; a color change in a Button component should be caught before it ships to 5 apps. Small teams may start with unit + a11y, add visual regression later.
ONE CONCRETE EXAMPLE: A Button component library. Unit test: Button accepts label, variant (primary, secondary), disabled state; @click emits click event; disabled state disables interaction. A11y test: Button has role="button", aria-label if no text, keyboard focusable (tabindex handled). Visual test: Storybook stories cover all variants (primary enabled, primary disabled, secondary enabled, secondary disabled), Percy captures screenshots on Chrome/Firefox/Safari, and on CSS changes, Percy flags the diff. If a dev changes --button-padding from 8px to 16px, Percy alerts; reviewer approves or rejects the change.
Read the original → storybook.js.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.