@scrymore/scry-sbcov
v0.3.0
Published
Storybook story coverage analyzer for React component libraries
Maintainers
Readme
scry-sbcov
A CLI tool that analyzes React component libraries to identify gaps in Storybook story coverage. Generates comprehensive JSON reports suitable for CI integration, quality gates, and coverage tracking.
Features
- Detect components without stories - Find React components that have no corresponding Storybook stories
- Analyze scenario coverage - For components with stories, identify missing prop variants and states (loading, error, disabled, etc.)
- Track new vs existing code - SonarQube-style analysis showing coverage metrics separately for new/modified code in PRs
- Execute and validate stories - Run stories to detect broken/failing stories (render errors, play function failures)
- Generate actionable reports - JSON output with suggested story names and args for missing scenarios
Installation
npm install @scrymore/scry-sbcov --save-devOr run directly with npx:
npx @scrymore/scry-sbcovQuick Start
# Basic analysis with output to file
scry-sbcov --output coverage.json
# CI mode with quality gates
scry-sbcov --ci --base origin/main --threshold-new-code 90
# With story execution (requires playwright)
scry-sbcov --execute --storybook-static ./storybook-static --output report.json
# Verbose output
scry-sbcov -vCLI Options
scry-sbcov [options]
Options:
-c, --config <path> Path to config file (default: scry-sbcov.config.js)
-o, --output <path> Output JSON report path (default: stdout)
--include <glob> Component file patterns (comma-separated)
--exclude <glob> Patterns to exclude (comma-separated)
--stories <glob> Story file patterns (comma-separated)
--base <branch> Base branch for new code analysis (default: main)
--no-git Disable git-based new code analysis
--execute Run stories and capture failures
--storybook-url <url> Storybook URL for execution (default: http://localhost:6006)
--storybook-static <dir> Path to static Storybook build
--ci CI mode: exit code 1 if quality gate fails
--threshold-component <n> Component coverage threshold % (default: 80)
--threshold-new-code <n> New code coverage threshold % (default: 90)
-v, --verbose Verbose output
--version Show version
--help Show helpConfiguration
Create a scry-sbcov.config.js file in your project root:
// scry-sbcov.config.js
module.exports = {
// Component detection
include: ['src/components/**/*.tsx'],
exclude: ['**/*.test.tsx', '**/*.spec.tsx', '**/index.tsx', '**/__mocks__/**'],
// Story detection
storyPatterns: ['**/*.stories.tsx', '**/*.stories.ts'],
// Git analysis
baseBranch: 'main',
enableGitAnalysis: true,
// Story execution
execute: false,
storybookUrl: 'http://localhost:6006',
storybookStaticDir: null,
executionTimeout: 15000,
// Quality gates
thresholds: {
componentCoverage: 80,
propCoverage: 70,
variantCoverage: 60,
newCodeCoverage: 90,
},
// Output
outputPath: './scry-sbcov-report.json',
// Scenario detection customization
scenarioPatterns: {
loading: ['isLoading', 'loading', 'isProcessing'],
error: ['isError', 'hasError', 'error', 'errorMessage'],
empty: ['isEmpty', 'empty', 'noData'],
disabled: ['disabled', 'isDisabled'],
},
// Component matching overrides
componentStoryMapping: {
// Manual overrides for complex cases
'src/components/Button/BaseButton.tsx': 'src/components/Button/Button.stories.tsx',
},
};You can also add configuration to package.json:
{
"scry-sbcov": {
"include": ["src/components/**/*.tsx"],
"thresholds": {
"componentCoverage": 85
}
}
}Report Output
The tool generates a comprehensive JSON report with the following structure:
interface StoryCoverageReport {
version: '1.0.0';
generatedAt: string;
// Git context
git: {
commitSha: string;
branch: string;
baseBranch: string | null;
baseCommitSha: string | null;
};
// Summary metrics
summary: {
totalComponents: number;
componentsWithStories: number;
componentsWithoutStories: number;
totalStoryFiles: number;
totalStories: number;
metrics: {
componentCoverage: number;
propCoverage: number;
variantCoverage: number;
scenarioCoverage: number;
};
health: {
status: 'healthy' | 'degraded' | 'broken' | 'not_executed';
passingStories: number;
failingStories: number;
passRate: number;
};
};
// New code analysis
newCode: {
enabled: boolean;
since: string;
newComponents: { total: number; withStories: number; coverage: number };
modifiedComponents: { total: number; newPropsAdded: number; coverage: number };
};
// Per-component coverage
components: ComponentCoverage[];
// Actionable recommendations
missingScenarios: MissingScenario[];
uncoveredComponents: UncoveredComponent[];
// Quality gate results
qualityGate: {
passed: boolean;
checks: QualityCheck[];
};
}CI Integration
GitHub Actions
name: Story Coverage
on: [pull_request]
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for git analysis
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Build Storybook
run: npm run build-storybook
- name: Run scry-sbcov
run: |
npx scry-sbcov \
--base origin/main \
--execute \
--storybook-static ./storybook-static \
--output coverage-report.json \
--ci
- name: Upload Report
uses: actions/upload-artifact@v4
with:
name: story-coverage-report
path: coverage-report.jsonGitLab CI
stages:
- build
- test
build-storybook:
stage: build
image: node:20
script:
- npm ci
- npm run build-storybook
artifacts:
paths:
- storybook-static
expire_in: 1 hour
story-coverage:
stage: test
image: node:20
needs:
- job: build-storybook
artifacts: true
variables:
GIT_DEPTH: 0 # Required for git analysis
script:
- npm ci
- npx scry-sbcov --base origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --output coverage-report.json --ci
artifacts:
paths:
- coverage-report.jsonProgrammatic Usage
import { analyze, loadConfig } from '@scrymore/scry-sbcov';
const config = await loadConfig({
base: 'main',
thresholdComponent: 80,
});
const report = await analyze(process.cwd(), config, true);
console.log(`Coverage: ${report.summary.metrics.componentCoverage}%`);
console.log(`Quality Gate: ${report.qualityGate.passed ? 'PASSED' : 'FAILED'}`);Detected Patterns
Component Types
- Function components
- Arrow function components
forwardRefwrapped componentsmemowrapped components- Class components (extending React.Component/PureComponent)
- HOC-wrapped components
Scenario Detection
The tool automatically detects common UI scenarios based on prop naming patterns:
| Pattern | Scenario |
|---------|----------|
| isLoading, loading, isProcessing | Loading State |
| isError, hasError, error | Error State |
| isEmpty, empty, noData | Empty State |
| disabled, isDisabled | Disabled State |
| isOpen, open, expanded | Open State |
| isVisible, visible, hidden | Visibility State |
| isSelected, selected, checked | Selection State |
Variant Coverage
For props with union literal types (e.g., variant: 'primary' | 'secondary'), the tool tracks which specific values are covered by stories.
Story Execution
To detect broken stories at runtime, install Playwright:
npm install playwright --save-devThen run with the --execute flag:
scry-sbcov --execute --storybook-url http://localhost:6006
# or with a static build
scry-sbcov --execute --storybook-static ./storybook-staticStory execution detects:
- Render errors
- Play function failures
- Console errors
- Timeouts
Requirements
- Node.js >= 18.0.0
- TypeScript project (for full prop extraction)
- Storybook (CSF 3 format recommended)
Optional Dependencies
playwright- Required for story execution
Development
Setup
git clone https://github.com/epinnock/scry-sbcov.git
cd scry-sbcov
npm installAvailable Scripts
npm run build # Build TypeScript to dist/
npm run dev # Build in watch mode
npm run test # Run tests in watch mode
npm run test:run # Run tests once
npm run test:coverage # Run tests with coverage report
npm run lint # Run ESLint
npm run typecheck # Run TypeScript type checkingCI Checks
Pull requests automatically run the following checks:
| Check | Command | Description |
|-------|---------|-------------|
| Type Check | npm run typecheck | Validates TypeScript types |
| Lint | npm run lint | Checks code style with ESLint |
| Tests | npm run test:run | Runs unit and integration tests |
| Build | npm run build | Ensures project compiles |
| Dogfood | CLI on fixtures | Runs scry-sbcov on test fixtures |
Tests run on Node.js 18, 20, and 22 to ensure compatibility.
Project Structure
scry-sbcov/
├── src/
│ ├── cli/ # CLI entry point and config loading
│ ├── core/ # Main analyzer, coverage calc, report gen
│ ├── detectors/ # Component detection (ts-morph)
│ ├── parsers/ # Story file parsing
│ ├── analyzers/ # Git analysis
│ └── types/ # TypeScript interfaces
├── tests/
│ ├── fixtures/ # Sample React components for testing
│ └── *.test.ts # Test files
└── bin/ # CLI executableContributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Ensure all CI checks pass locally:
npm run typecheck && npm run lint && npm run test:run && npm run build - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT
