generated from coulomb/repo-seed
- Add Vitest + jsdom testing framework - Create unit tests for engine.js and generator.js - Add integration tests for end-to-end workflows - Include test utilities and setup helpers - Document testing approach in TESTING.md - Document all dependencies in DEPENDS.md - Add Makefile with test targets and dev workflow 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
5.0 KiB
5.0 KiB
Timeline SVG - Test Infrastructure
This document describes the test-driven development (TDD) infrastructure for the Timeline SVG Generator project.
Test Framework Setup
The project uses Vitest with jsdom for testing browser-based JavaScript code.
Dependencies
{
"@vitest/ui": "^2.1.0",
"@vitest/coverage-v8": "^2.1.0",
"jsdom": "^25.0.0",
"vitest": "^2.1.0"
}
Installation
npm install
Running Tests
# Run all tests once
npm test
# Run tests in watch mode (for TDD)
npm run test:watch
# Run with coverage report
npm run test:coverage
# Open test UI (browser-based test runner)
npm run test:ui
Test Structure
Unit Tests
-
test/engine.test.js- Tests for timeline data processing- CSV parsing and validation
- Date parsing (multiple formats)
- Project configuration loading
- DOM integration
-
test/generator.test.js- Tests for SVG generation- SVG template processing
- Month grid generation
- Lane and item positioning
- XML escaping
Integration Tests
test/integration.test.js- End-to-end workflow tests- Complete timeline generation pipeline
- File upload simulation
- DOM event handling
- Export functionality
Test Utilities
test/setup.js- Global test setup and mockstest/testHelpers.js- Common test data and utilities
TDD Workflow
1. Red Phase - Write Failing Test
# Start test watcher
npm run test:watch
# Create test for new feature
touch test/newFeature.test.js
Example test:
describe('New Feature', () => {
it('should do something specific', () => {
const result = myNewFunction('input')
expect(result).toBe('expected output')
})
})
2. Green Phase - Make Test Pass
Implement minimal code to make the test pass:
// In the appropriate source file
function myNewFunction(input) {
return 'expected output' // Minimal implementation
}
3. Refactor Phase - Improve Code
# Ensure tests still pass after refactoring
npm test
Key Testing Patterns
Mocking Browser APIs
// In test/setup.js
global.fetch = vi.fn()
global.Papa = { parse: vi.fn() }
// In tests
mockFetch(sampleData)
DOM Testing
// Setup DOM elements
setupBasicDOM()
// Test DOM manipulation
await timelineEngine.loadProjectConfigObject(config)
expectElementToHaveText('#projectName', 'Test Project')
Testing Vanilla JS Modules
Since the project uses global objects, tests load modules by evaluating the source:
const fs = await import('fs/promises')
const engineCode = await fs.readFile('./engine.js', 'utf-8')
eval(engineCode)
const timelineEngine = global.window.timelineEngine
Coverage Goals
- Statements: >90%
- Branches: >85%
- Functions: >90%
- Lines: >90%
View detailed coverage:
npm run test:coverage
open coverage/index.html
Common Test Scenarios
Testing Date Parsing
it('should parse various date formats', () => {
expect(parseDate('2025-12-15')).toEqual(new Date(2025, 11, 15))
expect(parseDate('15.12.2025')).toEqual(new Date(2025, 11, 15))
expect(parseDate('invalid')).toBeNull()
})
Testing SVG Generation
it('should generate valid SVG with timeline items', () => {
const result = timelineGenerator.generate(items, config, template)
expect(result).toContain('<svg xmlns="http://www.w3.org/2000/svg">')
expect(result).toContain('Task Title')
})
Testing Error Handling
it('should handle missing configuration gracefully', () => {
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
timelineEngine.processCsv('data', null)
expect(consoleSpy).toHaveBeenCalledWith('No config or fieldMapping found.')
})
Debugging Tests
Using Test UI
npm run test:ui
Opens browser interface with:
- Test results visualization
- Coverage reports
- Test file exploration
- Real-time test watching
Console Debugging
it('should debug test data', () => {
console.log('Debug data:', testData)
// Test continues...
})
Adding New Tests
- Create test file in
test/directory - Import helpers from
test/testHelpers.js - Follow naming convention:
*.test.js - Group related tests with
describe()blocks - Use descriptive test names with
it('should ...')
CI Integration
Tests can be easily integrated into CI pipelines:
# GitHub Actions example
- name: Run tests
run: npm test
- name: Upload coverage
run: npm run test:coverage
Best Practices
- Test behavior, not implementation
- Use descriptive test names
- Keep tests focused and small
- Mock external dependencies
- Test both success and error cases
- Maintain test data helpers
- Run tests frequently during development
This test infrastructure enables confident refactoring and feature development while maintaining code quality and preventing regressions.