NCA Social Media
Aktualisiert:
Autor:
Roland Golla
Grünes Scanner Tor mit gelbem getByRole Schriftzug prüft echte Buttons

Was ist cy.getByRole?

cy.getByRole ist eine eingebaute Cypress Query, die Elemente über ihre Rolle und ihren Accessible Name findet. Sie ist seit Cypress 16.2.0 Teil von Cypress und braucht kein Plugin.
Die Rolle ist das, was ein Screenreader ansagt: Button, Link, Überschrift oder Tab. Der Accessible Name ist der Text dazu, etwa „Speichern“. Wie beides zusammenspielt, erklärt unser Eintrag zu Name, Rolle, Zustand in ARIA. Ein Test mit cy.getByRole sucht also genau so, wie assistive Technik eine Seite liest.
Bisher kam diese Abfrage über das Plugin Cypress Testing Library mit findByRole. Das Paket hat keinen aktiven Maintainer mehr. Cypress holt die Testing Library Queries deshalb Schritt für Schritt in den Kern, und cy.getByRole ist die erste davon.
Inhalt

cy.getByRole mit NCA: Schnelle Hilfe vom Experten

Bei uns läuft Cypress mit Cypress Cloud täglich in Production, auch diese Website wird damit getestet. Roland Golla ist Cypress Ambassador und arbeitet seit über 20 Jahren an Testing und Refactoring. Barrierefreiheit ist bei uns ein eigener Schwerpunkt, und genau da trifft cy.getByRole einen Nerv: Ein Selektor, der an Rolle und Name hängt, prüft bei jedem Lauf ein Stück Accessibility mit.
Im Cypress Workshop mit Roland Golla stellen wir bestehende Selektoren auf Rollen um und zeigen, wie Tests dabei stabil bleiben. Für ganze Teams gibt es die Cypress Remote Schulung für Teams. Wie Rollen Queries mit cypress-axe zusammenspielen, zeigt der Überblick zu Accessibility Testing Tools im NCA Glossar für Barrierefreiheit. Basistests für jede Website liefert unser NCA TESTIFY Cypress Plugin, und wenn KI Agenten Tests schreiben, gelten die NCA Agentic AI Coding Guardrails.
NCA Cypress Workshop mit Cypress Ambassador Roland Golla

E2E Tests, die euer Team selbst schreibt

Ein Tag inhouse mit Roland Golla, offizieller Cypress Ambassador und seit über 20 Jahren in Testing und Refactoring zu Hause. Auf unserem YouTube Kanal zeigt er in über 70 Live Coding Tutorials, wie Cypress in echten Projekten läuft. Dazu kommt unser Open Source Plugin NCA TESTIFY: Basistests für jede Website, mit einer Zeile im CI/CD Setup. Im Workshop lernt euer Team Setup, stabile Selektoren, Custom Commands und Tests in der Pipeline.

  1. 1
    Kostenloses Vorgespräch
    Projekt, Stack und Teststand klären
  2. 2
    Workshoptag bei euch
    Setup, Patterns und erste Tests im Team
  3. 3
    Praxistag optional
    Tests im eigenen Projekt und in CI
Roland Golla
Roland Golla
Fullstack Developer
Zum Cypress Workshop arrow_forward

So funktioniert cy.getByRole

Du gibst eine Rolle an und optional einen Namen. Cypress sucht alle passenden Elemente und wartet, bis sie da sind. Ein typischer Test für ein Formular sieht so aus:
Code:
          

describe('Profil', () => {
  it('speichert Änderungen', () => {
    cy.visit('/einstellungen')
    cy.getByRole('textbox', { name: 'Anzeigename' }).type('Jane Doe')
    cy.getByRole('button', { name: 'Änderungen speichern' }).click()
    cy.getByRole('alert').should('have.text', 'Gespeichert')
  })
})

  • Alle Treffer: Wie cy.get liefert cy.getByRole alle passenden Elemente in Dokumentreihenfolge. Mit einem genaueren Namen, .first() oder .eq() greifst du eins heraus.
  • Name exakt: Ein String muss den ganzen Namen treffen, inklusive Groß und Kleinschreibung. Für Teiltreffer nimmst du eine Regex, für eigene Logik eine Funktion.
  • Versteckt bleibt draußen: Elemente mit aria-hidden="true" oder display: none ignoriert die Query. Mit hidden: true kommen sie dazu.
  • Retry eingebaut: Die Query wartet, bis das Element erscheint und die Assertions grün sind.
  • Native zuerst: Gibt es ein HTML Element für die Rolle, trifft cy.getByRole nur dieses. Mehr dazu im nächsten Abschnitt.
Shadow DOM klappt auch, mit includeShadowDom: true oder über .shadow(). Alle Optionen stehen in der cy.getByRole API Referenz von Cypress.

Warum native Elemente der Default sind

Das ist der spannendste Teil des Features. Für Rollen mit eigenem HTML Element, etwa button, link, heading, dialog oder checkbox, trifft cy.getByRole nur das echte Element. Ein div mit role="button" fällt durch.
Code:
          

<button>Speichern</button>
<div role="button" tabindex="0">Abbrechen</div>

Code:
          

// findet und klickt den nativen Button
cy.getByRole('button', { name: 'Speichern' }).click()

// das div hat die Rolle nur über das Attribut und wird übersprungen
cy.getByRole('button', { name: 'Abbrechen' }).should('not.exist')

Warum so streng? Ein Rollen Selektor, der beides akzeptiert, deckt Fehler zu. Teams setzen schnell ein role Attribut, damit der Test grün wird, und vergessen den Rest. Der Test sieht dann barrierefrei aus, die Seite ist es nicht. Mit dem nativen Default schlägt der Test fehl, sobald jemand einen button gegen ein div tauscht. Das passt zur ersten Regel von ARIA: Gibt es ein natives Element, nimm es. Mehr zum Hintergrund steht in unserem Eintrag zu Semantic HTML.

Was ein role Attribut nicht mitbringt

role="button" ändert genau eine Sache: Der Screenreader sagt „Button“ an. Das Verhalten fehlt. Ein nativer button bringt dagegen alles mit:
  • Er steht automatisch in der Tab Reihenfolge.
  • Er reagiert auf Enter und Leertaste.
  • Er löst auch bei Tastatur ein click Event aus.
  • Er kennt das Attribut disabled.
  • Er schickt das umgebende Formular ab.
Ein div mit Klick Handler hat nichts davon. Für Menschen heißt das: Wer nur mit Tastatur arbeitet, springt mit Tab einfach vorbei. Wer einen Screenreader nutzt, hört „Speichern, Button“, drückt Enter, und je nach Setup passiert nichts. Mit der Leertaste scrollt die Seite, statt zu klicken. Und ein Button mit aria-disabled="true" lässt sich trotzdem auslösen. Ein Test mit simuliertem Mausklick sieht keinen dieser Fehler. Wie gute Bedienung per Tastatur aussieht, zeigt unser Eintrag zur Keyboard Navigation.

Zustände prüfen mit .filter()

Checked, selected, expanded oder Heading Level sind keine Optionen von cy.getByRole. Du hängst dafür .filter() an. Das liest sich klar und nutzt normale CSS Selektoren:
Code:
          

// der aktive Tab
cy.getByRole('tab').filter('[aria-selected="true"]')

// Überschriften der Ebene 2
cy.getByRole('heading').filter('[aria-level="2"], h2:not([aria-level])')

// eine angehakte native Checkbox
cy.getByRole('checkbox').filter(':checked')

// ein geöffnetes Menü
cy.getByRole('button').filter('[aria-expanded="true"]')

// der Link zur aktuellen Seite
cy.getByRole('link').filter('[aria-current="page"]')

// alle Buttons, die nicht deaktiviert sind
cy.getByRole('button').not(':disabled, [aria-disabled="true"]')

Stehen mehrere gleiche Elemente auf der Seite, hilft ein data-cy Attribut als Filter, zum Beispiel cy.getByRole('button').filter('[data-cy="checkout"]'). So bleibt die Rolle geprüft und der Treffer trotzdem eindeutig.

Wann du native: false brauchst

Manchmal ist ein role Attribut richtig, oder du kannst es nicht ändern. Dann gibst du native: false mit:
Code:
          

cy.getByRole('dialog', { name: 'Projekt löschen', native: false }).should('be.visible')

  • Ein Autocomplete als input mit role="combobox". Das native Gegenstück wäre ein select.
  • Ein Icon als svg mit role="img". Nativ wäre ein img.
  • Dialoge und Menüs aus Komponenten Bibliotheken, die du nicht selbst baust.
Für Rollen ohne HTML Element wie tab, menuitem oder switch brauchst du die Option nicht. Da zählt das role Attribut immer. Baut euer Projekt auf einer Bibliothek, die native Elemente nachbaut, setzt du den Default einmal zentral in der Support Datei, ähnlich wie bei Cypress Custom Commands. Ein einzelner Test kann dann trotzdem native: true verlangen.
Code:
          

// cypress/support/commands.js
Cypress.Commands.overwriteQuery(
  'getByRole',
  function (originalFn, role, options = {}) {
    return originalFn.call(this, role, { native: false, ...options })
  }
)

Migration von Cypress Testing Library

Eile ist nicht nötig. Cypress Testing Library läuft mit Cypress 16.2.0 weiter und registriert nur findBy Queries. Beide vertragen sich, du kannst Spec für Spec umstellen. Die meisten Aufrufe ändern nur den Namen:
Code:
          

// vorher: Cypress Testing Library
cy.findByRole('button', { name: 'Bestellen' }).click()
cy.findAllByRole('listitem').should('have.length', 3)
cy.findByRole('tab', { selected: true }).should('have.text', 'Versand')

// nachher: eingebaut in Cypress
cy.getByRole('button', { name: 'Bestellen' }).click()
cy.getByRole('listitem').should('have.length', 3)
cy.getByRole('tab').filter('[aria-selected="true"]').should('have.text', 'Versand')

Achtung bei eigenen Commands: Wer schon ein getByRole über Cypress.Commands.add oder addQuery angelegt hat, bekommt ab 16.2.0 einen Fehler. Dann umbenennen oder durch die eingebaute Query ersetzen. Die Cypress Doku enthält zusätzlich einen fertigen Prompt, mit dem KI Agenten in Cypress die Migration übernehmen. Den Diff reviewst du trotzdem selbst, und die neuen Specs lässt du mit Cypress Grep mehrfach laufen, bevor sie in die Suite kommen.

findByRole und cy.getByRole im Vergleich

Vier Unterschiede, die bei der Migration auffallen. Rote Tests durch den nativen Default sind kein Ärgernis: Behandle sie wie ein kleines Accessibility Review.
Thema findByRole (Testing Library) cy.getByRole (Cypress)
Native Elemente Findet auch ein div mit role="button" Nur der native button, sonst native: false
Mehrere Treffer Fehler bei mehr als einem Treffer Liefert alle, eingrenzen mit Name oder .first()
Zustände Optionen wie checked, selected, level Angehängtes .filter() mit Attribut oder Pseudo Klasse
Installation Eigenes Plugin ohne aktiven Maintainer Eingebaut ab Cypress 16.2.0

cy.getByRole, data-cy und Accessibility Scans einordnen

Drei Werkzeuge, drei Aufgaben. data-cy Attribute hängen an nichts außer dem Test. Sie sind maximal stabil und sagen nichts über Accessibility. Gut für Elemente, bei denen Text und Rolle egal sind, oder als Filter bei Doppelgängern.
cy.getByRole prüft nur, was dein Test anfasst. Das aber scharf: Rolle, Name und natives Element. Ändert sich das Label oder fliegt der native Button raus, wird der Test rot.
Accessibility Scans gehen in die Breite. Cypress Accessibility in Cypress Cloud lässt axe-core über jeden Zustand laufen, den aufgezeichnete Tests erreichen, ohne Änderung am Testcode. In unseren Projekten ist dafür cypress-axe fast immer dabei. Beides ergänzt cy.getByRole, keins ersetzt es. Welche Lücken danach noch bleiben, zeigt Cypress UI Coverage.
Und cy.prompt? Wenn Rollen und aria-label in der ElementSelector Priorität oben stehen, muss das Self Healing seltener eingreifen. Generierte Tests bleiben so näher an dem, was Nutzer wirklich sehen.

Role-based queries are a core way to write resilient, accessible tests

Jennifer Shehane, Autorin im Cypress Blog – Cypress Blog zum Launch von cy.getByRole

Aus der NCA Praxis: Rollen statt Klassen

In gewachsenen Suiten sehen wir oft Selektoren auf CSS Klassen. Ein Redesign, und die halbe Suite ist rot. Rollen und Namen ändern sich selten aus Versehen. Wer umstellt, bekommt stabilere Tests, weniger Flaky Tests und nebenbei einen ehrlichen Blick auf echte Barrieren. Schlägt ein Test im CI fehl, zeigt Cypress Test Replay, welches Element seine Rolle verloren hat. Dabei helfen wir Teams als Cypress Ambassador und mit über 20 Jahren Erfahrung in Testing und Refactoring.
Die Grundlagen dazu stehen im Glossar für Barrierefreiheit: ARIA, Accessibility Testing und der Eintrag zu DOM und Accessibility Tree. Warum das für Onlineshops auch rechtlich zählt, erklärt das Barrierefreiheitsstärkungsgesetz.
Passend dazu im NCA Cypress Glossar: das ESLint Plugin Cypress für saubere Testregeln und Testdaten in Cypress für Formulare, die du mit Rollen Queries durchspielst.
CYPRESS.IO Ambassador und IT Consultant für QA Engenieering und Qualität in PHP Projekten.
Erreichen Sie unsere Spezialisten zu barrierefreien Webdesign

Wir sind hier, um Ihnen zu helfen. Gemeinsam meistern wir Ihre digitalen Herausforderungen und fördern die Inklusion im Internet. Lassen Sie uns Ihre Projekte mit barrierefreiem Webdesign erfolgreich machen.

Häufige Fragen zu cy.getByRole

Die wichtigsten Antworten zu cy.getByRole, zur Migration von Testing Library und zum Zusammenspiel mit Accessibility Tests.
Was ist cy.getByRole 2026?

cy.getByRole ist eine eingebaute Cypress Query, die Elemente über Rolle und Accessible Name findet. Die Rolle ist das, was ein Screenreader ansagt, etwa Button oder Link. Der Name ist der Text dazu. Die Query liefert alle Treffer, wartet automatisch und braucht kein Plugin. Sie ist die erste Testing Library Query, die Cypress direkt in den Kern holt.

Ab welcher Version gibt es cy.getByRole 2026?

cy.getByRole steckt in Cypress ab Version 16.2.0. Ein Update reicht, eine zusätzliche Installation brauchst du nicht. Wer vorher schon ein eigenes getByRole als Custom Command angelegt hat, bekommt nach dem Update einen Fehler, weil der Name jetzt belegt ist. Dann den eigenen Command umbenennen oder entfernen und die eingebaute Query nutzen.

Brauche ich 2026 noch Cypress Testing Library?

Für Rollen Abfragen nicht mehr. cy.getByRole ersetzt findByRole und findAllByRole ohne Plugin. Nutzt du weitere Queries wie findByLabelText, behalte das Paket vorerst. Beide laufen nebeneinander, weil Testing Library nur findBy Queries registriert. Bedenke aber, dass das Paket keinen aktiven Maintainer mehr hat. Cypress plant, weitere Queries einzubauen.

Wie migriere ich 2026 von findByRole auf cy.getByRole?

Meist reicht es, den Namen zu tauschen. Drei Stellen brauchen Aufmerksamkeit: Native Elemente sind Default, also schlagen Tests auf ein div mit role fehl. cy.getByRole liefert alle Treffer, statt bei mehreren zu scheitern. Zustände wie checked oder selected wandern in ein angehängtes .filter(). Stell Spec für Spec um und lass die Suite nach jedem Schritt laufen.

Lohnt sich cy.getByRole 2026 für neue Tests?

Ja, für neue Tests ist cy.getByRole ein sehr guter erster Griff. Rollen und Namen ändern sich selten aus Versehen, deshalb halten die Tests auch ein Redesign aus. Gleichzeitig prüft jeder Test, ob ein Element die richtige Semantik hat. Wo Rolle und Text egal sind, bleiben data-cy Attribute die stabilste Wahl.

Warum findet cy.getByRole mein div mit role button nicht?

cy.getByRole trifft für Rollen mit nativem HTML Element nur das echte Element. Ein div mit role="button" zählt nicht. Du kannst native: false mitgeben oder besser das div durch einen echten button ersetzen. Dann bekommen Tastatur und Screenreader Nutzer das eingebaute Verhalten, und dein Test braucht keine Sonderoption.

Was bedeutet native: false bei cy.getByRole?

Mit native: false trifft cy.getByRole auch Elemente, die ihre Rolle nur über das role Attribut bekommen. Das brauchst du für Komponenten Bibliotheken, Autocomplete Felder mit role combobox oder Icons als svg mit role img. Für Rollen ohne HTML Gegenstück wie tab oder switch ist die Option überflüssig. Projektweit setzt du sie per overwriteQuery in der Support Datei.

Wie finde ich eine angehakte Checkbox oder eine h2?

Mit einem angehängten .filter(). Für die Checkbox schreibst du cy.getByRole('checkbox').filter(':checked'). Für Überschriften der Ebene 2 filterst du auf aria-level="2" oder ein h2 ohne aria-level. Nach dem gleichen Muster prüfst du ausgeklappte Menüs, gedrückte Toggle Buttons oder den aktiven Link mit aria-current.

Ersetzt cy.getByRole data-cy Attribute?

Nein, beide haben ihren Platz. data-cy ist unabhängig von Text, Rolle und HTML und damit maximal stabil. cy.getByRole prüft mit, ob ein Element für Menschen und assistive Technik verständlich ist. Bei mehreren gleichen Buttons kombinierst du beides: erst die Rolle, dann .filter() mit dem data-cy Attribut.

Ersetzt cy.getByRole einen Accessibility Scan?

Nein. cy.getByRole prüft nur die Elemente, die dein Test anfasst. Fehlende Labels, schwachen Kontrast oder kaputtes ARIA an anderen Stellen findet ein Scan mit axe-core, etwa über cypress-axe oder Cypress Accessibility in Cypress Cloud. Dazu kommen manuelle Tests mit Tastatur und Screenreader. cy.getByRole ist ein Baustein, kein vollständiges Audit.

Funktioniert cy.getByRole im Shadow DOM?

Ja. Du gibst includeShadowDom: true mit, setzt die gleichnamige Option in der Cypress Konfiguration oder hängst cy.getByRole an .shadow() an. Damit klappen Rollen Abfragen auch in Web Components. Mit .within() begrenzt du die Suche außerdem auf einen Bereich der Seite, etwa ein Formular oder einen Dialog.

Wie passen cy.getByRole und cy.prompt zusammen?

Gut. cy.getByRole bindet Tests an Rollen und Namen, die selten aus Versehen kippen. cy.prompt repariert Schritte per Self Healing und markiert jede Reparatur zum Review. Stehen Rollen und aria-label in der ElementSelector Priorität oben, muss cy.prompt seltener eingreifen. So bleiben generierte Tests näher an dem, was Nutzer wirklich sehen.