Technische Struktur und Designentscheidungen des Projekts.
Sprache: Rust (async, tokio) Größe: ~39.000 Zeilen Rust, 80+ Module Version: 0.6.3
src/
├── main.rs # CLI-Einstiegspunkt, Modus-Routing
├── lib.rs # Öffentliche API, Modul-Exports
├── error.rs # Zentrale Fehlertypen (AuditError)
├── util.rs # Hilfsfunktionen
│
├── cli/
│ ├── args.rs # Clap-Argumente (Args, WcagLevel, OutputFormat)
│ ├── config.rs # Konfigurationsdatei (auditmysite.toml)
│ └── doctor.rs # Diagnose-Werkzeug
│
├── audit/
│ ├── pipeline.rs # Kern-Audit-Pipeline (audit_page, run_single_audit)
│ ├── report.rs # AuditReport, BatchReport, PerformanceResults
│ ├── batch.rs # Parallele Stapelverarbeitung (run_concurrent_batch)
│ ├── scoring.rs # AccessibilityScorer, ViolationStatistics
│ ├── normalized.rs # Report-Normalisierung
│ ├── artifacts.rs # Artefakt-Persistenz und Caching
│ ├── history.rs # Verlauf-Tracking für Trend-Analyse
│ ├── crawl.rs # Seitenentdeckung via BFS-Crawl
│ ├── comparison.rs # Multi-Domain-Vergleich
│ ├── baseline.rs # Violation-Waivers / Baseline
│ ├── budget.rs # Performance-Budget-Prüfungen
│ ├── duplicate.rs # Near-Duplicate-Erkennung (SimHash)
│ └── summary.rs # Zusammenfassungs-Generierung
│
├── browser/
│ ├── types.rs # BrowserKind, DetectedBrowser
│ ├── detection.rs # System-Scan für Chrome/Edge/Chromium
│ ├── registry.rs # Plattformspezifische Browser-Pfade
│ ├── resolver.rs # Prioritätsbasierte Browser-Auswahl
│ ├── manager.rs # BrowserManager (Launch, CDP-Verbindung)
│ ├── pool.rs # BrowserPool (concurrent Page-Management)
│ └── installer.rs # Chrome for Testing / Headless Shell
│
├── accessibility/
│ ├── tree.rs # AXTree, AXNode, AXProperty
│ ├── extractor.rs # CDP-basierte AXTree-Extraktion
│ ├── enrichment.rs # DOM-Selektoren und HTML-Snippets
│ ├── styles.rs # CSS-Style-Extraktion
│ └── code_gen.rs # Code-Generierung
│
├── wcag/
│ ├── engine.rs # Rule-Dispatcher (check_all, RuleFilterConfig)
│ ├── types.rs # Violation, Severity, WcagResults, RuleMetadata
│ └── rules/ # 40+ WCAG-Regelimplementierungen (je eine Datei)
│ ├── mod.rs # Regel-Exports und Dispatcher-Registrierung
│ ├── text_alternatives.rs # 1.1.1
│ ├── contrast.rs # 1.4.3 (benötigt CDP)
│ ├── info_relationships.rs # 1.3.1
│ ├── keyboard.rs # 2.1.1
│ ├── language.rs # 3.1.1
│ └── ... (weitere Regelfiles)
│
├── output/
│ ├── cli.rs # Tabellen-Formatter für Terminal
│ ├── json.rs # JSON-Formatter
│ ├── report_model.rs # ViewModel (ReportViewModel und alle Blöcke)
│ ├── explanations.rs # Regel-Erklärungen (i18n)
│ ├── builder/ # Rohdaten → ViewModel
│ │ ├── mod.rs # Exports (build_view_model, build_batch_presentation)
│ │ ├── single.rs # Single-Report-Builder
│ │ ├── batch.rs # Batch-Report-Builder
│ │ ├── modules.rs # Modul-Score-Berechnungen, Lever/Context
│ │ ├── actions.rs # Maßnahmenplan (Aufwand, Priorität, Rolle)
│ │ ├── seo.rs # SEO-Aufbereitung
│ │ └── helpers.rs # Gemeinsame Hilfsfunktionen
│ └── pdf/ # PDF-Rendering via renderreport (Typst)
│ ├── mod.rs # Einstiegspunkt (generate_pdf, generate_batch_pdf)
│ ├── cover.rs # Cover-Page
│ ├── findings.rs # Findings-Sektion
│ ├── modules.rs # Modul-Übersicht und Tabellen
│ ├── detail_modules.rs # Performance, SEO, Security, Mobile-Detail
│ ├── batch.rs # Batch-Bericht-Struktur
│ ├── history.rs # Verlauf- und Methodik-Sektion
│ └── helpers.rs # Engine-Setup, i18n, Hilfsfunktionen
│
├── performance/ # Core Web Vitals, Render-Blocking, Content-Weight
├── seo/ # Meta, Headings, Schema.org, Social, Technical
├── security/ # Security-Header-Analyse
├── mobile/ # Mobile-Friendliness, UX-Heuristiken
├── ux/ # UX-Analyse (5 Dimensionen, Sättigungskurven)
│ ├── mod.rs # Modul-Exports
│ ├── analysis.rs # 5-Dimensionen-Analyse auf AXTree-Basis
│ └── scoring.rs # Sättigungskurven, Dimensions-Score, gewichteter Durchschnitt
├── journey/ # Journey-Analyse (Nutzerfluss, Seitentyp-Erkennung)
│ ├── mod.rs # Modul-Exports
│ ├── analysis.rs # 5-Dimensionen-Journey-Analyse auf AXTree-Basis
│ ├── page_intent.rs # Seitentyp-Erkennung (Shop, LeadGen, Editorial, etc.)
│ └── scoring.rs # Dimensions-Score, gewichteter Durchschnitt mit Intent-Gewichten
├── dark_mode/ # Dark-Mode-Support-Analyse
├── i18n/ # Project Fluent (.ftl), Standard-Sprache: Deutsch
└── taxonomy/ # Severity, Dimensions, IssueClass, Score-Enums
Datei: src/audit/report.rs
pub struct AuditReport {
pub url: String,
pub wcag_level: WcagLevel,
pub timestamp: DateTime<Utc>,
pub wcag_results: WcagResults,
pub score: f32, // 0–100
pub grade: String, // A–F
pub certificate: String, // SEHR GUT / GUT / SOLIDE / AUSBAUFÄHIG / UNGENÜGEND
pub statistics: ViolationStatistics,
pub nodes_analyzed: usize,
pub duration_ms: u64,
pub performance: Option<PerformanceResults>,
pub seo: Option<SeoAnalysis>,
pub security: Option<SecurityAnalysis>,
pub mobile: Option<MobileFriendliness>,
pub ux: Option<UxAnalysis>,
pub journey: Option<JourneyAnalysis>,
pub dark_mode: Option<DarkModeAnalysis>,
pub budget_violations: Vec<BudgetViolation>,
}Datei: src/wcag/types.rs
pub struct Violation {
pub rule: String, // z.B. "1.1.1"
pub rule_name: String, // z.B. "Non-text Content"
pub level: WcagLevel, // A / AA / AAA
pub severity: Severity, // Critical / High / Medium / Low
pub message: String,
pub node_id: String,
pub role: Option<String>,
pub name: Option<String>,
pub selector: Option<String>, // CSS-Selektor oder Positionshinweis
pub fix_suggestion: Option<String>,
pub html_snippet: Option<String>,
pub suggested_code: Option<String>,
pub tags: Vec<String>, // ["wcag2a", "wcag412"]
pub impact: Option<String>, // "critical" / "serious" / "moderate" / "minor"
}Datei: src/accessibility/tree.rs
pub struct AXTree {
pub nodes: HashMap<String, AXNode>,
pub root_id: Option<String>,
}
pub struct AXNode {
pub node_id: String,
pub ignored: bool,
pub role: Option<String>,
pub name: Option<String>,
pub description: Option<String>,
pub value: Option<String>,
pub properties: Vec<AXProperty>,
pub child_ids: Vec<String>,
pub parent_id: Option<String>,
pub backend_dom_node_id: Option<i64>,
}Datei: src/output/report_model.rs
Das ViewModel ist die einzige Schnittstelle zwischen Builder und Renderer. Es enthält ausschließlich aufbereitete Präsentationsdaten — keine Logik.
pub struct ReportViewModel {
pub meta: MetaBlock, // Titel, Version, Datum
pub cover: CoverBlock, // Cover-Page-Daten (Score, Zertifikat)
pub summary: SummaryBlock, // Hero-Zusammenfassung (Metriken, Empfehlung)
pub history: Option<HistoryTrendBlock>,
pub methodology: MethodologyBlock, // Scope, Methode, Einschränkungen
pub modules: ModulesBlock, // Modul-Scores (WCAG, Performance, SEO…)
pub severity: SeverityBlock, // Violations nach Schweregrad
pub findings: FindingsBlock, // Gruppierte Findings mit Kundenbeschreibung
pub module_details: ModuleDetailsBlock,
pub actions: ActionsBlock, // Maßnahmenplan mit Roadmap
pub appendix: AppendixBlock, // Technische Violation-Liste
}CLI-Args (Args)
│
├─ Browser-Erkennung (detect/find Chrome)
│ └─ Priorität: CLI --browser > Konfiguration > System-Scan > Installer
│
├─ [Einzel-Modus]
│ └─ BrowserManager::launch() → CDP-Verbindung
│ └─ audit_page(page, url, config)
│
└─ [Stapel-Modus]
└─ BrowserPool (n Pages) + FuturesUnordered (bounded Work-Queue)
└─ audit_page() je URL, max. `concurrency` gleichzeitig
audit_page():
1. AXTree-Extraktion via CDP
2. [--full] Performance-Metriken, SEO, Security, Mobile parallel
3. [--full] UX-Analyse auf AXTree (kein CDP nötig)
4. [--full] Journey-Analyse auf AXTree (kein CDP nötig)
5. wcag::check_all(&ax_tree, level) → Vec<Violation>
5. [AA/AAA] ContrastRule::check_with_page() → CDP-Styles + Kontrastberechnung
6. enrich_violations_with_page() → CSS-Selektoren, HTML-Snippets
7. AccessibilityScorer::calculate_score() → f32
8. → AuditReport
AuditReport
│
├─ [JSON] format_json_normalized() → JsonReport
├─ [Table] print_report()
└─ [PDF]
│
├─ normalize() → NormalizedReport
├─ build_view_model() → ReportViewModel
│ ├─ Violations gruppieren nach rule_id
│ ├─ Kundenbeschreibungen ableiten
│ ├─ Modul-Scores und Interpretationen berechnen
│ └─ Maßnahmenplan mit Aufwand/Priorität/Rolle erzeugen
│
└─ generate_pdf(vm, config)
├─ renderreport-Engine instanziieren (Typst)
├─ add_component() je ViewModel-Block
│ Cover → Summary → Methodology → Modules →
│ Findings → Detail-Module (inkl. UX) → Actions → Appendix
└─ Typst kompiliert → PDF-Bytes → Datei
Daten durchlaufen vier klar getrennte Ebenen — von der Rohmessung bis zur Endpräsentation.
Ebene 1: Messung / Extraktion
AXTree, CSS-Styles, HTTP-Header, Web Vitals, DOM-Größe
→ Rohdaten, keine Bewertung
Ebene 2: Befund
Violation, fehlende H1, schlechter Kontrast, leere Links
→ Technische Fakten mit Regelzuordnung (rule_id, wcag_criterion)
Ebene 3: Bewertung / Priorisierung
Severity, Score, RiskLevel, Aufwand, Rolle, Gruppencaps
→ Gewichtung, Sättigungskurven, Aggregation zu Modul-Scores
Ebene 4: Kommunikation / Storytelling
Kundenbeschreibung, Maßnahmenplan, PDF-Blöcke, Risiko-Callout
→ Aufbereitet für Entscheider, keine Implementierungsdetails
| Ebene | Dateien | Datentypen |
|---|---|---|
| 1 — Messung | accessibility/, performance/, seo/, security/, mobile/ |
AXTree, WebVitals, SeoAnalysis, SecurityAnalysis |
| 2 — Befund | wcag/types.rs, ux/analysis.rs, journey/analysis.rs |
Violation, UxIssue, FrictionPoint |
| 3 — Bewertung | audit/scoring.rs, audit/normalized.rs, ux/scoring.rs |
NormalizedFinding, ModuleScoreEntry, RiskAssessment |
| 4 — Kommunikation | output/report_model.rs, output/builder/, output/pdf/ |
ReportViewModel, FindingGroup, ActionsBlock |
Flussrichtung ist strikt: Ebene 4 liest nie direkt aus Ebene 1. Alle Berechnungen und Ableitungen finden in Ebene 3 (Builder) statt. Der PDF-Renderer in Ebene 4 transformiert nur noch das fertige ViewModel.
Dateien: src/ux/analysis.rs, src/ux/scoring.rs
Das UX-Modul analysiert die User Experience einer Seite anhand von 5 Dimensionen, vollständig auf Basis des bereits extrahierten AXTree — ohne zusätzliche CDP-Aufrufe.
| Dimension | Gewicht | Was wird geprüft |
|---|---|---|
| CTA Clarity | 30% | CTAs vorhanden, aussagekräftig benannt (DE/EN-Keywords), keine generischen Labels |
| Visual Hierarchy | 20% | H1-Präsenz, Heading-Reihenfolge, Heading-Verteilung |
| Content Clarity | 20% | Textumfang, Subheading-Dichte, Lesbarkeit |
| Trust Signals | 15% | Kontakt/Impressum/Datenschutz-Links, Vertrauenselemente |
| Cognitive Load | 15% | Link-Anzahl, interaktive Elemente, DOM-Größe |
Jede Dimension verwendet Sättigungskurven statt linearer Abzüge:
penalty = max_penalty × (1 - e^(-count / pivot))
Wenige Verstöße werden stark bestraft, weitere Verstöße desselben Typs haben abnehmenden Einfluss. Jede Dimension hat einen Group Cap, der verhindert dass ein einzelner Bereich den Gesamtscore dominiert.
UX läuft im audit_page()-Pipeline wenn --full aktiv ist. Der Score fließt mit Gewicht 15% in den overall_score ein.
Dateien: src/journey/analysis.rs, src/journey/page_intent.rs, src/journey/scoring.rs
Das Journey-Modul analysiert, wie gut eine Seite einen typischen Nutzerfluss unterstützt — vollständig auf Basis des AXTree, ohne zusätzliche CDP-Aufrufe.
| Dimension | Beschreibung |
|---|---|
| Entry Clarity | Ist der Seitenzweck sofort erkennbar? (H1, Titel, Above-the-fold-Content) |
| Orientation | Kann der Nutzer sich orientieren? (Navigation, Landmarks, Heading-Struktur) |
| Navigation | Sind Links verständlich, eindeutig und strukturiert? |
| Interaction | Können Nutzer mit Controls effektiv interagieren? (Button-Labels, Form-Labels) |
| Conversion | Kann der Nutzer das Seitenziel erreichen? (CTA-Präsenz, Dialog-Blocker, Formular-Komplexität) |
pub enum PageIntent { Shop, LeadGen, Editorial, Marketing, Corporate, Hub, Unknown }Der erkannte Seitentyp steuert die Gewichtung der Dimensionen. Ein Shop gewichtet Conversion und Trust höher, eine Editorial-Seite Content Clarity und Navigation.
Automatisch abgeleitete Reibungspunkte im Nutzerpfad, jedem Journey-Schritt zugeordnet und nach Severity priorisiert.
Journey läuft im audit_page()-Pipeline wenn --full aktiv ist. Der Score fließt mit Gewicht 10% in den overall_score ein.
Datei: src/audit/normalized.rs
Die Risikobewertung ist konzeptionell unabhängig vom Score. Ein Score von 81 kann trotzdem Risikostufe „Kritisch" tragen, wenn z.B. Level-A-Verletzungen vorliegen die unter BFSG/EAA rechtlich relevant sind.
pub enum RiskLevel { Low, Medium, High, Critical }| Bedingung | Stufe |
|---|---|
legal_flags > 0 && critical_issues > 0 |
Critical |
critical_issues >= 3 || blocking_issues >= 10 |
High |
high_issues >= 3 || critical_issues >= 1 |
Medium |
| sonst | Low |
- legal_flags: WCAG Level-A-Verletzungen mit rechtlicher Relevanz (BFSG/EAA)
- blocking_issues: Verletzungen von 4.1.2/2.1.1 (interaktive Elemente ohne Namen, fehlende Tastaturzugänglichkeit)
- critical_issues / high_issues: Violations nach Severity
Im PDF erscheint ein farbcodierter Risiko-Callout auf der Zusammenfassungsseite. Im CLI wird die Risikostufe farbig nach dem WCAG-Summary angezeigt. Im JSON liegt risk als eigenständiges Objekt im normalizedReport.
Datei: src/wcag/engine.rs
Alle Regeln werden zentral über ein Makro ausgelöst:
macro_rules! run_if_allowed {
($filter:expr, $axe_id:expr, $check_fn:expr, $results:expr, $tree:expr) => {
if $filter.should_run($axe_id) {
$results.merge($check_fn($tree));
}
};
}check_all() ruft run_level_a_rules(), run_level_aa_rules() und ggf. run_level_aaa_rules() auf. Jede Regel-Funktion erhält den AXTree und gibt Vec<Violation> zurück.
Die Kontrast-Prüfung (1.4.3) benötigt berechnete CSS-Stile und läuft asynchron direkt über CDP — sie ist nicht in den synchronen Dispatcher integriert, sondern wird separat nach check_all() aufgerufen.
- Neue Datei in
src/wcag/rules/anlegen check_*-Funktion implementieren:fn check_xyz(tree: &AXTree) -> Vec<Violation>- In
src/wcag/rules/mod.rsexportieren - In
src/wcag/engine.rsmitrun_if_allowed!registrieren
Runtime: Tokio Multi-Threaded Executor
Datei: src/browser/pool.rs
pub struct BrowserPool {
browser: BrowserManager,
pages: Arc<Mutex<VecDeque<Arc<Page>>>>,
semaphore: Arc<Semaphore>,
closed: Arc<AtomicBool>,
}- Pages werden wiederverwendet (kein Launch-Overhead je URL)
PooledPagegibt Page beim Drop automatisch zurück- Konfigurierbare Größe via
--concurrency(Standard: 3)
Datei: src/audit/batch.rs
FuturesUnorderedals bounded Work-Queue: exaktconcurrencyTasks gleichzeitig in-flight- Kein unbegrenztes
tokio::spawn()— neuer Task wird erst gestartet wenn ein laufender fertig ist - Atomarer Progress-Counter für Fortschrittsanzeige
- 2 Wiederholungsversuche je URL bei Fehler
Typ: AuditError enum
Datei: src/error.rs
Propagation: anyhow für Kontext-Ketten, thiserror für Typen
Wichtige Varianten:
ChromeNotFound— kein Browser gefundenNavigationFailed { url, reason }— Seite nicht ladbarPageLoadTimeout— Timeout überschrittenAXTreeExtractionFailed— CDP-Query fehlgeschlagenPoolTimeout / PoolExhausted— Browser-Pool-FehlerReportGenerationFailed— PDF/JSON-Generierung fehlgeschlagen
Strategie: Frühzeitige Validierung der CLI-Args; graceful Degradation bei optionalen Modulen (Performance/SEO/Security schlagen nicht den WCAG-Audit fehl).
| Crate | Zweck |
|---|---|
chromiumoxide |
Chrome DevTools Protocol |
tokio |
Async-Runtime (rt-multi-thread, sync, time, macros) |
clap |
CLI-Argumente |
serde / serde_json |
Serialisierung |
anyhow / thiserror |
Fehlerbehandlung |
reqwest |
HTTP-Client (rustls-tls) |
chrono |
Datum/Uhrzeit |
tracing |
Strukturiertes Logging |
fluent-bundle |
i18n (Project Fluent) |
renderreport |
PDF-Generierung (Typst-basiert, lokale Path-Dep) |
Nur JSON und PDF als Output-Formate — kein Output-Formatter-Trait, kein drittes Format geplant. Fokus auf wenige, hochwertige Ausgaben statt generischer Abstraktion.
renderreport als lokale Path-Dependency — renderreport ist ein eigenständiges Projekt, bereits auf crates.io veröffentlicht. Die lokale Abhängigkeit ist Entwicklungsbequemlichkeit während beide Projekte parallel weiterentwickelt werden. Wird auf Registry-Version umgestellt sobald renderreport stabil ist.
ViewModel ohne Logik — report_model.rs enthält ausschließlich Datenstrukturen. Alle Berechnungen, Gruppierungen und Ableitungen finden im Builder statt. Der PDF-Renderer transformiert nur noch.
Regelfiles je Datei — Jede WCAG-Regel lebt in einer eigenen Datei. Ermöglicht unabhängige Weiterentwicklung, einfaches Code-Review und minimale Merge-Konflikte.
Artefakt-Caching — AXTree und Metriken werden unter ~/.auditmysite/cache/{domain}/{url_hash}/v{VERSION}/ gespeichert. Die Versions-Unterverzeichnis sorgt für automatische Invalidierung bei Binary-Upgrades. FNV-1a-Hash (deterministisch über Prozesse/Plattformen) dient als Content-Fingerprint für Delta-Erkennung. --reuse-cache lädt gespeicherte Artefakte bei erneutem Audit derselben URL. --force-refresh umgeht den Cache.
Ein automatisiertes Tool auf AXTree-Basis kann nicht alles prüfen, was ein manueller WCAG-Audit abdeckt. Die folgende Übersicht macht transparent, wo die Grenzen liegen.
| Prüfung | Methode |
|---|---|
| Fehlende Alternativtexte (1.1.1) | AXTree-Analyse: img-Rollen ohne Name |
| Kontrast-Minimum (1.4.3, 1.4.11) | CDP-Styles: berechnete Farben + WCAG-Algorithmus |
| Fehlende Formular-Labels (4.1.2, 3.3.2) | AXTree: interaktive Elemente ohne Name |
| Tastaturbedienbarkeit (2.1.1) | AXTree: focusable + keyboard-Attribute |
| Heading-Hierarchie (1.3.1) | AXTree: Heading-Reihenfolge und -Ebenen |
| Sprache der Seite (3.1.1) | DOM: <html lang> Attribut |
| Landmark-Struktur | AXTree: Navigation, Main, Banner, Contentinfo |
| ARIA-Validierung | AXTree: Rollen, Attribute, Beziehungen |
| Security-Header | HTTP-Response-Header |
| Core Web Vitals | CDP Performance-Metriken |
| Prüfung | Einschränkung |
|---|---|
| CTA-Erkennung (UX) | Keyword-basiert, kann domänenspezifische CTAs übersehen |
| Trust-Signale (UX) | Link-Text-Analyse, erkennt nicht ob Zielseite existiert |
| Seitentyp / PageIntent (Journey) | Keyword-Heuristik, kann bei untypischen Seiten fehlschlagen |
| Cognitive Load | DOM-Größe als Proxy, nicht identisch mit visueller Komplexität |
| Content Clarity | Wortanzahl als Proxy, keine semantische Textqualitätsanalyse |
| SEO-Qualität | Meta-Tags und Struktur, kein Ranking-Signal |
| Prüfung | Grund |
|---|---|
| Sinnhaftigkeit von Alternativtexten | Tool erkennt Vorhandensein, nicht inhaltliche Qualität |
| Verständlichkeit von Texten (3.1.5) | Erfordert Sprachkompetenz, kein AXTree-Signal |
| Konsistente Navigation (3.2.3) | Multi-Page-Vergleich über Seitentypen nötig |
| Reihenfolge bei Tabulator (2.4.3) | DOM-Reihenfolge ≠ visuelle Reihenfolge in allen Fällen |
| Timing-abhängige Inhalte (2.2.1) | Erfordert Interaktions-Simulation |
| Audio/Video-Untertitel (1.2.x) | Medieninhalte werden nicht analysiert |
| Visuelles Design / Ästhetik | Grundsätzlich nicht automatisierbar |
| Tatsächliche Nutzerführung | Erfordert echte User-Tests |
automatisiertes Audit ≠ vollständige WCAG-Konformitätsprüfung. Das Tool deckt ca. 50–60% der prüfbaren WCAG-2.1-Kriterien automatisch ab und liefert damit eine solide Grundlage. Für eine offizielle Konformitätserklärung ist zusätzlich eine manuelle Expert:innen-Prüfung erforderlich.
| Typ | Umfang | Ausführung |
|---|---|---|
Unit-Tests (--lib) |
481+ Tests für Regeln, Scoring, Parsing, Normalisierung | cargo test --lib |
Integration-Tests (tests/) |
Report-Konsistenz, JSON-Schema-Validierung, Modul-Gewichte | cargo test |
| Schema-Tests | JSON-Output gegen docs/json-report.schema.json validiert |
CI + cargo test |
| Browser-Tests | Live-Audits gegen echte URLs (ignored by default) | cargo test -- --ignored |
- Regeln: Jede WCAG-Regel hat mindestens einen Unit-Test der prüft, ob die Regel bei einem konstruierten AXTree die erwartete Violation auslöst.
- Scoring: Sättigungskurven, Gruppencaps, Gewichtung, Grade/Certificate-Berechnung.
- Normalisierung: Score-Konsistenz zwischen AuditReport → NormalizedReport → JSON.
- Report-Konsistenz: Alle aktiven Module erscheinen in
module_scores, Gewichte summieren korrekt,overall_score= gewichteter Durchschnitt, Risk ist unabhängig vom Score. - JSON-Kontrakt: Pflichtfelder vorhanden, Taxonomie-Felder vorhanden, fix_guidance mit Code-Beispielen.
- UX/Journey: Dimensionen, Seitentyp-Erkennung, Friction-Points, Intent-Gewichte summieren auf 1.0.
- Kein Snapshot-Test für PDF-Rendering (Typst-Output ist binär)
- Keine Fixture-basierte HTML-Testseiten (AXTree wird direkt konstruiert)
- Kein Cross-Browser-Test (nur Chrome/Chromium via CDP)
- Keine Performance-Regressionstests (Laufzeit-Schwankungen in CI)
Crate: tracing mit tracing-subscriber
Alle Pipeline-Schritte loggen mit info!, warn!, debug!:
[INFO] Extracting 1247 nodes from AXTree
[INFO] Running WCAG checks at level AA...
[INFO] Found 3 contrast violations
[INFO] UX analysis: score=85, issues=2
[INFO] Journey analysis: score=72, intent=Marketing, friction_points=4
[WARN] Render-blocking analysis failed: timeout
Verbosity über --verbose / -v steuerbar. Standardmäßig nur INFO und höher.
Jeder Audit misst duration_ms (Gesamtlaufzeit pro URL). Modulspezifische Zeitmessung ist im tracing-Output sichtbar, aber noch nicht als strukturiertes Feld im Report.
| Fehlertyp | Handling |
|---|---|
| Browser-/CDP-Fehler | ChromeNotFound, PoolTimeout, PoolExhausted — Audit wird abgebrochen |
| Navigationsfehler | NavigationFailed, PageLoadTimeout — URL wird übersprungen, Retry (2x) |
| Modulfehler | warn! + None — optionale Module degradieren graceful |
| Report-Fehler | ReportGenerationFailed — nach allen Audits, nicht-fatal für Datenerfassung |
Bei Stapelverarbeitungen:
- Atomarer Progress-Counter für Fortschrittsanzeige (
[3/15]) BatchErrorsammelt fehlgeschlagene URLs mit FehlergrundCrawlDiagnosticsprotokolliert entdeckte/übersprungene/fehlgeschlagene URLs
--reuse-cache: Lädt gespeicherte Artefakte (AXTree + Metriken)--force-refresh: Ignoriert Cache vollständig- Cache-Hit/Miss ist im Debug-Log sichtbar, aber noch nicht als strukturierte Metrik im Report
auditmysite doctor prüft:
- Browser-Erkennung und -Version
- CDP-Verbindung
- Schreibrechte für Cache-/Report-Verzeichnisse
- Netzwerk-Konnektivität