feat: 添加MSW模拟服务和数据源集成
refactor: 重构页面组件移除冗余Layout组件 feat: 实现WebSocket和事件总线系统 feat: 添加队列和调度系统 docs: 更新架构文档和服务映射 style: 清理重复接口定义使用数据源 chore: 更新依赖项配置 feat: 添加运行时系统和领域引导 ci: 配置ESLint边界检查规则 build: 添加Redis和WebSocket依赖 test: 添加MSW浏览器环境入口 perf: 优化数据获取逻辑使用统一数据源 fix: 修复类型定义和状态管理问题
This commit is contained in:
789
scripts/run-tests.js
Normal file
789
scripts/run-tests.js
Normal file
@@ -0,0 +1,789 @@
|
||||
#!/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
|
||||
};
|
||||
Reference in New Issue
Block a user