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

340 lines
12 KiB
JavaScript

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 = `settings_persist_${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 registerUser(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 loginUser(page) {
log('🔐 Logging in...', 'info');
await page.goto(`${BASE_URL}/login`);
await page.waitForSelector('#username');
await page.type('#username', TEST_USER);
await page.type('#password', TEST_PASSWORD);
await page.click('button[type="submit"]');
await page.waitForNavigation();
log('✅ Login successful', 'success');
}
async function modifySettings(page) {
log('\n=== MODIFYING SETTINGS ===', 'section');
await page.goto(`${BASE_URL}/settings`);
await page.waitForSelector('.settings-form, #settings-form', { timeout: 10000 });
const testSettings = {
// LLM settings
temperature: 0.8,
maxTokens: 2048,
contextWindow: 8192,
// Search settings
iterations: 2,
questionsPerIteration: 3,
maxResults: 15,
timeRange: '1y',
// Report settings
citationFormat: 'domain_hyperlinks'
};
// Apply settings
log('📝 Applying test settings...', 'info');
// Temperature slider
const tempSlider = await page.$('input[name="llm.temperature"], #temperature-slider');
if (tempSlider) {
await page.evaluate((value) => {
const slider = document.querySelector('input[name="llm.temperature"], #temperature-slider');
if (slider) {
slider.value = value;
slider.dispatchEvent(new Event('change', { bubbles: true }));
}
}, testSettings.temperature);
log(` - Temperature set to: ${testSettings.temperature}`, 'info');
}
// Max tokens
const maxTokensInput = await page.$('input[name="llm.max_tokens"], #max-tokens');
if (maxTokensInput) {
await page.evaluate((el) => { el.value = ''; }, maxTokensInput);
await page.type('input[name="llm.max_tokens"], #max-tokens', testSettings.maxTokens.toString());
log(` - Max tokens set to: ${testSettings.maxTokens}`, 'info');
}
// Search iterations
const iterationsInput = await page.$('input[name="search.iterations"], #search-iterations');
if (iterationsInput) {
await page.evaluate((el) => { el.value = ''; }, iterationsInput);
await page.type('input[name="search.iterations"], #search-iterations', testSettings.iterations.toString());
log(` - Search iterations set to: ${testSettings.iterations}`, 'info');
}
// Questions per iteration
const questionsInput = await page.$('input[name="search.questions_per_iteration"], #questions-per-iteration');
if (questionsInput) {
await page.evaluate((el) => { el.value = ''; }, questionsInput);
await page.type('input[name="search.questions_per_iteration"], #questions-per-iteration', testSettings.questionsPerIteration.toString());
log(` - Questions per iteration set to: ${testSettings.questionsPerIteration}`, 'info');
}
// Citation format dropdown
const citationSelect = await page.$('select[name="report.citation_format"], #citation-format');
if (citationSelect) {
await page.select('select[name="report.citation_format"], #citation-format', testSettings.citationFormat);
log(` - Citation format set to: ${testSettings.citationFormat}`, 'info');
}
// Save settings
log('💾 Saving settings...', 'info');
const saveButton = await page.$('button[type="submit"], .save-settings-btn, #save-settings');
if (saveButton) {
await saveButton.click();
await delay(2000); // Wait for save
// Check for success message
const successMessage = await page.$('.alert-success, .success-message');
if (successMessage) {
log('✅ Settings saved successfully', 'success');
}
}
// Capture current settings
const currentSettings = await page.evaluate(() => {
const settings = {};
// Get all input values
const inputs = document.querySelectorAll('input[name], select[name], textarea[name]');
inputs.forEach(input => {
if (input.type === 'checkbox') {
settings[input.name] = input.checked;
} else {
settings[input.name] = input.value;
}
});
return settings;
});
return { testSettings, currentSettings };
}
async function verifySettingsPersistence(page, originalSettings) {
log('\n=== VERIFYING SETTINGS PERSISTENCE ===', 'section');
await page.goto(`${BASE_URL}/settings`);
await page.waitForSelector('.settings-form, #settings-form', { timeout: 10000 });
// Wait for settings to load
await delay(2000);
// Get current settings
const persistedSettings = await page.evaluate(() => {
const settings = {};
// Temperature
const tempSlider = document.querySelector('input[name="llm.temperature"], #temperature-slider');
if (tempSlider) settings.temperature = parseFloat(tempSlider.value);
// Max tokens
const maxTokens = document.querySelector('input[name="llm.max_tokens"], #max-tokens');
if (maxTokens) settings.maxTokens = parseInt(maxTokens.value, 10);
// Iterations
const iterations = document.querySelector('input[name="search.iterations"], #search-iterations');
if (iterations) settings.iterations = parseInt(iterations.value, 10);
// Questions per iteration
const questions = document.querySelector('input[name="search.questions_per_iteration"], #questions-per-iteration');
if (questions) settings.questionsPerIteration = parseInt(questions.value, 10);
// Citation format
const citation = document.querySelector('select[name="report.citation_format"], #citation-format');
if (citation) settings.citationFormat = citation.value;
return settings;
});
// Compare settings
log('🔍 Comparing settings...', 'info');
let allMatch = true;
Object.keys(originalSettings.testSettings).forEach(key => {
const original = originalSettings.testSettings[key];
const persisted = persistedSettings[key];
if (original !== persisted) {
log(` ❌ ${key}: Expected ${original}, got ${persisted}`, 'error');
allMatch = false;
} else {
log(` ✅ ${key}: ${persisted} (matches)`, 'success');
}
});
return allMatch;
}
async function testSettingsPersistence() {
const browser = await puppeteer.launch(getPuppeteerLaunchOptions());
const page = await browser.newPage();
// Set console log handler
page.on('console', msg => {
if (msg.type() === 'error' && !msg.text().includes('favicon')) {
log(`Browser console error: ${msg.text()}`, 'error');
}
});
try {
// Step 1: Register and modify settings
await registerUser(page);
const settingsData = await modifySettings(page);
// Step 2: Logout
log('\n=== LOGGING OUT ===', 'section');
await page.goto(`${BASE_URL}/logout`);
await delay(1000);
log('✅ Logged out', 'success');
// Step 3: Login again
await loginUser(page);
// Step 4: Verify settings persisted
const settingsMatch = await verifySettingsPersistence(page, settingsData);
if (settingsMatch) {
log('\n✅ All settings persisted correctly!', 'success');
} else {
throw new Error('Some settings did not persist correctly');
}
// Test settings on research page
log('\n=== VERIFYING SETTINGS APPLY TO RESEARCH ===', 'section');
await page.goto(`${BASE_URL}/research`);
await page.waitForSelector('#research-form, .research-form');
// Check if settings are reflected in research form
const researchFormSettings = await page.evaluate(() => {
const settings = {};
// Check hidden inputs or data attributes
const modelInput = document.querySelector('input[name="model"], #model');
if (modelInput) settings.model = modelInput.value;
const iterationsDisplay = document.querySelector('.iterations-display, [data-iterations]');
if (iterationsDisplay) {
settings.displayedIterations = iterationsDisplay.textContent ||
iterationsDisplay.getAttribute('data-iterations');
}
return settings;
});
log('📊 Research form reflects settings', 'info');
// Test settings reset
log('\n=== TESTING SETTINGS RESET ===', 'section');
await page.goto(`${BASE_URL}/settings`);
const resetButton = await page.$('.reset-settings-btn, button[data-action="reset"]');
if (resetButton) {
await resetButton.click();
// Handle confirmation dialog
page.on('dialog', async dialog => {
await dialog.accept();
});
await delay(2000);
// Verify some settings returned to defaults
const afterReset = await page.evaluate(() => {
const temp = document.querySelector('input[name="llm.temperature"], #temperature-slider');
return temp ? parseFloat(temp.value) : null;
});
if (afterReset !== null && afterReset !== settingsData.testSettings.temperature) {
log('✅ Reset functionality works', 'success');
}
}
// Capture final screenshot
await page.screenshot({
path: path.join(__dirname, 'screenshots', 'settings_persistence_final.png'),
fullPage: true
});
log('\n✅ Settings persistence test completed successfully!', 'success');
} catch (error) {
log(`\n❌ Test failed: ${error.message}`, 'error');
// Capture error screenshot
await page.screenshot({
path: path.join(__dirname, 'screenshots', 'settings_persistence_error.png'),
fullPage: true
});
throw error;
} finally {
await browser.close();
}
}
// Run the test
testSettingsPersistence().catch(error => {
console.error('Test execution failed:', error);
process.exit(1);
});