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

306 lines 15.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.StandardPipeline = void 0; const parsers_1 = require("../parsers"); const accessibility_checker_1 = require("./accessibility-checker"); const generators_1 = require("../generators"); const reports_1 = require("../reports"); const html_report_generator_1 = require("../reports/html-report-generator"); const security_scanner_1 = require("./security-scanner"); const path = __importStar(require("path")); class StandardPipeline { /** * Führt die Standard-Pipeline aus und erstellt KI-freundliche Output-Dateien */ async run(options) { const outputDir = options.outputDir || './reports'; const dateOnly = new Date().toISOString().split('T')[0]; // Nur Datum, kein Timestamp // Parser initialisieren const parser = new parsers_1.SitemapParser(); // Sitemap parsen const urls = await parser.parseSitemap(options.sitemapUrl); console.log(`📄 Sitemap geladen: ${urls.length} URLs gefunden`); // URLs filtern const filterPatterns = ['[...slug]', '[category]', '/demo/']; const filteredUrls = parser.filterUrls(urls, { filterPatterns }); console.log(`🔍 URLs gefiltert: ${filteredUrls.length} URLs zum Testen`); // URLs zu lokalen URLs konvertieren const baseUrl = new URL(options.sitemapUrl).origin; const localUrls = parser.convertToLocalUrls(filteredUrls, baseUrl); // 🆕 WICHTIG: URLs auf maxPages begrenzen const maxPages = options.maxPages || 20; const limitedUrls = localUrls.slice(0, maxPages); console.log(`📋 URLs auf ${maxPages} begrenzt: ${limitedUrls.length} URLs werden getestet`); // Accessibility-Checker initialisieren const checker = new accessibility_checker_1.AccessibilityChecker(); await checker.initialize(); console.log('🧪 Führe Accessibility-Tests aus...'); console.log(` 📊 Performance-Metriken sammeln: ${options.collectPerformanceMetrics ? 'Ja' : 'Nein'}`); console.log(` 📸 Screenshots aufnehmen: ${options.captureScreenshots ? 'Ja' : 'Nein'}`); console.log(` ⌨️ Tastaturnavigation testen: ${options.testKeyboardNavigation ? 'Ja' : 'Nein'}`); console.log(` 🎨 Farbkontrast testen: ${options.testColorContrast ? 'Ja' : 'Nein'}`); console.log(` 🎯 Fokus-Management testen: ${options.testFocusManagement ? 'Ja' : 'Nein'}`); console.log(` 🚀 Parallele Tests: ${options.useSequentialTesting ? 'Nein' : 'Ja'}`); if (options.useSequentialTesting) { console.log(` 📋 Verwende sequenzielle Tests (Legacy-Modus)...`); } else { console.log(` 🔧 Parallele Worker: ${options.maxConcurrent || 3}`); console.log(` 🔄 Max. Wiederholungen: ${options.maxRetries || 3}`); console.log(` ⏱️ Wiederholungsverzögerung: ${options.retryDelay || 2000}ms`); } // Tests ausführen const testOptions = { maxPages: maxPages, timeout: options.timeout || 10000, waitUntil: 'domcontentloaded', pa11yStandard: options.pa11yStandard || 'WCAG2AA', hideElements: options.hideElements, includeNotices: options.includeNotices, includeWarnings: options.includeWarnings, wait: options.wait, // 🆕 Neue Playwright-Optionen collectPerformanceMetrics: options.collectPerformanceMetrics, captureScreenshots: options.captureScreenshots, testKeyboardNavigation: options.testKeyboardNavigation, testColorContrast: options.testColorContrast, testFocusManagement: options.testFocusManagement, blockImages: options.blockImages, blockCSS: options.blockCSS, mobileEmulation: options.mobileEmulation, viewportSize: options.viewportSize, userAgent: options.userAgent, // 🚀 Parallele Test-Optionen useParallelTesting: !options.useSequentialTesting, // Keep this for compatibility, but it's now the default maxConcurrent: options.maxConcurrent, maxRetries: options.maxRetries, retryDelay: options.retryDelay, enableProgressBar: options.enableProgressBar, progressUpdateInterval: options.progressUpdateInterval, enableResourceMonitoring: options.enableResourceMonitoring, maxMemoryUsage: options.maxMemoryUsage, maxCpuUsage: options.maxCpuUsage }; // Wähle zwischen Queue (Standard) und sequenzieller Verarbeitung let results; if (options.useSequentialTesting) { console.log('📋 Verwende sequenzielle Tests (Legacy-Modus)...'); results = await checker.testMultiplePages(limitedUrls.map(url => url.loc), testOptions); } else { console.log('🚀 Verwende integrierte Queue-Verarbeitung mit kurzen Status-Updates (Standard)...'); results = await checker.testMultiplePagesWithQueue(limitedUrls.map(url => url.loc), testOptions); } console.log('\n📋 Erstelle Test-Zusammenfassung...'); // Zusammenfassung erstellen const summary = { totalPages: limitedUrls.length, // 🆕 Verwende limitedUrls statt localUrls testedPages: results.length, passedPages: results.filter(r => r.passed).length, failedPages: results.filter(r => !r.passed).length, totalErrors: results.reduce((sum, r) => sum + r.errors.length, 0), totalWarnings: results.reduce((sum, r) => sum + r.warnings.length, 0), totalDuration: results.reduce((sum, r) => sum + r.duration, 0), results }; await checker.cleanup(); console.log('📄 Generiere Ausgabedateien...'); // Output-Dateien generieren const outputGenerator = new generators_1.OutputGenerator(); const outputFiles = []; // Wähle zwischen Markdown und HTML Output if (options.outputFormat === 'html') { console.log(' 🌐 Generiere HTML-Bericht...'); const htmlReportGenerator = new html_report_generator_1.HtmlReportGenerator(); const htmlReportPath = await htmlReportGenerator.generateHtmlReport(summary, { outputDir: options.outputDir, includeCopyButtons: options.includeCopyButtons !== false }); outputFiles.push(htmlReportPath); } else { // Markdown für Menschen (Standard) - ohne Domain im Dateinamen const mdOutputPath = path.join(outputDir, `accessibility-report-${dateOnly}.md`); await outputGenerator.generateOutput(summary, { format: 'markdown', outputFile: mdOutputPath, includeDetails: options.includeDetails || true, includePa11yIssues: options.includePa11yIssues || false, summaryOnly: false }); outputFiles.push(mdOutputPath); } // Detailed-Report generieren (falls gewünscht) if (options.generateDetailedReport !== false && (summary.totalErrors > 0 || summary.totalWarnings > 0)) { console.log(' 📋 Generiere detaillierten Fehlerbericht...'); const detailedReportGenerator = new reports_1.DetailedReportGenerator(); const detailedReportPath = await detailedReportGenerator.generateDetailedReport(summary, { outputDir: options.outputDir, includeContext: true, includeRecommendations: true, groupByType: true, includeCodeExamples: true }); outputFiles.push(detailedReportPath); } // Performance-Report generieren (falls gewünscht) if (options.generatePerformanceReport !== false && options.collectPerformanceMetrics) { console.log(' 📊 Generiere Performance-Bericht...'); const performanceReportGenerator = new reports_1.PerformanceReportGenerator(); const performanceReportPath = await performanceReportGenerator.generatePerformanceReport(summary, { outputDir: options.outputDir, includeRecommendations: true, includePageDetails: true, includeCoreWebVitals: true, includeResourceAnalysis: true }); outputFiles.push(performanceReportPath); } // SEO-Report generieren (falls gewünscht) if (options.generateSeoReport !== false) { console.log(' 🔍 Generiere SEO-Bericht...'); const seoReportGenerator = new reports_1.SeoReportGenerator(); const seoReportPath = await seoReportGenerator.generateSeoReport(summary, { outputDir: options.outputDir, includeRecommendations: true, includePageDetails: true, includeTechnicalAnalysis: true, includeContentAnalysis: true }); outputFiles.push(seoReportPath); } // Security-Report generieren (falls gewünscht) if (options.generateSecurityReport !== false) { console.log(' 🔒 Führe Security-Scan durch und generiere Security-Bericht...'); // Security Scanner initialisieren const securityScanner = new security_scanner_1.SecurityScanner(); // Security-Scan für die erste URL durchführen (als Beispiel) if (limitedUrls.length > 0) { const firstUrl = limitedUrls[0].loc; console.log(` 🔍 Scanne ${firstUrl} auf Sicherheitslücken...`); // Browser-Instanz für Security-Scan erstellen const { chromium } = require('playwright'); const browser = await chromium.launch({ headless: true }); const page = await browser.newPage(); try { const securityScanResult = await securityScanner.scanPage(page, firstUrl, { skipCspForLocalhost: options.skipCspForLocalhost || false }); // Security-Report generieren - ohne Domain im Dateinamen const securityReportGenerator = new reports_1.SecurityReportGenerator(); if (options.outputFormat === 'html') { const securityHtmlPath = path.join(outputDir, `security-report-${dateOnly}.html`); await securityReportGenerator.generateHtmlReport(securityScanResult, securityHtmlPath); outputFiles.push(securityHtmlPath); } else { const securityMdPath = path.join(outputDir, `security-report-${dateOnly}.md`); await securityReportGenerator.generateMarkdownReport(securityScanResult, securityMdPath); outputFiles.push(securityMdPath); } console.log(` ✅ Security-Scan abgeschlossen mit Score: ${securityScanResult.overallScore}/100`); } catch (error) { console.error(' ❌ Security-Scan fehlgeschlagen:', error); } finally { await browser.close(); } } } return { summary, outputFiles }; } /** * Führt eine schnelle Pipeline nur mit Markdown-Output aus */ async runQuick(options) { const outputDir = options.outputDir || './reports'; const dateOnly = new Date().toISOString().split('T')[0]; // Nur Datum, kein Timestamp // Parser initialisieren const parser = new parsers_1.SitemapParser(); // Sitemap parsen const urls = await parser.parseSitemap(options.sitemapUrl); // URLs filtern const filterPatterns = ['[...slug]', '[category]', '/demo/']; const filteredUrls = parser.filterUrls(urls, { filterPatterns }); // URLs zu lokalen URLs konvertieren const baseUrl = new URL(options.sitemapUrl).origin; const localUrls = parser.convertToLocalUrls(filteredUrls, baseUrl); // 🆕 WICHTIG: URLs auf maxPages begrenzen const maxPages = options.maxPages || 20; const limitedUrls = localUrls.slice(0, maxPages); // Accessibility-Checker initialisieren const checker = new accessibility_checker_1.AccessibilityChecker(); await checker.initialize(); // Tests ausführen const testOptions = { maxPages: maxPages, timeout: options.timeout || 10000, waitUntil: 'domcontentloaded', pa11yStandard: options.pa11yStandard || 'WCAG2AA', hideElements: options.hideElements, includeNotices: options.includeNotices, includeWarnings: options.includeWarnings, wait: options.wait }; const results = await checker.testMultiplePages(limitedUrls.map(url => url.loc), testOptions); // Zusammenfassung erstellen const summary = { totalPages: limitedUrls.length, testedPages: results.length, passedPages: results.filter(r => r.passed).length, failedPages: results.filter(r => !r.passed).length, totalErrors: results.reduce((sum, r) => sum + r.errors.length, 0), totalWarnings: results.reduce((sum, r) => sum + r.warnings.length, 0), totalDuration: results.reduce((sum, r) => sum + r.duration, 0), results }; await checker.cleanup(); // Markdown-Output generieren - ohne Domain im Dateinamen const outputGenerator = new generators_1.OutputGenerator(); const markdownFile = path.join(outputDir, `accessibility-report-${dateOnly}.md`); await outputGenerator.generateOutput(summary, { format: 'markdown', outputFile: markdownFile, includeDetails: options.includeDetails || true, includePa11yIssues: options.includePa11yIssues || false, summaryOnly: false }); return { summary, markdownFile }; } } exports.StandardPipeline = StandardPipeline; //# sourceMappingURL=standard-pipeline.js.map