/** * Full Navigation Test with Search * Tests navigation through all pages and optionally runs a search * * Usage: * node test_full_navigation.js # Just navigate * node test_full_navigation.js --search # Navigate and run a search */ const puppeteer = require('puppeteer'); const AuthHelper = require('./auth_helper'); const { getPuppeteerLaunchOptions } = require('./puppeteer_config'); // NAVIGATION NOTE: Using 'domcontentloaded' instead of 'networkidle2' for page.goto() // because networkidle2 waits for no network activity for 500ms, but WebSocket // connections and background polling keep the network active, causing infinite hangs. // See: test_login_validation.js and auth_helper.js for detailed explanation. // Check command line arguments const runSearch = process.argv.includes('--search'); async function testFullNavigation() { 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('πŸ§ͺ Full Navigation Test' + (runSearch ? ' with Search' : '') + '\n'); try { // Ensure authentication console.log('πŸ” Ensuring authentication...'); await authHelper.ensureAuthenticatedWithTimeout(); console.log('βœ… Authentication successful\n'); // Test navigation through all main pages const pages = [ { path: '/', name: 'Home/Research', waitFor: '#query' }, { path: '/settings/', name: 'Settings', waitFor: '.setting-item, form' }, { path: '/metrics/', name: 'Metrics', waitFor: '#metrics-content, #loading' }, { path: '/history/', name: 'History', waitFor: '#history-container, .ldr-history-list, .card' }, { path: '/benchmark/', name: 'Benchmark', waitFor: 'form, .benchmark-form' }, { path: '/cost-analytics/', name: 'Cost Analytics', waitFor: '.cost-chart, canvas, #costChart' } ]; console.log('πŸ“„ Testing page navigation:'); for (const pageInfo of pages) { console.log(`\nπŸ” Navigating to ${pageInfo.name} (${pageInfo.path})`); await page.goto(`${baseUrl}${pageInfo.path}`, { waitUntil: 'domcontentloaded', timeout: 30000 }); // Wait for specific element to ensure page loaded try { await page.waitForSelector(pageInfo.waitFor, { timeout: 5000 }); console.log(`βœ… ${pageInfo.name} loaded successfully`); } catch { console.log(`⚠️ ${pageInfo.name} - Could not find expected element: ${pageInfo.waitFor}`); } // Small delay between navigations await new Promise(resolve => setTimeout(resolve, 1000)); } // Run search if requested if (runSearch) { console.log('\n\nπŸ”Ž Starting Research Test'); console.log('=' .repeat(50)); // Navigate back to home await page.goto(baseUrl, { waitUntil: 'domcontentloaded', timeout: 30000 }); // Wait for research form await page.waitForSelector('#query', { timeout: 5000 }); // Fill in search query const searchQuery = 'What are the benefits of TypeScript over JavaScript?'; console.log(`πŸ“ Entering search query: "${searchQuery}"`); await page.type('#query', searchQuery); // Select search options if available const modeSelect = await page.$('select[name="mode"]'); if (modeSelect) { await page.select('select[name="mode"]', 'quick'); console.log('βœ… Selected quick search mode'); } // Check current settings const settings = await page.evaluate(() => { const provider = document.querySelector('input[name="llm_provider"]')?.value || document.querySelector('#llm_provider')?.value || 'unknown'; const model = document.querySelector('input[name="llm_model"]')?.value || document.querySelector('#llm_model')?.value || 'unknown'; const searchEngine = document.querySelector('input[name="search_tool"]')?.value || document.querySelector('#search_tool')?.value || 'unknown'; return { provider, model, searchEngine }; }); console.log('\nπŸ“Š Current Settings:'); console.log(` LLM Provider: ${settings.provider}`); console.log(` LLM Model: ${settings.model}`); console.log(` Search Engine: ${settings.searchEngine}`); // Submit search console.log('\nπŸš€ Starting research...'); // Click submit button const submitButton = await page.$('button[type="submit"]'); if (!submitButton) { throw new Error('Submit button not found'); } // Set up response monitoring const responsePromise = page.waitForResponse(response => response.url().includes('/research/start') || response.url().includes('/api/research'), { timeout: 10000 } ); await submitButton.click(); try { const response = await responsePromise; console.log(`βœ… Research request sent - Status: ${response.status()}`); // Wait for redirect or progress page await page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 10000 }); const currentUrl = page.url(); console.log(`πŸ“ Redirected to: ${currentUrl}`); if (currentUrl.includes('/research/')) { console.log('βœ… Research started successfully!'); // Wait a bit to see some progress console.log('⏳ Waiting 10 seconds to observe progress...'); await new Promise(resolve => setTimeout(resolve, 10000)); // Check for any errors or status updates const statusElements = await page.$$('.status, .progress, .alert'); console.log(`Found ${statusElements.length} status elements`); } } catch (error) { console.log('⚠️ Research might have failed or timed out:', error.message); // Check for error messages const errorAlert = await page.$('.alert-danger'); if (errorAlert) { const errorText = await page.evaluate(el => el.textContent, errorAlert); console.log('❌ Error message:', errorText); } } } console.log('\nβœ… Navigation test completed successfully!'); } catch (error) { console.error('\n❌ Test failed:', error.message); // Log current URL console.log('Current URL:', page.url()); } // Keep browser open for a moment if search was run if (runSearch) { console.log('\n⏸️ Keeping browser open for 5 seconds...'); await new Promise(resolve => setTimeout(resolve, 5000)); } await browser.close(); console.log('\n🏁 Test session ended'); } // Run the test testFullNavigation().catch(error => { console.error('πŸ’₯ Test runner error:', error); process.exit(1); });