Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

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);
});