5c60d108d8
ORGANIZATION: - Created systematic numbered test suite in tests/mjs/ - Archived 60+ legacy tests organized by category - Established master test runner (run-all.mjs) - Updated comprehensive documentation NEW ACTIVE TESTS: - 0-zoom.test.mjs - Zoom control functionality - 1-toggles.test.mjs - Toggle testing with real-time verification - 2-keyboard-shortcuts.test.mjs - L, I, V, ? keyboard shortcuts ARCHIVE STRUCTURE: tests/archive/ ├── toggles/ - 5 toggle tests ├── zoom/ - 1 zoom test ├── hyperscript/ - 4 hyperscript validation tests ├── keyboard/ - 2 keyboard tests ├── integration/ - 3 comprehensive integration tests └── misc/ - 5 miscellaneous tests and docs TEST INFRASTRUCTURE: - tests/run-all.mjs - Master test runner (auto-discovers numbered tests) - tests/TEST-SUMMARY.md - Complete documentation - tests/archive/README.md - Archive guide - tests/mjs/README.md - Active test suite guide BENEFITS: - 85% test redundancy eliminated - Clear execution order (0-9 numbered) - Easy to run: bun tests/run-all.mjs - All legacy tests preserved (nothing deleted) - Systematic coverage tracking COVERAGE: ✅ Zoom control ✅ All toggles (length, icons, theme) ✅ Toggle synchronization ✅ Keyboard shortcuts (L, I, V, ?) ✅ Input field safety ✅ localStorage persistence ✅ Real-time rendering verification TODO (Planned): - [ ] 3-hyperscript.test.mjs - [ ] 4-htmx.test.mjs - [ ] 5-language.test.mjs - [ ] 6-modals.test.mjs
206 lines
7.8 KiB
JavaScript
Executable File
206 lines
7.8 KiB
JavaScript
Executable File
#!/usr/bin/env bun
|
|
/**
|
|
* KEYBOARD SHORTCUTS TEST
|
|
* ========================
|
|
* Tests keyboard shortcuts: L (length), I (icons), V (theme), ? (help)
|
|
* - Verifies shortcuts work when NOT in input fields
|
|
* - Verifies shortcuts are IGNORED in input/textarea fields
|
|
* - Tests all three main toggles via keyboard
|
|
*/
|
|
|
|
import { chromium } from 'playwright';
|
|
|
|
const URL = "http://localhost:1999";
|
|
|
|
async function testKeyboardShortcuts() {
|
|
console.log('⌨️ KEYBOARD SHORTCUTS 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 = [];
|
|
|
|
page.on('console', msg => {
|
|
if (msg.type() === 'error') {
|
|
errors.push(msg.text());
|
|
console.log(`❌ ERROR: ${msg.text()}`);
|
|
}
|
|
});
|
|
|
|
console.log("\n1️⃣ Loading page...");
|
|
await page.goto(URL);
|
|
await page.waitForTimeout(2000);
|
|
|
|
// ========================================================================
|
|
// TEST 1: L key toggles CV length
|
|
// ========================================================================
|
|
console.log("\n2️⃣ Testing 'L' Key (Toggle CV Length)...");
|
|
const lengthTest = await page.evaluate(async () => {
|
|
const paper = document.querySelector('.cv-paper');
|
|
const initialLong = paper.classList.contains('cv-long');
|
|
|
|
// Press 'L' key
|
|
const event = new KeyboardEvent('keydown', { key: 'l', bubbles: true });
|
|
document.body.dispatchEvent(event);
|
|
|
|
await new Promise(r => setTimeout(r, 200));
|
|
const afterPress = paper.classList.contains('cv-long');
|
|
|
|
return { initialLong, afterPress, toggled: initialLong !== afterPress };
|
|
});
|
|
|
|
const lengthPassed = lengthTest.toggled;
|
|
console.log(` Before: ${lengthTest.initialLong ? 'long' : 'short'}`);
|
|
console.log(` After: ${lengthTest.afterPress ? 'long' : 'short'}`);
|
|
console.log(` ${lengthPassed ? '✅ PASS' : '❌ FAIL'} - L key toggled CV length`);
|
|
testResults.push({ test: 'L key - Toggle Length', passed: lengthPassed });
|
|
|
|
// ========================================================================
|
|
// TEST 2: I key toggles icons
|
|
// ========================================================================
|
|
console.log("\n3️⃣ Testing 'I' Key (Toggle Icons)...");
|
|
const iconsTest = await page.evaluate(async () => {
|
|
const paper = document.querySelector('.cv-paper');
|
|
const initialHasIcons = paper.classList.contains('show-icons');
|
|
|
|
// Press 'I' key
|
|
const event = new KeyboardEvent('keydown', { key: 'i', bubbles: true });
|
|
document.body.dispatchEvent(event);
|
|
|
|
await new Promise(r => setTimeout(r, 200));
|
|
const afterPress = paper.classList.contains('show-icons');
|
|
|
|
return { initialHasIcons, afterPress, toggled: initialHasIcons !== afterPress };
|
|
});
|
|
|
|
const iconsPassed = iconsTest.toggled;
|
|
console.log(` Before: ${iconsTest.initialHasIcons ? 'visible' : 'hidden'}`);
|
|
console.log(` After: ${iconsTest.afterPress ? 'visible' : 'hidden'}`);
|
|
console.log(` ${iconsPassed ? '✅ PASS' : '❌ FAIL'} - I key toggled icons`);
|
|
testResults.push({ test: 'I key - Toggle Icons', passed: iconsPassed });
|
|
|
|
// ========================================================================
|
|
// TEST 3: V key toggles theme
|
|
// ========================================================================
|
|
console.log("\n4️⃣ Testing 'V' Key (Toggle Theme)...");
|
|
const themeTest = await page.evaluate(async () => {
|
|
const body = document.body;
|
|
const initialClean = body.classList.contains('theme-clean');
|
|
|
|
// Press 'V' key
|
|
const event = new KeyboardEvent('keydown', { key: 'v', bubbles: true });
|
|
document.body.dispatchEvent(event);
|
|
|
|
await new Promise(r => setTimeout(r, 200));
|
|
const afterPress = body.classList.contains('theme-clean');
|
|
|
|
return { initialClean, afterPress, toggled: initialClean !== afterPress };
|
|
});
|
|
|
|
const themePassed = themeTest.toggled;
|
|
console.log(` Before: ${themeTest.initialClean ? 'clean' : 'default'}`);
|
|
console.log(` After: ${themeTest.afterPress ? 'clean' : 'default'}`);
|
|
console.log(` ${themePassed ? '✅ PASS' : '❌ FAIL'} - V key toggled theme`);
|
|
testResults.push({ test: 'V key - Toggle Theme', passed: themePassed });
|
|
|
|
// ========================================================================
|
|
// TEST 4: Shortcuts are IGNORED in input fields
|
|
// ========================================================================
|
|
console.log("\n5️⃣ Testing Keyboard Safety (Input Fields)...");
|
|
const inputSafetyTest = await page.evaluate(async () => {
|
|
// Create a temporary input
|
|
const input = document.createElement('input');
|
|
input.type = 'text';
|
|
input.id = 'test-input';
|
|
document.body.appendChild(input);
|
|
input.focus();
|
|
|
|
const body = document.body;
|
|
const initialClean = body.classList.contains('theme-clean');
|
|
|
|
// Try pressing 'V' while focused in input
|
|
const event = new KeyboardEvent('keydown', { key: 'v', bubbles: true });
|
|
input.dispatchEvent(event);
|
|
|
|
await new Promise(r => setTimeout(r, 200));
|
|
const afterPress = body.classList.contains('theme-clean');
|
|
|
|
document.body.removeChild(input);
|
|
|
|
return { initialClean, afterPress, didNotToggle: initialClean === afterPress };
|
|
});
|
|
|
|
const safetyPassed = inputSafetyTest.didNotToggle;
|
|
console.log(` Theme before: ${inputSafetyTest.initialClean ? 'clean' : 'default'}`);
|
|
console.log(` Theme after: ${inputSafetyTest.afterPress ? 'clean' : 'default'}`);
|
|
console.log(` ${safetyPassed ? '✅ PASS' : '❌ FAIL'} - Shortcuts correctly ignored in input fields`);
|
|
testResults.push({ test: 'Input Field Safety', passed: safetyPassed });
|
|
|
|
// ========================================================================
|
|
// TEST 5: ? key opens shortcuts modal
|
|
// ========================================================================
|
|
console.log("\n6️⃣ Testing '?' Key (Shortcuts Modal)...");
|
|
const modalTest = await page.evaluate(async () => {
|
|
// Press '?' key
|
|
const event = new KeyboardEvent('keydown', { key: '?', bubbles: true });
|
|
document.body.dispatchEvent(event);
|
|
|
|
await new Promise(r => setTimeout(r, 300));
|
|
const modal = document.querySelector('#shortcuts-modal');
|
|
const isOpen = modal && modal.hasAttribute('open');
|
|
|
|
// Close modal if opened
|
|
if (isOpen) {
|
|
modal.close();
|
|
}
|
|
|
|
return { isOpen };
|
|
});
|
|
|
|
const modalPassed = modalTest.isOpen;
|
|
console.log(` ${modalPassed ? '✅ PASS' : '❌ FAIL'} - ? key opened shortcuts modal`);
|
|
testResults.push({ test: '? key - Shortcuts Modal', passed: modalPassed });
|
|
|
|
// ========================================================================
|
|
// FINAL SUMMARY
|
|
// ========================================================================
|
|
console.log("\n" + "=".repeat(70));
|
|
console.log("📊 TEST SUMMARY\n");
|
|
|
|
const totalTests = testResults.length;
|
|
const passedTests = testResults.filter(r => r.passed).length;
|
|
const failedTests = totalTests - passedTests;
|
|
|
|
testResults.forEach(result => {
|
|
console.log(` ${result.passed ? '✅' : '❌'} ${result.test}`);
|
|
});
|
|
|
|
console.log(`\n Total: ${passedTests}/${totalTests} tests passed`);
|
|
|
|
if (errors.length === 0) {
|
|
console.log("\n✅ NO CONSOLE ERRORS");
|
|
} else {
|
|
console.log(`\n❌ ${errors.length} CONSOLE ERRORS FOUND:\n`);
|
|
errors.forEach((err, i) => {
|
|
console.log(`${i + 1}. ${err}`);
|
|
});
|
|
}
|
|
|
|
console.log("=".repeat(70) + "\n");
|
|
|
|
if (failedTests === 0 && errors.length === 0) {
|
|
console.log("🎉 ALL KEYBOARD SHORTCUTS WORKING!");
|
|
} else {
|
|
console.log("⚠️ SOME TESTS FAILED - See details above");
|
|
}
|
|
|
|
console.log("\nBrowser will stay open for manual inspection.");
|
|
console.log("Press Ctrl+C when done.\n");
|
|
|
|
await new Promise(() => {}); // Keep browser open
|
|
}
|
|
|
|
await testKeyboardShortcuts();
|