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

330 lines
13 KiB
JavaScript

/**
* Research Workflow Comprehensive Test
* Tests the complete research lifecycle from submission to results
* CI-compatible: Works in both local and CI environments
*/
const puppeteer = require('puppeteer');
const AuthHelper = require('./auth_helper');
const { getPuppeteerLaunchOptions } = require('./puppeteer_config');
const { setupDefaultModel } = require('./model_helper');
const fs = require('fs');
const path = require('path');
const BASE_URL = 'http://127.0.0.1:5000';
async function testResearchWorkflow() {
const isCI = !!process.env.CI;
console.log(`🧪 Running research workflow test (CI mode: ${isCI})`);
// Create screenshots directory
const screenshotsDir = path.join(__dirname, 'screenshots');
if (!fs.existsSync(screenshotsDir)) {
fs.mkdirSync(screenshotsDir, { recursive: true });
}
const browser = await puppeteer.launch(getPuppeteerLaunchOptions());
const page = await browser.newPage();
const auth = new AuthHelper(page, BASE_URL);
// Set longer timeout for CI
const timeout = isCI ? 90000 : 60000;
page.setDefaultTimeout(timeout);
page.setDefaultNavigationTimeout(timeout);
let testsPassed = 0;
let testsFailed = 0;
let testsSkipped = 0;
try {
// Setup: Authenticate
console.log('🔐 Authenticating...');
await auth.ensureAuthenticatedWithTimeout();
console.log('✅ Authentication successful\n');
// Test 1: Home page loads with research form
console.log('📝 Test 1: Research form loads correctly');
try {
await page.goto(`${BASE_URL}/`, { waitUntil: 'domcontentloaded' });
// Check for query input
const queryInput = await page.$('#query, input[name="query"]');
if (queryInput) {
console.log('✅ Research form with query input found');
testsPassed++;
} else {
console.log('❌ Query input not found');
testsFailed++;
}
} catch (error) {
console.log(`❌ Test 1 failed: ${error.message}`);
testsFailed++;
}
// Test 2: Model configuration
console.log('\n📝 Test 2: Model can be configured');
try {
const modelConfigured = await setupDefaultModel(page);
if (modelConfigured) {
console.log('✅ Model configuration successful');
testsPassed++;
} else {
console.log('⚠️ Model configuration may have issues (continuing)');
testsSkipped++;
}
} catch (error) {
console.log(`⚠️ Model configuration error: ${error.message}`);
testsSkipped++;
}
// Test 3: Form fields are accessible
console.log('\n📝 Test 3: Form fields are accessible');
try {
const formElements = await page.evaluate(() => {
return {
hasQueryInput: !!document.querySelector('#query, input[name="query"]'),
hasSubmitButton: !!document.querySelector('button[type="submit"]'),
hasModelSelect: !!document.querySelector('#model, select[name="model"]'),
hasSearchEngineSelect: !!document.querySelector('#search_engine, select[name="search_engine"]')
};
});
const missingElements = [];
if (!formElements.hasQueryInput) missingElements.push('query input');
if (!formElements.hasSubmitButton) missingElements.push('submit button');
if (missingElements.length === 0) {
console.log('✅ All essential form elements found');
testsPassed++;
} else {
console.log(`⚠️ Missing elements: ${missingElements.join(', ')}`);
testsFailed++;
}
} catch (error) {
console.log(`❌ Test 3 failed: ${error.message}`);
testsFailed++;
}
// Test 4: Query can be entered
console.log('\n📝 Test 4: Query input accepts text');
try {
await page.goto(`${BASE_URL}/`, { waitUntil: 'domcontentloaded' });
const queryInput = await page.$('#query, input[name="query"]');
if (queryInput) {
// Set value atomically to avoid race with page JS event handlers
await page.$eval('#query', (el) => {
el.value = 'Test research query for workflow test';
el.dispatchEvent(new Event('input', { bubbles: true }));
});
const value = await page.$eval('#query, input[name="query"]', el => el.value);
if (value.includes('Test research query')) {
console.log('✅ Query input accepts text correctly');
testsPassed++;
} else {
console.log(`❌ Query value mismatch: ${value}`);
testsFailed++;
}
} else {
console.log('❌ Query input not found');
testsFailed++;
}
} catch (error) {
console.log(`❌ Test 4 failed: ${error.message}`);
testsFailed++;
}
// Test 5: Research submission workflow
console.log('\n📝 Test 5: Research submission workflow');
try {
await page.goto(`${BASE_URL}/`, { waitUntil: 'domcontentloaded' });
// Configure model
await setupDefaultModel(page);
// Enter query
await page.waitForSelector('#query', { timeout: 10000 });
await page.type('#query', 'What is machine learning?');
// Take screenshot before submission (skip in CI — diagnostic only)
if (!isCI) {
await page.screenshot({
path: path.join(screenshotsDir, 'research_workflow_before_submit.png')
});
}
// Try to submit
const submitButton = await page.$('button[type="submit"]');
if (submitButton) {
// Click and wait for response
try {
await Promise.race([
Promise.all([
page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 30000 }),
submitButton.click()
]),
new Promise((_, reject) => setTimeout(() => reject(new Error('Navigation timeout')), 30000))
]);
} catch {
// Check if we're on a research page anyway
await new Promise(resolve => setTimeout(resolve, 3000));
}
const url = page.url();
console.log(` Current URL after submission: ${url}`);
// Take screenshot after submission attempt (skip in CI — diagnostic only)
if (!isCI) {
await page.screenshot({
path: path.join(screenshotsDir, 'research_workflow_after_submit.png')
});
}
if (url.includes('/research/') || url.includes('/progress/')) {
console.log('✅ Research submission navigated to research page');
testsPassed++;
} else if (url === `${BASE_URL}/` || url.endsWith('/')) {
// Still on home page - might be validation error or config issue
const errorMsg = await page.evaluate(() => {
const alert = document.querySelector('.alert-danger, .error-message');
return alert ? alert.textContent : null;
});
if (errorMsg) {
console.log(`⚠️ Submission blocked: ${errorMsg.trim()}`);
} else {
console.log('⚠️ Stayed on home page (may need model configuration)');
}
testsSkipped++;
} else {
console.log(`⚠️ Unexpected URL after submission: ${url}`);
testsSkipped++;
}
} else {
console.log('❌ Submit button not found');
testsFailed++;
}
} catch (error) {
console.log(`⚠️ Test 5 had issues: ${error.message}`);
testsSkipped++;
}
// Test 6: History page shows research history
console.log('\n📝 Test 6: History page is accessible');
try {
await page.goto(`${BASE_URL}/history/`, { waitUntil: 'domcontentloaded' });
const hasHistoryContent = await page.evaluate(() => {
const body = document.body;
return body && (
body.innerText.includes('History') ||
body.innerText.includes('history') ||
body.innerText.includes('Research') ||
body.innerText.includes('No research')
);
});
if (hasHistoryContent) {
console.log('✅ History page loads correctly');
testsPassed++;
} else {
console.log('⚠️ History page content unclear');
testsPassed++;
}
} catch (error) {
console.log(`❌ Test 6 failed: ${error.message}`);
testsFailed++;
}
// Test 7: Navigation between pages works
console.log('\n📝 Test 7: Navigation between workflow pages');
try {
const pages = [
{ path: '/', name: 'Home' },
{ path: '/settings/', name: 'Settings' },
{ path: '/history/', name: 'History' },
{ path: '/metrics/', name: 'Metrics' }
];
let navSuccess = 0;
for (const pageInfo of pages) {
try {
await page.goto(`${BASE_URL}${pageInfo.path}`, {
waitUntil: 'domcontentloaded',
timeout: 15000
});
// Check we didn't get redirected to login
if (!page.url().includes('/auth/login')) {
navSuccess++;
}
} catch {
console.log(` ⚠️ Navigation to ${pageInfo.name} failed`);
}
}
if (navSuccess >= 3) {
console.log(`✅ Navigation works (${navSuccess}/${pages.length} pages accessible)`);
testsPassed++;
} else {
console.log(`⚠️ Navigation issues (${navSuccess}/${pages.length} pages)`);
testsFailed++;
}
} catch (error) {
console.log(`❌ Test 7 failed: ${error.message}`);
testsFailed++;
}
// Summary
console.log('\n' + '='.repeat(50));
console.log('📊 RESEARCH WORKFLOW TEST SUMMARY');
console.log('='.repeat(50));
console.log(`✅ Passed: ${testsPassed}`);
console.log(`⏭️ Skipped: ${testsSkipped}`);
console.log(`❌ Failed: ${testsFailed}`);
console.log(`📊 Success Rate: ${Math.round((testsPassed / (testsPassed + testsFailed + testsSkipped)) * 100)}%`);
// Take final screenshot (skip in CI — diagnostic only)
if (!isCI) {
await page.screenshot({
path: path.join(screenshotsDir, 'research_workflow_final.png'),
fullPage: true
});
}
if (testsFailed > 0) {
console.log('\n⚠️ Too many workflow tests failed');
process.exit(1);
}
console.log('\n🎉 Research workflow tests completed!');
process.exit(0);
} catch (error) {
console.error('\n❌ Test suite failed:', error.message);
// Skip diagnostic screenshot in CI — error context is in the logs
if (!isCI) {
try {
await page.screenshot({
path: path.join(screenshotsDir, `research_workflow_error_${Date.now()}.png`),
fullPage: true
});
console.log('📸 Error screenshot saved');
} catch (screenshotError) {
console.log('Could not save screenshot:', screenshotError.message);
}
}
process.exit(1);
} finally {
await browser.close();
}
}
// Run the test
testResearchWorkflow().catch(error => {
console.error('Fatal error:', error);
process.exit(1);
});