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' }); }, 10000); }); } async function main() { console.log('[1] Creating new tab and setting fake auth token...'); 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'); await cdpCommand(ws, 'Network.enable'); // Navigate to app domain first so we can set localStorage await cdpCommand(ws, 'Page.navigate', { url: 'http://localhost:5199/' }); await new Promise(r => setTimeout(r, 2000)); // Set fake auth token and user_id in localStorage console.log('[2] Injecting fake token into localStorage...'); const setStorage = await cdpCommand(ws, 'Runtime.evaluate', { expression: ` localStorage.setItem('token', 'fake_test_token_abc123'); localStorage.setItem('user_id', 'admin_test_user'); 'done' `, returnByValue: true, }); console.log(' localStorage set:', setStorage?.result?.value); // Now reload the page so auth store picks up the token console.log('[3] Reloading page with auth token...'); const errors = []; const logs = []; ws.on('message', (raw) => { try { const msg = JSON.parse(raw.toString()); if (msg.method === 'Runtime.exceptionThrown') { const ed = msg.params.exceptionDetails; const errText = ed.text || ed.exception?.description || ''; errors.push(errText); console.log(` ❌ EXCEPTION: ${errText.substring(0, 300)}`); if (ed.exception?.className) console.log(` class: ${ed.exception.className}`); if (ed.stackTrace?.callFrames) { ed.stackTrace.callFrames.slice(0, 5).forEach(f => { console.log(` at ${f.functionName || '(anon)'} (${f.url}:${f.lineNumber}:${f.columnNumber})`); }); } } if (msg.method === 'Log.entryAdded') { const entry = msg.params.entry; const text = entry.text?.substring(0, 200) || ''; console.log(` LOG [${entry.level}]: ${text}`); if (entry.level === 'error' || entry.level === 'warning') { errors.push(`[LOG:${entry.level}] ${text}`); } } if (msg.method === 'Runtime.consoleAPICalled') { const p = msg.params; if (p.type === 'error') { const text = p.args?.map(a => a.value || a.description || '').join(' ') || ''; errors.push(`[CONSOLE:${p.type}] ${text}`); console.log(` CONSOLE.error: ${text.substring(0, 200)}`); } else { logs.push(`[${p.type}] ${p.args?.map(a => a.value || '').join(' ').substring(0, 150)}`); } } if (msg.method === 'Network.responseReceived') { const resp = msg.params.response; if (resp.status >= 400) { console.log(` NET ${resp.status}: ${resp.url.substring(0, 150)}`); } } } catch {} }); await cdpCommand(ws, 'Page.reload', { ignoreCache: true }); await new Promise(r => setTimeout(r, 8000)); console.log('\n[4] Checking DOM state...'); // Check #root const e1 = await cdpCommand(ws, 'Runtime.evaluate', { expression: ` (() => { const root = document.getElementById('root'); if (!root) return 'NO_ROOT'; const h = root.innerHTML.trim(); if (!h) return 'ROOT_EMPTY'; return 'ROOT_LEN=' + h.length + ' FIRST:' + h.substring(0, 300); })() `, returnByValue: true, }); console.log(' #root:', e1?.result?.value); // Check body const e2 = await cdpCommand(ws, 'Runtime.evaluate', { expression: `document.body ? 'BODY_OK children=' + document.body.children.length : 'NO_BODY'`, returnByValue: true, }); console.log(' body:', e2?.result?.value); // Check if React rendered the chat interface const e3 = await cdpCommand(ws, 'Runtime.evaluate', { expression: ` (() => { const root = document.getElementById('root'); const h = root ? root.innerHTML : ''; const hasAppLayout = h.includes('h-screen'); const hasSidebar = h.includes('sidebar') || h.includes('新对话'); const hasHeader = h.includes('昔涟') && h.includes('退出'); const hasChatContainer = h.includes('ChatContainer') || h.includes('开始一段新对话'); const hasChatInput = h.includes('和昔涟说点什么'); return JSON.stringify({ hasAppLayout, hasSidebar, hasHeader, hasChatContainer, hasChatInput, totalLen: h.length }); })() `, returnByValue: true, }); console.log(' Features:', e3?.result?.value); // Check for any React ErrorBoundary or error state const e4 = await cdpCommand(ws, 'Runtime.evaluate', { expression: ` (() => { const body = document.body; return body ? body.innerText.substring(0, 500) : 'NO_BODY'; })() `, returnByValue: true, }); console.log(' Text:', e4?.result?.value); ws.close(); console.log('\n=== SUMMARY ==='); console.log('Total errors:', errors.length); errors.forEach((e, i) => console.log(` ERR${i+1}: ${e.substring(0, 500)}`)); console.log('Total logs:', logs.length); logs.forEach(l => console.log(' LOG:', l.substring(0, 200))); } main().catch(e => { console.error('Fatal:', e.message); process.exit(1); });