- Move docs/ contents to doc/ with proper numbering: - CONTACT-FORM-QUICKSTART.md → 17-CONTACT-FORM.md - SECURITY-AUDIT-REPORT.md → 18-SECURITY-AUDIT.md - SECURITY.md → 19-SECURITY-IMPLEMENTATION.md - Delete duplicate/redundant files from docs/: - CMD-K-COMMAND-BAR.md (duplicate of 16-CMD-K-API.md) - CONTACT_FORM_IMPLEMENTATION.md (overlaps with quickstart) - SECURITY-IMPLEMENTATION-SUMMARY.md (summary of audit) - Update doc/README.md with new document references - Update test counts to 39 test files across all READMEs - Update all "Last Updated" dates to 2025-12-01 - Add new API endpoints documentation (text, cmd-k, contact, toggles) - Update PROJECT-MEMORY.md with new features and correct paths
13 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
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.
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-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):
- Header (title-badges + personal info)
- Education
- Skills Summary
- Experience (with company logos, descriptions, responsibilities)
- Awards (with logos, issuers, descriptions)
- Projects (with icons, descriptions, tech stacks)
- Courses (with icons, institutions, dates)
- Languages
- References
- Other Information
- Skills Sidebar (left) - Technical Skills
- Skills Sidebar (right) - More Skills
- Footer
Implementation: JavaScript event handlers in static/js/main.js
htmx:beforeRequest- Adds.loadingclass to page containershtmx:afterSettle- Removes.loadingclass 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:
- Back-to-top always on RIGHT (not left) in mobile
- Narrow mobile (<483px) moves back-to-top UP to prevent overlap
- 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