Zum Hauptinhalt springen

Für Entwickler

Barrierefreiheitsprüfung in Ihrer CI

Prüfen Sie die wichtigsten Seiten jedes Preview-Deployments mit derselben Engine, die Ihre Live-Website überwacht, und stoppen Sie einen Pull Request, der schwere Barrieren einbauen würde, bevor er live geht.

Enthalten in den Paketen Growth (500 geprüfte Seiten pro Monat) und Agency (2.000).

So funktioniert es

  1. 01

    Schlüssel anlegen

    Im Tab API & CI Ihres Dashboards. Speichern Sie ihn als Secret in Ihrer CI, zum Beispiel als EQUALVIA_API_KEY.

  2. 02

    Einen Schritt ergänzen

    Führen Sie nach dem Preview-Deployment unser Skript mit bis zu 10 Seiten-URLs aus. Keine Abhängigkeiten, Node 18 oder neuer.

  3. 03

    Ergebnis erhalten

    Der Job schlägt bei Fehlern ab dem gewählten Schweregrad fehl und listet jeden mit Element und WCAG-Kriterium auf.

CI einrichten

Das Skript (/ci/equalvia-check.mjs) startet eine Prüfung, wartet auf das Ergebnis und gibt es aus. In GitHub Actions setzt es außerdem Fehler-Annotationen und eine Tabelle in die Job-Zusammenfassung.

GitHub Actions: nach jedem erfolgreichen Preview-Deployment

# .github/workflows/accessibility.yml
name: Accessibility
on: deployment_status

jobs:
  equalvia:
    if: github.event.deployment_status.state == 'success'
    runs-on: ubuntu-latest
    steps:
      - name: EqualVia accessibility check
        env:
          EQUALVIA_API_KEY: ${{ secrets.EQUALVIA_API_KEY }}
          URL: ${{ github.event.deployment_status.target_url }}
        run: |
          curl -fsSL https://equalvia.com/ci/equalvia-check.mjs -o equalvia-check.mjs
          node equalvia-check.mjs "$URL/" "$URL/pricing" "$URL/contact" --fail-on serious

Vercel, Netlify und die meisten Hoster melden Preview-Deployments an GitHub, und genau darauf hört der Trigger deployment_status. Sie möchten eine feste Version des Skripts? Legen Sie eine eigene Kopie ins Repository, statt es bei jedem Lauf herunterzuladen.

GitLab CI: nach dem Job, der die Review-App deployt

# .gitlab-ci.yml (after the job that deploys the review app)
accessibility:
  stage: test
  image: node:20
  variables:
    EQUALVIA_URLS: "$CI_ENVIRONMENT_URL/ $CI_ENVIRONMENT_URL/pricing"
  script:
    - curl -fsSL https://equalvia.com/ci/equalvia-check.mjs -o equalvia-check.mjs
    - node equalvia-check.mjs --fail-on serious

Jede andere CI (Bitbucket, CircleCI, Jenkins, Azure DevOps) funktioniert genauso: Skript herunterladen und mit Node ausführen.

Optionen des Skripts

OptionWirkung
<url> …Zu prüfende Seiten, bis zu 10. Alternativ EQUALVIA_URLS setzen (durch Leerzeichen getrennt).
--fail-on <level>Niedrigster Schweregrad, bei dem der Job fehlschlägt: critical, serious (Standard), moderate, minor oder none (nur berichten).
--baseline <siteId>Es zählen nur Fehler, die der letzte Scan dieser überwachten Website noch nicht hat. Siehe unten.
--label <text>Wird in der Prüfliste im Dashboard angezeigt. Standard: Branch und Commit aus den Variablen der CI.
--locale <en|hu|de>Sprache der Fehlertitel. Standard: die Ihres Kontos.
--timeout <seconds>Wie lange auf das Ergebnis gewartet wird. Standard: 300.
--jsonGibt das Rohergebnis als JSON statt der Zusammenfassung aus.

Exit-Codes

CodeBedeutung
0Bestanden.
1Nicht bestanden: Fehler ab dem Schwellenwert oder eine Seite, die nicht geprüft werden konnte.
2Die Prüfung konnte nicht laufen: Schlüssel fehlt oder ist widerrufen, Paket, Kontingent aufgebraucht, Netzwerk.

Nur neue Fehler

Kaum eine Website startet mit null Fehlern, und eine CI-Prüfung, die bei jedem Lauf fehlschlägt, wird abgeschaltet. Mit einer Baseline werden die Fehler einer Seite mit derselben Seite im letzten Scan Ihrer überwachten Website verglichen (über den Pfad, sodass eine Preview-URL ihr Live-Gegenstück findet), und nur die noch nicht vorhandenen zählen. Regeln, die Sie für die Website ignoriert haben, werden ebenfalls übersprungen. Die Website-IDs finden Sie im Tab API & CI des Dashboards oder über GET /api/v1/sites.

node equalvia-check.mjs "$URL/" "$URL/pricing" --fail-on serious --baseline SITE_ID

Gut zu wissen

  • Die Seiten müssen aus dem Internet erreichbar sein, denn unsere Server laden sie. Für eine geschützte Preview nutzen Sie eine öffentliche Staging-URL oder die Bypass-Option Ihres Hosters (bei Vercel den Query-Parameter für Protection Bypass; die URL wird mit der Prüfung gespeichert).
  • Jede URL einer Prüfung verbraucht eine Seite des Monatskontingents, unabhängig vom Ergebnis. Das Kontingent beginnt zu jedem Monatsanfang (UTC) neu.
  • Eine Seite, die nicht lädt, mit einem Fehlerstatus antwortet oder auf eine Fehlerseite umleitet, lässt die Prüfung fehlschlagen: Ein kaputtes Deployment soll nie bestehen.
  • Prüfungen sind von der Überwachung getrennt: Sie ändern weder Berichte noch Verlauf noch E-Mail-Zusammenfassungen Ihrer Websites.
  • Automatische Tests finden einen großen Teil der Barrieren, aber nicht alle. Behalten Sie die angeleiteten manuellen Prüfungen in Ihrem Release-Ablauf.

REST-API

Das Skript ist eine dünne Schicht über einer kleinen REST-API, die Sie von überall aufrufen können: aus eigenen Skripten, einem Ticketsystem oder einem internen Dashboard.

Authentifizierung

Senden Sie Ihren Schlüssel im Authorization-Header: Authorization: Bearer eqv_… Jede Antwort ist JSON. Fehler sehen so aus: {"error": {"code": "…", "message": "…"}}.

Endpunkte

MethodePfadLiefert
POST/api/v1/checksStartet eine Prüfung von 1 bis 10 URLs. Antwortet mit 202, der laufenden Prüfung und Ihrem Kontingent.
GET/api/v1/checks/{id}Eine Prüfung mit den Fehlern jeder Seite. Alle paar Sekunden abfragen, bis status nicht mehr "running" ist.
GET/api/v1/checksIhre 20 letzten Prüfungen, ohne Seitendetails.
GET/api/v1/sitesIhre überwachten Websites mit den Fehlerzahlen des letzten Scans.
GET/api/v1/sites/{id}/issuesAlle Fehler des letzten Scans einer Website: Regel, Schweregrad, WCAG- und EN-301-549-Bezüge (en301549: Abschnitte der V3.2.1, der im EU-Amtsblatt zitierten Fassung; en301549V4: Abschnitte der V4.1.1, WCAG 2.2), Seite, Element, HTML und Lösungsvorschlag. ?locale=de für deutsche Titel.
GET/api/v1/usageDiesen Monat verbrauchte Seiten, Ihr Limit und wann es neu beginnt.

Eine Prüfung starten

Der Body von POST /api/v1/checks:

FeldBedeutung
urlsPflicht. 1 bis 10 absolute http(s)-URLs.
failOncritical, serious (Standard), moderate, minor oder none.
baselineSiteIdOptional. Eine Ihrer überwachten Websites: Es zählen nur Fehler, die sie nicht hat.
labelOptional. Bis zu 120 Zeichen, zum Beispiel Branch und Commit.
localeOptional. en, hu oder de, die Sprache der Fehlertitel.
curl -X POST https://equalvia.com/api/v1/checks \
  -H "Authorization: Bearer $EQUALVIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://preview.example.com/"], "failOn": "serious"}'
curl https://equalvia.com/api/v1/checks/CHECK_ID \
  -H "Authorization: Bearer $EQUALVIA_API_KEY"

Das Ergebnis

passed ist null, solange die Prüfung läuft. failing zählt die Elemente, die das Ergebnis entschieden haben (ab failOn und, mit Baseline, neu); totals zählt alles Gefundene. Mit Baseline zeigen newTotals, newCount je Fehler und das Flag new je Element, was neu ist.

{
  "check": {
    "id": "cm1x8k2q40001",
    "status": "completed",
    "passed": false,
    "failOn": "serious",
    "baselineSiteId": null,
    "label": "feature/checkout @ 3f6e478",
    "pageCount": 1,
    "pagesWithErrors": 0,
    "totals": { "critical": 1, "serious": 2, "moderate": 0, "minor": 1, "total": 4 },
    "newTotals": null,
    "failing": 3,
    "pages": [
      {
        "url": "https://preview.example.com/",
        "httpStatus": 200,
        "issues": [
          {
            "ruleId": "image-alt",
            "title": "Images without alternative text",
            "impact": "critical",
            "wcag": ["1.1.1"],
            "helpUrl": "https://dequeuniversity.com/rules/axe/4.13/image-alt",
            "count": 1,
            "elements": [{ "target": ".hero > img", "html": "<img src=\"/hero.jpg\">" }]
          }
        ]
      }
    ]
  }
}

Fehler

Das Feld code bleibt stabil, message ist für Menschen gedacht.

HTTPCodeBedeutung
400INVALID_REQUESTBody oder eine URL ist ungültig.
401UNAUTHORIZEDSchlüssel fehlt, ist unbekannt oder widerrufen.
403PLAN_REQUIREDDas Paket des Kontos enthält keinen API-Zugang.
403QUOTA_EXCEEDEDDas monatliche Seitenkontingent würde überschritten.
404NOT_FOUND / BASELINE_NOT_FOUNDKeine solche Prüfung oder Website in Ihrem Konto.
409BUSYEs laufen bereits 2 Prüfungen.
429RATE_LIMITEDZu viele Anfragen mit dem Schlüssel; siehe Retry-After.

Limits

  • 10 URLs pro Prüfung, 2 gleichzeitig laufende Prüfungen pro Konto
  • 120 Anfragen pro Minute und Schlüssel
  • 500 geprüfte Seiten pro Monat bei Growth, 2.000 bei Agency
  • Bis zu 10 Schlüssel pro Konto