Files
cv-site/tests
juanatsap 2d3d3de8cd feat: lazy load ninja-keys + HTML Invoker Commands API
- Lazy load ninja-keys only on CMD+K press (0 requests on initial load)
- Use esm.sh bundled module (3 requests vs ~81 previously)
- Add esm.sh to CSP whitelist
- Implement HTML Invoker Commands API for modals:
  - commandfor="modal-id" + command="show-modal" for opening
  - commandfor="modal-id" + command="close" for closing
  - Removes need for onclick handlers on modal buttons
- Refactor index.html into layout partials (head, body-scripts)
- Add comprehensive tests for both features
2025-12-02 08:29:54 +00:00
..

CV Project - Test Suite

⚠️ CRITICAL: SINGLE SOURCE OF TRUTH

These tests ARE the specification. These tests ARE the requirements.

If a test passes but the feature doesn't work → THE TEST IS WRONG If a feature works but the test fails → THE FEATURE IS WRONG If something breaks and the test didn't catch it → THE TEST IS INCOMPLETE

Non-Negotiable Rules

  1. NO CODE CHANGES without corresponding test validation
  2. ALL bug fixes MUST include a test that would have caught the bug
  3. EVERY feature MUST have test coverage before deployment
  4. IF A TEST PASSES, THE FEATURE MUST WORK PERFECTLY

Quick Start

# Run ALL tests (the complete specification)
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

Test Suite Structure

tests/
├── mjs/                      # 🎯 ACTIVE TESTS - SOURCE OF TRUTH
│   ├── 0-zoom.test.mjs
│   ├── 1-toggles.test.mjs
│   ├── 2-keyboard-shortcuts.test.mjs
│   ├── 3-hyperscript.test.mjs
│   ├── 4-htmx.test.mjs
│   ├── 5-language.test.mjs
│   ├── 6-modals.test.mjs
│   ├── 7-mobile-responsive.test.mjs
│   └── README.md
├── archive/                  # Historical tests (reference only)
├── screenshots/              # Visual verification
├── run-all.mjs              # Master test runner
└── TEST-SUMMARY.md          # Complete documentation

NO OTHER FILES. NO EXCEPTIONS.

The 8 Tests (Complete Specification)

0-zoom.test.mjs

What it validates:

  • Zoom control elements exist and are accessible
  • Zoom toggle shows/hides control
  • Zoom slider changes page zoom
  • Real-time zoom updates (no page refresh)

If this fails: Zoom functionality is broken

1-toggles.test.mjs

What it validates:

  • Length toggle (short/long CV)
  • Icon toggle (show/hide icons) - with screenshot verification
  • Theme toggle (default/clean)
  • Action bar and menu synchronization
  • localStorage persistence
  • Real-time rendering (no refresh needed)

If this fails: Toggle functionality is broken Historical bug caught: Icon toggle class mismatch (.show-logos vs .show-icons)

2-keyboard-shortcuts.test.mjs

What it validates:

  • L key toggles CV length
  • I key toggles icons
  • V key toggles theme
  • ? key opens shortcuts modal
  • Shortcuts ignored in input/textarea fields

If this fails: Keyboard navigation is broken

3-hyperscript.test.mjs

What it validates:

  • No parse errors on page load
  • All functions defined (toggleCVLength, toggleIcons, toggleTheme, handleKeyboardShortcut)
  • Keyboard event handlers work
  • Def statement count ≤3 (hyperscript parser limit)
  • Proper operator precedence (parentheses around or/and)

If this fails: Hyperscript integration is broken Historical bug caught: Exceeded 3 def statement limit

4-htmx.test.mjs

What it validates:

  • HTMX library loaded
  • HTMX elements present (hx-get, hx-post, hx-swap, hx-target)
  • Request/response cycle works
  • Loading indicators configured

If this fails: HTMX integration is broken

5-language.test.mjs

What it validates:

  • Language toggle controls exist
  • Default language is English
  • Spanish loads via URL parameter (?lang=es)
  • Language toggle button works
  • localStorage/cookie persistence

If this fails: Internationalization is broken

6-modals.test.mjs

What it validates:

  • Modal elements exist (info, shortcuts, PDF)
  • ? key opens shortcuts modal
  • Info and PDF modals open correctly
  • ESC key closes modals
  • Accessibility attributes (role, aria-label, aria-modal)

If this fails: Modal functionality is broken

7-mobile-responsive.test.mjs

What it validates:

  • 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)

If this fails: Mobile experience is broken

Test Output Format

Every test provides:

  • Clear pass/fail indicators
  • 📊 Summary of results
  • Detailed error messages with file:line references
  • 🎉 Success confirmation
  • 💡 Browser stays open for manual verification

When Tests Fail

Investigation Protocol

  1. Read the test output - It tells you EXACTLY what failed
  2. Look at the browser - Tests leave browser open for inspection
  3. Check screenshots (if test uses them)
  4. Read the test code - It's the specification
  5. Fix the code OR fix the test - One of them is wrong

Fixing Tests vs Fixing Code

Fix the CODE if:

  • The test correctly describes desired behavior
  • The implementation doesn't match the test
  • The test caught a real bug

Fix the TEST if:

  • The test doesn't match actual requirements
  • The test has false positives/negatives
  • The test is outdated

After fixing EITHER, verify:

bun tests/run-all.mjs  # ALL tests must pass

Adding New Tests

Numbering Convention

Tests are numbered 0-9 for execution order:

  • Use next available number (8, 9, ...)
  • Numbers indicate priority/dependency
  • Master runner auto-discovers numbered tests

Test Template

#!/usr/bin/env bun
/**
 * {FEATURE} TEST
 * ==============
 * What this validates and why it matters
 */

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 = [];

  // Track errors
  page.on('console', msg => {
    if (msg.type() === 'error') {
      errors.push(msg.text());
      console.log(`❌ ERROR: ${msg.text()}`);
    }
  });

  // ... test implementation ...

  // ALWAYS provide summary
  console.log("\n" + "=".repeat(70));
  console.log("📊 TEST SUMMARY\n");
  // ... summary ...

  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}();

Required Test Components

Every test MUST include:

  1. Clear purpose statement - What does this test validate?
  2. Error tracking - Capture console errors
  3. Test results array - Track pass/fail for each assertion
  4. Summary output - Show what passed/failed
  5. Browser stays open - For manual verification
  6. File:line references - When tests fail

Test Requirements

  • Server: Running on http://localhost:1999
  • Browser: Playwright Chromium (headed mode)
  • Runtime: Bun (#!/usr/bin/env bun)
  • Exit: Ctrl+C after manual verification

Archive Directory

tests/archive/ contains 60+ historical tests organized by category:

  • toggles/ - Toggle implementation evolution
  • zoom/ - Zoom functionality iterations
  • hyperscript/ - Hyperscript debugging
  • htmx/ - HTMX behavior validation
  • keyboard/ - Keyboard shortcut iterations
  • language/ - Language switching attempts
  • visual/ - Visual regression tests
  • performance/ - Performance benchmarks
  • integration/ - Full integration tests
  • misc/ - One-off debugging tests

Purpose: Historical reference and edge case documentation Status: Superseded by systematic test suite Usage: Reference only - DO NOT RUN

Accountability

Every time something breaks in production:

  1. Which test should have caught this?

    • If test exists → Fix the test
    • If test missing → Write the test
  2. Why didn't the test catch it?

    • Incomplete coverage → Expand test
    • False positive → Fix assertions
    • Wrong assumptions → Update spec
  3. How do we prevent this?

    • Add regression test
    • Document in TEST-SUMMARY.md
    • Update this README

Success Criteria

All 8 tests pass Browser manual verification confirms No console errors Features work as specified

If any test fails, deployment is BLOCKED.


Last Updated: 2025-12-01 Test Count: 39 test files (comprehensive coverage including CMD+K, contact form, and PDF tests) Status: Production specification Responsibility: These tests define what "working" means