/** * Research Diagnosis Test * Detailed diagnostic test to understand why research doesn't start */ const puppeteer = require('puppeteer'); const AuthHelper = require('./auth_helper'); const { getPuppeteerLaunchOptions } = require('./puppeteer_config'); async function testResearchDiagnosis() { const browser = await puppeteer.launch(getPuppeteerLaunchOptions()); const page = await browser.newPage(); const baseUrl = 'http://127.0.0.1:5000'; const authHelper = new AuthHelper(page, baseUrl); console.log('πŸ”¬ Research Diagnosis Test'); console.log('=' .repeat(60) + '\n'); // Collect all console messages const consoleLogs = []; page.on('console', msg => { const entry = `[${msg.type().toUpperCase()}] ${msg.text()}`; consoleLogs.push(entry); console.log(`πŸ–₯️ ${entry}`); }); // Collect JavaScript errors page.on('pageerror', error => { console.log(`❌ JS Error: ${error.message}`); }); // Monitor all network requests await page.setRequestInterception(true); const networkLog = []; page.on('request', request => { const logEntry = { url: request.url(), method: request.method(), headers: request.headers(), postData: request.postData(), timestamp: new Date().toISOString() }; networkLog.push(logEntry); // Log important requests if (request.url().includes('/api/') || request.url().includes('/research/')) { console.log(`\nπŸ“€ ${request.method()} ${request.url()}`); if (request.postData()) { console.log('πŸ“¦ Request Body:', request.postData()); } } request.continue(); }); page.on('response', async response => { if (response.url().includes('/api/') || response.url().includes('/research/')) { console.log(`πŸ“₯ Response: ${response.status()} ${response.statusText()}`); // Try to get response body for errors if (response.status() >= 400) { try { const body = await response.text(); console.log('πŸ“„ Error Response Body:', body); } catch { console.log('Could not read response body'); } } } }); try { // Step 1: Authenticate console.log('πŸ” Authenticating...'); await authHelper.ensureAuthenticated(); console.log('βœ… Authenticated\n'); // Step 2: Go to home page await page.goto(baseUrl, { waitUntil: 'domcontentloaded', timeout: 30000 }); // Step 3: Check what's on the page console.log('πŸ“‹ Checking page structure...\n'); const pageInfo = await page.evaluate(() => { const info = { forms: [], scripts: [], apiEndpoints: [], formElements: {} }; // Find all forms document.querySelectorAll('form').forEach(form => { info.forms.push({ id: form.id, action: form.action, method: form.method, onsubmit: form.onsubmit ? 'has onsubmit handler' : 'no handler' }); }); // Find form elements const elements = ['#query', '#mode-quick', '#mode-detailed', '#model_provider', '#search_engine', '#iterations', '#questions_per_iteration', 'button[type="submit"]']; elements.forEach(selector => { const el = document.querySelector(selector); info.formElements[selector] = el ? { found: true, type: el.type || el.tagName, value: el.value || '', disabled: el.disabled } : { found: false }; }); // Find loaded scripts document.querySelectorAll('script[src]').forEach(script => { if (script.src.includes('research') || script.src.includes('form')) { info.scripts.push(script.src); } }); // Check for API endpoints in JavaScript const scriptContent = Array.from(document.scripts) .map(s => s.textContent) .join('\n'); const apiMatches = scriptContent.match(/['"]\/api\/[^'"]+['"]/g) || []; info.apiEndpoints = [...new Set(apiMatches.map(m => m.slice(1, -1)))]; return info; }); console.log('Forms found:', pageInfo.forms); console.log('\nForm elements:'); Object.entries(pageInfo.formElements).forEach(([selector, info]) => { console.log(` ${selector}: ${info.found ? 'βœ… Found' : '❌ Not found'}`); if (info.found && info.value) { console.log(` Value: ${info.value}`); } }); console.log('\nAPI endpoints found in JavaScript:', pageInfo.apiEndpoints); console.log('\nResearch-related scripts:', pageInfo.scripts); // Step 4: Fill the form console.log('\nπŸ“ Filling research form...\n'); // Clear and type query await page.click('#query', { clickCount: 3 }); // Triple click to select all await page.type('#query', 'What is artificial intelligence?'); console.log('βœ… Entered query'); // Select quick mode const quickMode = await page.$('#mode-quick'); if (quickMode) { await page.click('#mode-quick'); console.log('βœ… Selected quick mode'); } // Get form data before submission const formData = await page.evaluate(() => { const data = {}; const form = document.getElementById('research-form'); if (form) { const fd = new FormData(form); for (const [key, value] of fd.entries()) { data[key] = value; } } // Also check hidden inputs and selects document.querySelectorAll('input[type="hidden"], select').forEach(el => { if (el.name || el.id) { data[el.name || el.id] = el.value; } }); return data; }); console.log('\nπŸ“Š Form data to be submitted:'); console.log(JSON.stringify(formData, null, 2)); // Step 5: Check JavaScript state console.log('\nπŸ”§ Checking JavaScript state...\n'); const jsState = await page.evaluate(() => { const state = { jQuery: typeof $ !== 'undefined', socketIO: typeof io !== 'undefined', formHandlers: [], globalFunctions: [] }; // Check for form submit handlers const form = document.getElementById('research-form'); if (form) { // Check jQuery handlers if (typeof $ !== 'undefined' && $._data) { const events = $._data(form, 'events'); if (events && events.submit) { state.formHandlers.push('jQuery submit handler'); } } // Check native handlers if (form.onsubmit) { state.formHandlers.push('Native onsubmit handler'); } } // Check for global functions const funcs = ['startResearch', 'submitResearch', 'validateForm']; funcs.forEach(func => { if (typeof window[func] === 'function') { state.globalFunctions.push(func); } }); return state; }); console.log('JavaScript environment:'); console.log(` jQuery loaded: ${jsState.jQuery}`); console.log(` Socket.IO loaded: ${jsState.socketIO}`); console.log(` Form handlers: ${jsState.formHandlers.join(', ') || 'None'}`); console.log(` Global functions: ${jsState.globalFunctions.join(', ') || 'None'}`); // Step 6: Submit the form console.log('\nπŸš€ Attempting to submit research...\n'); // Take screenshot before submit await page.screenshot({ path: './screenshots/diagnosis_before_submit.png' }); // Find submit button const submitButton = await page.$('button[type="submit"]'); if (!submitButton) { throw new Error('Submit button not found!'); } // Click and monitor what happens console.log('Clicking submit button...'); await submitButton.click(); // Wait a bit to see what happens await new Promise(resolve => setTimeout(resolve, 5000)); // Check current state const afterSubmit = await page.evaluate(() => { return { url: window.location.href, alerts: Array.from(document.querySelectorAll('.alert')).map(a => ({ class: a.className, text: a.textContent.trim() })), bodyClasses: document.body.className, visibleModals: Array.from(document.querySelectorAll('.modal.show')).length, activeRequests: typeof $.active !== 'undefined' ? $.active : 'unknown' }; }); console.log('\nπŸ“ After submit state:'); console.log(` URL: ${afterSubmit.url}`); console.log(` Alerts: ${afterSubmit.alerts.length}`); afterSubmit.alerts.forEach(alert => { console.log(` - [${alert.class}] ${alert.text}`); }); console.log(` Active AJAX requests: ${afterSubmit.activeRequests}`); // Take final screenshot await page.screenshot({ path: './screenshots/diagnosis_after_submit.png' }); // Step 7: Summary console.log('\n' + '=' .repeat(60)); console.log('πŸ“Š DIAGNOSIS SUMMARY'); console.log('=' .repeat(60)); console.log('\nπŸ” Key Findings:'); // Check console logs for errors const errors = consoleLogs.filter(log => log.includes('ERROR')); if (errors.length > 0) { console.log('\n❌ JavaScript Errors:'); errors.forEach(err => console.log(` - ${err}`)); } // Check network failures const failedRequests = networkLog.filter(req => { const response = networkLog.find(r => r.url === req.url && r.status); return response && response.status >= 400; }); if (failedRequests.length > 0) { console.log('\n❌ Failed API Calls:'); failedRequests.forEach(req => { console.log(` - ${req.method} ${req.url}`); }); } console.log('\nπŸ’‘ Recommendations:'); console.log('1. Check server logs for SQLAlchemy errors'); console.log('2. Verify all required form fields are being sent'); console.log('3. Check if API endpoints are correctly configured'); console.log('4. Ensure database migrations are up to date'); } catch (error) { console.error('\n❌ Test error:', error.message); console.error(error.stack); await page.screenshot({ path: './screenshots/diagnosis_error.png' }); } // Save detailed logs const fs = require('fs'); fs.writeFileSync('./diagnosis_network_log.json', JSON.stringify(networkLog, null, 2)); fs.writeFileSync('./diagnosis_console_log.json', JSON.stringify(consoleLogs, null, 2)); console.log('\nπŸ“ Detailed logs saved to:'); console.log(' - ./diagnosis_network_log.json'); console.log(' - ./diagnosis_console_log.json'); console.log('\n⏸️ Keeping browser open for manual inspection...'); console.log('Press Ctrl+C to close'); // Keep browser open indefinitely for debugging await new Promise(() => {}); } // Run the test testResearchDiagnosis().catch(error => { console.error('πŸ’₯ Test runner error:', error); process.exit(1); });