Verwendung mit test-matchers
Für Unit- und Komponententests: Prüfen Sie Barrierefreiheit direkt in einer Jest- oder Vitest-Suite, gegen das DOM, das der Test ohnehin hat, statt einen echten oder Headless-Browser zu steuern. Wenn Sie stattdessen vollständig gerenderte Seiten testen, nutzen Sie die browsergesteuerten Bindings.
@surea11y/test-matchers bietet toHaveNoA11yViolations() sowie toHaveAnnounced() für Live-Regionen. Beide fügen sich unverändert in expect.extend() beider Frameworks ein, ohne eigenen framework-spezifischen Code. Er scannt die jsdom-basierte Umgebung, in der Ihr Test ohnehin läuft; er hängt nicht selbst von jsdom ab und richtet auch keine Umgebung für Sie ein. Die Engine von surea11y ist synchron, also auch dieser Matcher: kein await, und damit auch kein vergessenes await, bei dem ein Test über ein aufgelöstes Promise stillschweigend besteht.
$ npm install --save-dev @surea11y/core @surea11y/test-matchers
@surea11y/core ist die Engine, die der Matcher ausführt; installieren Sie sie wie oben zusammen mit dem Matcher. Um gebautes HTML stattdessen vom Terminal oder in einem CI-Schritt zu prüfen, außerhalb eines Test-Runners, siehe CLI.
Einrichtung
Ihre Testumgebung muss bereits jsdom-basiert sein: Dieser Matcher scannt das document/window, das sie bereitstellt. Registrieren Sie den Matcher einmal, in der Setup-Datei, die Ihr Test-Runner ohnehin lädt:
Jest
// jest.setup.jsexpect.extend({toHaveNoA11yViolations: require('@surea11y/test-matchers').toHaveNoA11yViolations});// jest.config.jsmodule.exports = {testEnvironment: 'jsdom', // or the explicit jest-environment-jsdom package, depending on your Jest versionsetupFilesAfterEnv: ['./jest.setup.js']};
Vitest
// vitest.setup.jsimport { expect } from 'vitest';import { toHaveNoA11yViolations } from '@surea11y/test-matchers';expect.extend({ toHaveNoA11yViolations });// vitest.config.jsexport default {test: {environment: 'jsdom', // Vitest doesn't bundle jsdom -- install it as a devDependency toosetupFiles: ['./vitest.setup.js']}};
Die mitgelieferte .d.ts erweitert sowohl Jests globales Interface jest.Matchers als auch die Interfaces von @vitest/expect, ohne dass dafür ein Import von @types/jest oder vitest nötig ist. Wirksam wird nur die Erweiterung für das Framework, das tatsächlich installiert ist.
Verwendung
Funktioniert mit einem einfachen DOM-Knoten:
test('no accessibility violations', () => {document.body.innerHTML = '<img src="logo.png">';expect(document.body).toHaveNoA11yViolations(); // fails: missing alt});
...oder mit jedem container einer Testing Library, ob von React Testing Library, wrapper.element von Vue Test Utils, Angular Testing Library oder Svelte Testing Library, denn alle stellen ein gerendertes DOM-Element auf dieselbe Weise bereit:
const { render } = require('@testing-library/react');test('MyComponent has no accessibility violations', () => {const { container } = render(<MyComponent />);expect(container).toHaveNoA11yViolations();});
Auch auf der Seite des Test-Runners ist das framework-unabhängig: Die Snippets oben sind identisch, ob sie unter Jest oder Vitest laufen, sobald der Matcher registriert ist.
Mit .not prüfen
test('a page with a violation fails the assertion', () => {document.body.innerHTML = '<main><img src="logo.png"></main>';expect(document.body).not.toHaveNoA11yViolations();});
Einen Scan für mehrere Assertions wiederverwenden
Wenn Sie ein surea11y-Scan-Ergebnis bereits selbst berechnen, etwa um über mehrere it()-Blöcke hinweg auf bestimmte Regeln zu prüfen, ohne jedes Mal neu zu scannen, übergeben Sie statt eines DOM-Knotens direkt das Ergebnisobjekt:
const { runDomRulesInPage } = require('@surea11y/core');const result = runDomRulesInPage(null, '#main', {}, null);expect(result).toHaveNoA11yViolations();
Scans filtern und konfigurieren
Das zweite Argument akzeptiert alles, was @surea11y/core akzeptiert; den vollen Umfang finden Sie unter Engine-Optionen. Einige häufige Fälle:
// Only run rules relevant to WCAG 2.0 Aexpect(container).toHaveNoA11yViolations({ tags: { include: 'wcag2a' } });// Skip a rule you've decided not to enforce yetexpect(container).toHaveNoA11yViolations({ rules: { exclude: 'target-size-minimum' } });// Ignore a third-party widget you don't controlexpect(container).toHaveNoA11yViolations({ excludeSelectors: ['.intercom-launcher'] });// EN 301 549 V4.1.1 (WCAG 2.2 A and AA); 'en301549-v3.2.1' for V3.2.1 (WCAG 2.1 A and AA)expect(container).toHaveNoA11yViolations({ profile: 'en301549-v4.1.1' });
Ein WCAG-Ziel wählen (runOnly)
Das dritte Argument ist das runOnly des Scans und wird unverändert an die Engine übergeben. runOnly.wcag wählt nach Konformitätsziel aus: { wcag: { version: '2.2', level: 'AA' } } führt die Regeln für die Kriterien der Stufen A und AA von WCAG 2.2 aus, nach der Stufe, die jedes Kriterium in dieser Version hat. bestPractices: true ergänzt die Regeln, die kein WCAG-Kriterium nennen, etwa region und heading-order; allein angegeben führt es nur diese aus, und neben engineOptions.profile fügt es sie den Regeln des Profils hinzu.
// WCAG 2.2 A and AAexpect(container).toHaveNoA11yViolations({}, { wcag: { version: '2.2', level: 'AA' } });// The same, and the best practicesexpect(container).toHaveNoA11yViolations({}, { wcag: { version: '2.2', level: 'AA' }, bestPractices: true });
runOnly nimmt auch Regel-IDs und Tags an (includeRuleIds, tags, excludeRuleIds, ...), die die Regeln eines Ziels ergänzen; die Ausschlüsse wirken danach. Ein runOnly, das irgendetwas auswählt, ersetzt die Auswahl in engineOptions.rules/.tags vollständig: Geben Sie eine Auswahl auf die eine oder die andere Weise an, nicht auf beide. Übergeben Sie {} oder null als engineOptions, wenn Sie nur runOnly brauchen. Regel-IDs werden ohne Rücksicht auf Groß- und Kleinschreibung gelesen ('IMG-ALT-PRESENT').
Ein Ziel bringt seine Stufe mit. Ein Test, der stattdessen Regeln oder Tags benennt, kann eine mit engineOptions.wcagLevel setzen (@surea11y/core 1.12.0 und neuer): die Stufe der Kriterien, die der Scan meldet, ohne zu ändern, welche Regeln laufen. contrast-computable prüft 1.4.3 (AA) und 1.4.6 (AAA), daher meldet der Scan unten nur 1.4.3. Die Assertion entscheidet nach Ergebnissen mit fail, daher ändert das die Kriterien im Ergebnis, nicht, woran der Test scheitert.
expect(container).toHaveNoA11yViolations({ wcagLevel: 'AA' }, { includeRuleIds: ['contrast-computable'] });
Mit Packs scannen
Ein Pack bringt Regeln, eine Norm oder eine Checkliste sowie deren Profile und Meldungen aus einem eigenen Paket mit. Der Matcher scannt in Node, daher wird ein Pack als das Objekt selbst in engineOptions.packs übergeben, und sein Profil wird mit engineOptions.profile gewählt:
const acmePolicy = require('./acme-policy-pack');const policy = { packs: [acmePolicy], profile: 'acme-web-2026' };test("a page that breaks the pack's house rule fails the assertion", () => {document.body.innerHTML = '<main><h1>Welcome</h1><video autoplay src="intro.mp4"></video></main>';expect(document).not.toHaveNoA11yViolations(policy);});// A pack's checklist profile, and the best practicesexpect(container).toHaveNoA11yViolations(policy, { bestPractices: true });
Die eigenen Regeln eines Packs erscheinen im Ergebnis wie die von core, mit IDs, die mit seinem Namensraum beginnen (acme-no-autoplay). Halten Sie die Pack-Objekte an einer Stelle (einer Setup-Datei oder einem Modul): core bereitet für jede Menge von Pack-Objekten eine Engine vor und behält sie für den nächsten Scan mit denselben. Ein Pack, das core nicht ausführen kann (sein core-Bereich schließt das installierte core aus, es ist nicht gültig, oder sein Namensraum kollidiert mit dem eines anderen Packs), steht in skippedPacks des Ergebnisses, und die Assertion scheitert daran, statt zu bestehen, während die Regeln des Packs nie gelaufen sind.
API
| Parameter | Typ | Bedeutung |
|---|---|---|
received | Element, Document oder Scan-Ergebnis | Was geprüft wird. Ein DOM-Element/Document wird automatisch gescannt; bei einem Objekt der Form { checksResults: [...] } wird direkt darauf geprüft, ohne Scan. Alles andere wirft einen TypeError. |
engineOptions | Objekt (optional) | Wird unverändert an den Scan von @surea11y/core durchgereicht: dasselbe Optionsobjekt, das überall sonst im Ökosystem verwendet wird (siehe Engine-Optionen). Wird ignoriert, wenn received bereits ein Scan-Ergebnis ist. |
runOnly | Objekt, String oder String[] (optional) | Wird unverändert als runOnly des Scans durchgereicht: ein WCAG-Ziel ({ wcag: { version: '2.2', level: 'AA' } }), bestPractices, Regel-IDs oder Tags. Siehe Ein WCAG-Ziel wählen. Wird ignoriert, wenn received bereits ein Scan-Ergebnis ist. |
options | Objekt (optional) | { failOnSeverity, leanFail, wcagOnly, howToCheck }: siehe Nur bei schwerwiegenden Problemen fehlschlagen und Fragen, die wahrscheinlich nicht erfüllt sind. Jede Option ersetzt den Standardwert, den configureA11yMatchers() setzt. |
Das zweite Argument kann stattdessen ein einziges Objekt mit allem sein, { engineOptions, runOnly, failOnSeverity, leanFail, wcagOnly, howToCheck }: toHaveNoA11yViolations({ leanFail: true }). Es wird so gelesen, wenn es einen dieser Schlüssel hat, von denen keiner eine Engine-Option ist; ein Objekt, das sie mit Engine-Optionen mischt, wirft einen TypeError.
Gibt die Form { pass, message } zurück, die expect.extend() in beiden Frameworks erwartet — Sie rufen das nie direkt auf; es wird einmal über expect.extend() eingebunden, wie oben unter Einrichtung gezeigt. Das Paket exportiert außerdem configureA11yMatchers(options) für Standardwerte in der ganzen Suite, installInternalsHook(win?) für Web Components sowie installListenerHook(win?), installLiveRegionHook(win?) und den Matcher toHaveAnnounced() für Klick-Handler und Live-Regionen.
Was geprüft wird und was nicht
Nur Fehlschläge lassen die Assertion scheitern, wie bei jedem anderen surea11y-Binding, wo cantTell-Ergebnisse als Hinweis gelten, nicht als Fehler. Jeder Befund wird nach seinem eigenen Ergebnis gelesen, nicht nach dem seiner Regel: Eine Regel, die bei einem Element fehlschlägt, kann zu einem anderen eine Frage stellen, und diese Frage zählt nicht als Fehlschlag. Ein vager Link wie <a href="/pricing">Click here</a> ist cantTell, nicht fail, und lässt einen bestandenen Test daher allein nicht scheitern, außer Sie verlangen das mit leanFail (unten). Scheitert eine Assertion aber aus anderen Gründen, werden die Fragen nach den Fehlschlägen aufgelistet, damit sie sichtbar bleiben. Unter Bekannte Einschränkungen steht, was diese Engine überhaupt nicht automatisiert.
Ein Scan, der nicht prüfen konnte, was er prüfen sollte, scheitert ebenfalls, statt über nichts zu bestehen: ein Element, das nicht im Dokument liegt, in dem der Scan läuft (abgetrennt oder aus einem anderen Dokument), eine eigene Regel, die nicht gelaufen ist (aufgeführt in skippedCustomRules), oder ein Pack, das nicht gelaufen ist (aufgeführt in skippedPacks). Die Meldung nennt jedes davon mit dem Grund. Eine eigene Regel, die der Test selbst ausschließt, ist keine Lücke und lässt ihn nicht scheitern.
Ein Aufruf ohne Auswahl führt auch die Best Practices aus. Seit @surea11y/core 1.12 lässt eine davon, empty-heading, eine Überschrift ohne zugänglichen Namen scheitern, wo sie früher nachfragte. Eine Komponente, die <h2></h2> rendert (oft ein Titel-Prop, das im Test leer bleibt), lässt daher einen Aufruf ohne Optionen scheitern. Ein Screenreader kündigt diese Überschrift ohne Inhalt an: Geben Sie dem Test echten Inhalt oder beheben Sie die Komponente. Ein Aufruf mit einem WCAG-Ziel, das die Best Practices auslässt, führt sie nicht aus.
Der Scan selbst kann eine Ausnahme werfen, und der Test scheitert dann mit dem Fehler der Engine, der einen code trägt: INVALID_RUN_ONLY (eine Liste von Regeln oder Tags, in der kein Wert eine Regel oder ein Tag nennt, oder ein runOnly.wcag-Ziel, das keines ist), INVALID_ENGINE_OPTIONS (mit strictOptions: true eine Option, die die Engine nicht liest, oder ein Wert, den sie nicht verwenden kann) oder PAGE_BUILTINS_BROKEN (der eigene Code des Tests oder der Seite hat ein JavaScript-Built-in beschädigt, auf das sich die Engine verlässt).
Ein auf ein Element beschränkter Scan meldet nur, was darin liegt: Ein Verstoß an anderer Stelle der Seite lässt eine auf einen container beschränkte Assertion nie scheitern. Intern wird das gescannte Element vorübergehend mit einem eindeutigen Attribut markiert und über diesen Selektor gescannt, für Ihren Test unsichtbar.
Einige wenige Regeln prüfen eine Eigenschaft der ganzen Seite, nicht etwas in einem bestimmten Teilbaum: page-title-present, html-lang-attr-present und ein paar weitere prüfen direkt document.title/document.documentElement, weil die Frage, ob die Seite einen Titel hat, für ein beliebiges Komponenten-Snippet keinen Sinn ergibt. Übergeben Sie ein Element (einen container einer Testing Library, document.body), melden diese Regeln notApplicable statt fail, sodass ein fehlendes <title> nie einen Test auf Komponentenebene scheitern lässt; übergeben Sie document selbst, werden sie tatsächlich ausgewertet. Wenn Sie document direkt scannen, setzen Sie document.title und lang von document.documentElement einmal in Ihrer Setup-Datei statt in jedem Test.
Nur bei schwerwiegenden Problemen fehlschlagen
Jedes Regelergebnis hat einen Schweregrad: critical, serious, moderate oder minor. Um Tests zunächst nur bei schwerwiegenden Problemen scheitern zu lassen, während der Rest weiter gemeldet wird, setzen Sie eine Stufe für die ganze Suite in der Setup-Datei mit configureA11yMatchers(), oder für eine Assertion in deren Optionen, die den Standardwert ersetzen (failOnSeverity: null schaltet ihn dort ab):
// jest.setup.js (vitest.setup.js: the same, with import)const { toHaveNoA11yViolations, configureA11yMatchers } = require('@surea11y/test-matchers');expect.extend({ toHaveNoA11yViolations });configureA11yMatchers({ failOnSeverity: 'serious' });// one assertionexpect(container).toHaveNoA11yViolations({ failOnSeverity: 'critical' });
Fehlschlagende Regeln unterhalb der Stufe lassen den Test nicht scheitern; scheitert er aber, listet die Meldung jeden Fehlschlag auf und markiert die unterhalb der Stufe. Es ist dieselbe Schwelle wie bei surea11y scan --fail-on-severity. Ein Scan, der etwas ausgelassen hat (ein Bereich, der auf nichts passte, eine eigene Regel oder ein Pack, die nicht gelaufen sind), lässt die Assertion unabhängig von der Stufe scheitern.
Fragen, die wahrscheinlich nicht erfüllt sind
Ein cantTell ist eine Frage an eine Person. Seit @surea11y/core 1.14 kann eine Frage tendieren: Wo die Hinweise auf der Seite in eine Richtung zeigen, sagt sie, in welche (fail oder pass) und warum, und jede Frage einer core-Regel enthält die Schritte, mit denen sie sich beantworten lässt (howToCheck). Eine Fehlermeldung listet die Fragen nach den Fehlschlägen: zuerst die wahrscheinlich nicht erfüllten, dann die wahrscheinlich erfüllten, jeweils mit Grund, dann die offenen, nach Regel. { howToCheck: true } listet jede Frage vollständig auf, mit ihren Schritten.
Standardmäßig lässt eine Frage den Test nie scheitern. { leanFail: true } lässt ihn auch bei den Fragen scheitern, die wahrscheinlich nicht erfüllt sind, und wcagOnly: true lässt die von Best-Practice-Regeln weg:
test('the settings page has no failures or likely failures', () => {const { container } = render(<Settings />); // an <h1>, then an <h3>expect(container).toHaveNoA11yViolations(); // passes: heading-order is a questionexpect(container).toHaveNoA11yViolations({ leanFail: true }); // fails: it leans failexpect(container).toHaveNoA11yViolations({ leanFail: true, wcagOnly: true }); // passes: heading-order is a best practice});
Das ist optional, weil eine Tendenz ein Hinweis ist, kein Beweis: Ob ein Befund tendiert, und in welche Richtung, kann sich in einer Minor-Version von core ändern. configureA11yMatchers({ leanFail: true }) schaltet es für die ganze Suite ein.
Web Components
Viele Web Components halten ihre ElementInternals in einem privaten Feld und geben sich darüber einen Namen, setzen ihre Zustände oder geben sich eine Rolle. Kein Skript kann das zurücklesen, daher fragt der Scan standardmäßig bei einem solchen Element nach (cantTell), statt es zu beurteilen: Der Test scheitert nicht, aber geprüft wird auch nichts, und eine so gesetzte Rolle wird gar nicht gesehen.
installInternalsHook(win?) lässt den Scan sie lesen. Rufen Sie es einmal in der Setup-Datei auf, bevor eine Komponente definiert wird, damit es jeden Aufruf von attachInternals() sieht; win ist standardmäßig das globale window:
// jest.setup.jsconst {toHaveNoA11yViolations,installInternalsHook} = require('@surea11y/test-matchers');installInternalsHook();expect.extend({ toHaveNoA11yViolations });
// vitest.setup.jsimport { expect } from 'vitest';import {toHaveNoA11yViolations,installInternalsHook} from '@surea11y/test-matchers';installInternalsHook();expect.extend({ toHaveNoA11yViolations });
Damit besteht eine Komponente, die sich über ihre ElementInternals benennt; eine, die sie anhängt, aber keinen Namen setzt, scheitert wie jedes unbenannte Bedienelement; und eine, die nur über sie ein switch ist, wird als solcher geprüft. engine.environment.internalsHook im Scan-Ergebnis zeigt, ob der Hook da war. Er umhüllt HTMLElement.prototype.attachInternals im Testfenster, was in einem Test harmlos ist und der Grund, warum er optional ist. Eine Grenze gibt es: jest-environment-jsdom 30 bringt jsdom 26 mit, wo eine Komponente, die eine ARIA-Eigenschaft auf ihren ElementInternals setzt, einen Fehler wirft, mit oder ohne Hook (Vitest mit jsdom 29 kommt damit zurecht). Seit @surea11y/core 1.14 wird der Hook auch unter Vitest als 'early' erfasst, sodass eine Komponente, die nie ElementInternals angehängt hat, dort keine offene Frage mehr ist. Die Details stehen in der README des Pakets.
Klick-Handler und Live-Regionen
Zwei weitere optionale Hooks, seit @surea11y/core 1.14, werden genauso installiert, in der Setup-Datei, bevor Ihr Code läuft. installListenerHook() zeichnet die Klick-, Tastatur-, Fokus- und Maus-Listener auf, die von da an hinzugefügt werden, damit die Tastaturregeln sie beurteilen: Ein <div role="button">, das nur auf click hört, ergibt fail (CLICK_HANDLER_NO_KEY_LISTENER) und besteht, sobald es auch auf keydown hört. installLiveRegionHook() zeichnet auf, was die Live-Regionen der Seite erhalten: Der Scan stellt eine Frage zu einer Region, die schon mit ihrem Text eingefügt wurde und die Screenreader oft nicht ansagen, und toHaveAnnounced() prüft, ob eine Aktion den Nutzenden etwas mitgeteilt hat. Installieren Sie nur die, die Sie brauchen; jeder ist unabhängig:
// jest.setup.js (vitest.setup.js: the same, with import)const {toHaveNoA11yViolations,toHaveAnnounced,installInternalsHook,installListenerHook,installLiveRegionHook} = require('@surea11y/test-matchers');installInternalsHook();installListenerHook();installLiveRegionHook();expect.extend({toHaveNoA11yViolations,toHaveAnnounced});
test('saving says so', async () => {const user = userEvent.setup();const { container } = render(<SaveBar />);await user.click(screen.getByRole('button', { name: 'Save' }));expect(container).toHaveAnnounced('Saved');expect(window).not.toHaveAnnounced(/error/i);});
Ein String muss der ganze Text sein; ein RegExp darf auf einen Teil passen. Auf einem Element zählen nur die Live-Regionen, die es ist oder enthält; auf window oder document jede Ansage, seit der Hook installiert wurde. Es ist das, was die Seite zur Ansage bereitgestellt hat, nicht das, was ein Screenreader gesagt hat, und toHaveAnnounced() wirft ohne den Hook einen Fehler. Zwei Dinge sollten Sie wissen: React hängt seine Listener an den Root, in den es rendert, nicht an jedes Element, sodass der Scan bei einer React-Komponente die Listener des Roots sieht und ihre Buttons nach ihrem Markup beurteilt, wie ohne den Hook; und der Live-Region-Hook liest Änderungen in Gruppen, also erst rendern und dann handeln, mit einem await dazwischen (await user.click()), wie es echte Nutzende tun. Die Details stehen in der README des Pakets.
Fehlermeldungen
Die Meldung listet jedes fehlschlagende Vorkommen auf, nicht nur jede Regel — eine Regel kann mehrere Elemente markieren —, mit Regel-ID, Schweregrad, einer lesbaren Zusammenfassung, dem Selektor des betroffenen Elements und, wo vorhanden, einem Hinweis zur Behebung. Sie nennt das @surea11y/core-Release, das das Ergebnis erzeugt hat, zum Zitieren in einem Fehlerbericht, und listet danach die Fragen auf, die nicht als Fehlschläge zählen. Mit einer übersprungenen Überschriftenebene neben dem Bild:
expected no accessibility violations, but found 1:1) img-alt-present (serious): This <img> has no alt attribute.at body > main > imgAdd an alt attribute that says what the image shows, or alt="" if the image is purely decorative.Scanned with @surea11y/core 1.14.1.2 findings need manual review (cantTell, not counted as failures):1) heading-order (minor, likely fails): This heading jumps from level 1 to level 3, skipping a level.at body > main > h3Go down one level at a time, so an <h2> is followed by an <h3> rather than an <h4>, and the outline of the page stays easy to follow.Why it likely fails: The heading skips a level after the one before it.Open questions, which only a person can answer: manual-review.
Vor der Versionszeile kann die Meldung Hinweise dazu enthalten, wie der Scan lief: Hat der Scan zu Custom Elements Fragen gestellt, die er mit dem Internals-Hook hätte lesen können, oder Befunde beurteilt, die der Listener- oder Live-Region-Hook entschieden hätte, sagt eine Zeile, wie viele, und dass Sie ihn installieren sollten. Mit { leanFail: true } rücken die wahrscheinlich nicht erfüllten Fragen zu den Fehlschlägen auf, und die Kopfzeile zählt beides (found 1 failure and 1 likely failure:).
Ein Pack, das nicht gelaufen ist, wird mit dem Grund genannt:
expected no accessibility violations, but the scan left out what it was asked to check:No accessibility violations found in what was scanned.Pack "@acme/a11y-policy" did not run: it supports core ^2.0.0, and this is core 1.14.0.Scanned with @surea11y/core 1.14.1.
Ausführbare Beispiele für beide Frameworks nebeneinander: Jest und Vitest, und dasselbe mit einem Pack: Jest und Vitest, und eine kleine Komponente, geprüft mit dem Listener- und dem Live-Region-Hook, toHaveAnnounced() und leanFail: Jest und Vitest. Den vollständigen Umfang von engineOptions (Locale, Kontrastmodi, Shadow DOM, eigene Regeln, Tag-Kombinationen für WCAG-Versionen) finden Sie in ENGINE_OPTIONS.md. Dieses Paket reicht weiter, was Sie übergeben, statt diese Referenz zu duplizieren.