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
335 lines
10 KiB
JavaScript
335 lines
10 KiB
JavaScript
const { spawn } = require('child_process');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
|
|
// Test configuration
|
|
const TEST_TIMEOUT = 120000; // 2 minutes per test (reduced for faster execution)
|
|
|
|
// 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',
|
|
magenta: '\x1b[35m'
|
|
};
|
|
|
|
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,
|
|
'test': colors.magenta
|
|
};
|
|
const color = typeColors[type] || colors.reset;
|
|
console.log(`${color}[${timestamp}] ${message}${colors.reset}`);
|
|
}
|
|
|
|
// Get all test files dynamically
|
|
function getAllTestFiles() {
|
|
const testDir = __dirname;
|
|
const files = fs.readdirSync(testDir);
|
|
|
|
return files.filter(file => {
|
|
// Include files that start with 'test_' and end with '.js'
|
|
if (!file.startsWith('test_') || !file.endsWith('.js')) {
|
|
return false;
|
|
}
|
|
|
|
// Exclude our comprehensive test files
|
|
const excludeFiles = [
|
|
'test_api_key_comprehensive.js', // Already know this has issues
|
|
'test_settings_simple.js' // Debug file
|
|
];
|
|
|
|
return !excludeFiles.includes(file);
|
|
}).sort();
|
|
}
|
|
|
|
// Test results
|
|
const results = {
|
|
total: 0,
|
|
passed: 0,
|
|
failed: 0,
|
|
timeout: 0,
|
|
skipped: 0,
|
|
details: []
|
|
};
|
|
|
|
async function runTest(testFile) {
|
|
return new Promise((resolve) => {
|
|
const testPath = path.join(__dirname, testFile);
|
|
|
|
// Check if test file exists
|
|
if (!fs.existsSync(testPath)) {
|
|
log(`⚠️ Test file not found: ${testFile}`, 'warning');
|
|
results.skipped++;
|
|
results.details.push({
|
|
name: testFile,
|
|
status: 'skipped',
|
|
reason: 'File not found'
|
|
});
|
|
resolve();
|
|
return;
|
|
}
|
|
|
|
const startTime = Date.now();
|
|
const testProcess = spawn('node', [testPath], {
|
|
cwd: __dirname,
|
|
env: { ...process.env, NODE_ENV: 'test', HEADLESS: 'true' }
|
|
});
|
|
|
|
let output = '';
|
|
let errorOutput = '';
|
|
let hasOutput = false;
|
|
|
|
// Capture stdout
|
|
testProcess.stdout.on('data', (data) => {
|
|
const text = data.toString();
|
|
output += text;
|
|
hasOutput = true;
|
|
|
|
// Only show first 100 chars of output
|
|
const preview = text.substring(0, 100);
|
|
if (preview.length < text.length) {
|
|
process.stdout.write(preview + '...\n');
|
|
} else {
|
|
process.stdout.write(preview);
|
|
}
|
|
});
|
|
|
|
// Capture stderr
|
|
testProcess.stderr.on('data', (data) => {
|
|
const text = data.toString();
|
|
errorOutput += text;
|
|
|
|
// Show error output
|
|
if (text.length > 100) {
|
|
process.stderr.write(text.substring(0, 100) + '...\n');
|
|
} else {
|
|
process.stderr.write(text);
|
|
}
|
|
});
|
|
|
|
// Set timeout
|
|
const timeout = setTimeout(() => {
|
|
log(`⏱️ Test timeout after ${TEST_TIMEOUT/1000} seconds`, 'error');
|
|
testProcess.kill('SIGTERM');
|
|
results.timeout++;
|
|
results.details.push({
|
|
name: testFile,
|
|
status: 'timeout',
|
|
duration: TEST_TIMEOUT/1000,
|
|
output: output.substring(0, 500),
|
|
error: errorOutput.substring(0, 500)
|
|
});
|
|
resolve();
|
|
}, TEST_TIMEOUT);
|
|
|
|
// Handle test completion
|
|
testProcess.on('close', (code) => {
|
|
clearTimeout(timeout);
|
|
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
|
|
|
|
if (code === 0) {
|
|
log(`✅ Test passed (${duration}s)`, 'success');
|
|
results.passed++;
|
|
results.details.push({
|
|
name: testFile,
|
|
status: 'passed',
|
|
duration
|
|
});
|
|
} else if (code !== null) {
|
|
log(`❌ Test failed with code ${code} (${duration}s)`, 'error');
|
|
results.failed++;
|
|
results.details.push({
|
|
name: testFile,
|
|
status: 'failed',
|
|
duration,
|
|
code,
|
|
output: output.substring(0, 500),
|
|
error: errorOutput.substring(0, 500)
|
|
});
|
|
}
|
|
|
|
resolve();
|
|
});
|
|
|
|
// Handle errors
|
|
testProcess.on('error', (error) => {
|
|
clearTimeout(timeout);
|
|
log(`❌ Failed to run test: ${error.message}`, 'error');
|
|
results.failed++;
|
|
results.details.push({
|
|
name: testFile,
|
|
status: 'failed',
|
|
error: error.message
|
|
});
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
async function generateReport() {
|
|
log('\n' + '='.repeat(80), 'section');
|
|
log('📊 COMPREHENSIVE TEST SUMMARY REPORT', 'section');
|
|
log('='.repeat(80), 'section');
|
|
|
|
const successRate = results.total > 0 ?
|
|
((results.passed / results.total) * 100).toFixed(1) : 0;
|
|
|
|
log(`\nTotal Tests: ${results.total}`, 'info');
|
|
log(`✅ Passed: ${results.passed}`, 'success');
|
|
log(`❌ Failed: ${results.failed}`, results.failed > 0 ? 'error' : 'info');
|
|
log(`⏱️ Timeout: ${results.timeout}`, results.timeout > 0 ? 'warning' : 'info');
|
|
log(`⏭️ Skipped: ${results.skipped}`, 'warning');
|
|
log(`📈 Success Rate: ${successRate}%`,
|
|
successRate >= 80 ? 'success' : successRate >= 50 ? 'warning' : 'error');
|
|
|
|
// Group results by status
|
|
const passed = results.details.filter(t => t.status === 'passed');
|
|
const failed = results.details.filter(t => t.status === 'failed');
|
|
const timeout = results.details.filter(t => t.status === 'timeout');
|
|
const skipped = results.details.filter(t => t.status === 'skipped');
|
|
|
|
// Show passed tests
|
|
if (passed.length > 0) {
|
|
log('\n✅ PASSED TESTS:', 'success');
|
|
passed.forEach(test => {
|
|
log(` ${test.name} (${test.duration}s)`, 'info');
|
|
});
|
|
}
|
|
|
|
// Show failed tests
|
|
if (failed.length > 0) {
|
|
log('\n❌ FAILED TESTS:', 'error');
|
|
failed.forEach(test => {
|
|
log(` ${test.name} (${test.duration}s) - Exit code: ${test.code || 'N/A'}`, 'error');
|
|
if (test.error) {
|
|
log(` Error: ${test.error.substring(0, 100)}...`, 'error');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Show timeout tests
|
|
if (timeout.length > 0) {
|
|
log('\n⏱️ TIMEOUT TESTS:', 'warning');
|
|
timeout.forEach(test => {
|
|
log(` ${test.name}`, 'warning');
|
|
});
|
|
}
|
|
|
|
// Show skipped tests
|
|
if (skipped.length > 0) {
|
|
log('\n⏭️ SKIPPED TESTS:', 'warning');
|
|
skipped.forEach(test => {
|
|
log(` ${test.name} - ${test.reason}`, 'warning');
|
|
});
|
|
}
|
|
|
|
// Save report to file
|
|
const reportPath = path.join(__dirname, 'comprehensive_test_report.json');
|
|
fs.writeFileSync(reportPath, JSON.stringify(results, null, 2));
|
|
log(`\n💾 Test report saved to: ${reportPath}`, 'info');
|
|
}
|
|
|
|
async function checkServerRunning() {
|
|
const http = require('http');
|
|
|
|
return new Promise((resolve) => {
|
|
const options = {
|
|
hostname: '127.0.0.1',
|
|
port: 5000,
|
|
path: '/',
|
|
method: 'GET',
|
|
timeout: 5000
|
|
};
|
|
|
|
const req = http.request(options, (res) => {
|
|
resolve(res.statusCode === 200 || res.statusCode === 302 || res.statusCode === 404);
|
|
});
|
|
|
|
req.on('error', () => {
|
|
resolve(false);
|
|
});
|
|
|
|
req.on('timeout', () => {
|
|
req.destroy();
|
|
resolve(false);
|
|
});
|
|
|
|
req.end();
|
|
});
|
|
}
|
|
|
|
async function runAllTests() {
|
|
log('🚀 Starting LDR COMPREHENSIVE UI Test Suite', 'section');
|
|
log(`📅 Date: ${new Date().toLocaleString()}`, 'info');
|
|
|
|
// Check if server is running
|
|
log('\n🔍 Checking if LDR server is running...', 'info');
|
|
const serverRunning = await checkServerRunning();
|
|
|
|
if (!serverRunning) {
|
|
log('❌ LDR server is not running on http://127.0.0.1:5000', 'error');
|
|
log('💡 Please start the server first', 'info');
|
|
process.exit(1);
|
|
}
|
|
|
|
log('✅ Server is running', 'success');
|
|
|
|
// Get all test files
|
|
const testFiles = getAllTestFiles();
|
|
results.total = testFiles.length;
|
|
|
|
log(`\n📋 Found ${testFiles.length} test files to run`, 'info');
|
|
log('Note: Tests will run with reduced output to prevent log overflow\n', 'info');
|
|
|
|
// Run tests sequentially
|
|
const startTime = Date.now();
|
|
|
|
for (let i = 0; i < testFiles.length; i++) {
|
|
const testFile = testFiles[i];
|
|
log(`\n[${i + 1}/${testFiles.length}] 🧪 Running: ${testFile}`, 'test');
|
|
await runTest(testFile);
|
|
}
|
|
|
|
const totalDuration = ((Date.now() - startTime) / 1000).toFixed(2);
|
|
log(`\n⏱️ Total test duration: ${totalDuration}s`, 'info');
|
|
|
|
// Generate report
|
|
await generateReport();
|
|
|
|
// Exit with appropriate code
|
|
if (results.failed > 0 || results.timeout > 0) {
|
|
log('\n❌ Some tests failed or timed out. Please check the results above.', 'error');
|
|
process.exit(1);
|
|
} else if (results.passed === results.total) {
|
|
log('\n🎉 All tests passed!', 'success');
|
|
process.exit(0);
|
|
} else {
|
|
log('\n⚠️ Some tests were skipped. Please check the results above.', 'warning');
|
|
process.exit(0);
|
|
}
|
|
}
|
|
|
|
// Handle interruptions gracefully
|
|
process.on('SIGINT', () => {
|
|
log('\n\n🛑 Test suite interrupted by user', 'warning');
|
|
generateReport().then(() => {
|
|
process.exit(1);
|
|
});
|
|
});
|
|
|
|
// Run all tests
|
|
runAllTests().catch(error => {
|
|
log(`\n❌ Test suite error: ${error.message}`, 'error');
|
|
process.exit(1);
|
|
});
|