UNPKG

@casoon/auditmysite

Version:

A comprehensive command-line tool for automated accessibility, security, performance, and SEO testing using Playwright and pa11y, based on sitemap URLs

229 lines 8.61 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ParallelTestManager = void 0; const event_driven_queue_1 = require("./event-driven-queue"); const accessibility_checker_1 = require("./accessibility-checker"); class ParallelTestManager { constructor(options = {}) { this.isRunning = false; this.startTime = null; this.activeTests = new Map(); this.options = { maxConcurrent: 3, maxRetries: 3, retryDelay: 1000, enableProgressBar: true, progressUpdateInterval: 1000, enableResourceMonitoring: true, maxMemoryUsage: 512, // 512 MB maxCpuUsage: 80, // 80% ...options }; // Event-Driven Queue initialisieren this.queue = new event_driven_queue_1.EventDrivenQueue({ maxRetries: this.options.maxRetries, maxConcurrent: this.options.maxConcurrent, retryDelay: this.options.retryDelay, enableEvents: true, eventCallbacks: { onUrlAdded: this.handleUrlAdded.bind(this), onUrlStarted: this.handleUrlStarted.bind(this), onUrlCompleted: this.handleUrlCompleted.bind(this), onUrlFailed: this.handleUrlFailed.bind(this), onUrlRetrying: this.handleUrlRetrying.bind(this), onQueueEmpty: this.handleQueueEmpty.bind(this), onProgressUpdate: this.handleProgressUpdate.bind(this), onError: this.handleError.bind(this) } }); // Accessibility Checker initialisieren this.accessibilityChecker = new accessibility_checker_1.AccessibilityChecker(); } async initialize() { await this.accessibilityChecker.initialize(); console.log(`🚀 Parallel Test Manager initialized with ${this.options.maxConcurrent} concurrent workers`); } async runTests(urls) { if (this.isRunning) { throw new Error('Test manager is already running'); } this.isRunning = true; this.startTime = new Date(); this.activeTests.clear(); console.log(`🧪 Starting parallel tests for ${urls.length} URLs with ${this.options.maxConcurrent} workers`); // URLs zur Queue hinzufügen this.queue.addUrls(urls); // Event-Listener für Queue-Events this.setupEventListeners(); // Parallele Test-Ausführung starten await this.processQueue(); const duration = this.startTime ? Date.now() - this.startTime.getTime() : 0; const stats = this.queue.getStats(); const results = this.queue.getCompletedResults(); const errors = this.queue.getFailedResults(); this.isRunning = false; return { results, stats, duration, errors }; } async processQueue() { return new Promise((resolve, reject) => { // Event-Listener für Queue-Ende this.queue.onQueueEmpty(() => { resolve(); }); // Event-Listener für Fehler this.queue.onError((event) => { reject(new Error(event.data.error)); }); // Starte Worker-Prozesse this.startWorkers(); }); } startWorkers() { // Starte initiale Worker bis zur maxConcurrent-Grenze for (let i = 0; i < this.options.maxConcurrent; i++) { this.processNextUrl(); } } async processNextUrl() { if (!this.isRunning) return; const queuedUrl = this.queue.getNextUrl(); if (!queuedUrl) return; try { // Resource-Monitoring if (this.options.enableResourceMonitoring) { this.checkResourceLimits(); } // Test ausführen const testPromise = this.accessibilityChecker.testPage(queuedUrl.url, this.options.testOptions); this.activeTests.set(queuedUrl.url, testPromise); const result = await testPromise; this.queue.markCompleted(queuedUrl.url, result); } catch (error) { this.queue.markFailed(queuedUrl.url, String(error)); } finally { this.activeTests.delete(queuedUrl.url); // Starte nächsten Worker this.processNextUrl(); } } checkResourceLimits() { const memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024; // MB const cpuUsage = process.cpuUsage().user / 1000000; // Sekunden if (memoryUsage > this.options.maxMemoryUsage) { console.warn(`⚠️ High memory usage: ${memoryUsage.toFixed(2)} MB`); // Optional: Queue pausieren oder Worker reduzieren } if (cpuUsage > this.options.maxCpuUsage) { console.warn(`⚠️ High CPU usage: ${cpuUsage.toFixed(2)}s`); // Optional: Queue pausieren oder Worker reduzieren } } // Event Handler handleUrlAdded(url, priority) { console.log(`📋 Added URL to queue: ${url} (priority: ${priority})`); } handleUrlStarted(url) { console.log(`🚀 Started testing: ${url}`); this.options.onTestStart?.(url); } handleUrlCompleted(url, result, duration) { const status = result.passed ? '✅ PASSED' : '❌ FAILED'; console.log(`${status} ${url} (${duration}ms) - ${result.errors.length} errors, ${result.warnings.length} warnings`); this.options.onTestComplete?.(url, result); } handleUrlFailed(url, error, attempts) { console.log(`💥 Failed ${url} (attempt ${attempts}): ${error}`); this.options.onTestError?.(url, error); } handleUrlRetrying(url, attempts) { console.log(`🔄 Retrying ${url} (attempt ${attempts + 1}/${this.options.maxRetries})`); } handleQueueEmpty() { console.log('🎉 All tests completed!'); this.options.onQueueEmpty?.(); } handleProgressUpdate(stats) { if (this.options.enableProgressBar) { this.displayProgressBar(stats); } this.options.onProgressUpdate?.(stats); } handleError(error) { console.error(`❌ Queue error: ${error}`); } setupEventListeners() { // Progress-Update-Interval if (this.options.enableProgressBar) { setInterval(() => { const stats = this.queue.getStats(); this.handleProgressUpdate(stats); }, this.options.progressUpdateInterval); } } displayProgressBar(stats) { const progress = Math.round(stats.progress); const barLength = 30; const filledLength = Math.round((progress / 100) * barLength); const bar = '█'.repeat(filledLength) + '░'.repeat(barLength - filledLength); const eta = stats.estimatedTimeRemaining > 0 ? `ETA: ${Math.round(stats.estimatedTimeRemaining / 1000)}s` : ''; const memory = `Memory: ${stats.memoryUsage}MB`; const workers = `Workers: ${stats.activeWorkers}/${this.options.maxConcurrent}`; process.stdout.write(`\r🧪 Progress: [${bar}] ${progress}% | ${stats.completed}/${stats.total} | ${workers} | ${memory} | ${eta}`); if (stats.progress >= 100) { process.stdout.write('\n'); } } // Public API pause() { this.queue.pause(); console.log('⏸️ Tests paused'); } resume() { this.queue.resume(); console.log('▶️ Tests resumed'); this.startWorkers(); } stop() { this.isRunning = false; this.queue.clear(); console.log('⏹️ Tests stopped'); } getStats() { return this.queue.getStats(); } getActiveTests() { return this.activeTests.size; } getQueueSize() { return this.queue.getQueueSize(); } setMaxConcurrent(max) { this.queue.setMaxConcurrent(max); console.log(`🔧 Max concurrent workers set to ${max}`); } // Resource Management getMemoryUsage() { return process.memoryUsage().heapUsed / 1024 / 1024; } getCpuUsage() { return process.cpuUsage().user / 1000000; } // Cleanup async cleanup() { this.stop(); await this.accessibilityChecker.cleanup(); } } exports.ParallelTestManager = ParallelTestManager; //# sourceMappingURL=parallel-test-manager.js.map