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
219 lines
8.1 KiB
JavaScript
219 lines
8.1 KiB
JavaScript
/**
|
|
* Collections Auto-Index Toggle UI Test
|
|
*
|
|
* Tests the auto-index toggle on the collections page that controls
|
|
* whether documents are automatically indexed when uploaded or downloaded.
|
|
*
|
|
* What this tests:
|
|
* - Toggle loads initial state from settings API
|
|
* - Toggle changes persist to settings API
|
|
* - Toggle reflects correct state after page reload
|
|
* - Error handling when API calls fail
|
|
*
|
|
* Prerequisites: Web server running on http://127.0.0.1:5000
|
|
*
|
|
* Usage: node tests/ui_tests/test_collections_auto_index.js
|
|
*/
|
|
|
|
const puppeteer = require('puppeteer');
|
|
const AuthHelper = require('./auth_helper');
|
|
const { getPuppeteerLaunchOptions, takeScreenshot } = require('./puppeteer_config');
|
|
|
|
const BASE_URL = 'http://127.0.0.1:5000';
|
|
const COLLECTIONS_URL = `${BASE_URL}/library/collections`;
|
|
const SETTINGS_API_KEY = 'research_library.auto_index_enabled';
|
|
|
|
async function delay(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
async function runTests() {
|
|
const browser = await puppeteer.launch(getPuppeteerLaunchOptions());
|
|
const page = await browser.newPage();
|
|
const authHelper = new AuthHelper(page, BASE_URL);
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
|
|
// Monitor console errors
|
|
const consoleErrors = [];
|
|
page.on('console', msg => {
|
|
if (msg.type() === 'error') {
|
|
consoleErrors.push(msg.text());
|
|
console.log(' Browser console error:', msg.text());
|
|
}
|
|
});
|
|
|
|
// Monitor network errors
|
|
const networkErrors = [];
|
|
page.on('response', response => {
|
|
if (response.status() >= 400) {
|
|
networkErrors.push({ status: response.status(), url: response.url() });
|
|
}
|
|
});
|
|
|
|
try {
|
|
console.log('🧪 Testing Collections Auto-Index Toggle\n');
|
|
|
|
// Authenticate first
|
|
console.log('📝 Authenticating...');
|
|
await authHelper.ensureAuthenticated();
|
|
console.log('✅ Authenticated\n');
|
|
|
|
// Test 1: Toggle exists on collections page
|
|
console.log('Test 1: Toggle exists on collections page');
|
|
await page.goto(COLLECTIONS_URL, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
await delay(2000); // Wait for JS to load and execute
|
|
|
|
const toggleExists = await page.$('#auto-index-toggle');
|
|
if (toggleExists) {
|
|
console.log(' ✅ Toggle element found');
|
|
passed++;
|
|
} else {
|
|
console.log(' ❌ Toggle element not found');
|
|
failed++;
|
|
}
|
|
|
|
// Test 2: Toggle has associated label with tooltip
|
|
console.log('\nTest 2: Toggle has label with tooltip');
|
|
const labelExists = await page.$('label.ldr-checkbox-label');
|
|
const hasTooltip = await page.evaluate(() => {
|
|
const span = document.querySelector('label.ldr-checkbox-label .ldr-help-tooltip');
|
|
return span !== null;
|
|
});
|
|
|
|
if (labelExists && hasTooltip) {
|
|
console.log(' ✅ Label with tooltip exists');
|
|
passed++;
|
|
} else {
|
|
console.log(` ❌ Label (${!!labelExists}) or tooltip (${hasTooltip}) missing`);
|
|
failed++;
|
|
}
|
|
|
|
// Test 3: Toggle loads initial state from API
|
|
console.log('\nTest 3: Toggle loads state from settings API');
|
|
|
|
// Get the current setting value directly from API
|
|
const apiResponse = await page.evaluate(async (key) => {
|
|
const response = await fetch(`/settings/api/${key}`);
|
|
return response.json();
|
|
}, SETTINGS_API_KEY);
|
|
|
|
const toggleChecked = await page.evaluate(() => {
|
|
return document.getElementById('auto-index-toggle').checked;
|
|
});
|
|
|
|
const expectedChecked = apiResponse.value === true || apiResponse.value === 'true';
|
|
if (toggleChecked === expectedChecked) {
|
|
console.log(` ✅ Toggle state (${toggleChecked}) matches API value (${apiResponse.value})`);
|
|
passed++;
|
|
} else {
|
|
console.log(` ❌ Toggle state (${toggleChecked}) does not match API value (${apiResponse.value})`);
|
|
failed++;
|
|
}
|
|
|
|
// Test 4: Toggle change persists to API
|
|
console.log('\nTest 4: Toggle change persists to API');
|
|
const initialState = toggleChecked;
|
|
|
|
// Click the toggle to change state
|
|
await page.click('#auto-index-toggle');
|
|
await delay(1000); // Wait for API call
|
|
|
|
// Verify state changed in UI
|
|
const newToggleState = await page.evaluate(() => {
|
|
return document.getElementById('auto-index-toggle').checked;
|
|
});
|
|
|
|
// Verify state changed in API
|
|
const newApiResponse = await page.evaluate(async (key) => {
|
|
const response = await fetch(`/settings/api/${key}`);
|
|
return response.json();
|
|
}, SETTINGS_API_KEY);
|
|
|
|
const expectedNewState = newApiResponse.value === true || newApiResponse.value === 'true';
|
|
|
|
if (newToggleState !== initialState && newToggleState === expectedNewState) {
|
|
console.log(` ✅ Toggle changed from ${initialState} to ${newToggleState} and API reflects this`);
|
|
passed++;
|
|
} else {
|
|
console.log(` ❌ Toggle change failed: UI=${newToggleState}, API=${newApiResponse.value}, expected different from ${initialState}`);
|
|
failed++;
|
|
}
|
|
|
|
// Test 5: State persists after page reload
|
|
console.log('\nTest 5: State persists after page reload');
|
|
const stateBeforeReload = newToggleState;
|
|
|
|
await page.reload({ waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
await delay(2000); // Wait for JS to load state
|
|
|
|
const stateAfterReload = await page.evaluate(() => {
|
|
return document.getElementById('auto-index-toggle').checked;
|
|
});
|
|
|
|
if (stateAfterReload === stateBeforeReload) {
|
|
console.log(` ✅ State persisted after reload: ${stateAfterReload}`);
|
|
passed++;
|
|
} else {
|
|
console.log(` ❌ State changed after reload: was ${stateBeforeReload}, now ${stateAfterReload}`);
|
|
failed++;
|
|
}
|
|
|
|
// Test 6: Toggle back to original state
|
|
console.log('\nTest 6: Toggle back to original state');
|
|
await page.click('#auto-index-toggle');
|
|
await delay(1000);
|
|
|
|
const restoredState = await page.evaluate(() => {
|
|
return document.getElementById('auto-index-toggle').checked;
|
|
});
|
|
|
|
if (restoredState === initialState) {
|
|
console.log(` ✅ Restored to original state: ${restoredState}`);
|
|
passed++;
|
|
} else {
|
|
console.log(` ❌ Failed to restore: expected ${initialState}, got ${restoredState}`);
|
|
failed++;
|
|
}
|
|
|
|
// Test 7: No console or network errors during tests
|
|
console.log('\nTest 7: No critical errors during tests');
|
|
const criticalConsoleErrors = consoleErrors.filter(e =>
|
|
!e.includes('favicon') && !e.includes('404')
|
|
);
|
|
const criticalNetworkErrors = networkErrors.filter(e =>
|
|
!e.url.includes('favicon') && e.status >= 500
|
|
);
|
|
|
|
if (criticalConsoleErrors.length === 0 && criticalNetworkErrors.length === 0) {
|
|
console.log(' ✅ No critical errors');
|
|
passed++;
|
|
} else {
|
|
console.log(` ❌ Found errors: ${criticalConsoleErrors.length} console, ${criticalNetworkErrors.length} network`);
|
|
criticalConsoleErrors.forEach(e => console.log(` Console: ${e}`));
|
|
criticalNetworkErrors.forEach(e => console.log(` Network: ${e.status} ${e.url}`));
|
|
failed++;
|
|
}
|
|
|
|
// Take screenshot for debugging
|
|
await takeScreenshot(page, '/tmp/collections_auto_index_test.png');
|
|
|
|
} catch (error) {
|
|
console.error('\n❌ Test error:', error.message);
|
|
await takeScreenshot(page, '/tmp/collections_auto_index_error.png');
|
|
failed++;
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
|
|
// Summary
|
|
console.log('\n' + '='.repeat(50));
|
|
console.log(`📊 Results: ${passed} passed, ${failed} failed`);
|
|
console.log('='.repeat(50));
|
|
|
|
process.exit(failed > 0 ? 1 : 0);
|
|
}
|
|
|
|
runTests();
|