@casoon/auditmysite
Version:
A comprehensive command-line tool for automated accessibility, security, performance, and SEO testing using Playwright and pa11y, based on sitemap URLs
700 lines • 32.4 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;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AccessibilityChecker = void 0;
const pa11y_1 = __importDefault(require("pa11y"));
const browser_manager_1 = require("./browser-manager");
const lighthouse_integration_1 = require("./lighthouse-integration");
const simple_queue_1 = require("./simple-queue");
const parallel_test_manager_1 = require("./parallel-test-manager");
const event_driven_queue_1 = require("./event-driven-queue");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
class AccessibilityChecker {
constructor() {
this.browserManager = null;
this.lighthouseIntegration = null;
this.testQueue = null;
this.parallelTestManager = null;
this.eventDrivenQueue = null;
}
async initialize() {
// 🆕 Browser Manager für geteilten Browser
this.browserManager = new browser_manager_1.BrowserManager({
headless: true,
port: 9222
});
await this.browserManager.initialize();
// 🆕 Lighthouse Integration
this.lighthouseIntegration = new lighthouse_integration_1.LighthouseIntegration(this.browserManager);
}
async cleanup() {
if (this.browserManager) {
await this.browserManager.cleanup();
}
}
async testPage(url, options = {}) {
if (!this.browserManager) {
throw new Error("Browser Manager not initialized");
}
const startTime = Date.now();
const page = await this.browserManager.getPage();
const result = {
url,
title: "",
imagesWithoutAlt: 0,
buttonsWithoutLabel: 0,
headingsCount: 0,
errors: [],
warnings: [],
passed: true,
duration: 0,
};
try {
if (options.verbose)
console.log(` 🔧 Configuring page...`);
// 🆕 Erweiterte Page-Konfiguration
await this.configurePage(page, options);
if (options.verbose)
console.log(` 🌐 Navigating to page...`);
await page.goto(url, {
waitUntil: options.waitUntil || "domcontentloaded",
timeout: options.timeout || 10000,
});
// 🆕 Performance-Metriken sammeln
if (options.collectPerformanceMetrics) {
if (options.verbose)
console.log(` 📊 Collecting performance metrics...`);
await this.collectPerformanceMetrics(page, result, options);
}
// Seitentitel prüfen
if (options.verbose)
console.log(` 📋 Extracting page title...`);
result.title = await page.title();
// Bilder ohne alt-Attribut
if (options.verbose)
console.log(` 🖼️ Checking images for alt attributes...`);
result.imagesWithoutAlt = await page.locator("img:not([alt])").count();
if (result.imagesWithoutAlt > 0) {
result.warnings.push(`${result.imagesWithoutAlt} images without alt attribute`);
}
// Buttons ohne aria-label
if (options.verbose)
console.log(` 🔘 Checking buttons for aria labels...`);
result.buttonsWithoutLabel = await page
.locator("button:not([aria-label])")
.filter({ hasText: "" })
.count();
if (result.buttonsWithoutLabel > 0) {
result.warnings.push(`${result.buttonsWithoutLabel} buttons without aria-label`);
}
// Überschriften-Hierarchie
if (options.verbose)
console.log(` 📝 Checking heading hierarchy...`);
result.headingsCount = await page
.locator("h1, h2, h3, h4, h5, h6")
.count();
if (result.headingsCount === 0) {
result.errors.push("No headings found");
}
// 🆕 Erweiterte Accessibility-Tests
if (options.testKeyboardNavigation) {
if (options.verbose)
console.log(` ⌨️ Testing keyboard navigation...`);
await this.testKeyboardNavigation(page, result, options);
}
if (options.testColorContrast) {
if (options.verbose)
console.log(` 🎨 Testing color contrast...`);
await this.testColorContrast(page, result, options);
}
if (options.testFocusManagement) {
if (options.verbose)
console.log(` 🎯 Testing focus management...`);
await this.testFocusManagement(page, result, options);
}
// 🆕 Screenshots
if (options.captureScreenshots) {
if (options.verbose)
console.log(` 📸 Capturing screenshots...`);
await this.captureScreenshots(page, url, result, options);
}
// pa11y Accessibility-Tests durchführen
if (options.verbose)
console.log(` 🔍 Running pa11y accessibility tests...`);
try {
// 🆕 Optimierte pa11y-Konfiguration für localhost
const pa11yResult = await (0, pa11y_1.default)(url, {
timeout: options.timeout || 15000, // Erhöht für localhost
wait: options.wait || 2000, // Länger warten für localhost
standard: options.pa11yStandard || 'WCAG2AA',
hideElements: options.hideElements || 'iframe[src*="google-analytics"], iframe[src*="doubleclick"]',
includeNotices: options.includeNotices !== false,
includeWarnings: options.includeWarnings !== false,
runners: options.runners || ['axe', 'htmlcs'],
// 🆕 Vereinfachte Chrome-Konfiguration für localhost
chromeLaunchConfig: {
...options.chromeLaunchConfig,
args: [
'--disable-web-security',
'--disable-features=VizDisplayCompositor',
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-gpu',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding'
]
},
log: options.verbose ? console : undefined,
});
// pa11y-Ergebnisse in unser Format konvertieren
pa11yResult.issues.forEach((issue) => {
// Detaillierte Issue-Informationen speichern
const detailedIssue = {
code: issue.code,
message: issue.message,
type: issue.type,
selector: issue.selector,
context: issue.context,
impact: issue.impact,
help: issue.help,
helpUrl: issue.helpUrl
};
result.pa11yIssues = result.pa11yIssues || [];
result.pa11yIssues.push(detailedIssue);
// Für Kompatibilität auch in errors/warnings
const message = `${issue.code}: ${issue.message}`;
if (issue.type === 'error') {
result.errors.push(message);
}
else if (issue.type === 'warning') {
result.warnings.push(message);
}
else if (issue.type === 'notice') {
result.warnings.push(`Notice: ${message}`);
}
});
// Zusätzliche pa11y-Metriken
if (pa11yResult.documentTitle) {
result.title = pa11yResult.documentTitle;
}
// pa11y Score berechnen
if (pa11yResult.issues.length > 0) {
const totalIssues = pa11yResult.issues.length;
const errorIssues = pa11yResult.issues.filter(issue => issue.type === 'error').length;
result.pa11yScore = Math.max(0, 100 - (errorIssues * 10) - (totalIssues - errorIssues) * 2);
}
else {
result.pa11yScore = 100;
}
}
catch (pa11yError) {
// 🆕 Bessere Fehlerbehandlung für pa11y
const errorMessage = pa11yError instanceof Error ? pa11yError.message : String(pa11yError);
// Timeout-Fehler speziell behandeln
if (errorMessage.includes('timeout') || errorMessage.includes('Timeout')) {
if (options.verbose) {
console.log(` ⚠️ pa11y timeout for ${url} - skipping pa11y tests`);
}
// Timeout-Fehler nicht als Warning hinzufügen, da sie auf localhost normal sind
}
else {
// Andere pa11y-Fehler als Warning hinzufügen
result.warnings.push(`pa11y test failed: ${errorMessage}`);
}
}
// 🆕 Lighthouse Tests durchführen (mit geteiltem Browser)
if (options.lighthouse) {
if (options.verbose)
console.log(` �� Running Lighthouse tests...`);
try {
const lighthouseResult = await this.lighthouseIntegration.runLighthouse(url);
// Lighthouse-Ergebnisse speichern
result.lighthouseScores = {
performance: lighthouseResult.performance,
accessibility: lighthouseResult.accessibility,
bestPractices: lighthouseResult.bestPractices,
seo: lighthouseResult.seo
};
result.lighthouseMetrics = lighthouseResult.metrics;
if (options.verbose) {
console.log(` 📊 Lighthouse Scores: P:${lighthouseResult.performance} A:${lighthouseResult.accessibility} BP:${lighthouseResult.bestPractices} SEO:${lighthouseResult.seo}`);
}
}
catch (lighthouseError) {
result.warnings.push(`Lighthouse test failed: ${lighthouseError}`);
}
}
// Prüfe auf kritische Fehler
if (result.errors.length > 0) {
result.passed = false;
}
}
catch (error) {
result.errors.push(`Navigation error: ${error}`);
result.passed = false;
}
finally {
await page.close();
result.duration = Date.now() - startTime;
}
return result;
}
async testMultiplePages(urls, options = {}) {
const results = [];
const maxPages = options.maxPages || urls.length;
const pagesToTest = urls.slice(0, maxPages);
// Einfache Queue erstellen
this.testQueue = new simple_queue_1.SimpleQueue({
maxRetries: 3,
maxConcurrent: 1,
priorityPatterns: [
{ pattern: '/home', priority: 1 },
{ pattern: '/', priority: 2 },
{ pattern: '/about', priority: 3 },
{ pattern: '/contact', priority: 3 },
{ pattern: '/blog', priority: 4 },
{ pattern: '/products', priority: 4 }
]
});
// URLs zur Queue hinzufügen
this.testQueue.addUrls(pagesToTest);
console.log(`🧪 Testing ${pagesToTest.length} pages using queue system...`);
this.testQueue.showStats();
let completedCount = 0;
const maxAttempts = pagesToTest.length * 3; // Sicherheitsgrenze
let attempts = 0;
while (completedCount < pagesToTest.length && attempts < maxAttempts) {
attempts++;
// Nächste URL aus der Queue holen
const queuedUrl = this.testQueue.getNextUrl();
if (!queuedUrl) {
// Keine URLs mehr in der Queue
break;
}
const startTime = Date.now();
console.log(`\n📄 Testing page ${completedCount + 1}/${pagesToTest.length}: ${queuedUrl.url}`);
console.log(` ⏱️ Starting test (attempt ${queuedUrl.attempts})...`);
try {
const result = await this.testPage(queuedUrl.url, options);
const duration = Date.now() - startTime;
result.duration = duration;
results.push(result);
// URL als abgeschlossen markieren
this.testQueue.markCompleted(queuedUrl.url, result);
completedCount++;
console.log(` ✅ Test completed in ${duration}ms`);
if (result.passed) {
console.log(` 🎯 Result: PASSED (${result.errors.length} errors, ${result.warnings.length} warnings)`);
}
else {
console.log(` 🎯 Result: FAILED (${result.errors.length} errors, ${result.warnings.length} warnings)`);
}
// Status alle 5 URLs anzeigen
if (completedCount % 5 === 0) {
this.testQueue.showStats();
}
}
catch (error) {
const duration = Date.now() - startTime;
console.error(` 💥 Error testing page after ${duration}ms: ${error}`);
// URL als fehlgeschlagen markieren
this.testQueue.markFailed(queuedUrl.url, String(error));
// Error-Result erstellen
const errorResult = {
url: queuedUrl.url,
title: "",
imagesWithoutAlt: 0,
buttonsWithoutLabel: 0,
headingsCount: 0,
errors: [`Test failed: ${error}`],
warnings: [],
passed: false,
duration,
};
results.push(errorResult);
completedCount++;
}
}
// Finale Statistiken anzeigen
console.log('\n📊 Final Queue Statistics:');
this.testQueue.showStats();
return results;
}
/**
* 🚀 Parallele Accessibility-Tests mit Event-Driven Queue
*
* Diese Methode verwendet das Event-Driven Queue System für parallele Tests
* mit Echtzeit-Status-Reporting und Resource-Monitoring.
*/
async testMultiplePagesParallel(urls, options = {}) {
const maxPages = options.maxPages || urls.length;
const pagesToTest = urls.slice(0, maxPages);
// Parallele Test-Optionen
const parallelOptions = {
maxConcurrent: options.maxConcurrent || 3,
maxRetries: options.maxRetries || 3,
retryDelay: options.retryDelay || 2000,
enableProgressBar: options.enableProgressBar !== false,
progressUpdateInterval: options.progressUpdateInterval || 1000,
enableResourceMonitoring: options.enableResourceMonitoring !== false,
maxMemoryUsage: options.maxMemoryUsage || 512,
maxCpuUsage: options.maxCpuUsage || 80,
testOptions: options,
eventCallbacks: {
onUrlStarted: (url) => {
if (options.verbose) {
console.log(`🚀 Starting parallel test: ${url}`);
}
},
onUrlCompleted: (url, result, duration) => {
const status = result.passed ? '✅ PASSED' : '❌ FAILED';
console.log(`${status} ${url} (${duration}ms) - ${result.errors.length} errors, ${result.warnings.length} warnings`);
},
onUrlFailed: (url, error, attempts) => {
console.error(`💥 Error testing ${url} (attempt ${attempts}): ${error}`);
},
onProgressUpdate: (stats) => {
if (options.verbose) {
console.log(`📊 Progress: ${stats.progress.toFixed(1)}% | Workers: ${stats.activeWorkers}/${options.maxConcurrent || 3} | Memory: ${stats.memoryUsage}MB`);
}
},
onQueueEmpty: () => {
console.log('🎉 All parallel tests completed!');
}
}
};
// Parallel Test Manager initialisieren
this.parallelTestManager = new parallel_test_manager_1.ParallelTestManager(parallelOptions);
try {
console.log(`🚀 Starting parallel accessibility tests for ${pagesToTest.length} pages with ${parallelOptions.maxConcurrent} workers`);
console.log(`⚙️ Configuration: maxRetries=${parallelOptions.maxRetries}, retryDelay=${parallelOptions.retryDelay}ms`);
// Manager initialisieren
await this.parallelTestManager.initialize();
// Tests ausführen
const startTime = Date.now();
const result = await this.parallelTestManager.runTests(pagesToTest);
const totalDuration = Date.now() - startTime;
// Ergebnisse ausgeben
console.log('\n📋 Parallel Test Results Summary:');
console.log('==================================');
console.log(`⏱️ Total Duration: ${totalDuration}ms`);
console.log(`📄 URLs Tested: ${result.results.length}`);
console.log(`✅ Successful: ${result.results.filter(r => r.passed).length}`);
console.log(`❌ Failed: ${result.results.filter(r => !r.passed).length}`);
console.log(`💥 Errors: ${result.errors.length}`);
// Performance-Metriken
const avgTimePerUrl = totalDuration / pagesToTest.length;
const speedup = avgTimePerUrl > 0 ? (avgTimePerUrl * pagesToTest.length) / totalDuration : 0;
console.log('\n🚀 Performance Metrics:');
console.log('======================');
console.log(`Average time per URL: ${avgTimePerUrl.toFixed(0)}ms`);
console.log(`Speedup factor: ${speedup.toFixed(1)}x`);
console.log(`Throughput: ${(pagesToTest.length / (totalDuration / 1000)).toFixed(1)} URLs/second`);
// Detaillierte Statistiken
console.log('\n📊 Queue Statistics:');
console.log('===================');
console.log(`Total: ${result.stats.total}`);
console.log(`Completed: ${result.stats.completed}`);
console.log(`Failed: ${result.stats.failed}`);
console.log(`Retrying: ${result.stats.retrying}`);
console.log(`Progress: ${result.stats.progress.toFixed(1)}%`);
console.log(`Average Duration: ${result.stats.averageDuration}ms`);
console.log(`Memory Usage: ${result.stats.memoryUsage}MB`);
console.log(`CPU Usage: ${result.stats.cpuUsage}s`);
// Fehler-Details
if (result.errors.length > 0) {
console.log('\n❌ Failed URLs:');
console.log('===============');
result.errors.forEach((error, index) => {
console.log(`${index + 1}. ${error.url} (${error.attempts} attempts): ${error.error}`);
});
}
return result.results;
}
catch (error) {
console.error('❌ Parallel test execution failed:', error);
throw error;
}
finally {
// Cleanup
if (this.parallelTestManager) {
await this.parallelTestManager.cleanup();
this.parallelTestManager = null;
}
}
}
/**
* 🚀 Integrierte Queue-Verarbeitung mit kurzen Status-Updates
* Diese Methode nutzt die Event-Driven Queue direkt für maximale Effizienz
*/
async testMultiplePagesWithQueue(urls, options = {}) {
console.log(`🚀 Starte integrierte Queue-Verarbeitung für ${urls.length} URLs`);
// Initialisiere Browser
if (!this.browserManager) {
this.browserManager = new browser_manager_1.BrowserManager({
headless: true,
port: 9222
});
await this.browserManager.initialize();
}
// Erstelle Event-Driven Queue
this.eventDrivenQueue = new event_driven_queue_1.EventDrivenQueue({
maxConcurrent: options.maxConcurrent || 3,
maxRetries: options.maxRetries || 3,
retryDelay: options.retryDelay || 2000,
enableShortStatus: true,
statusUpdateInterval: 2000,
eventCallbacks: {
onShortStatus: (status) => {
// Überschreibe die aktuelle Zeile mit dem Status
process.stdout.write(`\r${status}`);
},
onUrlCompleted: (url, result, duration) => {
const shortUrl = url.split('/').pop() || url;
console.log(`\n✅ ${shortUrl} (${duration}ms)`);
},
onUrlFailed: (url, error, attempts) => {
const shortUrl = url.split('/').pop() || url;
console.log(`\n❌ ${shortUrl} (Versuch ${attempts})`);
}
}
});
// Definiere den Processor für jede URL
const processOptions = {
processor: async (url) => {
return await this.testPage(url, options);
},
onResult: (url, result) => {
// Optional: Zusätzliche Verarbeitung nach erfolgreichem Test
},
onError: (url, error) => {
console.error(`\n💥 Fehler bei ${url}: ${error}`);
}
};
try {
// Verarbeite alle URLs mit der Queue
const results = await this.eventDrivenQueue.processUrls(urls, processOptions);
console.log(`\n🎉 Queue-Verarbeitung abgeschlossen!`);
console.log(`📊 Ergebnisse: ${results.length} URLs getestet`);
return results;
}
finally {
// Cleanup
this.eventDrivenQueue = null;
}
}
// 🆕 Erweiterte Page-Konfiguration
async configurePage(page, options) {
// Viewport-Konfiguration
const viewportSize = options.viewportSize || { width: 1920, height: 1080 };
await page.setViewportSize(viewportSize);
// User-Agent setzen (Standard: auditmysite)
const userAgent = options.userAgent || 'auditmysite/1.0 (+https://github.com/casoon/AuditMySite)';
await page.setExtraHTTPHeaders({
'User-Agent': userAgent
});
// Network-Interception für Performance
if (options.blockImages) {
await page.route('**/*.{png,jpg,jpeg,gif,svg,webp}', route => {
route.abort();
});
}
if (options.blockCSS) {
await page.route('**/*.css', route => {
route.abort();
});
}
// Console-Logging
page.on('console', msg => {
if (options.verbose) {
console.log(`Browser Console: ${msg.text()}`);
}
});
// Error-Handling
page.on('pageerror', error => {
if (options.verbose) {
console.log(`JavaScript Error: ${error.message}`);
}
});
}
// 🆕 Performance-Metriken sammeln
async collectPerformanceMetrics(page, result, options) {
try {
const metrics = await page.evaluate(() => {
const navigation = performance.getEntriesByType('navigation')[0];
return {
loadTime: navigation.loadEventEnd - navigation.loadEventStart,
domContentLoaded: navigation.domContentLoadedEventEnd - navigation.domContentLoadedEventStart,
firstPaint: performance.getEntriesByName('first-paint')[0]?.startTime || 0,
firstContentfulPaint: performance.getEntriesByName('first-contentful-paint')[0]?.startTime || 0,
largestContentfulPaint: performance.getEntriesByName('largest-contentful-paint')[0]?.startTime || 0
};
});
result.performanceMetrics = metrics;
// Performance-Warnungen
if (metrics.loadTime > 3000) {
result.warnings.push(`Slow page load: ${Math.round(metrics.loadTime)}ms`);
}
}
catch (error) {
if (options.verbose) {
console.log(`Performance metrics collection failed: ${error}`);
}
}
}
// 🆕 Keyboard Navigation Test
async testKeyboardNavigation(page, result, options) {
try {
const keyboardNavigation = await page.evaluate(() => {
const focusableElements = document.querySelectorAll('button, input, select, textarea, a[href], [tabindex]:not([tabindex="-1"])');
const navigation = [];
// Simuliere Tab-Navigation für die ersten 10 Elemente
for (let i = 0; i < Math.min(focusableElements.length, 10); i++) {
const element = focusableElements[i];
navigation.push(`${element.tagName.toLowerCase()}: ${element.textContent?.trim().substring(0, 50) || element.outerHTML}`);
}
return navigation;
});
result.keyboardNavigation = keyboardNavigation;
}
catch (error) {
if (options.verbose) {
console.log(`Keyboard navigation test failed: ${error}`);
}
}
}
// 🆕 Color Contrast Test (vereinfacht)
async testColorContrast(page, result, options) {
try {
const contrastIssues = await page.evaluate(() => {
const elements = document.querySelectorAll('p, span, div, h1, h2, h3, h4, h5, h6, a, button, input, label');
const issues = [];
elements.forEach(el => {
const style = window.getComputedStyle(el);
const color = style.color;
const backgroundColor = style.backgroundColor;
// Einfache Kontrast-Prüfung (vereinfacht)
if (color && backgroundColor &&
color !== backgroundColor &&
color !== 'rgba(0, 0, 0, 0)' &&
backgroundColor !== 'rgba(0, 0, 0, 0)') {
issues.push(`${el.tagName}: ${color} on ${backgroundColor}`);
}
});
return issues.slice(0, 10); // Limitiere auf 10 Issues
});
if (contrastIssues.length > 0) {
result.colorContrastIssues = contrastIssues;
result.warnings.push(`${contrastIssues.length} potential color contrast issues found`);
}
}
catch (error) {
if (options.verbose) {
console.log(`Color contrast test failed: ${error}`);
}
}
}
// 🆕 Focus Management Test
async testFocusManagement(page, result, options) {
try {
const focusIssues = await page.evaluate(() => {
const issues = [];
// Prüfe auf focus-visible
const focusableElements = document.querySelectorAll('button, input, select, textarea, a[href]');
focusableElements.forEach(el => {
const style = window.getComputedStyle(el);
if (style.outline === 'none' &&
style.border === 'none' &&
!el.classList.contains('focus-visible') &&
!el.classList.contains('focus')) {
issues.push(`Element without focus indicator: ${el.tagName} - ${el.textContent?.trim().substring(0, 30) || 'no text'}`);
}
});
return issues.slice(0, 10); // Limitiere auf 10 Issues
});
if (focusIssues.length > 0) {
result.focusManagementIssues = focusIssues;
result.warnings.push(`${focusIssues.length} focus management issues found`);
}
}
catch (error) {
if (options.verbose) {
console.log(`Focus management test failed: ${error}`);
}
}
}
// 🆕 Screenshot-Funktionalität
async captureScreenshots(page, url, result, options) {
try {
// Screenshots-Ordner erstellen
const screenshotsDir = './screenshots';
if (!fs.existsSync(screenshotsDir)) {
fs.mkdirSync(screenshotsDir, { recursive: true });
}
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const domain = new URL(url).hostname.replace(/\./g, '-');
// Desktop Screenshot
const desktopPath = path.join(screenshotsDir, `${domain}-desktop-${timestamp}.png`);
await page.screenshot({
path: desktopPath,
fullPage: true
});
result.screenshots = { desktop: desktopPath };
// Mobile Screenshot
await page.setViewportSize({ width: 375, height: 667 });
const mobilePath = path.join(screenshotsDir, `${domain}-mobile-${timestamp}.png`);
await page.screenshot({
path: mobilePath,
fullPage: true
});
result.screenshots.mobile = mobilePath;
// Reset viewport
await page.setViewportSize({ width: 1920, height: 1080 });
}
catch (error) {
if (options.verbose) {
console.log(`Screenshot capture failed: ${error}`);
}
}
}
}
exports.AccessibilityChecker = AccessibilityChecker;
//# sourceMappingURL=accessibility-checker.js.map