Files
juanatsap 24f32421ad chore: improve test targets and documentation
- Add test-local target for running all tests from project root
- Add -short flag to test-unit for CI-safe execution
- Expand tests/README.md with Go backend test documentation
- Rename css-bundling test to follow numbered convention (81-)
2025-12-06 15:24:07 +00:00

374 lines
10 KiB
Markdown

# 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
### Go Backend Tests
```bash
# Run unit tests (fast, CI-safe)
make test
# Run ALL tests including integration (requires Chrome)
make test-all
# Run integration tests only
make test-integration
# Run with coverage report
go test -v -race -coverprofile=coverage.txt ./...
go tool cover -html=coverage.txt # View in browser
```
### Frontend Tests (Playwright)
```bash
# Run ALL frontend 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
```
---
## Go Backend Test Structure
Go tests are **colocated with source code** (Go convention):
```
internal/
├── handlers/
│ ├── cv_pages.go
│ ├── cv_pages_test.go # Handler tests
│ ├── cv_contact_test.go
│ ├── cv_htmx_test.go
│ ├── cv_security_test.go
│ ├── cv_text_test.go
│ ├── cv_cmdk_test.go
│ ├── pdf_test.go # PDF generation (integration tag)
│ └── benchmarks_test.go
├── models/cv/
│ ├── loader_test.go # JSON loading tests
│ └── validation_test.go # Data validation tests
├── middleware/
│ ├── preferences_test.go
│ └── benchmarks_test.go
├── validation/
│ └── contact_test.go # Form validation tests
├── fileutil/
│ └── fileutil_test.go
└── lang/
└── lang_test.go
tests/
├── integration/
│ └── email_test.go # SMTP integration (requires credentials)
└── security/
└── contact_security_test.go # Security-focused tests
```
### Go Test Categories
| Category | Command | Description |
|----------|---------|-------------|
| Unit | `make test` | Fast, CI-safe (skips path-dependent tests) |
| Local | `make test-local` | All unit tests (run from project root) |
| Integration | `make test-integration` | Requires Chrome/SMTP |
| All | `make test-all` | Complete suite with integration |
| Benchmarks | `go test -bench=. ./...` | Performance tests |
### CI/CD Integration
- **GitHub Actions**: `.github/workflows/test.yml`
- **Coverage target**: 70% (warning if below)
- **Artifacts**: coverage.txt, benchmark.txt uploaded
---
## 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:**
```bash
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
```javascript
#!/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