#!/usr/bin/env node import { chromium } from 'playwright'; (async () => { console.log('šŸ”¬ DEFINITIVE TEST - JavaScript Migration\n'); console.log('Testing scroll behavior migration from hyperscript to JavaScript\n'); const browser = await chromium.launch({ headless: false, args: [ '--disable-http-cache', '--disable-cache', '--disable-application-cache', '--disable-offline-load-stale-cache', '--disk-cache-size=0' ] }); const context = await browser.newContext({ ignoreHTTPSErrors: true, bypassCSP: true, serviceWorkers: 'block' }); const page = await context.newPage(); // Track errors const errors = []; let parseErrorDetails = null; page.on('console', msg => { if (msg.type() === 'error') { const text = msg.text(); errors.push(text); if (text.includes('Expected') || text.includes('hyperscript')) { parseErrorDetails = text; } } }); page.on('pageerror', err => { errors.push(err.message); if (err.message.includes('Expected') || err.message.includes('hyperscript')) { parseErrorDetails = err.message; } }); // Load with aggressive cache-busting const timestamp = Date.now(); const random = Math.random().toString(36).substring(7); const url = `http://localhost:1999/?lang=en&_t=${timestamp}&_r=${random}`; console.log(`šŸ“„ Loading: ${url}\n`); console.log('ā³ Waiting for page to fully load...\n'); await page.goto(url, { waitUntil: 'networkidle', timeout: 15000 }); await page.waitForTimeout(4000); console.log('═'.repeat(70)); console.log('VERIFICATION RESULTS'); console.log('═'.repeat(70) + '\n'); // TEST 1: Check for parse errors const hasParseError = errors.some(e => e.includes('Expected') || e.includes('found') || e.toLowerCase().includes('parse') ); console.log('1. HYPERSCRIPT PARSE ERRORS:'); if (hasParseError) { console.log(' āŒ STILL PRESENT\n'); console.log(' Error details:'); console.log(' ' + parseErrorDetails.split('\n').join('\n ')); } else { console.log(' āœ… NONE - Migration successful!\n'); } // TEST 2: Verify hyperscript file no longer has handleScroll console.log('2. HYPERSCRIPT FILE CHECK:'); const hyperscriptFile = await page.evaluate(async () => { const cacheBuster = Date.now() + Math.random(); const response = await fetch(`/static/hyperscript/functions._hs?_=${cacheBuster}`, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache' } }); const text = await response.text(); return { size: text.length, hasHandleScroll: text.includes('def handleScroll()'), hasScrollNote: text.includes('Scroll behavior has been moved to /static/js/scroll-behavior.js') }; }); console.log(` - File size: ${hyperscriptFile.size} bytes`); console.log(` - Has handleScroll(): ${hyperscriptFile.hasHandleScroll ? 'āŒ YES (BAD)' : 'āœ… NO (GOOD)'}`); console.log(` - Has migration note: ${hyperscriptFile.hasScrollNote ? 'āœ… YES' : 'āŒ NO'}`); // TEST 3: Verify JavaScript file is loaded console.log('\n3. JAVASCRIPT FILE CHECK:'); const jsFile = await page.evaluate(async () => { const cacheBuster = Date.now() + Math.random(); const response = await fetch(`/static/js/scroll-behavior.js?_=${cacheBuster}`, { cache: 'no-store', headers: { 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache' } }); const text = await response.text(); return { loaded: response.ok, size: text.length, hasHandleScroll: text.includes('function handleScroll()'), hasDOMContentLoaded: text.includes('DOMContentLoaded') }; }); console.log(` - File loaded: ${jsFile.loaded ? 'āœ… YES' : 'āŒ NO'}`); console.log(` - File size: ${jsFile.size} bytes`); console.log(` - Has handleScroll function: ${jsFile.hasHandleScroll ? 'āœ… YES' : 'āŒ NO'}`); console.log(` - Has DOMContentLoaded: ${jsFile.hasDOMContentLoaded ? 'āœ… YES' : 'āŒ NO'}`); // TEST 4: Verify HTML template includes JS file console.log('\n4. HTML TEMPLATE CHECK:'); const htmlContent = await page.content(); const hasJsInclude = htmlContent.includes('/static/js/scroll-behavior.js'); console.log(` - Includes JS file: ${hasJsInclude ? 'āœ… YES' : 'āŒ NO'}`); // TEST 5: Test scroll behavior functionality console.log('\n5. FUNCTIONAL TEST - Scroll Behavior:'); await page.evaluate(() => window.scrollTo(0, 0)); await page.waitForTimeout(300); let btnCheck = await page.evaluate(() => { const btn = document.querySelector('#back-to-top'); return { exists: !!btn, display: btn ? window.getComputedStyle(btn).display : 'N/A' }; }); console.log(` - At top (0px): display = "${btnCheck.display}" ${btnCheck.display === 'none' ? 'āœ…' : 'āŒ Expected "none"'}`); await page.evaluate(() => window.scrollTo(0, 500)); await page.waitForTimeout(300); btnCheck = await page.evaluate(() => { const btn = document.querySelector('#back-to-top'); return { display: btn ? window.getComputedStyle(btn).display : 'N/A' }; }); console.log(` - At 500px: display = "${btnCheck.display}" ${btnCheck.display === 'flex' ? 'āœ…' : 'āŒ Expected "flex"'}`); // TEST 6: Test at-bottom functionality console.log('\n6. AT-BOTTOM CLASS TEST:'); await page.evaluate(() => window.scrollTo(0, document.documentElement.scrollHeight)); await page.waitForTimeout(300); const atBottomCheck = await page.evaluate(() => { const backToTop = document.querySelector('#back-to-top'); const infoBtn = document.querySelector('#info-button'); const shortcutsBtn = document.querySelector('#shortcuts-button'); return { backToTop: backToTop?.classList.contains('at-bottom') ?? false, infoBtn: infoBtn?.classList.contains('at-bottom') ?? false, shortcutsBtn: shortcutsBtn?.classList.contains('at-bottom') ?? false }; }); console.log(` - back-to-top has .at-bottom: ${atBottomCheck.backToTop ? 'āœ…' : 'āŒ'}`); console.log(` - info-button has .at-bottom: ${atBottomCheck.infoBtn ? 'āœ…' : 'āŒ'}`); console.log(` - shortcuts-button has .at-bottom: ${atBottomCheck.shortcutsBtn ? 'āœ…' : 'āŒ'}`); console.log('\n' + '═'.repeat(70)); // FINAL VERDICT const allTestsPass = !hasParseError && !hyperscriptFile.hasHandleScroll && hyperscriptFile.hasScrollNote && jsFile.loaded && jsFile.hasHandleScroll && hasJsInclude; if (allTestsPass) { console.log('āœ… SUCCESS: JavaScript migration is COMPLETE!'); console.log('\n āœ“ No hyperscript parse errors'); console.log(' āœ“ handleScroll removed from hyperscript'); console.log(' āœ“ JavaScript file loaded and functional'); console.log(' āœ“ HTML template updated correctly'); console.log(' āœ“ Scroll behavior works as expected'); console.log(' āœ“ At-bottom positioning works correctly'); } else { console.log('āŒ ISSUES DETECTED:'); if (hasParseError) console.log(' - Hyperscript parse errors still present'); if (hyperscriptFile.hasHandleScroll) console.log(' - handleScroll still in hyperscript file'); if (!hyperscriptFile.hasScrollNote) console.log(' - Migration note missing'); if (!jsFile.loaded) console.log(' - JavaScript file not loading'); if (!jsFile.hasHandleScroll) console.log(' - JavaScript handleScroll function missing'); if (!hasJsInclude) console.log(' - HTML template not updated'); } console.log('═'.repeat(70)); console.log('\nšŸ’” Browser window left open for manual inspection'); console.log(' Check Console tab and test scrolling manually'); console.log('\nPress Ctrl+C when done\n'); await new Promise(() => {}); })();