# 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 ```bash # 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 bun tests/mjs/14-button-positioning.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. ```bash bun tests/run-all.mjs ``` ### Screenshots Toggle tests save screenshots to `tests/screenshots/`: - `before-icon-toggle.png` - Before clicking icon toggle - `after-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 1. **Numbering**: Use next available number (3, 4, 5...) 2. **Naming**: `{number}-{feature}.test.mjs` 3. **Structure**: Follow pattern from existing tests 4. **Documentation**: Update this file ### Test Template ```javascript #!/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 1. **Icon Toggle Bug** (1-toggles.test.mjs) - Class name mismatch: `.show-logos` vs `.show-icons` - Required page refresh to see changes - Fixed by correcting class names in cv-functions.js 2. **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: 1. Keep tests focused (single responsibility) 2. Make them self-documenting 3. Provide clear pass/fail criteria 4. Update this documentation 5. Add to run-all.mjs automatically (it auto-discovers numbered tests) --- **Last Updated**: 2025-12-01 **Test Count**: 39 test files - Comprehensive coverage **Coverage**: Complete (UI, keyboard, HTMX, i18n, modals, mobile, zoom, hover-sync, hyperscript, skeleton loaders, color themes, button positioning, PDF modal, icons, dark theme, course icons, references, toast notifications) **Status**: SINGLE SOURCE OF TRUTH - Production specification **Philosophy**: Each test validates specific functionality and edge cases ### 12-skeleton-language-transitions.test.mjs **Purpose**: Skeleton loader animations during language transitions for ALL 13 curriculum sections - ✅ Component wrapper structure (dual-state: actual + skeleton content) - **13 sections total** - ✅ Skeleton CSS loaded (shimmer animation verified) - ✅ First language switch (EN → ES) - Loading class added/removed - ✅ Second language switch (ES → EN) - Consistent behavior - ✅ Third language switch (EN → ES) - Regression check - ✅ No stuck loading states (all containers clean after transition) - ✅ JavaScript event handlers configured (languageSwitching flag) **Sections with skeleton loaders (structural fidelity)**: 1. Header (title-badges + personal info) 2. Education 3. Skills Summary 4. Experience (with company logos, descriptions, responsibilities) 5. Awards (with logos, issuers, descriptions) 6. Projects (with icons, descriptions, tech stacks) 7. Courses (with icons, institutions, dates) 8. Languages 9. References 10. Other Information 11. Skills Sidebar (left) - Technical Skills 12. Skills Sidebar (right) - More Skills 13. Footer **Implementation**: JavaScript event handlers in `static/js/main.js` - `htmx:beforeRequest` - Adds `.loading` class to page containers - `htmx:afterSettle` - Removes `.loading` class after swap completes (100ms delay) - **Structural fidelity**: Each skeleton mirrors the exact structure of its actual content (logos, text lines, lists) **Critical**: Migrated from hyperscript to JavaScript for reliable Playwright testing **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` ### 14-button-positioning.test.mjs **Purpose**: Button positioning & responsive layout across all viewport sizes - ✅ Desktop layout (>900px) - Vertical stacking on left side + back-to-top on right - ✅ Wide mobile (483-900px) - Horizontal layout at bottom + back-to-top on right - ✅ Narrow mobile (<483px) - Back-to-top moved UP to avoid overlap (still on right) - ✅ Button visibility - Zoom hidden in mobile, all buttons clickable - ✅ Accessibility validation - All buttons have proper attributes **Desktop Layout:** - Download, Print, Shortcuts, Info → LEFT side, vertically stacked (22rem, 18rem, 6rem, 2rem) - Back-to-top → RIGHT side (2rem) - Zoom button → VISIBLE **Wide Mobile (483-900px):** - Download, Print, Shortcuts, Info → Horizontal layout at bottom center - Back-to-top → RIGHT side (1.5rem bottom) - Zoom button → HIDDEN **Narrow Mobile (<483px):** - Download, Print, Shortcuts, Info → Horizontal layout at bottom - Back-to-top → RIGHT side, MOVED UP (5.5rem bottom) to avoid overlap - Zoom button → HIDDEN **Critical**: Verifies responsive button positioning fixes including: 1. Back-to-top always on RIGHT (not left) in mobile 2. Narrow mobile (<483px) moves back-to-top UP to prevent overlap 3. Consistent hover effects across all buttons **Run**: `bun tests/mjs/14-button-positioning.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 - **14-button-positioning.test.mjs** - Button positioning & responsive layout