Storybook Testing
Storybook serves as the component documentation and local interaction layer. Stories span all three UI packages (shared, admin, client) and are aggregated into a single Storybook instance hosted from packages/shared.
The public component library deploys as a standalone Vercel-hosted Storybook site at https://design.greengoods.app/. The deployed build uses the public browser dialect as its Storybook chrome and exposes the design-tool import bundle from the same root URL. GitHub Actions validates the build through design.yml; Vercel owns publication.
How To Approach Tests
Storybook stories serve two practical purposes: living component documentation and a fast local surface for exploring component states. The philosophy is that every shared foundation should have a story, and stories should demonstrate the component's range of states — default, edge cases, responsive behavior, and error states.
Storybook is now a light regression gate. The repo CI verifies the DesignMD contract, generated artifacts, design-token runtime projection, banned vocabulary, required Storybook coverage for shared foundations plus curated admin surfaces and client dialect shell stories, story-quality guardrails for admin, shared Canvas, and curated client PWA/public stories, a small browser-mode Storybook test lane for storybook-ci stories, then builds the unified Storybook to catch compile-time issues. Keep the CI tag curated; do not tag every story by default.
Architecture
The Storybook config lives at packages/shared/.storybook/main.ts and pulls stories from three glob patterns:
stories: [
"../src/**/*.stories.@(ts|tsx)", // shared
"../../../packages/admin/src/**/*.stories.@(ts|tsx)", // admin
"../../../packages/client/src/**/*.stories.@(ts|tsx)", // client
]
A custom packageScopedAliasPlugin Vite plugin resolves @/ imports dynamically based on the importing file's package. Files under packages/admin/ resolve @/ to packages/admin/src/, and files under packages/client/ resolve to packages/client/src/.
The preview CSS imports the shared theme plus the admin M3 token/override CSS used by Admin/* stories. Shell and canvas stories should use private helpers from packages/shared/.storybook so their frame matches the intended canvas context without depending on package app entrypoints.
Addons
The current Storybook config enables:
@storybook/addon-a11y-- Accessibility audits via axe-core@storybook/addon-docs-- Autodocs pages fortags: ["autodocs"]@storybook/addon-vitest-- Browser-mode story smoke andplay()tests@storybook/addon-mcp-- Local MCP endpoint for agent access to Storybook knowledge@chromatic-com/storybook-- Visual testing UI integration when Chromatic is configured
Completing Test Coverage
Story Format
All stories use Component Story Format 3 (CSF3). Each story file exports a meta default export and named story exports:
import type { Meta, StoryObj } from "@storybook/react";
import { MyComponent } from "./MyComponent";
const meta = {
title: "Shared/Primitives/MyComponent",
component: MyComponent,
tags: ["autodocs"],
} satisfies Meta<typeof MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: { label: "Click me" },
};
export const Disabled: Story = {
args: { label: "Disabled", disabled: true },
};
Title Hierarchy
Stories are organized by package and ownership in the sidebar:
Shared/Primitives/*,Shared/Canvas/*,Shared/Form/*,Shared/Feedback/*,Shared/Display/*,Shared/Cards/*,Shared/Progress/*-- Storybook-backed shared foundationsShared/Tokens/*-- Design token documentation (colors, typography, shadows, animation, material roles)Admin/Primitives/*-- Admin-onlyAdmin*wrappersAdmin/Shell/*-- Admin-owned canvas shell and account surfacesAdmin/Workflows/*-- Curated reusable admin workflow surfacesClient/PWA/*-- Installed-PWA shell, status, and protected route state catalogsClient/Public/*-- Public browser shell, route frames, and website navigationClient/*-- Legacy client component stories outside the required contract until they are migrated
For consolidated state views, prefer a StateCatalog story name over generic Gallery. Keep individual stories for states that agents need to link to directly, and use the theme toolbar instead of adding one-off dark-mode duplicates unless the component has a dark-mode-specific behavior.
Deterministic Fixtures
Admin stories and shared stories consumed by admin must be deterministic:
- Use fixture helpers from
packages/shared/.storybook/fixtures.ts. - Do not use
Date.now(), zero-argumentnew Date(),picsum.photos, or placeholder IPFS CIDs. - Use the frozen Storybook clock (
STORYBOOK_NOW_SECONDS,hoursAgo,daysAgo,daysFromNow) for relative-time or expiry states. - Use data URL fixture images (
FIXTURE_WORK_MEDIA,FIXTURE_IMAGE_*) instead of live external media.
This is the model for future shared/client cleanup. Full cleanup can happen incrementally, but anything that backs admin review or the client PWA/public shell contract should follow it now.
Design Token Stories
The packages/shared/src/components/Tokens/ directory contains stories that document the design system's visual language:
Colors.stories.tsx-- Semantic color tokens fromtheme.cssTypography.stories.tsx-- Font scales and text stylesShadows.stories.tsx-- Elevation levelsAnimations.stories.tsx-- Motion tokensDesignToolImports.stories.tsx-- Import map for Google Stitch, Claude Design, Storybook MCP, and other tools
These are not interactive components -- they serve as living documentation of the design system.
Design Tool Imports
Storybook prepares a generated static bundle before local dev, test, and build commands run:
cd packages/shared && bun run storybook:prepare-design-assets
The bundle is served from the Storybook root. In the Vercel standalone deploy, that means:
https://design.greengoods.app/DESIGN.md-- canonical Warm Earth DesignMD sourcehttps://design.greengoods.app/DESIGN.browser.md-- preferred public-browser dialect for the component libraryhttps://design.greengoods.app/design-md.generated.json-- machine-readable DesignMD tokenshttps://design.greengoods.app/theme.css-- runtime CSS token projectionhttps://design.greengoods.app/storybook-design-manifest.json-- machine-readable map across design files, story roots, and import surfaceshttps://design.greengoods.app/index.json-- Storybook component and state cataloghttps://design.greengoods.app/social-card.png-- 1200x630 social preview image for shared Storybook links
Google Stitch should load the root DesignMD file, the browser dialect file, and the generated token JSON. Claude Design should load the same files plus index.json so it can reference actual story roots and component states. Storybook MCP remains a local development server capability via @storybook/addon-mcp; the static deploy provides the shareable story index and design exports.
Vercel Deploy
Standalone Storybook publication is owned by Vercel, not GitHub Actions. Configure the Vercel project with:
- Root Directory --
packages/shared - Include source files outside of the Root Directory in the Build Step -- enabled
- Build config -- read from
packages/shared/vercel.json - Production domain --
design.greengoods.app
The shared-package vercel.json moves back to the repository root during install/build commands so Bun can resolve the workspace lockfile and cross-package Storybook stories, then serves packages/shared/storybook-static as the root of design.greengoods.app.
The standalone site also injects Open Graph and Twitter card metadata through Storybook head files. Storybook root URLs and ?path=/docs/... URLs share the same social preview image because the manager shell serves those routes from one static HTML entrypoint.
Agent Workflow
For agent-driven TDD, treat Storybook as the state catalog and Vitest/RTL as the assertion layer:
- add or update a real component story by default; use a mock-only render only when the story is clearly tagged
visual-harness - use deterministic fixtures from
packages/shared/.storybook/fixtures.tsoradminFixtures.ts - use
StateCatalogfor state matrices instead of genericGallery; keep axis catalogs such asVariantGalleryandSizeGallery - write the focused Vitest/RTL test for the behavior or contract
- add a
play()interaction only when it catches meaningful behavior without making the story brittle - tag only stable, high-value story files with
storybook-ci - use Storybook locally to inspect the resulting UI states and interaction paths
That keeps stories useful for exploration without turning CI into a slow, brittle browser harness.
New Admin Component Flow
When adding an admin UI component, build the Storybook state catalog before wiring the component deeply into a route:
- decide ownership first: reusable primitive, hook, provider, store, or config goes in
@green-goods/shared; admin-only workflow or shell composition stays inpackages/admin - compose from existing shared Canvas primitives and admin
Admin*wrappers before adding a new wrapper - add a co-located CSF3 story with deterministic fixtures and the relevant
packages/shared/.storybookdecorators - render the real component by default; use
visual-harnessonly for audited wallet-bound or provider-bound exceptions - cover the useful state catalog: default, loading, empty, error, permission/role, edge, and responsive states where applicable
- add focused Vitest/RTL tests for behavior Storybook cannot prove, such as permissions, routing, mutation handling, and data transforms
- wire the component into the admin route after the Storybook surface is coherent
- run
check:stories,check:story-quality, andbuild-storybook; runtest:stories:cionly when adding or changing curatedstorybook-cicoverage
This keeps Storybook as the first operator-visible review surface while preserving tests as the assertion layer.
Mock Patterns in Stories
Stories that depend on React Query or routing use decorators to provide the necessary context:
export default {
title: "Admin/Workflows/GardenCard",
decorators: [withRouter(["/garden"])],
};
Private Storybook helpers live under packages/shared/.storybook. Prefer those helpers for router, query, theme, and canvas wrappers before adding one-off decorators. For components that rely on shared hooks, mock the hook return values using parameters or wrapper decorators rather than mocking modules directly.
Viewport Patterns
Stories for responsive components include viewport-specific stories:
export const Mobile: Story = {
parameters: {
viewport: { defaultViewport: "mobile1" },
},
};
Admin components use standard responsive breakpoints (sm:, md:, lg:), while some client components use container queries (@[480px]:) for container-aware responsiveness.
Running Tests
# Development server
cd packages/shared && bun run storybook
# Curated browser-mode Storybook smoke / play tests
cd packages/shared && bun run test:stories:ci
# Build static site
cd packages/shared && bun run build-storybook
# Check the required Storybook contract for shared foundations, curated admin surfaces,
# and required client PWA/public shell stories (CI gate)
cd packages/shared && bun run check:stories
# Check admin/shared Canvas plus curated client shell story determinism and harness conventions
cd packages/shared && bun run check:story-quality
CI Integration
The design.yml workflow triggers on PRs that modify DesignMD files, Storybook config, story files, the curated story coverage contract, and component or view files that feed the unified Storybook build. It runs eight required command gates:
- DesignMD lint (
check:design-md) -- Validates the root, admin, client, and docs DesignMD files - Generated DesignMD artifacts (
check:design-generated) -- Confirms generated design artifacts are current - Design-token contract (
check:design-tokens) -- Confirms the shared theme runtime projection still exposes the expected Warm Earth tokens - Vocabulary guardrail (
lint:vocab) -- Blocks banned product and UI vocabulary across protected surfaces - Storybook contract (
check:stories) -- Ensures shared foundations, curated admin surfaces, and required client PWA/public shell stories have corresponding stories - Story quality (
check:story-quality) -- Catches nondeterministic fixtures, unmarked mock harnesses, generic gallery exports, and dark-mode duplicate stories across the protected Storybook surface - Storybook interaction smoke (
test:stories:ci) -- Runs browser-mode Vitest against curatedstorybook-cistories - Build verification (
build-storybook) -- Confirms the static Storybook site compiles without errors across shared, admin, and client stories
The built artifact is uploaded via actions/upload-artifact@v4 for review.
Chromatic Flow
Chromatic is manual opt-in. Normal PR and push runs stop after the local Storybook gates and uploaded artifact:
check:storiesverifies that required shared foundations and curated admin surfaces have stories.test:stories:ciruns browser-mode Vitest against stablestorybook-cistories.build-storybookcreatespackages/shared/storybook-staticand uploads it as the CI review artifact.- A maintainer can run the Design workflow manually with
publish_chromaticenabled to publish the built Storybook to Chromatic when the snapshot budget allows it.
The manual Chromatic lane is intentionally non-blocking for visual diffs: --exit-zero-on-changes lets Chromatic collect baselines and surface screenshot changes without failing the workflow while the design lane is being established. Do not protect the Chromatic UI Tests check unless the team has approved baselines and snapshot budget.
The standalone component library deploy is owned by Vercel. The Storybook GitHub Actions lane remains the validation gate for Storybook coverage, interaction smoke tests, and the static Storybook build artifact.
The docs deploy is owned by docs.yml and only ships Docusaurus. The standalone component library deploy is owned by Vercel, while design.yml remains the GitHub Actions validation gate for design tokens, Storybook coverage, interaction smoke tests, and the static Storybook build artifact.
Resources
- Storybook Documentation -- Official Storybook docs
- CSF3 Format -- Component Story Format reference
- Storybook config:
packages/shared/.storybook/main.ts - Design tokens:
packages/shared/src/components/Tokens/ - CI workflow:
.github/workflows/design.yml - Storybook deploy config:
packages/shared/vercel.json
Next page
Next: Test Cases
Learn about the test case structure and quality standards across the project.
Test Cases