Files
wehub-resource-sync 7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
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
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

570 lines
22 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const puppeteer = require('puppeteer');
const { BROWSER_CONFIG } = require('./browser_config');
const AuthHelper = require('./auth_helper');
const { getPuppeteerLaunchOptions } = require('./puppeteer_config');
// Use consistent base URL for all requests
const BASE_URL = 'http://localhost:5000';
// Colors for console output
const colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
magenta: '\x1b[35m',
cyan: '\x1b[36m'
};
function log(message, color = colors.reset) {
console.log(`${color}[${new Date().toISOString()}] ${message}${colors.reset}`);
}
function logError(message) {
console.error(`${colors.red}[${new Date().toISOString()}] ERROR: ${message}${colors.reset}`);
}
function logSuccess(message) {
log(`✓ ${message}`, colors.green);
}
function logInfo(message) {
log(` ${message}`, colors.blue);
}
function logWarning(message) {
log(`⚠ ${message}`, colors.yellow);
}
async function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function takeScreenshot(page, name) {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const filename = `/tmp/benchmark_test_${name}_${timestamp}.png`;
await page.screenshot({ path: filename, fullPage: true });
logInfo(`Screenshot saved: ${filename}`);
}
async function waitForTextOnPage(page, text, timeout = 30000) {
logInfo(`Waiting for text: "${text}"`);
try {
await page.waitForFunction(
(searchText) => document.body.innerText.includes(searchText),
{ timeout },
text
);
logSuccess(`Found text: "${text}"`);
return true;
} catch {
logError(`Text not found within ${timeout}ms: "${text}"`);
return false;
}
}
async function typeWithDelay(page, selector, text, charDelay = 50) {
await page.focus(selector);
await page.evaluate(sel => {
document.querySelector(sel).value = '';
}, selector);
for (const char of text) {
await page.type(selector, char);
await new Promise(resolve => setTimeout(resolve, charDelay));
}
}
async function keepSessionAlive(page) {
// Make a simple API call to keep the session active
try {
await page.evaluate(async () => {
const response = await fetch('/api/settings', {
credentials: 'same-origin'
});
console.log('Keep-alive response:', response.status);
});
} catch {
// Ignore errors
}
}
(async () => {
let browser;
try {
log('=== Starting Benchmark Settings Puppeteer Test ===', colors.bright);
browser = await puppeteer.launch(getPuppeteerLaunchOptions());
logSuccess('Browser launched');
const page = await browser.newPage();
// Set viewport to ensure consistent rendering
await page.setViewport({ width: 1280, height: 800 });
// Log browser console errors
page.on('console', msg => {
if (msg.type() === 'error') {
logError(`Browser console: ${msg.text()}`);
}
});
// Log network errors
page.on('requestfailed', request => {
if (!request.url().includes('favicon')) {
logError(`Request failed: ${request.url()} - ${request.failure().errorText}`);
}
});
// Register and login using AuthHelper with consistent base URL
const auth = new AuthHelper(page, BASE_URL);
const username = 'benchmark_' + Date.now();
const password = 'T3st!Secure#2024$LDR';
logInfo(`Creating user: ${username}`);
await auth.register(username, password);
// Verify we're logged in
const isLoggedIn = await auth.isLoggedIn();
if (!isLoggedIn) {
throw new Error('Failed to authenticate user');
}
logSuccess('User authenticated successfully');
await takeScreenshot(page, 'after_auth');
// Keep session alive
await keepSessionAlive(page);
// Configure Ollama provider and model in settings
logInfo('Configuring Ollama provider and gemma3:12b model for benchmarks...');
// Keep session alive before navigation
await keepSessionAlive(page);
// Save cookies before navigation
const cookies = await page.cookies();
logInfo(`Saved ${cookies.length} cookies from session`);
// Navigate to settings - use consistent base URL
await page.goto(`${BASE_URL}/settings`, { waitUntil: 'domcontentloaded' });
await delay(2000);
// Check if we're still logged in (not redirected to login)
const currentUrl = page.url();
if (currentUrl.includes('/auth/login')) {
logError('Session lost - redirected to login page');
await takeScreenshot(page, 'session_lost_settings');
// Restore cookies and try again
await page.setCookie(...cookies);
await page.goto(`${BASE_URL}/settings`, { waitUntil: 'domcontentloaded' });
await delay(1000);
// If still redirected, login again
if (page.url().includes('/auth/login')) {
await auth.login(username, password);
await page.goto(`${BASE_URL}/settings`, { waitUntil: 'domcontentloaded' });
await delay(2000);
}
}
// Set provider to Ollama
logInfo('Setting provider to Ollama...');
const providerSet = await page.evaluate(() => {
// Try multiple selectors for the provider field
const providerSelectors = [
'select[name="llm.provider"]',
'#llm\\.provider',
'select[id*="provider"]',
'select[data-setting="llm.provider"]',
'#provider',
'.provider-select',
'select.ldr-form-control' // Look for any select with
// ldr-form-control class
];
let providerSelect = null;
for (const selector of providerSelectors) {
try {
const element = document.querySelector(selector);
if (element && element.tagName === 'SELECT') {
// Check if this is likely the provider select by looking at its options
const options = Array.from(element.options).map(opt => opt.value.toLowerCase());
if (options.some(opt => opt.includes('ollama') || opt.includes('openai') || opt.includes('anthropic'))) {
providerSelect = element;
console.log(`Found provider select with selector: ${selector}`);
break;
}
}
} catch {
// Some selectors might throw errors, continue
}
}
if (providerSelect) {
// Find the Ollama option
const ollamaOption = Array.from(providerSelect.options).find(
opt => opt.value.toLowerCase() === 'ollama' || opt.text.toLowerCase().includes('ollama')
);
if (ollamaOption) {
providerSelect.value = ollamaOption.value;
providerSelect.dispatchEvent(new Event('change', { bubbles: true }));
console.log(`Set provider to Ollama (value: ${ollamaOption.value})`);
return true;
}
console.log('Could not find Ollama option in provider select');
console.log('Available options:', Array.from(providerSelect.options).map(opt => opt.value));
}
console.log('Could not find provider field');
return false;
});
if (providerSet) {
logSuccess('Provider set to Ollama');
await delay(1000); // Wait for model list to update
// Set model to gemma3:12b
logInfo('Setting model to gemma3:12b...');
const modelSet = await page.evaluate(() => {
// Try multiple selectors for the model field
const modelSelectors = [
'select[name="llm.model"]',
'#llm\\.model',
'select[id*="model"]',
'select[data-setting="llm.model"]',
'#model',
'.model-select'
];
let modelSelect = null;
for (const selector of modelSelectors) {
try {
const element = document.querySelector(selector);
if (element && element.tagName === 'SELECT') {
// Check if this is likely the model select
const options = element.options ? Array.from(element.options).map(opt => opt.value.toLowerCase()) : [];
if (options.some(opt => opt.includes('gemma') || opt.includes('gpt') || opt.includes('claude'))) {
modelSelect = element;
console.log(`Found model select with selector: ${selector}`);
break;
}
}
} catch {
// Some selectors might throw errors, continue
}
}
if (modelSelect) {
// Look for gemma3:12b option
const options = modelSelect.options ? Array.from(modelSelect.options) : [];
const gemmaOption = options.find(opt =>
opt.value === 'gemma3:12b' ||
opt.value.toLowerCase() === 'gemma3:12b' ||
opt.text.includes('gemma3:12b') ||
opt.text.toLowerCase().includes('gemma3:12b')
);
if (gemmaOption) {
modelSelect.value = gemmaOption.value;
modelSelect.dispatchEvent(new Event('change', { bubbles: true }));
console.log(`Set model to gemma3:12b (value: ${gemmaOption.value})`);
return true;
}
console.log('Could not find gemma3:12b option');
console.log('Available model options:', options.map(opt => opt.value).slice(0, 10));
// Try to find any Ollama model as fallback
const ollamaOption = options.find(opt =>
opt.value.toLowerCase().includes('gemma') ||
opt.text.toLowerCase().includes('gemma')
);
if (ollamaOption) {
modelSelect.value = ollamaOption.value;
modelSelect.dispatchEvent(new Event('change', { bubbles: true }));
console.log(`Set model to fallback Ollama model: ${ollamaOption.value}`);
return true;
}
}
console.log('Could not find model field');
return false;
});
if (modelSet) {
logSuccess('Model set to gemma3:12b');
} else {
logWarning('Could not set model to gemma3:12b');
}
// Set minimal iterations for faster testing
logInfo('Setting minimal iterations for faster testing...');
await page.evaluate(() => {
const iterationsInput = document.querySelector('input[name="search.iterations"]') ||
document.querySelector('#search\\.iterations');
if (iterationsInput) {
iterationsInput.value = '1';
iterationsInput.dispatchEvent(new Event('change', { bubbles: true }));
console.log('Set iterations to 1');
}
const questionsInput = document.querySelector('input[name="search.questions_per_iteration"]') ||
document.querySelector('#search\\.questions_per_iteration');
if (questionsInput) {
questionsInput.value = '1';
questionsInput.dispatchEvent(new Event('change', { bubbles: true }));
console.log('Set questions per iteration to 1');
}
});
// Try to save settings
const saved = await page.evaluate(() => {
// Look for save button
const saveButtons = Array.from(document.querySelectorAll('button')).filter(
btn => btn.textContent.includes('Save') || btn.textContent.includes('Update')
);
if (saveButtons.length > 0) {
saveButtons[0].click();
console.log('Clicked save button');
return true;
}
// Try submitting the form
const forms = document.querySelectorAll('form');
if (forms.length > 0) {
forms[0].submit();
console.log('Submitted form');
return true;
}
return false;
});
if (saved) {
await delay(2000);
logSuccess('Settings saved');
} else {
logWarning('Could not save settings');
}
} else {
logWarning('Could not set provider - continuing anyway');
}
await takeScreenshot(page, 'after_settings');
// Keep session alive before navigation
await keepSessionAlive(page);
// Navigate to benchmark page
logInfo('Navigating to benchmark page...');
// Save current cookies again
const settingsCookies = await page.cookies();
logInfo(`Saved ${settingsCookies.length} cookies before benchmark navigation`);
await page.goto(`${BASE_URL}/benchmark`, { waitUntil: 'domcontentloaded' });
await delay(2000);
// Check if we were redirected to login
const benchmarkUrl = page.url();
if (benchmarkUrl.includes('/auth/login')) {
logError('Session lost when navigating to benchmark - redirected to login page');
await takeScreenshot(page, 'session_lost_benchmark');
// Restore cookies and try again
await page.setCookie(...settingsCookies);
await page.goto(`${BASE_URL}/benchmark`, { waitUntil: 'domcontentloaded' });
await delay(1000);
// If still redirected, login again
if (page.url().includes('/auth/login')) {
await auth.login(username, password);
await page.goto(`${BASE_URL}/benchmark`, { waitUntil: 'domcontentloaded' });
await delay(2000);
}
}
await takeScreenshot(page, 'benchmark_page');
// Check if benchmark page loaded
const hasBenchmarkTitle = await waitForTextOnPage(page, 'Benchmark Dashboard', 5000);
if (!hasBenchmarkTitle) {
logError('Benchmark page did not load correctly');
await takeScreenshot(page, 'benchmark_error');
// Try alternative text to verify we're on the benchmark page
const hasBenchmarkText = await page.evaluate(() => {
const text = document.body.innerText.toLowerCase();
return text.includes('benchmark') || text.includes('simpleqa') || text.includes('browsecomp');
});
if (hasBenchmarkText) {
logInfo('Found benchmark-related content on page');
}
}
// Look for benchmark interface elements
logInfo('Analyzing benchmark page...');
try {
// Log page content for debugging
const pageTitle = await page.title();
logInfo(`Page title: ${pageTitle}`);
// Check for dataset configuration section
const hasDatasets = await page.evaluate(() => {
const text = document.body.innerText;
return text.includes('SimpleQA') || text.includes('BrowseComp') || text.includes('Dataset');
});
if (hasDatasets) {
logSuccess('Found dataset configuration section');
// Try to set minimal dataset counts
try {
// Look for SimpleQA input fields
const simpleQAInputs = await page.$$('input[type="number"]');
if (simpleQAInputs.length > 0) {
logInfo(`Found ${simpleQAInputs.length} number input fields`);
// Set first input (likely SimpleQA) to 2
await simpleQAInputs[0].click({ clickCount: 3 });
await simpleQAInputs[0].type('2');
logSuccess('Set first dataset count to 2');
// If there's a second input (BrowseComp), set it to 0
if (simpleQAInputs.length > 1) {
await simpleQAInputs[1].click({ clickCount: 3 });
await simpleQAInputs[1].type('0');
logSuccess('Set second dataset count to 0');
}
}
} catch (configError) {
logWarning(`Could not configure datasets: ${configError.message}`);
}
}
// Look for any button that might start the benchmark
const buttons = await page.$$('button');
let startButton = null;
for (const button of buttons) {
const buttonText = await page.evaluate(el => el.textContent || '', button);
const buttonClass = await page.evaluate(el => el.className || '', button);
logInfo(`Found button: "${buttonText.trim()}" (class: ${buttonClass})`);
// Check for various possible button texts
if (buttonText.match(/start|run|begin|execute|launch/i) &&
(buttonText.match(/benchmark/i) || buttonClass.includes('primary'))) {
startButton = button;
logSuccess(`Selected button: "${buttonText.trim()}"`);
break;
}
}
if (!startButton && buttons.length > 0) {
// If no specific benchmark button found, try the first primary button
for (const button of buttons) {
const buttonClass = await page.evaluate(el => el.className || '', button);
if (buttonClass.includes('primary') || buttonClass.includes('success')) {
startButton = button;
const buttonText = await page.evaluate(el => el.textContent || '', button);
logWarning(`Using primary button as fallback: "${buttonText.trim()}"`);
break;
}
}
}
if (startButton) {
logInfo('Clicking start button...');
// Keep session alive before starting benchmark
await keepSessionAlive(page);
await startButton.click();
await delay(2000);
// Check for any alerts or errors
await page.on('dialog', async dialog => {
logInfo(`Dialog appeared: ${dialog.message()}`);
await dialog.accept();
});
await takeScreenshot(page, 'after_start_click');
// Wait and check for progress
logInfo('Waiting for benchmark to start...');
await delay(5000);
// Check if benchmark is running
const isRunning = await page.evaluate(() => {
const text = document.body.innerText;
return text.includes('progress') || text.includes('running') ||
text.includes('Processing') || text.includes('%');
});
if (isRunning) {
logSuccess('Benchmark appears to be running!');
await takeScreenshot(page, 'benchmark_running');
} else {
logWarning('Could not confirm benchmark is running');
// Check for error messages
const hasError = await page.evaluate(() => {
const text = document.body.innerText;
return text.includes('error') || text.includes('Error') ||
text.includes('failed') || text.includes('Failed');
});
if (hasError) {
logError('Page contains error messages');
// Try to extract error message
const errorText = await page.evaluate(() => {
const errorElements = Array.from(document.querySelectorAll('*')).filter(el => {
const text = el.textContent || '';
return (text.includes('error') || text.includes('Error')) &&
el.children.length === 0; // Leaf nodes only
});
return errorElements.map(el => el.textContent.trim()).join(' | ');
});
logError(`Error details: ${errorText}`);
}
}
await takeScreenshot(page, 'benchmark_final_state');
} else {
logError('Could not find any button to start benchmark');
await takeScreenshot(page, 'no_start_button');
}
} catch (error) {
logError(`Error during benchmark test: ${error.message}`);
await takeScreenshot(page, 'benchmark_error');
}
// Log page title and URL for debugging
const title = await page.title();
const url = page.url();
logInfo(`Final page - Title: ${title}, URL: ${url}`);
logSuccess('Benchmark test completed');
} catch (error) {
logError(`Test failed: ${error.message}`);
console.error(error.stack);
process.exit(1);
} finally {
if (browser) {
await browser.close();
logSuccess('Browser closed');
}
}
})();