Comprehensive guide to the test suite for BDCHM Interactive Documentation
⚠️ NOTE: A diverged version exists atTESTING.root-snapshot-2025-11-03.md(4.6k, newer, Phase 6.4+ focused). This file (17k) is older but more comprehensive. They need to be merged - see TASKS.md.
# Run tests in watch mode (recommended during development)
npm test
# Run all tests once (useful for CI or verification)
npm test -- --run
# Run specific test file
npm test -- adaptiveLayout --run
# Run tests with verbose output
npm test -- --reporter=verbose
# Generate coverage report
npm test:coverageExtract logic into testable utilities
- ❌ Don't test: React components with complex interactions, visual styling, animations
- ✅ Do test: Pure functions, data transformations, filtering logic, calculations
Use TDD for non-visual features
- Write tests first for data transformations, state management, filtering
- Let tests guide the API design of utility functions
Hybrid approach for visual features
- Test logic layer separately (calculations, data processing)
- Verify visual correctness manually in browser
Aim for regression prevention, not just coverage
- Focus on edge cases and critical paths
- Document expected behavior through tests
- Make tests readable and maintainable
✅ Tested with automated tests:
- Pure functions (space calculations, duplicate detection)
- Data transformations (entity name extraction, type detection)
- Filtering logic (relationship filtering, visibility checks)
- Geometric calculations (SVG path generation, anchor points)
- JSX structure (correct elements, props passed correctly)
👁️ Verified manually in browser:
- SVG rendering quality and performance
- Colors, gradients, animations
- Layout aesthetics and spacing
- User interactions (drag, resize, hover effects)
- Responsive behavior across screen sizes
Total: 134 tests across 8 test files (all passing ✅)
Purpose: Data pipeline completeness reporting
Reports on the health of the data pipeline without failing tests:
- YAML → Metadata.json transformation
- Metadata → ModelData loading
- Variable specifications loading
Run: npm test -- data-integrity
Purpose: Core data loading and processing
Tests:
- Model data loading and structure validation
- Hierarchical class tree construction from flat list
- Reverse index building (enum→classes, slot→classes)
- Variable mapping validation
- Slot and enum definition parsing
- Abstract class detection
- Data consistency checks (no duplicates, valid properties)
Run: npm test -- dataLoader
Purpose: Component rendering verification
Tests:
- Class hierarchy rendering with nested structure
- Selected class highlighting
- Data attributes for element identification (used for SVG links)
- Empty state handling
Run: npm test -- ClassSection
Purpose: Element relationship detection
Tests all element types for relationship discovery:
- ClassElement: inheritance, enum properties, class references, self-references
- SlotElement: range detection for enums and classes
- VariableElement: class mapping
- EnumElement: no outgoing relationships (as expected)
- Filtering: by type, target type, visibility, self-refs
- Combined filtering: multiple criteria simultaneously
Run: npm test -- linkLogic
Purpose: SVG link rendering utilities
Tests:
- Relationship filtering: showInheritance, showProperties, onlyEnums, onlyClasses, visibility
- Link building: converting relationships to renderable link objects
- Geometric calculations: center points, anchor point selection, edge detection
- SVG path generation: bezier curves, self-referential loops
- Visual styling: color mapping, stroke width by relationship type
Run: npm test -- linkHelpers
Purpose: Adaptive detail panel display logic
Tests:
- Space calculation: remaining space with various panel configurations
- Mode determination: 'stacked' vs 'dialog' based on available space
- Edge cases: empty panels, exact threshold, negative space
- Real-world scenarios: common screen sizes (desktop 1920px, laptop 1366px, tablet 1024px, 4K 3840px)
Example test:
it('typical desktop monitor (1920x1080) with both panels should use stacked mode', () => {
const result = calculateDisplayMode(1920, 1, 1);
expect(result.mode).toBe('stacked'); // 860px remaining > 600px threshold
});
it('laptop screen (1366x768) with both panels should use dialog mode', () => {
const result = calculateDisplayMode(1366, 1, 1);
expect(result.mode).toBe('dialog'); // 140px remaining < 600px threshold
});Run: npm test -- adaptiveLayout
Purpose: Entity duplicate prevention
Tests:
- Entity name extraction: classes use
name, variables usevariableLabel - Entity type detection: structural property checks (
children,permissible_values,slot_uri) - Duplicate finding: by name and type, cross-type disambiguation
- Edge cases: empty arrays, multiple duplicates, same names across different types
Example test:
it('distinguishes same name across different entity types', () => {
const sameNameClass = { name: 'SameName', children: [] };
const sameNameEnum = { name: 'SameName', permissible_values: {} };
// Should find class duplicate at index 0 (not confused with enum)
const classIndex = findDuplicateIndex([class, enum], sameNameClass, 'class');
expect(classIndex).toBe(0);
// Should find enum duplicate at index 1 (not confused with class)
const enumIndex = findDuplicateIndex([class, enum], sameNameEnum, 'enum');
expect(enumIndex).toBe(1);
});Run: npm test -- duplicateDetection
Purpose: Panel title and header color utilities
Tests:
- Header colors: type-based color selection (blue for classes, purple for enums, green for slots, orange for variables)
- Title generation: JSX rendering for all entity types
- Styling verification: bold text, font sizes, inheritance display
- React rendering: ensures valid JSX structure can be rendered
Example test:
it('renders class title with parent', () => {
const title = getPanelTitle({ name: 'Specimen', parent: 'Entity' });
const { container } = render(title);
expect(container.textContent).toContain('Class:');
expect(container.textContent).toContain('Specimen');
expect(container.textContent).toContain('extends Entity');
});Run: npm test -- panelHelpers
Utility function (src/utils/myUtility.ts):
export function calculateSomething(input: number): number {
return input * 2 + 10;
}Test file (src/test/myUtility.test.ts):
import { describe, it, expect } from 'vitest';
import { calculateSomething } from '../utils/myUtility';
describe('calculateSomething', () => {
it('doubles input and adds 10', () => {
expect(calculateSomething(5)).toBe(20); // 5 * 2 + 10 = 20
});
it('handles zero', () => {
expect(calculateSomething(0)).toBe(10);
});
it('handles negative numbers', () => {
expect(calculateSomething(-5)).toBe(0); // -5 * 2 + 10 = 0
});
});Component (src/components/MyComponent.tsx):
export function MyComponent({ name }: { name: string }) {
return <div className="greeting">Hello, {name}!</div>;
}Test file (src/test/MyComponent.test.tsx):
import { describe, it, expect } from 'vitest';
import { render } from '@testing-library/react';
import { MyComponent } from '../components/MyComponent';
describe('MyComponent', () => {
it('renders greeting with name', () => {
const { container } = render(<MyComponent name="Alice" />);
expect(container.textContent).toBe('Hello, Alice!');
});
it('applies correct CSS class', () => {
const { container } = render(<MyComponent name="Bob" />);
const div = container.querySelector('div');
expect(div?.className).toContain('greeting');
});
});- Group related tests with
describeblocks - Use descriptive test names that explain the expected behavior
- Test edge cases (empty inputs, null values, boundary conditions)
- Keep tests focused - one assertion per test when possible
- Use setup helpers for repeated mock data (see test files for examples)
Approach: Test-driven development (TDD)
- Created
linkLogic.test.tsfirst with relationship detection tests - Implemented Element classes to pass tests
- Created
linkHelpers.test.tsfor SVG rendering utilities - Implemented rendering logic to pass tests
Result: All link logic fully tested before visual implementation
Approach: Extract and test
- Identified testable logic embedded in components
- Extracted pure functions to utility files
- Wrote comprehensive tests (23 + 28 + 16 = 67 tests)
- Refactored components to use tested utilities
Result: Doubled test suite size (67 → 134), improved code quality
DetailPanelStack rendering tests
- Test panels render in reversed order (newest first)
- Verify correct props passed to DetailPanel
- Test close button functionality
- Mock DetailPanel to isolate testing
DetailDialog interaction tests
- Drag and resize functionality
- Escape key closes oldest dialog
- Dialog stacking order (z-index)
State persistence round-trip tests
- Save state → load from URL → verify match
- Dialog positions preserved correctly
- Panel configurations restored
Search and filter tests (when implemented)
- Full-text search across entities
- Faceted filtering logic
- Search result highlighting
Integration tests
- Full navigation flows (click class → dialog opens → links appear)
- Cross-panel navigation
- State transitions
E2E tests (Playwright or Cypress)
- Full user workflows
- Multi-step interactions
- Visual regression testing
Performance tests
- Large model handling (many classes, variables)
- Rendering speed with many links/dialogs
- Memory usage tracking
If tests fail unexpectedly:
- Read the error message carefully - Vitest provides clear stack traces
- Check if the API changed - Did you modify function signatures?
- Verify test assumptions - Are mock data structures still valid?
- Run single test file - Isolate the failing test:
npm test -- filename - Add console.log in tests to debug - Vitest shows console output
"Cannot find module" errors
- Check import paths are correct (relative paths from test to source)
- Ensure the file being imported exists
"Expected X but received Y"
- Double-check the expected value matches actual implementation
- Use
console.logto inspect actual values
Tests pass locally but fail in CI
- Check for timing issues (async operations)
- Verify environment differences (window.innerWidth mocking)
React Testing Library issues
- Ensure you're using
render()from@testing-library/react - Check that components are properly exported
When adding new features:
- Extract testable logic into utility functions
- Write tests first for data transformations and calculations
- Refactor components to use tested utilities
- Document test coverage in this file
- Run full test suite before committing:
npm test -- --run
For questions about testing strategy, see CLAUDE.md for architecture context.
This section documents the original test plan for Phase 3e (Adaptive Detail Panel Display). All Priority 1 tests have been implemented and are passing. Priorities 2-3 are optional future work.
Test file: src/test/adaptiveLayout.test.ts (23 tests) ✅
Tests space calculation and display mode determination:
- Calculate remaining space with both panels populated
- Calculate remaining space with one panel empty
- Calculate remaining space with no panels
- Determine 'stacked' mode when space ≥ threshold
- Determine 'dialog' mode when space < threshold
- Handle edge case at exact threshold (600px)
- Real-world screen sizes (1920px desktop, 1366px laptop, 4K, tablet)
Implementation: Extracted to src/utils/layoutHelpers.ts
Test file: src/test/duplicateDetection.test.ts (28 tests) ✅
Tests entity duplicate prevention:
- Detect duplicate class by name
- Detect duplicate enum by name
- Detect duplicate slot by name
- Detect duplicate variable by variableLabel
- Handle non-duplicate entities correctly
- Find existing entity index correctly
- Handle empty arrays
- Cross-type disambiguation (class vs enum with same name)
Implementation: Extracted to src/utils/duplicateDetection.ts
Test file: src/test/panelHelpers.test.tsx (16 tests) ✅
Tests panel title JSX generation:
- Generate title for class without parent
- Generate title for class with parent (includes "extends")
- Generate title for enum
- Generate title for slot
- Generate title for variable
- Render correct JSX structure (bold elements, text sizes)
Implementation: Extracted to src/utils/panelHelpers.tsx
Test file: src/test/panelHelpers.test.tsx (included in 16 tests above) ✅
Tests type-based color selection:
- Return blue color for ClassNode
- Return purple color for EnumDefinition
- Return green color for SlotDefinition
- Return orange color for VariableSpec
- Verify color strings include both light and dark variants
Implementation: Extracted to src/utils/panelHelpers.tsx
Test file: src/test/DetailPanelStack.test.tsx (not yet created)
Potential tests:
- Render null when panels array is empty
- Render panels in reversed order (newest first)
- Apply correct header color for each entity type
- Render close button for each panel
- Pass hideHeader and hideCloseButton props to DetailPanel
Implementation approach:
- Use React Testing Library
- Mock DetailPanel component to verify props
- Test array reversal logic
Test file: src/test/adaptiveModeIntegration.test.tsx (not yet created)
Potential tests:
- Switch from 'dialog' to 'stacked' when resizing window wider
- Switch from 'stacked' to 'dialog' when resizing window narrower
- Preserve dialog data when switching modes
- Maintain panel order across mode switches
Challenges:
- Requires mocking window.innerWidth and resize events
- Needs full component tree (App + PanelLayout + panels)
- May be slow/flaky
- Deferred unless critical regressions occur
These features are verified manually in browser:
- Colored header backgrounds (visual correctness)
- Panel height constraints (300px-500px)
- Scrolling behavior in stacked mode
- Smooth transitions when resizing
- Hover effects on close button
- Typography (bold, text sizes, alignment)