Complete color theme system (light/dark/auto) with dynamic UI: Features: - Color theme switcher with auto/light/dark modes - Dynamic button colors on hover (purple/yellow/blue per theme) - localStorage persistence across sessions - Proper button positioning (desktop and mobile) - Mobile: 5-button layout with theme before info button Fixes: - CSP updated to allow jsDelivr CDN for iconify icons - Button repositioning: Download PDF and Print Friendly at top - Hover-only colors (not persistent) - Mobile button order corrected Files: - static/css/color-theme.css - Theme system with CSS variables - static/js/color-theme.js - Theme switching logic - templates/partials/color-theme-switcher.html - Button component - internal/middleware/security.go - CSP fix for jsDelivr - tests/mjs/13-color-theme-switcher.test.mjs - Comprehensive test - tests/TEST-SUMMARY.md - Updated test documentation
10 KiB
CV Project - Test Suite Documentation
⚠️ SINGLE SOURCE OF TRUTH
These tests define what "working" means. If a test passes, the feature MUST work. If a feature breaks, a test MUST fail.
Complete testing infrastructure for the CV website application.
Quick Start
# Run all systematic tests
bun tests/run-all.mjs
# Run individual test
bun tests/mjs/0-zoom.test.mjs
bun tests/mjs/1-toggles.test.mjs
bun tests/mjs/2-keyboard-shortcuts.test.mjs
bun tests/mjs/3-hyperscript.test.mjs
bun tests/mjs/4-htmx.test.mjs
bun tests/mjs/5-language.test.mjs
bun tests/mjs/6-modals.test.mjs
bun tests/mjs/7-mobile-responsive.test.mjs
Active Test Suite (tests/mjs/)
Systematic numbered tests - the source of truth for functionality verification.
0-zoom.test.mjs
Purpose: Zoom control functionality
- ✅ Zoom control elements exist
- ✅ Zoom toggle shows/hides control
- ✅ Zoom slider changes page zoom
- ✅ Real-time zoom updates (no refresh)
Run: bun tests/mjs/0-zoom.test.mjs
1-toggles.test.mjs
Purpose: Comprehensive toggle testing with real-time visual verification
- ✅ Length toggle (Action Bar)
- ✅ Icon toggle (Action Bar) - with screenshot verification
- ✅ Theme toggle (Action Bar)
- ✅ Length toggle (Menu + Sync)
- ✅ Icon toggle (Menu + Sync) - verifies no refresh needed
- ✅ Theme toggle (Menu + Sync)
- ✅ localStorage persistence
- ✅ Synchronization between action bar and menu
Critical: This test caught the icon toggle bug (class name mismatch: .show-logos vs .show-icons)
Run: bun tests/mjs/1-toggles.test.mjs
2-keyboard-shortcuts.test.mjs
Purpose: Keyboard shortcut functionality
- ✅ L key - Toggle CV length
- ✅ I key - Toggle icons
- ✅ V key - Toggle theme
- ✅ ? key - Open shortcuts modal
- ✅ Input field safety (shortcuts ignored in input/textarea)
Run: bun tests/mjs/2-keyboard-shortcuts.test.mjs
3-hyperscript.test.mjs
Purpose: Hyperscript integrity and parse error detection
- ✅ No parse errors on page load
- ✅ Function definitions verified (toggleCVLength, toggleIcons, toggleTheme, handleKeyboardShortcut)
- ✅ Keyboard event handlers work
- ✅ Def statement count (≤3 limit)
- ✅ Operator precedence validation
Run: bun tests/mjs/3-hyperscript.test.mjs
4-htmx.test.mjs
Purpose: HTMX functionality validation
- ✅ HTMX library loaded
- ✅ HTMX elements present (hx-get, hx-post, hx-swap, hx-target)
- ✅ Request/response cycle
- ✅ Loading indicators
Run: bun tests/mjs/4-htmx.test.mjs
5-language.test.mjs
Purpose: Language switching functionality
- ✅ Language toggle controls exist
- ✅ Default language (English)
- ✅ Spanish via URL parameter (?lang=es)
- ✅ Language toggle button
- ✅ localStorage/cookie persistence
Run: bun tests/mjs/5-language.test.mjs
6-modals.test.mjs
Purpose: Modal functionality and accessibility
- ✅ Modal elements exist (info, shortcuts, PDF)
- ✅ Shortcuts modal opens with ? key
- ✅ Info modal opens
- ✅ PDF modal opens
- ✅ ESC key closes modals
- ✅ Accessibility attributes (role, aria-label, aria-modal)
Run: bun tests/mjs/6-modals.test.mjs
7-mobile-responsive.test.mjs
Purpose: Mobile viewport rendering and interactions
- ✅ Mobile viewport (375px) - no horizontal scroll
- ✅ Tablet viewport (768px) - proper layout
- ✅ Touch interactions (hamburger menu)
- ✅ Responsive breakpoints (320px - 1920px)
- ✅ Viewport meta tag
- ✅ Touch-friendly button sizes (≥44px)
- ✅ Text readability (≥14px font)
Run: bun tests/mjs/7-mobile-responsive.test.mjs
8-hover-sync.test.mjs
Purpose: Hover state synchronization between UI elements
- ✅ PDF button hover sync (action bar ↔ menu)
- ✅ Print button hover sync (action bar ↔ menu)
- ✅ Zoom control highlight on hover
- ✅ No refresh required for hover effects
Critical: Tests JavaScript wrapper → Hyperscript call pattern
Run: bun tests/mjs/8-hover-sync.test.mjs
9-hyperscript-def-limit.test.mjs
Purpose: Verify NO 3-def limit with hyperscript 0.9.14+
- ✅ Multiple def statements across multiple files
- ✅ All hyperscript functions load correctly
- ✅ Toggle functions work (toggleCVLength, toggleIcons, toggleTheme)
- ✅ Hover sync functions work (syncPdfHover, syncPrintHover, highlightZoomControl)
Historical: Proves hyperscript 0.9.14+ has no def limit
Run: bun tests/mjs/9-hyperscript-def-limit.test.mjs
10-zoom-persistence.test.mjs
Purpose: Zoom level persistence across page reloads
- ✅ Zoom saves to localStorage when changed
- ✅ Zoom restores correctly on reload (e.g., 150%)
- ✅ Reset to 100% works and persists
- ✅ localStorage updates in real-time
Critical: Fixed bug where zoom-control.html:10 set wrong element's value
Run: bun tests/mjs/10-zoom-persistence.test.mjs
11-zoom-ui-exclusion.test.mjs
Purpose: Verify UI elements excluded from zoom
- ✅ Footer outside zoom-wrapper (DOM structure)
- ✅ Action bar outside zoom-wrapper
- ✅ Menu outside zoom-wrapper
- ✅ CV content inside zoom-wrapper
- ✅ UI elements unchanged at 200% zoom
- ✅ CV content properly zooms
Critical: Ensures only CV paper zooms, not UI chrome
Run: bun tests/mjs/11-zoom-ui-exclusion.test.mjs
Test Philosophy
Single Source of Truth: The 12 tests in tests/mjs/ (0-11) are the ONLY tests.
- No archive, no legacy tests, no redundancy
- Each test is systematic, comprehensive, and essential
- If a test doesn't provide unique value, it doesn't exist
Test Infrastructure
Master Test Runner
File: tests/run-all.mjs
Runs all numbered tests in sequence, provides summary report.
bun tests/run-all.mjs
Screenshots
Toggle tests save screenshots to tests/screenshots/:
before-icon-toggle.png- Before clicking icon toggleafter-icon-toggle.png- After clicking icon toggle
Use these to visually verify real-time rendering changes.
Test Requirements
- Server: Must be running on http://localhost:1999
- Browser: Playwright launches Chromium (headed mode for manual verification)
- Bun: All tests use
#!/usr/bin/env bun - Exit: Press Ctrl+C after reviewing test results
Test Output Format
All tests provide:
- ✅ Clear pass/fail indicators
- 📊 Summary of results
- ❌ Detailed error messages
- 🎉 Success confirmation
- 💡 Browser stays open for manual verification
Test Development Guidelines
Creating New Tests
- Numbering: Use next available number (3, 4, 5...)
- Naming:
{number}-{feature}.test.mjs - Structure: Follow pattern from existing tests
- Documentation: Update this file
Test Template
#!/usr/bin/env bun
/**
* {FEATURE} TEST
* ==============
* Description of what this tests
*/
import { chromium } from 'playwright';
const URL = "http://localhost:1999";
async function test{Feature}() {
console.log('🧪 {FEATURE} TEST\n');
console.log('='.repeat(70));
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage({ viewport: { width: 1920, height: 1080 } });
const errors = [];
const testResults = [];
// ... test implementation ...
console.log("\nBrowser will stay open for manual inspection.");
console.log("Press Ctrl+C when done.\n");
await new Promise(() => {}); // Keep browser open
}
await test{Feature}();
Future Enhancements (Optional)
Core functionality COMPLETELY covered. Optional future tests:
- Print CSS validation (8-print.test.mjs)
- PDF generation testing (9-pdf.test.mjs)
- Performance benchmarks - Core Web Vitals
- Cross-browser - Firefox, Safari
- Accessibility audit - WCAG AA compliance
- Advanced interactions - Hover states, scroll behavior
Historical Notes
Test Cleanup - Nov 17, 2025
- DELETED entire archive directory (tests/archive/)
- Eliminated 17+ redundant legacy test files
- Kept ONLY 12 systematic tests (0-11) - single source of truth
- 100% test redundancy eliminated
- Zero tolerance for duplicate or unnecessary tests
Key Bug Fixes Caught By Tests
-
Icon Toggle Bug (1-toggles.test.mjs)
- Class name mismatch:
.show-logosvs.show-icons - Required page refresh to see changes
- Fixed by correcting class names in cv-functions.js
- Class name mismatch:
-
Hyperscript Parser Limit (archived)
- Max 3 def statements total across all files
- Moved toggle functions to JavaScript
- Upgraded hyperscript 0.9.12 → 0.9.14
Contributing
When adding tests:
- Keep tests focused (single responsibility)
- Make them self-documenting
- Provide clear pass/fail criteria
- Update this documentation
- Add to run-all.mjs automatically (it auto-discovers numbered tests)
Last Updated: 2025-11-18 Test Count: 14 active (0-13) - NO archive, NO legacy tests Coverage: Complete (UI, keyboard, libraries, i18n, modals, mobile, zoom, hover-sync, hyperscript, skeleton loaders, color themes) Status: SINGLE SOURCE OF TRUTH - Production specification Philosophy: Zero redundancy - Every test is essential and unique
12-skeleton-language-transitions.test.mjs
Purpose: Skeleton loader display during language transitions
- ✅ Skeleton loaders appear during language switch
- ✅ Content replaced without full page reload
- ✅ Skeleton removed after content loads
- ✅ No layout shift during transition
Run: bun tests/mjs/12-skeleton-language-transitions.test.mjs
13-color-theme-switcher.test.mjs
Purpose: Color theme switcher with dynamic button colors
- ✅ Button positioning (Download PDF and Print Friendly at top)
- ✅ Theme cycling (auto → light → dark → auto)
- ✅ Dynamic button colors per theme mode
- Auto: Purple (#9b59b6) 💜
- Light: Orange/Yellow (#f39c12) ☀️
- Dark: Blue (#3498db) 🌙
- ✅ Icon changes per theme (sun/moon/auto icons)
- ✅ localStorage persistence
- ✅ data-color-theme attribute updates
Run: bun tests/mjs/13-color-theme-switcher.test.mjs
New Tests (2025-11-17/18)
- 8-hover-sync.test.mjs - JavaScript wrapper → Hyperscript call pattern
- 9-hyperscript-def-limit.test.mjs - Proves no 3-def limit with 0.9.14+
- 10-zoom-persistence.test.mjs - Zoom level localStorage persistence
- 11-zoom-ui-exclusion.test.mjs - UI elements excluded from zoom
- 12-skeleton-language-transitions.test.mjs - Skeleton loaders for language switch
- 13-color-theme-switcher.test.mjs - Dynamic color theme switcher