refactor: 重构页面组件移除冗余Layout组件 feat: 实现WebSocket和事件总线系统 feat: 添加队列和调度系统 docs: 更新架构文档和服务映射 style: 清理重复接口定义使用数据源 chore: 更新依赖项配置 feat: 添加运行时系统和领域引导 ci: 配置ESLint边界检查规则 build: 添加Redis和WebSocket依赖 test: 添加MSW浏览器环境入口 perf: 优化数据获取逻辑使用统一数据源 fix: 修复类型定义和状态管理问题
789 lines
24 KiB
JavaScript
789 lines
24 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const { execSync } = require('child_process');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
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}${message}${COLORS.reset}`);
|
|
}
|
|
|
|
function logStep(step, message) {
|
|
console.log(`\n${COLORS.cyan}[${step}]${COLORS.reset} ${message}`);
|
|
}
|
|
|
|
function logSuccess(message) {
|
|
console.log(`${COLORS.green}✅${COLORS.reset} ${message}`);
|
|
}
|
|
|
|
function logError(message) {
|
|
console.log(`${COLORS.red}❌${COLORS.reset} ${message}`);
|
|
}
|
|
|
|
function logWarning(message) {
|
|
console.log(`${COLORS.yellow}⚠️${COLORS.reset} ${message}`);
|
|
}
|
|
|
|
function executeCommand(command, description) {
|
|
try {
|
|
logStep('EXEC', description);
|
|
const result = execSync(command, {
|
|
encoding: 'utf8',
|
|
stdio: 'inherit'
|
|
});
|
|
logSuccess(description);
|
|
return true;
|
|
} catch (error) {
|
|
logError(`${description} failed: ${error.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function runUnitTests() {
|
|
logStep(1, 'Running Unit Tests');
|
|
|
|
try {
|
|
const testResults = {
|
|
server: runServerUnitTests(),
|
|
dashboard: runDashboardUnitTests(),
|
|
client: runClientUnitTests(),
|
|
extension: runExtensionUnitTests()
|
|
};
|
|
|
|
const totalTests = Object.values(testResults).reduce((sum, result) => sum + result.total, 0);
|
|
const passedTests = Object.values(testResults).reduce((sum, result) => sum + result.passed, 0);
|
|
const failedTests = Object.values(testResults).reduce((sum, result) => sum + result.failed, 0);
|
|
|
|
console.log(`\n${COLORS.cyan}Unit Tests Summary:${COLORS.reset}`);
|
|
console.log(` Total: ${totalTests}`);
|
|
console.log(` ${COLORS.green}Passed: ${passedTests}${COLORS.reset}`);
|
|
console.log(` ${COLORS.red}Failed: ${failedTests}${COLORS.reset}`);
|
|
console.log(` Success Rate: ${((passedTests / totalTests) * 100).toFixed(2)}%`);
|
|
|
|
return failedTests === 0;
|
|
} catch (error) {
|
|
logError(`Unit tests failed: ${error.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function runServerUnitTests() {
|
|
try {
|
|
const output = execSync('cd server && npm test -- --coverage --json', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = JSON.parse(output);
|
|
const total = results.numTotalTests;
|
|
const passed = results.numPassedTests;
|
|
const failed = results.numFailedTests;
|
|
|
|
console.log(`\n${COLORS.cyan}Server Unit Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${total}, Passed: ${passed}, Failed: ${failed}`);
|
|
console.log(` Coverage: ${results.coverageMap ? 'Generated' : 'Not available'}`);
|
|
|
|
return { total, passed, failed };
|
|
} catch (error) {
|
|
logError('Server unit tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runDashboardUnitTests() {
|
|
try {
|
|
const output = execSync('cd dashboard && npm test -- --coverage --json', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = JSON.parse(output);
|
|
const total = results.numTotalTests;
|
|
const passed = results.numPassedTests;
|
|
const failed = results.numFailedTests;
|
|
|
|
console.log(`\n${COLORS.cyan}Dashboard Unit Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${total}, Passed: ${passed}, Failed: ${failed}`);
|
|
console.log(` Coverage: ${results.coverageMap ? 'Generated' : 'Not available'}`);
|
|
|
|
return { total, passed, failed };
|
|
} catch (error) {
|
|
logError('Dashboard unit tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runClientUnitTests() {
|
|
try {
|
|
const output = execSync('cd client && npm test -- --coverage --json', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = JSON.parse(output);
|
|
const total = results.numTotalTests;
|
|
const passed = results.numPassedTests;
|
|
const failed = results.numFailedTests;
|
|
|
|
console.log(`\n${COLORS.cyan}Client Unit Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${total}, Passed: ${passed}, Failed: ${failed}`);
|
|
console.log(` Coverage: ${results.coverageMap ? 'Generated' : 'Not available'}`);
|
|
|
|
return { total, passed, failed };
|
|
} catch (error) {
|
|
logError('Client unit tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runExtensionUnitTests() {
|
|
try {
|
|
const output = execSync('cd extension && npm test -- --coverage --json', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = JSON.parse(output);
|
|
const total = results.numTotalTests;
|
|
const passed = results.numPassedTests;
|
|
const failed = results.numFailedTests;
|
|
|
|
console.log(`\n${COLORS.cyan}Extension Unit Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${total}, Passed: ${passed}, Failed: ${failed}`);
|
|
console.log(` Coverage: ${results.coverageMap ? 'Generated' : 'Not available'}`);
|
|
|
|
return { total, passed, failed };
|
|
} catch (error) {
|
|
logError('Extension unit tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runIntegrationTests() {
|
|
logStep(2, 'Running Integration Tests');
|
|
|
|
try {
|
|
const testResults = {
|
|
api: runAPIIntegrationTests(),
|
|
database: runDatabaseIntegrationTests(),
|
|
redis: runRedisIntegrationTests(),
|
|
websocket: runWebSocketIntegrationTests()
|
|
};
|
|
|
|
const totalTests = Object.values(testResults).reduce((sum, result) => sum + result.total, 0);
|
|
const passedTests = Object.values(testResults).reduce((sum, result) => sum + result.passed, 0);
|
|
const failedTests = Object.values(testResults).reduce((sum, result) => sum + result.failed, 0);
|
|
|
|
console.log(`\n${COLORS.cyan}Integration Tests Summary:${COLORS.reset}`);
|
|
console.log(` Total: ${totalTests}`);
|
|
console.log(` ${COLORS.green}Passed: ${passedTests}${COLORS.reset}`);
|
|
console.log(` ${COLORS.red}Failed: ${failedTests}${COLORS.reset}`);
|
|
console.log(` Success Rate: ${((passedTests / totalTests) * 100).toFixed(2)}%`);
|
|
|
|
return failedTests === 0;
|
|
} catch (error) {
|
|
logError(`Integration tests failed: ${error.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function runAPIIntegrationTests() {
|
|
try {
|
|
const output = execSync('cd server && npm run test:integration', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}API Integration Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('API integration tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runDatabaseIntegrationTests() {
|
|
try {
|
|
const output = execSync('cd server && npm run test:database', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Database Integration Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Database integration tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runRedisIntegrationTests() {
|
|
try {
|
|
const output = execSync('cd server && npm run test:redis', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Redis Integration Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Redis integration tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runWebSocketIntegrationTests() {
|
|
try {
|
|
const output = execSync('cd server && npm run test:websocket', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}WebSocket Integration Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('WebSocket integration tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function parseTestOutput(output) {
|
|
const lines = output.split('\n');
|
|
let total = 0, passed = 0, failed = 0;
|
|
|
|
lines.forEach(line => {
|
|
const totalMatch = line.match(/Tests:\s+(\d+)/);
|
|
const passedMatch = line.match(/Passed:\s+(\d+)/);
|
|
const failedMatch = line.match(/Failed:\s+(\d+)/);
|
|
|
|
if (totalMatch) total = parseInt(totalMatch[1]);
|
|
if (passedMatch) passed = parseInt(passedMatch[1]);
|
|
if (failedMatch) failed = parseInt(failedMatch[1]);
|
|
});
|
|
|
|
return { total, passed, failed };
|
|
}
|
|
|
|
function runE2ETests() {
|
|
logStep(3, 'Running End-to-End Tests');
|
|
|
|
try {
|
|
const testResults = {
|
|
userFlow: runUserFlowTests(),
|
|
businessFlow: runBusinessFlowTests(),
|
|
adminFlow: runAdminFlowTests()
|
|
};
|
|
|
|
const totalTests = Object.values(testResults).reduce((sum, result) => sum + result.total, 0);
|
|
const passedTests = Object.values(testResults).reduce((sum, result) => sum + result.passed, 0);
|
|
const failedTests = Object.values(testResults).reduce((sum, result) => sum + result.failed, 0);
|
|
|
|
console.log(`\n${COLORS.cyan}E2E Tests Summary:${COLORS.reset}`);
|
|
console.log(` Total: ${totalTests}`);
|
|
console.log(` ${COLORS.green}Passed: ${passedTests}${COLORS.reset}`);
|
|
console.log(` ${COLORS.red}Failed: ${failedTests}${COLORS.reset}`);
|
|
console.log(` Success Rate: ${((passedTests / totalTests) * 100).toFixed(2)}%`);
|
|
|
|
return failedTests === 0;
|
|
} catch (error) {
|
|
logError(`E2E tests failed: ${error.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function runUserFlowTests() {
|
|
try {
|
|
const output = execSync('cd dashboard && npm run test:e2e:user', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}User Flow Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('User flow tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runBusinessFlowTests() {
|
|
try {
|
|
const output = execSync('cd dashboard && npm run test:e2e:business', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Business Flow Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Business flow tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runAdminFlowTests() {
|
|
try {
|
|
const output = execSync('cd dashboard && npm run test:e2e:admin', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Admin Flow Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Admin flow tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runPerformanceTests() {
|
|
logStep(4, 'Running Performance Tests');
|
|
|
|
try {
|
|
const testResults = {
|
|
load: runLoadTests(),
|
|
stress: runStressTests(),
|
|
endurance: runEnduranceTests()
|
|
};
|
|
|
|
const totalTests = Object.values(testResults).reduce((sum, result) => sum + result.total, 0);
|
|
const passedTests = Object.values(testResults).reduce((sum, result) => sum + result.passed, 0);
|
|
const failedTests = Object.values(testResults).reduce((sum, result) => sum + result.failed, 0);
|
|
|
|
console.log(`\n${COLORS.cyan}Performance Tests Summary:${COLORS.reset}`);
|
|
console.log(` Total: ${totalTests}`);
|
|
console.log(` ${COLORS.green}Passed: ${passedTests}${COLORS.reset}`);
|
|
console.log(` ${COLORS.red}Failed: ${failedTests}${COLORS.reset}`);
|
|
console.log(` Success Rate: ${((passedTests / totalTests) * 100).toFixed(2)}%`);
|
|
|
|
return failedTests === 0;
|
|
} catch (error) {
|
|
logError(`Performance tests failed: ${error.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function runLoadTests() {
|
|
try {
|
|
const output = execSync('cd server && npm run test:load', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Load Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Load tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runStressTests() {
|
|
try {
|
|
const output = execSync('cd server && npm run test:stress', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Stress Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Stress tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runEnduranceTests() {
|
|
try {
|
|
const output = execSync('cd server && npm run test:endurance', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Endurance Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Endurance tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runSecurityTests() {
|
|
logStep(5, 'Running Security Tests');
|
|
|
|
try {
|
|
const testResults = {
|
|
vulnerability: runVulnerabilityTests(),
|
|
penetration: runPenetrationTests(),
|
|
compliance: runComplianceTests()
|
|
};
|
|
|
|
const totalTests = Object.values(testResults).reduce((sum, result) => sum + result.total, 0);
|
|
const passedTests = Object.values(testResults).reduce((sum, result) => sum + result.passed, 0);
|
|
const failedTests = Object.values(testResults).reduce((sum, result) => sum + result.failed, 0);
|
|
|
|
console.log(`\n${COLORS.cyan}Security Tests Summary:${COLORS.reset}`);
|
|
console.log(` Total: ${totalTests}`);
|
|
console.log(` ${COLORS.green}Passed: ${passedTests}${COLORS.reset}`);
|
|
console.log(` ${COLORS.red}Failed: ${failedTests}${COLORS.reset}`);
|
|
console.log(` Success Rate: ${((passedTests / totalTests) * 100).toFixed(2)}%`);
|
|
|
|
return failedTests === 0;
|
|
} catch (error) {
|
|
logError(`Security tests failed: ${error.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function runVulnerabilityTests() {
|
|
try {
|
|
const output = execSync('npm audit --json', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = JSON.parse(output);
|
|
const vulnerabilities = results.vulnerabilities || {};
|
|
|
|
const total = Object.values(vulnerabilities).reduce((sum, vulns) => sum + vulns.length, 0);
|
|
const critical = vulnerabilities.critical ? vulnerabilities.critical.length : 0;
|
|
const high = vulnerabilities.high ? vulnerabilities.high.length : 0;
|
|
const moderate = vulnerabilities.moderate ? vulnerabilities.moderate.length : 0;
|
|
const low = vulnerabilities.low ? vulnerabilities.low.length : 0;
|
|
const passed = total - (critical + high);
|
|
const failed = critical + high;
|
|
|
|
console.log(`\n${COLORS.cyan}Vulnerability Tests:${COLORS.reset}`);
|
|
console.log(` Critical: ${critical}, High: ${high}, Moderate: ${moderate}, Low: ${low}`);
|
|
console.log(` Total: ${total}, Passed: ${passed}, Failed: ${failed}`);
|
|
|
|
return { total, passed, failed };
|
|
} catch (error) {
|
|
logError('Vulnerability tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runPenetrationTests() {
|
|
try {
|
|
const output = execSync('cd server && npm run test:security', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Penetration Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Penetration tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runComplianceTests() {
|
|
try {
|
|
const output = execSync('cd server && npm run test:compliance', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Compliance Tests:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Compliance tests failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runCodeQualityChecks() {
|
|
logStep(6, 'Running Code Quality Checks');
|
|
|
|
try {
|
|
const checkResults = {
|
|
linting: runLintingChecks(),
|
|
formatting: runFormattingChecks(),
|
|
complexity: runComplexityChecks(),
|
|
duplication: runDuplicationChecks()
|
|
};
|
|
|
|
const totalChecks = Object.values(checkResults).reduce((sum, result) => sum + result.total, 0);
|
|
const passedChecks = Object.values(checkResults).reduce((sum, result) => sum + result.passed, 0);
|
|
const failedChecks = Object.values(checkResults).reduce((sum, result) => sum + result.failed, 0);
|
|
|
|
console.log(`\n${COLORS.cyan}Code Quality Checks Summary:${COLORS.reset}`);
|
|
console.log(` Total: ${totalChecks}`);
|
|
console.log(` ${COLORS.green}Passed: ${passedChecks}${COLORS.reset}`);
|
|
console.log(` ${COLORS.red}Failed: ${failedChecks}${COLORS.reset}`);
|
|
console.log(` Success Rate: ${((passedChecks / totalChecks) * 100).toFixed(2)}%`);
|
|
|
|
return failedChecks === 0;
|
|
} catch (error) {
|
|
logError(`Code quality checks failed: ${error.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function runLintingChecks() {
|
|
try {
|
|
const output = execSync('npm run lint -- --format json', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = JSON.parse(output);
|
|
const total = results.length;
|
|
const passed = results.filter(r => r.errorCount === 0 && r.warningCount === 0).length;
|
|
const failed = total - passed;
|
|
|
|
console.log(`\n${COLORS.cyan}Linting Checks:${COLORS.reset}`);
|
|
console.log(` Total: ${total}, Passed: ${passed}, Failed: ${failed}`);
|
|
|
|
return { total, passed, failed };
|
|
} catch (error) {
|
|
logError('Linting checks failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runFormattingChecks() {
|
|
try {
|
|
const output = execSync('npm run format:check', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Formatting Checks:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Formatting checks failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runComplexityChecks() {
|
|
try {
|
|
const output = execSync('npm run complexity:check', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Complexity Checks:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Complexity checks failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function runDuplicationChecks() {
|
|
try {
|
|
const output = execSync('npm run duplication:check', {
|
|
encoding: 'utf8',
|
|
stdio: 'pipe'
|
|
});
|
|
|
|
const results = parseTestOutput(output);
|
|
console.log(`\n${COLORS.cyan}Duplication Checks:${COLORS.reset}`);
|
|
console.log(` Total: ${results.total}, Passed: ${results.passed}, Failed: ${results.failed}`);
|
|
|
|
return results;
|
|
} catch (error) {
|
|
logError('Duplication checks failed');
|
|
return { total: 0, passed: 0, failed: 1 };
|
|
}
|
|
}
|
|
|
|
function generateTestReport() {
|
|
logStep(7, 'Generating Test Report');
|
|
|
|
const report = {
|
|
timestamp: new Date().toISOString(),
|
|
project: {
|
|
name: 'Crawlful Hub',
|
|
version: '1.0.0'
|
|
},
|
|
summary: {
|
|
totalTests: 0,
|
|
passedTests: 0,
|
|
failedTests: 0,
|
|
skippedTests: 0,
|
|
successRate: 0,
|
|
duration: 0
|
|
},
|
|
categories: {
|
|
unitTests: {
|
|
total: 0,
|
|
passed: 0,
|
|
failed: 0,
|
|
coverage: 0
|
|
},
|
|
integrationTests: {
|
|
total: 0,
|
|
passed: 0,
|
|
failed: 0
|
|
},
|
|
e2eTests: {
|
|
total: 0,
|
|
passed: 0,
|
|
failed: 0
|
|
},
|
|
performanceTests: {
|
|
total: 0,
|
|
passed: 0,
|
|
failed: 0
|
|
},
|
|
securityTests: {
|
|
total: 0,
|
|
passed: 0,
|
|
failed: 0
|
|
},
|
|
codeQualityChecks: {
|
|
total: 0,
|
|
passed: 0,
|
|
failed: 0
|
|
}
|
|
},
|
|
recommendations: [
|
|
'Fix failing tests before deployment',
|
|
'Improve test coverage for critical paths',
|
|
'Add more integration tests',
|
|
'Implement automated security scanning',
|
|
'Set up continuous testing pipeline'
|
|
],
|
|
nextSteps: [
|
|
'Review test failures',
|
|
'Fix critical issues',
|
|
'Re-run failed tests',
|
|
'Update documentation',
|
|
'Prepare for deployment'
|
|
]
|
|
};
|
|
|
|
const reportPath = path.join(process.cwd(), 'test-report.json');
|
|
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
|
|
logSuccess(`Test report generated: ${reportPath}`);
|
|
return true;
|
|
}
|
|
|
|
function main() {
|
|
console.log(`${COLORS.bright}${COLORS.blue}
|
|
╔══════════════════════════════════════════════════════════╗
|
|
║ ║
|
|
║ CRAWLFUL HUB - COMPREHENSIVE TEST SUITE ║
|
|
║ ║
|
|
║ Complete Quality Assurance & Testing ║
|
|
║ ║
|
|
╚══════════════════════════════════════════════════════════╝
|
|
${COLORS.reset}`);
|
|
|
|
logStep('START', 'Starting comprehensive testing...\n');
|
|
|
|
const results = {
|
|
unitTests: runUnitTests(),
|
|
integrationTests: runIntegrationTests(),
|
|
e2eTests: runE2ETests(),
|
|
performanceTests: runPerformanceTests(),
|
|
securityTests: runSecurityTests(),
|
|
codeQualityChecks: runCodeQualityChecks(),
|
|
reportGeneration: generateTestReport()
|
|
};
|
|
|
|
console.log(`\n${COLORS.bright}${COLORS.blue}
|
|
══════════════════════════════════════════════════════════
|
|
TESTING COMPLETE
|
|
══════════════════════════════════════════════════════════
|
|
${COLORS.reset}`);
|
|
|
|
const successCount = Object.values(results).filter(Boolean).length;
|
|
const totalCount = Object.keys(results).length;
|
|
|
|
console.log(`\n${COLORS.cyan}Summary:${COLORS.reset}`);
|
|
console.log(` ${COLORS.green}✅${COLORS.reset} Successful: ${successCount}/${totalCount}`);
|
|
console.log(` ${COLORS.red}❌${COLORS.reset} Failed: ${totalCount - successCount}/${totalCount}`);
|
|
|
|
if (successCount === totalCount) {
|
|
logSuccess('🚀 All tests completed successfully!');
|
|
console.log(`\n${COLORS.yellow}Next Steps:${COLORS.reset}`);
|
|
console.log(' 1. Review test-report.json');
|
|
console.log(' 2. Check test coverage reports');
|
|
console.log(' 3. Review performance metrics');
|
|
console.log(' 4. Address any warnings');
|
|
console.log(' 5. Prepare for deployment');
|
|
} else {
|
|
logWarning('Some tests failed. Please review the errors above.');
|
|
console.log(`\n${COLORS.yellow}Action Items:${COLORS.reset}`);
|
|
console.log(' 1. Review test failures');
|
|
console.log(' 2. Fix critical issues');
|
|
console.log(' 3. Re-run failed tests');
|
|
console.log(' 4. Update documentation');
|
|
}
|
|
|
|
process.exit(successCount === totalCount ? 0 : 1);
|
|
}
|
|
|
|
if (require.main === module) {
|
|
main();
|
|
}
|
|
|
|
module.exports = {
|
|
runUnitTests,
|
|
runIntegrationTests,
|
|
runE2ETests,
|
|
runPerformanceTests,
|
|
runSecurityTests,
|
|
runCodeQualityChecks,
|
|
generateTestReport
|
|
}; |