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
350 lines
16 KiB
JavaScript
350 lines
16 KiB
JavaScript
/**
|
|
* Test for autocomplete selection behavior
|
|
* Tests that clicking on autocomplete suggestions properly selects the item
|
|
* for both LLM model and search engine dropdowns
|
|
*/
|
|
|
|
const puppeteer = require('puppeteer');
|
|
const AuthHelper = require('./auth_helper');
|
|
|
|
// Default timeout for tests
|
|
const TEST_TIMEOUT = 30000;
|
|
|
|
// Test configuration
|
|
const config = {
|
|
baseUrl: process.env.BASE_URL || 'http://127.0.0.1:5000',
|
|
headless: process.env.HEADLESS !== 'false',
|
|
slowMo: parseInt(process.env.SLOW_MO || '0', 10),
|
|
devtools: process.env.DEVTOOLS === 'true'
|
|
};
|
|
|
|
// Function to run tests when file is executed directly
|
|
async function runTests() {
|
|
let browser;
|
|
let allTestsPassed = true;
|
|
|
|
try {
|
|
console.log('\n📋 Autocomplete Selection Tests\n');
|
|
console.log(`Configuration: headless=${config.headless}, baseUrl=${config.baseUrl}\n`);
|
|
|
|
browser = await puppeteer.launch({
|
|
headless: config.headless,
|
|
slowMo: config.slowMo,
|
|
devtools: config.devtools,
|
|
args: [
|
|
'--no-sandbox',
|
|
'--disable-setuid-sandbox',
|
|
'--disable-dev-shm-usage',
|
|
'--disable-web-security',
|
|
'--disable-features=IsolateOrigins,site-per-process'
|
|
]
|
|
});
|
|
|
|
// Test 1: LLM model autocomplete selection
|
|
console.log('🧪 Test 1: Should select LLM model from autocomplete when clicked');
|
|
try {
|
|
const page = await browser.newPage();
|
|
await page.setViewport({ width: 1280, height: 800 });
|
|
const authHelper = new AuthHelper(page, config.baseUrl);
|
|
page.setDefaultTimeout(TEST_TIMEOUT);
|
|
|
|
await authHelper.ensureAuthenticated();
|
|
await page.goto(`${config.baseUrl}/`, { waitUntil: 'domcontentloaded' });
|
|
|
|
// Wait for and click the model input
|
|
await page.waitForSelector('#model', { visible: true });
|
|
await page.click('#model');
|
|
|
|
// Wait for dropdown to appear
|
|
await page.waitForSelector('#model-dropdown-list', { visible: true });
|
|
await page.waitForSelector('.ldr-custom-dropdown-item', { visible: true });
|
|
|
|
const dropdownItems = await page.$$('.ldr-custom-dropdown-item');
|
|
console.log(` Found ${dropdownItems.length} model options`);
|
|
|
|
if (dropdownItems.length > 0) {
|
|
// Get the first item's text
|
|
const firstItemText = await page.evaluate(el => el.textContent, dropdownItems[0]);
|
|
|
|
// Clear input and type part of the model name
|
|
await page.evaluate(() => { document.getElementById('model').value = ''; });
|
|
const searchText = firstItemText.substring(0, Math.min(3, firstItemText.length));
|
|
await page.type('#model', searchText);
|
|
console.log(` Typed "${searchText}" to filter models`);
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Check if dropdown is still visible
|
|
const dropdownVisible = await page.evaluate(() => {
|
|
const dropdown = document.getElementById('model-dropdown-list');
|
|
return dropdown && window.getComputedStyle(dropdown).display !== 'none';
|
|
});
|
|
|
|
if (!dropdownVisible) {
|
|
console.log(' Dropdown closed, reopening...');
|
|
await page.click('#model');
|
|
await page.waitForSelector('#model-dropdown-list', { visible: true });
|
|
}
|
|
|
|
// Click the first filtered item
|
|
const filteredItems = await page.$$('.ldr-custom-dropdown-item');
|
|
if (filteredItems.length > 0) {
|
|
const itemToClick = await page.evaluate(el => el.textContent, filteredItems[0]);
|
|
console.log(` Clicking on: "${itemToClick}"`);
|
|
await filteredItems[0].click();
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Check the selected value
|
|
const selectedModel = await page.evaluate(() => document.getElementById('model').value);
|
|
const hiddenValue = await page.evaluate(() => {
|
|
const hidden = document.getElementById('model_hidden');
|
|
return hidden ? hidden.value : null;
|
|
});
|
|
|
|
console.log(` Display value: "${selectedModel}"`);
|
|
console.log(` Hidden value: "${hiddenValue}"`);
|
|
|
|
if (selectedModel && selectedModel !== searchText) {
|
|
console.log(' ✅ Model autocomplete selection works correctly');
|
|
} else {
|
|
console.log(' ❌ Model was not properly selected from autocomplete');
|
|
console.log(' Issue confirmed: Clicking autocomplete does not select the item');
|
|
allTestsPassed = false;
|
|
}
|
|
} else {
|
|
console.log(' ⚠️ No filtered items found');
|
|
}
|
|
} else {
|
|
console.log(' ⚠️ No model options available');
|
|
}
|
|
|
|
await page.close();
|
|
} catch (error) {
|
|
console.error(` ❌ Test failed: ${error.message}`);
|
|
allTestsPassed = false;
|
|
}
|
|
|
|
// Test 2: Search engine autocomplete selection
|
|
console.log('\n🧪 Test 2: Should select search engine from autocomplete when clicked');
|
|
try {
|
|
const page = await browser.newPage();
|
|
await page.setViewport({ width: 1280, height: 800 });
|
|
const authHelper = new AuthHelper(page, config.baseUrl);
|
|
page.setDefaultTimeout(TEST_TIMEOUT);
|
|
|
|
await authHelper.ensureAuthenticated();
|
|
await page.goto(`${config.baseUrl}/`, { waitUntil: 'domcontentloaded' });
|
|
|
|
// Wait for and click the search engine input
|
|
await page.waitForSelector('#search_engine', { visible: true });
|
|
await page.click('#search_engine');
|
|
|
|
// Wait for dropdown to appear
|
|
await page.waitForSelector('#search-engine-dropdown-list', { visible: true });
|
|
|
|
await page.waitForFunction(() => {
|
|
const items = document.querySelectorAll('#search-engine-dropdown-list .ldr-custom-dropdown-item');
|
|
return items.length > 0;
|
|
});
|
|
|
|
const dropdownItems = await page.$$('#search-engine-dropdown-list .ldr-custom-dropdown-item');
|
|
console.log(` Found ${dropdownItems.length} search engine options`);
|
|
|
|
if (dropdownItems.length > 0) {
|
|
// Get the first item's text
|
|
const firstItemText = await page.evaluate(el => el.textContent, dropdownItems[0]);
|
|
|
|
// Clear input and type part of the search engine name
|
|
await page.evaluate(() => { document.getElementById('search_engine').value = ''; });
|
|
const searchText = firstItemText.substring(0, Math.min(3, firstItemText.length));
|
|
await page.type('#search_engine', searchText);
|
|
console.log(` Typed "${searchText}" to filter search engines`);
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Click the first filtered item
|
|
const filteredItems = await page.$$('#search-engine-dropdown-list .ldr-custom-dropdown-item');
|
|
if (filteredItems.length > 0) {
|
|
const itemToClick = await page.evaluate(el => el.textContent, filteredItems[0]);
|
|
console.log(` Clicking on: "${itemToClick}"`);
|
|
await filteredItems[0].click();
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Check the selected value
|
|
const selectedEngine = await page.evaluate(() => document.getElementById('search_engine').value);
|
|
const hiddenValue = await page.evaluate(() => {
|
|
const hidden = document.getElementById('search_engine_hidden');
|
|
return hidden ? hidden.value : null;
|
|
});
|
|
|
|
console.log(` Display value: "${selectedEngine}"`);
|
|
console.log(` Hidden value: "${hiddenValue}"`);
|
|
|
|
if (selectedEngine && selectedEngine !== searchText) {
|
|
console.log(' ✅ Search engine autocomplete selection works correctly');
|
|
} else {
|
|
console.log(' ❌ Search engine was not properly selected from autocomplete');
|
|
console.log(' Issue confirmed: Clicking autocomplete does not select the item');
|
|
allTestsPassed = false;
|
|
}
|
|
} else {
|
|
console.log(' ⚠️ No filtered items found');
|
|
}
|
|
} else {
|
|
console.log(' ⚠️ No search engine options available');
|
|
}
|
|
|
|
await page.close();
|
|
} catch (error) {
|
|
console.error(` ❌ Test failed: ${error.message}`);
|
|
allTestsPassed = false;
|
|
}
|
|
|
|
// Test 3: Keyboard navigation
|
|
console.log('\n🧪 Test 3: Should verify keyboard navigation works for selection');
|
|
try {
|
|
const page = await browser.newPage();
|
|
await page.setViewport({ width: 1280, height: 800 });
|
|
const authHelper = new AuthHelper(page, config.baseUrl);
|
|
page.setDefaultTimeout(TEST_TIMEOUT);
|
|
|
|
await authHelper.ensureAuthenticated();
|
|
await page.goto(`${config.baseUrl}/`, { waitUntil: 'domcontentloaded' });
|
|
|
|
// Test with model dropdown
|
|
await page.waitForSelector('#model', { visible: true });
|
|
await page.click('#model');
|
|
await page.waitForSelector('#model-dropdown-list .ldr-custom-dropdown-item', { visible: true });
|
|
|
|
const itemCount = await page.evaluate(() => {
|
|
return document.querySelectorAll('#model-dropdown-list .ldr-custom-dropdown-item').length;
|
|
});
|
|
console.log(` Found ${itemCount} items in dropdown`);
|
|
|
|
if (itemCount > 0) {
|
|
// Use arrow key to navigate
|
|
await page.keyboard.press('ArrowDown');
|
|
|
|
// Check if first item is highlighted
|
|
const firstItemActive = await page.evaluate(() => {
|
|
const items = document.querySelectorAll('#model-dropdown-list .ldr-custom-dropdown-item');
|
|
return items[0] && items[0].classList.contains('active');
|
|
});
|
|
console.log(` First item highlighted: ${firstItemActive}`);
|
|
|
|
// Press Enter to select
|
|
await page.keyboard.press('Enter');
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Check the selected value
|
|
const selectedModel = await page.evaluate(() => document.getElementById('model').value);
|
|
|
|
if (selectedModel) {
|
|
console.log(` ✅ Keyboard navigation selected: "${selectedModel}"`);
|
|
} else {
|
|
console.log(' ❌ Keyboard navigation failed to select');
|
|
allTestsPassed = false;
|
|
}
|
|
}
|
|
|
|
await page.close();
|
|
} catch (error) {
|
|
console.error(` ❌ Test failed: ${error.message}`);
|
|
allTestsPassed = false;
|
|
}
|
|
|
|
// Test 4: Type and Enter behavior (reveals the issue)
|
|
console.log('\n🧪 Test 4: Type and immediate Enter (reveals the issue)');
|
|
try {
|
|
const page = await browser.newPage();
|
|
await page.setViewport({ width: 1280, height: 800 });
|
|
const authHelper = new AuthHelper(page, config.baseUrl);
|
|
page.setDefaultTimeout(TEST_TIMEOUT);
|
|
|
|
await authHelper.ensureAuthenticated();
|
|
await page.goto(`${config.baseUrl}/`, { waitUntil: 'domcontentloaded' });
|
|
|
|
// Open model dropdown
|
|
await page.waitForSelector('#model', { visible: true });
|
|
await page.click('#model');
|
|
await page.waitForSelector('#model-dropdown-list .ldr-custom-dropdown-item', { visible: true });
|
|
|
|
// Get a model name to type
|
|
const firstModelText = await page.evaluate(() => {
|
|
const firstItem = document.querySelector('#model-dropdown-list .ldr-custom-dropdown-item');
|
|
return firstItem ? firstItem.textContent : null;
|
|
});
|
|
|
|
if (firstModelText) {
|
|
// Clear and type part of the model name
|
|
await page.evaluate(() => { document.getElementById('model').value = ''; });
|
|
const searchText = firstModelText.substring(0, Math.min(5, firstModelText.length));
|
|
await page.type('#model', searchText);
|
|
console.log(` Typed "${searchText}"`);
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
|
|
// Press Enter without using arrow keys
|
|
await page.keyboard.press('Enter');
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
|
// Check what was selected
|
|
const selectedValue = await page.evaluate(() => document.getElementById('model').value);
|
|
|
|
if (selectedValue === searchText) {
|
|
console.log(` ⚠️ Enter key only kept typed text: "${selectedValue}"`);
|
|
console.log(' 📝 Issue confirmed: User must either:');
|
|
console.log(' - Click on the autocomplete suggestion');
|
|
console.log(' - Use arrow keys then Enter');
|
|
console.log(' - Typing and pressing Enter alone does NOT select from autocomplete');
|
|
} else {
|
|
console.log(` ✅ Enter key selected from autocomplete: "${selectedValue}"`);
|
|
}
|
|
}
|
|
|
|
await page.close();
|
|
} catch (error) {
|
|
console.error(` ❌ Test failed: ${error.message}`);
|
|
allTestsPassed = false;
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error(`\n❌ Test suite failed: ${error.message}`);
|
|
allTestsPassed = false;
|
|
} finally {
|
|
if (browser) {
|
|
await browser.close();
|
|
}
|
|
|
|
console.log('\n' + '='.repeat(60));
|
|
console.log('📊 Test Summary:');
|
|
console.log(' - Model autocomplete: Tests if clicking selects the item');
|
|
console.log(' - Search engine autocomplete: Tests if clicking selects the item');
|
|
console.log(' - Keyboard navigation: Tests arrow key + Enter selection');
|
|
console.log(' - Type and Enter: Reveals if typing + Enter selects first match');
|
|
console.log('='.repeat(60));
|
|
|
|
if (allTestsPassed) {
|
|
console.log('✅ All tests completed successfully\n');
|
|
process.exit(0);
|
|
} else {
|
|
console.log('❌ Some tests revealed issues with autocomplete selection\n');
|
|
console.log('The tests confirm that when typing in the autocomplete fields:');
|
|
console.log('1. The dropdown appears and filters correctly');
|
|
console.log('2. However, pressing Enter does not select the first match');
|
|
console.log('3. Users must either click or use arrow keys to select\n');
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Run tests if this file is executed directly
|
|
if (require.main === module) {
|
|
runTests().catch(error => {
|
|
console.error('Fatal error:', error);
|
|
process.exit(1);
|
|
});
|
|
}
|
|
|
|
module.exports = { runTests };
|