Resumen

Las pruebas de accesibilidad que te dicen lo que no pueden decirte.

Pruebas de accesibilidad deterministas para Playwright, Cypress, Puppeteer, Selenium, WebdriverIO, Jest/Vitest y pipelines de CI.

@surea11y/core es un motor de pruebas de accesibilidad que ejecutas en tu propia suite de pruebas, canalización de CI o desde la línea de comandos.

Lo que lo distingue es lo que hace con los casos que las pruebas automatizadas no pueden resolver. Implementa el Accessibility Conformance Testing (ACT) Rules Format abierto del W3C, validado con el corpus público de casos de prueba de ACT, en lugar de evaluarse únicamente con sus propias pruebas. Informa hallazgos, ausencia de hallazgos y, de forma poco habitual, incertidumbre explícita, de modo que los resultados son auditables en lugar de tranquilizadores.

Sure significa certeza sobre lo que se sabe, y honestidad sobre lo que no. Te dice lo que no te puede decir.

145 reglas de accesibilidad · 60 reglas ACT del W3C verificadas con los casos de prueba del W3C · 957 casos de referencia · resultados deterministas · incertidumbre explícita

enginev1.16.1licenseMPL-2.0

Ver qué cambió en la última versión

No es un único producto

surea11y es una familia de paquetes que comparten un mismo motor, no una única herramienta con un único comando de instalación. Instala el que coincida con cómo ya pruebas, junto con @surea11y/core, el motor que ejecuta. Instala core por sí solo para ejecutar el motor sobre un DOM que ya tengas, o para crear tu propia herramienta sobre él:

Quiero…Instalar
Agregar comprobaciones de accesibilidad a las pruebas de Playwright@surea11y/playwright + @surea11y/core
…Puppeteer@surea11y/puppeteer + @surea11y/core
…Selenium@surea11y/selenium + @surea11y/core
…Cypress@surea11y/cypress + @surea11y/core
…WebdriverIO@surea11y/webdriverio + @surea11y/core
Verificar la accesibilidad en pruebas de componentes o unitarias con Jest/Vitest@surea11y/test-matchers + @surea11y/core
Analizar páginas desde una terminal o una canalización de CI, como HTML estático o en Chromium@surea11y/cli
Comprobar EN 301 549, el estándar europeo, con cualquiera de los anteriores@surea11y/pack-en301549 + @surea11y/core
Comprobar ARIA según el propio WAI-ARIA 1.2, junto a WCAG o por sí solo@surea11y/pack-wai-aria + @surea11y/core
Comprobar tus propias reglas, perfiles o estándar, públicos o internosUn pack propio: ver Escribir un pack
Ejecutar el motor sobre un DOM que ya tengas@surea11y/core
Crear tu propia herramienta sobre el motor: una CLI, una extensión, un panel, un generador de informes@surea11y/core

Consulta Primeros pasos para ver la instalación y el uso de cada integración (binding). Si estás creando una herramienta, BUILDING_ON_CORE.md (en GitHub, en inglés) explica el contrato estable, cómo ejecutar análisis, cómo elegir comprobaciones y cómo presentar los resultados sin afirmar más de lo que dicen.

Para un primer vistazo sin suite de pruebas, carga el bundle independiente en una página y analízala desde la consola del navegador: await a11ycore.run() analiza la página, a11ycore.table(result) lista los resultados, a11ycore.highlight(result) los recuadra en la página y await a11ycore.openReport(result) abre el informe HTML. INTEGRATION.md (en GitHub, en inglés) lista las demás funciones de ayuda, como a11ycore.inspect('headings') para los encabezados, los landmarks, los nombres o el orden del foco de una página.

En qué se diferencian sus resultados

Cada regla toma una decisión determinista, a partir de un vocabulario fijo de cuatro resultados, no la forma violations/passes/incomplete/inapplicable que usan otras herramientas populares de pruebas de accesibilidad:

  • fail (fail): una violación demostrable a partir del DOM. Reservado para casos objetivos y normativos.
  • pass (pass): se cumple la condición específica de esta regla. No es una afirmación de que la página sea accesible.
  • can't tell (cantTell): una persona tiene que decidir esto, y el resultado indica qué era ambiguo.
  • n/a (notApplicable): la precondición de la regla no está presente.

cantTell expresa uno de los principios centrales del proyecto. Un motor que descarta en silencio lo que no puede determinar produce un informe más corto y una falsa sensación de cobertura. Consulta Resultados e informes para conocer la estructura completa del resultado, y Conformidad para ver cómo los resultados individuales se combinan en un veredicto de WCAG, incluida la forma en que se resuelve y aplica una versión de WCAG objetivo (2.0/2.1/2.2).

Un cantTell no te deja solo con una pregunta. Cada uno que informa una regla de core dice cómo responderla: unos pocos pasos a partir del elemento que señala, y lo que verás si cumple y si falla, en el idioma del análisis. Cuando la página aporta indicios, el resultado además se inclina hacia pass o fail, con los hechos que leyó, su motivo y lo que podría hacerlo erróneo. Cada inclinación se cuenta frente a los casos de prueba ACT del W3C y, cuando se ha contado en al menos cinco, dice cuántas veces acertó; hasta entonces no lleva ninguna cifra, nunca una estimación. El resultado sigue siendo cantTell: una inclinación ordena las preguntas, y las sigue respondiendo una persona. Consulta Cómo comprobarlo e Inclinaciones en el Esquema de salida, y LEANS.md (en GitHub, en inglés) para saber qué hace que un resultado se incline y hasta qué punto fiarse de ello.

Un análisis es la mitad de una evaluación, y el motor te da también la otra mitad. Para cada criterio de WCAG que evalúan sus reglas, core tiene un procedimiento de prueba para cada parte de él: los pasos que sigue una persona en un navegador, las herramientas que necesita (un teclado, un lector de pantalla, el zoom) y lo que ve si cumple y si falla, en cinco idiomas. Son el mismo texto del que sale el «Cómo comprobarlo» de un hallazgo. Léelos como datos, o genéralos como una referencia o como una hoja de trabajo que registra cada resultado y los agrega por criterio, sin análisis para una auditoría manual, o junto a uno para lo que deja abierto. Consulta Procedimientos de prueba, o abre la hoja de trabajo de WCAG 2.2 AA.

El informe HTML presenta las preguntas en el orden en que las revisa una persona: «Probable fallo: confírmelo», «Probablemente cumple: confírmelo» y «Lo debe revisar una persona». Cada tarjeta tiene sus pasos de «Cómo comprobarlo», y las de los dos primeros grupos dicen por qué se inclinan, y una última sección, «Lo que queda para una persona», enumera las comprobaciones que ninguna regla decide por completo, criterio por criterio, junto al resultado del análisis para cada uno. En CI, los informes JUnit y SARIF también pueden bloquear la compilación por los resultados que se inclinan hacia el fallo, desactivado por defecto, y una baseline puede aceptar los que una página ya tiene, de modo que solo los nuevos rompen la compilación. Consulta Informe HTML y Baseline / allowlist, o abre un informe de ejemplo de una pequeña página de pago.

Un pass que pasó por poco lo dice. Las reglas que miden contra un umbral (contraste, tamaño del objetivo, espaciado del texto) informan de un margin cuando el pass más ajustado quedó cerca del límite: el elemento que más se acercó sin dejar de cumplirlo. Un texto con 4,52:1 frente a un mínimo de 4,5:1 pasa, y el margen lo muestra, así que puedes corregirlo antes de que un cambio pequeño lo convierta en un fail. Consulta el Esquema de salida.

Nombra el estándar y el motor elige las reglas. { wcag: { version: '2.2', level: 'AA' } } ejecuta las reglas de los criterios A y AA de WCAG 2.2, según el nivel que tiene cada criterio en esa versión, y bestPractices: true añade las comprobaciones que WCAG no exige. profile: 'wcag21-aa' hace lo mismo por su nombre, para WCAG 2.0, 2.1 y 2.2 en cada nivel, y puede analizarse junto al perfil de un pack. Un estándar más allá de WCAG, como uno nacional o la política propia de tu organización, llega como un pack: sus reglas, perfiles y elementos de lista de comprobación se ejecutan junto a los de core y aparecen en todos los informes. Consulta Opciones del motor y Packs.

Nombra varios estándares, y un solo análisis juzga la página con cada uno. profile: ['wcag22-aa', 'wai-aria-1.2'] la juzga con WCAG y con WAI-ARIA a la vez: cada perfil decide como lo haría un análisis solo de él, el resultado cuenta como un análisis con las reglas de todos, y cada hallazgo dice qué hace de él cada perfil. Un atributo que un rol no admite es una pregunta para WCAG 4.1.2 y un fallo de WAI-ARIA, y el resultado dice ambas cosas, así que nada se cuenta dos veces y nada se pierde. Consulta Opciones del motor.

Si nombras comprobaciones en lugar de un estándar, el resultado sigue indicando a qué criterios de WCAG afectan. Un análisis que ejecuta solo link-name-present informa también de 2.4.4 y 4.1.2, más el AAA 2.4.9 si el análisis no fija un nivel, y un criterio cuyas otras comprobaciones el análisis dejó fuera resulta cantTell («Comprobado en parte» en el informe HTML), no pass. wcagLevel: 'AA' fija el nivel de los criterios que informa un análisis, y los informes JUnit, SARIF y EARL lo siguen, así que una compilación AA no falla por un criterio AAA.

Ningún criterio de WCAG se da por cumplido a partir de reglas que solo comprueban una parte de él. Un criterio cumple solo cuando sus reglas comprueban todo lo que pide, y todavía no hay ninguno comprobado tan a fondo, así que cuando todas las reglas de un criterio cumplen, el criterio resulta cantTell: las partes que comprueban las reglas se cumplen, y una persona comprueba el resto. Un informe sin ningún fallo dice lo mismo bajo su titular: ninguna regla ha fallado, y eso no significa que la página sea conforme. Dar esos criterios por cumplidos sería la falsa sensación de cobertura que este motor está hecho para evitar. Consulta Mapeo de conformidad con WCAG.

Un fallo de WCAG es un fallo de WCAG, no una especificación incumplida que WCAG no cuenta. Donde solo se incumple WAI-ARIA o el modelo de contenido de HTML, y el nombre, el rol y el valor de los que dependen las personas sobreviven, las reglas de estructura ARIA y HTML preguntan en lugar de fallar, con pasos para comprobarlo. El pack de WAI-ARIA lee los mismos hallazgos según los propios MUST de WAI-ARIA, así que un equipo que se exige la especificación puede fallar por ella, si así lo elige.

Los componentes web se juzgan por lo que exponen. Un elemento personalizado que se da un nombre, estados o un rol mediante ElementInternals se comprueba con ellos cuando el motor puede leerlos, y se pregunta por él cuando no puede. Para ejecuciones de prueba y de auditoría, internalsHookScript() es un script opcional que permite al análisis leer los internals que un componente guarda en privado, de modo que esos elementos se aprueban o fallan en lugar de quedar en cantTell. INTEGRATION.md (en GitHub) muestra cómo instalarlo antes de los scripts de la propia página.

Las reglas llegan a tres criterios que ninguna regla cubría antes: 3.3.1 Identificación de errores (un campo marcado como no válido cuyo mensaje de error falta, está oculto o no está asociado a él), 4.1.3 Mensajes de estado (una región viva a la que las tecnologías de apoyo no pueden llegar) y 1.4.5 Imágenes de texto (texto dibujado en una imagen que podría ser texto real). Las tres preguntan en lugar de fallar. Las reglas de teclado leen los controladores de eventos del marcado; con listenerHookScript(), otro script opcional que se instala antes de los de la propia página, juzgan también los listeners añadidos desde script, así que un role="button" en el orden de tabulación con un listener de clic y ninguno de teclado en ningún lugar al que lleguen sus teclas (en él, dentro de él, en sus ancestros, en un shadow root en el que esté, el documento o la ventana), y sin ningún listener de foco que pudiera añadir uno, falla: Intro y Espacio no hacen nada. INTEGRATION.md (en GitHub) muestra cómo instalarlo, y su equivalente para los mensajes de estado, el hook de regiones vivas.

En un navegador, el contraste se mide tal como se dibuja la página: el texto de una página sin fondo propio, sobre el lienzo que pinta el navegador, claro u oscuro; el texto generado con ::before, ::after y los marcadores de lista; un <select> cerrado. Antes se omitían o se preguntaba por ellos. El texto dibujado solo con un contorno o una sombra falla ahora donde todos los colores con los que se dibuja quedan por debajo de la proporción. Un único carácter que hace las veces del nombre de un control, como la «X» de un botón llamado «Cerrar», se pregunta en lugar de fallar: saber si es un icono o una letra requiere a una persona.

Verificado contra el corpus de ACT

El motor incluye 145 reglas. Las que tienen una contraparte en W3C ACT Rules se ejecutan contra los casos de prueba que el W3C publica para ellas, el conjunto que puntúa el propio listado de implementaciones del W3C: 957 ejemplos en 60 reglas de ACT. El motor no falla en ninguno de los ejemplos que ACT marca como aprobados o no aplicables, por lo que no informa falsos positivos frente a ese corpus. Es un resultado sobre esos ejemplos, no una garantía para cualquier página; cuando el motor no puede decidir un caso, devuelve cantTell, algo que ACT permite a una implementación automatizada.

Se cumple en los dos lugares donde se ejecuta el motor: en jsdom, como lo ejecutan test-matchers y la CLI por defecto, y en Chromium, como lo hacen las integraciones de navegador, con cada caso de prueba cargado como una página real, incluidos sus scripts y hojas de estilo enlazadas. Veintidós ejemplos que ACT marca como fallidos quedan sin señalar en jsdom, y 18 en Chromium. En su mayoría son juicios de valor, como si un encabezado describe el contenido que tiene debajo; los cuatro que detecta el navegador necesitan los scripts o las hojas de estilo de la propia página, que jsdom no ejecuta. Consulta ACT_RULE_MAPPING.md para ver cada uno, con el razonamiento.

Dos informes de implementación EARL registran el resultado de cada uno de esos casos, incluidos los resultados aprobados y no aplicables, de modo que una regla que permaneció en silencio porque nada le era aplicable se distingue de una que directamente no está implementada: SureA11y, ejecutado en jsdom, y SureA11y in a browser, ejecutado en Chromium. Consulta Informe EARL para conocer el formato.

Principios clave

  • Ejecución determinista. La misma página, renderizada en las mismas condiciones y analizada con las mismas opciones, recibe las mismas decisiones. Los tiempos, las marcas de tiempo y los detalles del entorno en el resultado pueden variar entre ejecuciones. Las animaciones y transiciones en curso se detienen durante el análisis, así que un fundido a medias no cambia lo que miden las reglas.
  • Conservador por diseño. Las reglas de core reservan fail para violaciones objetivas y normativas, para que las falsas alarmas sean poco frecuentes.
  • Trazabilidad frente a los estándares. Las reglas se asignan al Criterio de Éxito de WCAG aplicable siempre que corresponde.
  • Salida estable y legible por máquina. Los identificadores de regla permanecen estables sin importar el idioma.
  • Independiente del framework. Se ejecuta dentro de jsdom o de cualquier framework de automatización de navegador.
  • Extensible. Agrega reglas personalizadas, registra políticas y filtra análisis por ID de regla, etiquetas o versión de WCAG.
  • Informes localizados. Los mensajes legibles por humanos se pueden traducir sin afectar los datos legibles por máquina: hoy incluye en, fr, de, es y ja.

Filosofía

Automatiza lo que se puede determinar objetivamente. Nunca finjas automatizar lo que no se puede.

Algunos requisitos de WCAG se pueden comprobar con total confianza. Otros necesitan juicio humano, conocimiento del contexto o una evaluación de usabilidad. Una puntuación única o un veredicto binario borra esa diferencia; surea11y la informa. Por eso existen cantTell y notApplicable como resultados, y eso da forma a cada regla del motor.

Lo que surea11y no detecta

Ser explícito sobre los límites de la automatización es parte de la misma filosofía. Por ejemplo, surea11y no:

  • confirma que un texto alternativo sea significativo, solo que esté presente (un atributo alt con el valor "image123.png" aprueba la comprobación objetiva, y se pregunta por él, inclinado hacia el fallo, como nombre de archivo);
  • juzga si una elección de contraste de color es estéticamente apropiada, solo si cumple la relación de contraste aplicable;
  • determina si un mensaje de error realmente explica el problema, ya que eso depende de una lógica de validación que un análisis estático no puede ver;
  • detecta una trampa de foco de teclado o contenido recortado al 400% de zoom, ya que ambos requieren simular una interacción real del usuario a lo largo del tiempo, no solo leer el DOM en un instante.

Algunas comprobaciones implementadas informan cantTell cuando una persona tiene que decidir. Otros aspectos, como las trampas de teclado y el reflujo al aplicar zoom, el motor no los comprueba en absoluto y necesitan pruebas aparte: ningún cantTell los sustituye, así que un resultado sin ninguno no significa que se hayan cubierto. Consulta Limitaciones conocidas para ver la lista completa, y los procedimientos de prueba para saber cómo comprueba una persona los criterios que evalúan las reglas.

Sobre el proyecto

surea11y es un proyecto independiente de código abierto, desarrollado a la vista de todos.

@surea11y/core y todos los paquetes de integración están publicados en npm. Las incidencias, las conversaciones y cada cambio son públicos en GitHub, y las contribuciones son bienvenidas. Consulta CONTRIBUTING.md (en inglés) para ver las pautas de contribución.