Files
cv-site/tests/TEST-SUMMARY.md
T
juanatsap f3cce51fb3 feat: implement color theme switcher with dynamic button colors
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
2025-11-18 15:49:30 +00:00

324 lines
10 KiB
Markdown

# 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
```
## 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-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