7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
361 lines
15 KiB
JavaScript
361 lines
15 KiB
JavaScript
const puppeteer = require('puppeteer');
|
|
const AuthHelper = require('./auth_helper');
|
|
const { getPuppeteerLaunchOptions } = require('./puppeteer_config');
|
|
|
|
// Test configuration
|
|
const BASE_URL = 'http://127.0.0.1:5000';
|
|
const PREDEFINED_QUESTION = 'What are the latest developments in renewable energy technology in 2024?';
|
|
const SEARCH_TIMEOUT = 5000; // 5 seconds timeout for search
|
|
const POLL_INTERVAL = 500; // Check every 0.5 seconds
|
|
|
|
async function analyzeSearchFunctionality() {
|
|
console.log('🔍 Starting Research Search Analysis Test...\n');
|
|
|
|
let browser;
|
|
try {
|
|
// Launch browser
|
|
browser = await puppeteer.launch(getPuppeteerLaunchOptions());
|
|
|
|
const page = await browser.newPage();
|
|
const authHelper = new AuthHelper(page, BASE_URL);
|
|
|
|
// Log browser console errors
|
|
page.on('console', msg => {
|
|
if (msg.type() === 'error') {
|
|
console.log(` Browser error: ${msg.text()}`);
|
|
}
|
|
});
|
|
|
|
// Set up request logging
|
|
page.on('request', request => {
|
|
if (request.url().includes('/api/') || request.url().includes('/research')) {
|
|
console.log(`→ REQUEST: ${request.method()} ${request.url()}`);
|
|
}
|
|
});
|
|
|
|
page.on('response', response => {
|
|
if (response.url().includes('/api/') || response.url().includes('/research')) {
|
|
console.log(`← RESPONSE: ${response.status()} ${response.url()}`);
|
|
}
|
|
});
|
|
|
|
// Step 1: Authentication
|
|
console.log('🔐 Step 1: Authenticating...');
|
|
await authHelper.ensureAuthenticated();
|
|
console.log('✅ Authentication successful\n');
|
|
|
|
// Step 2: Navigate to research page
|
|
console.log('📄 Step 2: Navigating to research page...');
|
|
await page.goto(`${BASE_URL}/`, { waitUntil: 'domcontentloaded' });
|
|
|
|
// Check if research form exists
|
|
const researchForm = await page.$('#research-form');
|
|
if (!researchForm) {
|
|
throw new Error('Research form not found on page');
|
|
}
|
|
console.log('✅ Research form found\n');
|
|
|
|
// Step 3: Fill in research question
|
|
console.log('📝 Step 3: Filling research form...');
|
|
console.log(` Question: "${PREDEFINED_QUESTION}"`);
|
|
|
|
// Type the question
|
|
await page.type('#query', PREDEFINED_QUESTION);
|
|
|
|
// Wait for models to load
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// The custom dropdown uses an input field and stores the value in a hidden input
|
|
console.log(' Looking for model dropdown elements...');
|
|
|
|
// Check current model value
|
|
const currentModel = await page.$eval('#model_hidden', el => el.value).catch(() => 'not found');
|
|
console.log(` Current model value in hidden input: ${currentModel}`);
|
|
|
|
// Click the model input to open dropdown
|
|
const modelInput = await page.$('#model');
|
|
if (modelInput) {
|
|
console.log(' Clicking model input to open dropdown...');
|
|
await modelInput.click();
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
|
|
// Look for dropdown options in the list
|
|
const modelOptions = await page.$$('#model-dropdown-list li');
|
|
console.log(` Found ${modelOptions.length} model options`);
|
|
|
|
if (modelOptions.length > 0) {
|
|
// Get the text and value of first option
|
|
const firstOption = await page.evaluate(el => ({
|
|
text: el.textContent.trim(),
|
|
value: el.getAttribute('data-value') || el.textContent.trim()
|
|
}), modelOptions[0]);
|
|
|
|
console.log(` Clicking first model option: ${firstOption.text} (${firstOption.value})`);
|
|
await modelOptions[0].click();
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
|
|
// Verify selection
|
|
const selectedModel = await page.$eval('#model_hidden', el => el.value).catch(() => 'error');
|
|
console.log(` Selected model: ${selectedModel}`);
|
|
} else {
|
|
console.log(' No model options found in dropdown list');
|
|
}
|
|
} else {
|
|
// Fallback to regular select if custom dropdown not found
|
|
const modelOptions = await page.$$eval('#model option', options =>
|
|
options.map(opt => ({ value: opt.value, text: opt.textContent }))
|
|
);
|
|
console.log(` Available models: ${modelOptions.length}`);
|
|
modelOptions.forEach(model => {
|
|
console.log(` - ${model.value}: ${model.text}`);
|
|
});
|
|
|
|
if (modelOptions.length > 0) {
|
|
await page.select('#model', modelOptions[0].value);
|
|
console.log(` Selected model: ${modelOptions[0].value}`);
|
|
}
|
|
}
|
|
|
|
// Handle search engine selection
|
|
console.log(' Checking search engine options...');
|
|
|
|
// Check current search engine value
|
|
const currentEngine = await page.$eval('#search_engine_hidden', el => el.value).catch(() => 'not found');
|
|
console.log(` Current search engine value in hidden input: ${currentEngine}`);
|
|
|
|
// Click the search engine input to open dropdown
|
|
const searchInput = await page.$('#search_engine');
|
|
if (searchInput) {
|
|
console.log(' Clicking search engine input to open dropdown...');
|
|
await searchInput.click();
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
|
|
// Look for dropdown options in the list
|
|
const searchOptions = await page.$$('#search-engine-dropdown-list li');
|
|
console.log(` Found ${searchOptions.length} search engine options`);
|
|
|
|
if (searchOptions.length > 0) {
|
|
// Get the text and value of first option
|
|
const firstOption = await page.evaluate(el => ({
|
|
text: el.textContent.trim(),
|
|
value: el.getAttribute('data-value') || el.textContent.trim()
|
|
}), searchOptions[0]);
|
|
|
|
console.log(` Clicking first search engine option: ${firstOption.text} (${firstOption.value})`);
|
|
await searchOptions[0].click();
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
|
|
// Verify selection
|
|
const selectedEngine = await page.$eval('#search_engine_hidden', el => el.value).catch(() => 'error');
|
|
console.log(` Selected search engine: ${selectedEngine}`);
|
|
} else {
|
|
console.log(' No search engine options found in dropdown list');
|
|
}
|
|
} else {
|
|
// Fallback to checkboxes
|
|
const searchEngines = await page.$$eval('[name="search_engines"]:checked', engines =>
|
|
engines.map(e => e.value)
|
|
);
|
|
console.log(` Selected search engines: ${searchEngines.join(', ') || 'None'}`);
|
|
|
|
if (searchEngines.length === 0) {
|
|
const availableEngines = await page.$$('[name="search_engines"]');
|
|
if (availableEngines.length > 0) {
|
|
await availableEngines[0].click();
|
|
console.log(' Selected first available search engine');
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log('✅ Form filled successfully\n');
|
|
|
|
// Step 4: Submit research
|
|
console.log('🚀 Step 4: Submitting research...');
|
|
|
|
// Click submit button - specifically the research submit button
|
|
const submitButton = await page.$('#start-research-btn');
|
|
if (!submitButton) {
|
|
// Fallback to form submit button
|
|
const fallbackButton = await page.$('#research-form button[type="submit"]');
|
|
if (!fallbackButton) {
|
|
throw new Error('Submit button not found');
|
|
}
|
|
}
|
|
|
|
// Set up response interceptor for research submission
|
|
const submissionPromise = page.waitForResponse(
|
|
response => response.url().includes('/research') && response.request().method() === 'POST',
|
|
{ timeout: 30000 }
|
|
);
|
|
|
|
await submitButton.click();
|
|
|
|
try {
|
|
const response = await submissionPromise;
|
|
console.log(`✅ Research submitted - Response: ${response.status()}`);
|
|
|
|
if (response.status() !== 200) {
|
|
const responseText = await response.text();
|
|
console.log(`⚠️ Non-200 response: ${responseText}`);
|
|
}
|
|
} catch {
|
|
console.log('❌ No response received for research submission');
|
|
}
|
|
|
|
// Wait a bit for any redirects
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Step 5: Analyze current state
|
|
console.log('\n📊 Step 5: Analyzing search state...');
|
|
|
|
const currentUrl = page.url();
|
|
console.log(` Current URL: ${currentUrl}`);
|
|
|
|
// Check if we're on a results page
|
|
if (currentUrl.includes('/research/') || currentUrl.includes('/results')) {
|
|
console.log('✅ Redirected to results page');
|
|
|
|
// Monitor search progress
|
|
console.log('\n⏳ Step 6: Monitoring search progress...');
|
|
|
|
let searchComplete = false;
|
|
let errorFound = false;
|
|
let resultsFound = false;
|
|
const startTime = Date.now();
|
|
|
|
while (!searchComplete && (Date.now() - startTime) < SEARCH_TIMEOUT) {
|
|
// Check for various indicators
|
|
const indicators = await page.evaluate(() => {
|
|
const result = {
|
|
// Check for progress indicators
|
|
progressBar: !!document.querySelector('.progress-bar'),
|
|
spinner: !!document.querySelector('.spinner-border'),
|
|
loadingText: !!document.querySelector('[class*="loading"]'),
|
|
|
|
// Check for completion indicators
|
|
results: !!document.querySelector('.research-results'),
|
|
summary: !!document.querySelector('.research-summary'),
|
|
sources: document.querySelectorAll('.source-item').length,
|
|
|
|
// Check for error indicators
|
|
errorAlert: !!document.querySelector('.alert-danger'),
|
|
errorMessage: document.querySelector('.alert-danger')?.textContent || '',
|
|
|
|
// Check for status messages
|
|
statusText: document.querySelector('.status-message')?.textContent || '',
|
|
|
|
// Check page content
|
|
bodyText: document.body.innerText.substring(0, 500)
|
|
};
|
|
|
|
return result;
|
|
});
|
|
|
|
// Log current state
|
|
console.log(`\n [${Math.floor((Date.now() - startTime) / 1000)}s] Search state:`);
|
|
console.log(` Progress indicators: ${indicators.progressBar || indicators.spinner || indicators.loadingText ? 'Active' : 'None'}`);
|
|
console.log(` Results found: ${indicators.results || indicators.summary ? 'Yes' : 'No'}`);
|
|
console.log(` Sources found: ${indicators.sources}`);
|
|
|
|
if (indicators.errorAlert) {
|
|
console.log(` ❌ ERROR: ${indicators.errorMessage}`);
|
|
errorFound = true;
|
|
searchComplete = true;
|
|
}
|
|
|
|
if (indicators.results || indicators.summary || indicators.sources > 0) {
|
|
console.log(' ✅ Search results detected!');
|
|
resultsFound = true;
|
|
searchComplete = true;
|
|
}
|
|
|
|
if (indicators.statusText) {
|
|
console.log(` Status: ${indicators.statusText}`);
|
|
}
|
|
|
|
// Check if search is still in progress
|
|
if (!searchComplete) {
|
|
await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL));
|
|
}
|
|
}
|
|
|
|
// Final analysis
|
|
console.log('\n📋 Step 7: Final Analysis:');
|
|
console.log(` Search duration: ${Math.floor((Date.now() - startTime) / 1000)} seconds`);
|
|
console.log(` Search completed: ${searchComplete}`);
|
|
console.log(` Results found: ${resultsFound}`);
|
|
console.log(` Errors encountered: ${errorFound}`);
|
|
|
|
// Take screenshot
|
|
await page.screenshot({ path: 'research_search_analysis.png', fullPage: true });
|
|
console.log(' 📸 Screenshot saved as research_search_analysis.png');
|
|
|
|
// Get final page content for debugging
|
|
const finalContent = await page.evaluate(() => {
|
|
return {
|
|
title: document.title,
|
|
hasResults: !!document.querySelector('.research-results'),
|
|
resultCount: document.querySelectorAll('.result-item').length,
|
|
sourceCount: document.querySelectorAll('.source-item').length,
|
|
errorCount: document.querySelectorAll('.alert-danger').length,
|
|
warningCount: document.querySelectorAll('.alert-warning').length
|
|
};
|
|
});
|
|
|
|
console.log('\n Final page analysis:');
|
|
console.log(` Title: ${finalContent.title}`);
|
|
console.log(` Has results section: ${finalContent.hasResults}`);
|
|
console.log(` Result items: ${finalContent.resultCount}`);
|
|
console.log(` Source items: ${finalContent.sourceCount}`);
|
|
console.log(` Errors: ${finalContent.errorCount}`);
|
|
console.log(` Warnings: ${finalContent.warningCount}`);
|
|
|
|
// Overall test result
|
|
console.log('\n🏁 TEST SUMMARY:');
|
|
if (resultsFound && !errorFound) {
|
|
console.log('✅ Search functionality is WORKING - Results were generated');
|
|
} else if (errorFound) {
|
|
console.log('❌ Search functionality FAILED - Errors were encountered');
|
|
} else {
|
|
console.log('⚠️ Search functionality UNCLEAR - No results or errors detected within timeout');
|
|
}
|
|
|
|
} else {
|
|
console.log('❌ Did not redirect to results page');
|
|
console.log(' Search functionality appears to be broken');
|
|
|
|
// Don't wait for full timeout if we didn't redirect
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
|
|
// Check for any error messages on current page
|
|
const pageErrors = await page.$$eval('.alert-danger', alerts =>
|
|
alerts.map(alert => alert.textContent.trim())
|
|
);
|
|
|
|
if (pageErrors.length > 0) {
|
|
console.log('\n Errors found on page:');
|
|
pageErrors.forEach(error => console.log(` - ${error}`));
|
|
}
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('\n❌ Test failed with error:', error.message);
|
|
throw error;
|
|
} finally {
|
|
if (browser) {
|
|
await browser.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Run the test
|
|
analyzeSearchFunctionality()
|
|
.then(() => {
|
|
console.log('\n✅ Research search analysis test completed');
|
|
process.exit(0);
|
|
})
|
|
.catch(error => {
|
|
console.error('\n❌ Research search analysis test failed:', error);
|
|
process.exit(1);
|
|
});
|