import { WebSocket } from 'ws'; import http from 'http'; const CDP_HOST = 'localhost'; const CDP_PORT = 9222; function httpRequest(method, path) { return new Promise((resolve, reject) => { const req = http.request({ hostname: CDP_HOST, port: CDP_PORT, method, path }, (res) => { let data = ''; res.on('data', (c) => data += c); res.on('end', () => { try { resolve(JSON.parse(data)); } catch(e) { resolve(data); } }); }); req.on('error', reject); req.end(); }); } function cdpCommand(ws, method, params = {}) { const id = Math.floor(Math.random() * 1000000); return new Promise((resolve) => { const handler = (raw) => { try { const msg = JSON.parse(raw.toString()); if (msg.id === id) { ws.off('message', handler); resolve(msg.result || msg); } } catch {} }; ws.on('message', handler); ws.send(JSON.stringify({ id, method, params })); setTimeout(() => { ws.off('message', handler); resolve({ error: 'timeout' }); }, 8000); }); } async function testPage(label) { console.log(`\n=== ${label} ===`); const newTab = await httpRequest('PUT', '/json/new?about:blank'); const ws = new WebSocket(newTab.webSocketDebuggerUrl); await new Promise((resolve) => ws.on('open', resolve)); await cdpCommand(ws, 'Runtime.enable'); await cdpCommand(ws, 'Page.enable'); await cdpCommand(ws, 'Log.enable'); const errors = []; const logs = []; ws.on('message', (raw) => { try { const msg = JSON.parse(raw.toString()); if (msg.method === 'Runtime.exceptionThrown') { errors.push(msg.params.exceptionDetails.text || JSON.stringify(msg.params.exceptionDetails).substring(0, 200)); } if (msg.method === 'Log.entryAdded' && msg.params.entry.level === 'error') { errors.push('[LOG] ' + msg.params.entry.text?.substring(0, 200)); } if (msg.method === 'Runtime.consoleAPICalled') { logs.push(`[${msg.params.type}] ${msg.params.args?.map(a => a.value || '').join(' ').substring(0, 150)}`); } } catch {} }); await cdpCommand(ws, 'Page.navigate', { url: 'http://localhost:5199/' }); await new Promise(r => setTimeout(r, 6000)); // Check #root const e1 = await cdpCommand(ws, 'Runtime.evaluate', { expression: `(() => { const r = document.getElementById('root'); return r ? (r.innerHTML.trim() ? 'CONTENT(' + r.innerHTML.length + ')' : 'EMPTY') : 'NO_ROOT'; })()`, returnByValue: true, }); console.log(' #root:', e1?.result?.value); // Check if JS loaded const e2 = await cdpCommand(ws, 'Runtime.evaluate', { expression: `typeof React !== 'undefined' ? 'React OK' : 'React MISSING'`, returnByValue: true, }); console.log(' React:', e2?.result?.value); // Check SW status const e3 = await cdpCommand(ws, 'Runtime.evaluate', { expression: `(() => { try { return 'serviceWorker' in navigator ? 'SW supported' : 'SW not supported'; } catch(e) { return 'Error: '+e.message; } })()`, returnByValue: true, }); console.log(' SW:', e3?.result?.value); console.log(' Errors:', errors.length); errors.forEach(e => console.log(' ', e.substring(0, 200))); console.log(' Logs:', logs.length); ws.close(); } async function main() { // First visit - install SW await testPage('1st VISIT (SW install)'); // Wait a bit for SW activation console.log('\nWaiting 3s for SW activation...'); await new Promise(r => setTimeout(r, 3000)); // Second visit - SW should be active await testPage('2nd VISIT (SW active)'); // Third visit await testPage('3rd VISIT'); console.log('\n=== DONE ==='); } main().catch(e => { console.error('Fatal:', e.message); process.exit(1); });