const puppeteer = require('puppeteer'); const path = require('path'); const { getPuppeteerLaunchOptions } = require('./puppeteer_config'); // Test configuration const BASE_URL = 'http://127.0.0.1:5000'; const TEST_USER = `details_test_${Date.now()}`; const TEST_PASSWORD = 'TestPass123!'; // Colors for console output const colors = { reset: '\x1b[0m', bright: '\x1b[1m', green: '\x1b[32m', red: '\x1b[31m', yellow: '\x1b[33m', blue: '\x1b[34m', cyan: '\x1b[36m' }; function log(message, type = 'info') { const timestamp = new Date().toISOString().split('T')[1].split('.')[0]; const typeColors = { 'info': colors.cyan, 'success': colors.green, 'error': colors.red, 'warning': colors.yellow, 'section': colors.blue }; const color = typeColors[type] || colors.reset; console.log(`${color}[${timestamp}] ${message}${colors.reset}`); } async function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function registerAndLogin(page) { log('šŸ“ Registering new user...', 'info'); await page.goto(`${BASE_URL}/register`); await page.waitForSelector('#username'); await page.type('#username', TEST_USER); await page.type('#password', TEST_PASSWORD); await page.type('#password_confirm', TEST_PASSWORD); await page.click('button[type="submit"]'); await page.waitForNavigation(); log('āœ… Registration successful', 'success'); } async function createAndWaitForResearch(page) { log('šŸ”¬ Creating research for details test...', 'info'); await page.goto(`${BASE_URL}/research`); await page.waitForSelector('#query'); // Set a specific query const testQuery = 'Benefits of green tea for health'; await page.evaluate((q) => { document.getElementById('query').value = q; }, testQuery); // Submit research await page.click('#submit-research'); // Wait for research to complete log('ā³ Waiting for research to complete...', 'info'); const startTime = Date.now(); const maxWaitTime = 120000; // 2 minutes while (Date.now() - startTime < maxWaitTime) { const progressText = await page.$eval('.progress-info', el => el.textContent).catch(() => ''); if (progressText.includes('100%') || progressText.includes('completed')) { log('āœ… Research completed', 'success'); break; } await delay(1000); } // Get research ID from URL or page const researchId = await page.evaluate(() => { // Try to extract from URL or page elements const urlMatch = window.location.pathname.match(/research\/([a-f0-9-]+)/); if (urlMatch) return urlMatch[1]; // Try to find in page data const researchLink = document.querySelector('a[href*="/results/"]'); if (researchLink) { const match = researchLink.href.match(/results\/([a-f0-9-]+)/); if (match) return match[1]; } return null; }); return { query: testQuery, id: researchId }; } async function testResearchDetails() { const browser = await puppeteer.launch(getPuppeteerLaunchOptions()); const page = await browser.newPage(); // Set console log handler page.on('console', msg => { if (msg.type() === 'error') { log(`Browser console error: ${msg.text()}`, 'error'); } }); try { // Register and login await registerAndLogin(page); // Create a research and wait for completion const research = await createAndWaitForResearch(page); // Navigate to details page log('\n=== TESTING RESEARCH DETAILS PAGE ===', 'section'); // First go to history to find the research await page.goto(`${BASE_URL}/history`); await page.waitForSelector('.history-item'); // Click on the first research item const detailsLink = await page.$('.history-item a[href*="/details/"], .history-item a[href*="/results/"]'); if (detailsLink) { await detailsLink.click(); await page.waitForNavigation(); } else if (research.id) { // Try direct navigation if we have the ID await page.goto(`${BASE_URL}/results/${research.id}`); } // Wait for details page to load await page.waitForSelector('.report-content, .results-container', { timeout: 10000 }); // Capture details page content const pageDetails = await page.evaluate(() => { const details = { title: document.title, url: window.location.href, hasReport: !!document.querySelector('.report-content, .markdown-content'), sections: [], metadata: {}, actions: { hasDownloadButton: !!document.querySelector('.download-btn, [data-action="download"]'), hasExportButton: !!document.querySelector('.export-btn, [data-action="export"]'), hasPrintButton: !!document.querySelector('.print-btn, [data-action="print"]'), hasShareButton: !!document.querySelector('.share-btn, [data-action="share"]'), hasBackButton: !!document.querySelector('.back-btn, a[href*="/history"]') } }; // Get report sections const headings = document.querySelectorAll('h1, h2, h3'); headings.forEach(h => { details.sections.push({ level: h.tagName, text: h.textContent.trim() }); }); // Get metadata if available const metaElements = document.querySelectorAll('.metadata-item, .meta-info, .research-info'); metaElements.forEach(el => { const label = el.querySelector('.label, .meta-label')?.textContent || ''; const value = el.querySelector('.value, .meta-value')?.textContent || el.textContent; if (label) { details.metadata[label] = value; } }); // Check for citations details.hasCitations = document.querySelectorAll('a[href*="http"], .citation, .reference').length > 0; // Check for research metrics details.hasMetrics = !!document.querySelector('.metrics, .research-metrics, .statistics'); return details; }); log('šŸ“Š Details page content:', 'info'); log(` - URL: ${pageDetails.url}`, 'info'); log(` - Has report content: ${pageDetails.hasReport}`, 'info'); log(` - Number of sections: ${pageDetails.sections.length}`, 'info'); log(` - Has citations: ${pageDetails.hasCitations}`, 'info'); log(` - Has metrics: ${pageDetails.hasMetrics}`, 'info'); // Verify essential elements if (!pageDetails.hasReport) { throw new Error('No report content found on details page'); } log('āœ… Report content present', 'success'); if (pageDetails.sections.length > 0) { log(`āœ… Found ${pageDetails.sections.length} sections in report`, 'success'); pageDetails.sections.slice(0, 5).forEach(section => { log(` - ${section.level}: ${section.text}`, 'info'); }); } // Test export functionality log('\n=== TESTING EXPORT OPTIONS ===', 'section'); if (pageDetails.actions.hasExportButton) { const exportButton = await page.$('.export-btn, [data-action="export"]'); await exportButton.click(); await delay(500); // Check for export options const exportOptions = await page.evaluate(() => { const options = []; const exportLinks = document.querySelectorAll('.export-option, .export-format, a[download]'); exportLinks.forEach(link => { options.push({ format: link.textContent || link.getAttribute('data-format') || '', href: link.href || '' }); }); return options; }); if (exportOptions.length > 0) { log(`āœ… Found ${exportOptions.length} export formats:`, 'success'); exportOptions.forEach(opt => { log(` - ${opt.format}`, 'info'); }); } } // Test download functionality if (pageDetails.actions.hasDownloadButton) { log('āœ… Download option available', 'success'); } // Test print functionality if (pageDetails.actions.hasPrintButton) { log('āœ… Print option available', 'success'); } // Test navigation log('\n=== TESTING NAVIGATION ===', 'section'); if (pageDetails.actions.hasBackButton) { const backButton = await page.$('.back-btn, a[href*="/history"]'); await backButton.click(); await page.waitForNavigation(); const afterNavUrl = page.url(); if (afterNavUrl.includes('/history')) { log('āœ… Back navigation to history works', 'success'); // Navigate back to details await page.goBack(); await page.waitForSelector('.report-content, .results-container'); } } // Test interactive elements log('\n=== TESTING INTERACTIVE ELEMENTS ===', 'section'); // Check for collapsible sections const collapsibles = await page.$$('.collapsible, .accordion, details'); if (collapsibles.length > 0) { log(`šŸ“Š Found ${collapsibles.length} collapsible sections`, 'info'); // Test first collapsible await collapsibles[0].click(); await delay(300); log('āœ… Collapsible sections work', 'success'); } // Check for copy buttons const copyButtons = await page.$$('.copy-btn, [data-action="copy"]'); if (copyButtons.length > 0) { log(`šŸ“Š Found ${copyButtons.length} copy buttons`, 'info'); log('āœ… Copy functionality available', 'success'); } // Capture final screenshot await page.screenshot({ path: path.join(__dirname, 'screenshots', 'research_details_final.png'), fullPage: true }); // Test metrics section if available if (pageDetails.hasMetrics) { log('\n=== TESTING METRICS SECTION ===', 'section'); const metrics = await page.evaluate(() => { const metricsData = {}; const metricElements = document.querySelectorAll('.metric, .stat, [data-metric]'); metricElements.forEach(el => { const label = el.querySelector('.metric-label, .label')?.textContent || el.getAttribute('data-metric') || ''; const value = el.querySelector('.metric-value, .value')?.textContent || el.textContent; if (label) { metricsData[label] = value; } }); return metricsData; }); log('šŸ“Š Research metrics:', 'info'); Object.entries(metrics).forEach(([key, value]) => { log(` - ${key}: ${value}`, 'info'); }); } log('\nāœ… Research details page test completed successfully!', 'success'); } catch (error) { log(`\nāŒ Test failed: ${error.message}`, 'error'); // Capture error screenshot await page.screenshot({ path: path.join(__dirname, 'screenshots', 'research_details_error.png'), fullPage: true }); throw error; } finally { await browser.close(); } } // Run the test testResearchDetails().catch(error => { console.error('Test execution failed:', error); process.exit(1); });