@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
JavaScript
;
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