ba44b435e7
Inline Hyperscript Refactoring: - Body tag keyboard handlers: 20→8 lines (using helper functions) - Zoom control handlers: 85→35 lines (using zoom._hs) - PDF modal card selection: 90→6 lines (3 identical blocks eliminated) New Hyperscript Files: - zoom._hs: handleZoomInput, handleZoomReset, initZoomControl - pdf-modal._hs: selectPdfCard, handlePdfCardKey JavaScript Elimination (232 lines removed): - cv-functions.js: REMOVED - hyperscript defs are globally available - scroll-at-bottom-handler.js: REMOVED - duplicate of handleScroll() - footer-buttons-interaction.js: REMOVED - moved to hyperscript Added Tests: - 32-hyperscript-multi-src.test.mjs: Verifies multi-file loading - 33-keyboard-shortcuts-refactored.test.mjs: Keyboard shortcuts - 34-hyperscript-refactor-comprehensive.test.mjs: Full test suite Key Findings: - No hyperscript multi-file bug in 0.9.14 - Hyperscript def statements are globally accessible - Previous refactoring failures were syntax errors, not library bugs
285 lines
12 KiB
JavaScript
285 lines
12 KiB
JavaScript
/**
|
|
* Test: Hyperscript Multiple External SRC Files Bug Investigation
|
|
*
|
|
* HYPOTHESIS: Hyperscript 0.9.14 has issues when loading multiple
|
|
* <script type="text/hyperscript" src="..."> files, even though:
|
|
* - Each file parses correctly individually
|
|
* - All content works when concatenated inline
|
|
*
|
|
* This test aims to create a minimal reproducible case.
|
|
*/
|
|
|
|
import puppeteer from 'puppeteer';
|
|
|
|
const BASE_URL = 'http://localhost:1999';
|
|
|
|
async function testMultiFileSrcBug() {
|
|
console.log('🧪 HYPERSCRIPT MULTI-SRC FILE BUG INVESTIGATION\n');
|
|
console.log('=' .repeat(70) + '\n');
|
|
|
|
const browser = await puppeteer.launch({
|
|
headless: false,
|
|
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
defaultViewport: { width: 1280, height: 900 }
|
|
});
|
|
|
|
const page = await browser.newPage();
|
|
|
|
// Collect console messages and errors
|
|
const consoleMessages = [];
|
|
const errors = [];
|
|
|
|
page.on('console', msg => {
|
|
consoleMessages.push({ type: msg.type(), text: msg.text() });
|
|
if (msg.type() === 'error') {
|
|
console.log(` ❌ Console Error: ${msg.text()}`);
|
|
}
|
|
});
|
|
|
|
page.on('pageerror', error => {
|
|
errors.push(error.message);
|
|
console.log(` ❌ Page Error: ${error.message}`);
|
|
});
|
|
|
|
try {
|
|
// =====================================================================
|
|
// TEST 1: Load actual CV page and check hyperscript status
|
|
// =====================================================================
|
|
console.log('1️⃣ Loading CV page to check hyperscript file loading...\n');
|
|
|
|
await page.goto(BASE_URL, { waitUntil: 'networkidle2', timeout: 30000 });
|
|
|
|
// Check which hyperscript files were loaded
|
|
const scriptTags = await page.evaluate(() => {
|
|
const scripts = document.querySelectorAll('script[type="text/hyperscript"]');
|
|
return Array.from(scripts).map(s => ({
|
|
src: s.src || 'INLINE',
|
|
hasContent: s.textContent.length > 0,
|
|
contentLength: s.textContent.length,
|
|
contentPreview: s.textContent.substring(0, 100)
|
|
}));
|
|
});
|
|
|
|
console.log(` Found ${scriptTags.length} hyperscript script tags:\n`);
|
|
scriptTags.forEach((tag, i) => {
|
|
if (tag.src === 'INLINE') {
|
|
console.log(` ${i + 1}. INLINE (${tag.contentLength} chars)`);
|
|
} else {
|
|
console.log(` ${i + 1}. SRC: ${tag.src}`);
|
|
}
|
|
});
|
|
console.log();
|
|
|
|
// =====================================================================
|
|
// TEST 2: Check if hyperscript is loaded and functioning
|
|
// =====================================================================
|
|
console.log('2️⃣ Checking hyperscript functionality...\n');
|
|
|
|
const hyperscriptStatus = await page.evaluate(() => {
|
|
return {
|
|
hyperscriptExists: typeof _hyperscript !== 'undefined',
|
|
browserUtilsExists: typeof _hyperscript !== 'undefined' && _hyperscript.browserInit,
|
|
initScrollBehaviorExists: typeof initScrollBehavior === 'function',
|
|
handleScrollExists: typeof handleScroll === 'function',
|
|
printFriendlyExists: typeof printFriendly === 'function'
|
|
};
|
|
});
|
|
|
|
console.log(` _hyperscript loaded: ${hyperscriptStatus.hyperscriptExists ? '✅' : '❌'}`);
|
|
console.log(` initScrollBehavior: ${hyperscriptStatus.initScrollBehaviorExists ? '✅' : '❌'}`);
|
|
console.log(` handleScroll: ${hyperscriptStatus.handleScrollExists ? '✅' : '❌'}`);
|
|
console.log(` printFriendly: ${hyperscriptStatus.printFriendlyExists ? '✅' : '❌'}`);
|
|
console.log();
|
|
|
|
// =====================================================================
|
|
// TEST 3: Test keyboard shortcuts (which use inline hyperscript)
|
|
// =====================================================================
|
|
console.log('3️⃣ Testing keyboard shortcuts (inline hyperscript)...\n');
|
|
|
|
// Test '?' shortcut to open shortcuts modal
|
|
await page.keyboard.press('?');
|
|
await new Promise(r => setTimeout(r, 500));
|
|
|
|
const shortcutsModalOpen = await page.evaluate(() => {
|
|
const modal = document.getElementById('shortcuts-modal');
|
|
return modal && modal.open;
|
|
});
|
|
|
|
console.log(` '?' key opens shortcuts modal: ${shortcutsModalOpen ? '✅ WORKS' : '❌ FAILS'}`);
|
|
|
|
// Close modal
|
|
if (shortcutsModalOpen) {
|
|
await page.keyboard.press('Escape');
|
|
await new Promise(r => setTimeout(r, 300));
|
|
}
|
|
|
|
// Test 'V' shortcut to toggle theme
|
|
const themeStateBefore = await page.evaluate(() => {
|
|
const toggle = document.getElementById('themeToggle');
|
|
return toggle ? toggle.checked : null;
|
|
});
|
|
|
|
await page.keyboard.press('v');
|
|
await new Promise(r => setTimeout(r, 300));
|
|
|
|
const themeStateAfter = await page.evaluate(() => {
|
|
const toggle = document.getElementById('themeToggle');
|
|
return toggle ? toggle.checked : null;
|
|
});
|
|
|
|
const vKeyWorks = themeStateBefore !== null && themeStateAfter !== null && themeStateBefore !== themeStateAfter;
|
|
console.log(` 'V' key toggles theme: ${vKeyWorks ? '✅ WORKS' : '❌ FAILS'}`);
|
|
console.log();
|
|
|
|
// =====================================================================
|
|
// TEST 4: Test scroll behavior (uses external file functions)
|
|
// =====================================================================
|
|
console.log('4️⃣ Testing scroll behavior (external file functions)...\n');
|
|
|
|
// Scroll down
|
|
await page.evaluate(() => window.scrollTo(0, 500));
|
|
await new Promise(r => setTimeout(r, 500));
|
|
|
|
const scrollDownResult = await page.evaluate(() => {
|
|
const actionBar = document.querySelector('.action-bar');
|
|
return actionBar ? actionBar.classList.contains('header-hidden') : null;
|
|
});
|
|
|
|
console.log(` Header hides on scroll down: ${scrollDownResult ? '✅ WORKS' : scrollDownResult === false ? '⚠️ Not hidden (mobile mode?)' : '❌ FAILS'}`);
|
|
|
|
// Scroll back up
|
|
await page.evaluate(() => window.scrollTo(0, 0));
|
|
await new Promise(r => setTimeout(r, 500));
|
|
|
|
const scrollUpResult = await page.evaluate(() => {
|
|
const actionBar = document.querySelector('.action-bar');
|
|
return actionBar ? !actionBar.classList.contains('header-hidden') : null;
|
|
});
|
|
|
|
console.log(` Header shows on scroll up: ${scrollUpResult ? '✅ WORKS' : '❌ FAILS'}`);
|
|
console.log();
|
|
|
|
// =====================================================================
|
|
// TEST 5: Create minimal reproduction page
|
|
// =====================================================================
|
|
console.log('5️⃣ Creating minimal reproduction test page...\n');
|
|
|
|
// Create a new page with minimal multi-file setup
|
|
const testPage = await browser.newPage();
|
|
|
|
testPage.on('console', msg => {
|
|
if (msg.type() === 'error') {
|
|
console.log(` ❌ Test Page Error: ${msg.text()}`);
|
|
}
|
|
});
|
|
|
|
testPage.on('pageerror', error => {
|
|
console.log(` ❌ Test Page Exception: ${error.message}`);
|
|
});
|
|
|
|
// Create test HTML that loads hyperscript like the CV does
|
|
const testHTML = `
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Hyperscript Multi-File Test</title>
|
|
<script type="text/hyperscript" src="/static/hyperscript/utils._hs"></script>
|
|
<script type="text/hyperscript" src="/static/hyperscript/toggles._hs"></script>
|
|
<script type="text/hyperscript" src="/static/hyperscript/hover-sync._hs"></script>
|
|
<script type="text/hyperscript" src="/static/hyperscript/keyboard._hs"></script>
|
|
<script src="https://unpkg.com/hyperscript.org@0.9.14"></script>
|
|
</head>
|
|
<body>
|
|
<h1>Multi-File Hyperscript Test</h1>
|
|
<div id="test-target">Original</div>
|
|
<button id="test-btn" _="on click put 'Clicked!' into #test-target">Click Me</button>
|
|
<div id="status"></div>
|
|
<script>
|
|
document.getElementById('status').textContent =
|
|
'initScrollBehavior: ' + (typeof initScrollBehavior === 'function' ? 'YES' : 'NO') +
|
|
', handleScroll: ' + (typeof handleScroll === 'function' ? 'YES' : 'NO') +
|
|
', printFriendly: ' + (typeof printFriendly === 'function' ? 'YES' : 'NO');
|
|
</script>
|
|
</body>
|
|
</html>
|
|
`;
|
|
|
|
// We can't serve arbitrary HTML, but we can check the existing hyperscript files
|
|
console.log(' Checking hyperscript file contents from server...\n');
|
|
|
|
// Fetch each hyperscript file
|
|
const hsFiles = [
|
|
'/static/hyperscript/utils._hs',
|
|
'/static/hyperscript/toggles._hs',
|
|
'/static/hyperscript/hover-sync._hs',
|
|
'/static/hyperscript/keyboard._hs'
|
|
];
|
|
|
|
for (const file of hsFiles) {
|
|
try {
|
|
const response = await page.evaluate(async (url) => {
|
|
const res = await fetch(url);
|
|
const text = await res.text();
|
|
return {
|
|
status: res.status,
|
|
contentType: res.headers.get('content-type'),
|
|
length: text.length,
|
|
preview: text.substring(0, 200)
|
|
};
|
|
}, BASE_URL + file);
|
|
|
|
console.log(` ${file}:`);
|
|
console.log(` Status: ${response.status}, Size: ${response.length} chars`);
|
|
console.log(` Content-Type: ${response.contentType}`);
|
|
} catch (err) {
|
|
console.log(` ${file}: ❌ Error - ${err.message}`);
|
|
}
|
|
}
|
|
|
|
await testPage.close();
|
|
|
|
// =====================================================================
|
|
// SUMMARY
|
|
// =====================================================================
|
|
console.log('\n' + '=' .repeat(70));
|
|
console.log('📊 TEST SUMMARY\n');
|
|
|
|
const allWorking = shortcutsModalOpen && vKeyWorks && (scrollDownResult !== null) && (scrollUpResult !== null);
|
|
|
|
if (allWorking) {
|
|
console.log(' ✅ All hyperscript features are working!');
|
|
console.log(' ✅ Both inline and external file functions work correctly.');
|
|
console.log('\n CONCLUSION: No multi-file bug detected in current setup.');
|
|
console.log(' The previous errors may have been caused by:');
|
|
console.log(' - Syntax errors in the refactored code');
|
|
console.log(' - Order of script loading');
|
|
console.log(' - Content-Type headers for ._hs files');
|
|
} else {
|
|
console.log(' ⚠️ Some features not working. Check errors above.');
|
|
console.log('\n This may indicate a multi-file loading issue.');
|
|
}
|
|
|
|
console.log('\n Console errors detected: ' + consoleMessages.filter(m => m.type === 'error').length);
|
|
console.log(' Page errors detected: ' + errors.length);
|
|
|
|
if (errors.length > 0) {
|
|
console.log('\n Error details:');
|
|
errors.forEach((err, i) => console.log(` ${i + 1}. ${err}`));
|
|
}
|
|
|
|
console.log('\n' + '=' .repeat(70));
|
|
console.log('\nBrowser staying open for manual inspection...');
|
|
console.log('Press Ctrl+C when done.\n');
|
|
|
|
// Keep browser open for inspection
|
|
await new Promise(() => {});
|
|
|
|
} catch (error) {
|
|
console.error('Test error:', error);
|
|
await browser.close();
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
testMultiFileSrcBug();
|