Preguntas frecuentes
"Mis resultados cambiaron al actualizar a core 1.16"
La 1.16 acerca jsdom al navegador y redacta sus mensajes para cualquier estándar. Los cambios que más probablemente se noten en un pipeline:
- Con jsdom, solo un diálogo abierto con
showModal() es modal, como en un navegador. La página detrás de un <dialog open aria-modal="true"> se juzga ahora, así que una prueba con jsdom que simula un modal de esa manera ve hallazgos detrás de él; engineOptions.assumeModal: true mantiene el comportamiento anterior (consulta Limitaciones conocidas; con test-matchers 1.6.0, pásalo también a installLiveRegionHook(), consulta test-matchers). Nada detrás de un diálogo modal recibe el foco, y de varios abiertos con showModal() solo se juzga el superior. - jsdom oculta lo que oculta un navegador. Las reglas dentro de
@layer, @supports y @container ocultan elementos, así que hidden y sr-only de Tailwind v4 funcionan; clip: rect(0 0 0 0) cuenta como recortado; el <area> de un mapa de imagen está en la página. Desaparecen los hallazgos sobre contenido que siempre estuvo oculto. - Los mensajes y los pasos describen la comprobación en lugar de nombrar el criterio de WCAG, en todas las configuraciones regionales, así que un informe para otro estándar se lee bien. Los mapeos y
failWhen no cambian; una prueba que compare el texto de los mensajes necesita actualizarse. - Se juzgan las páginas profundas. Un elemento a 200 o más niveles de profundidad se juzga con todo lo que tiene encima, hasta 10.000 niveles, donde un fallo tan profundo pasaba a ser una pregunta anotada en
error; así que pueden aparecer fallos ahí. Más allá de 10.000 es una pregunta, informada en ancestorWalkLimit. - Las páginas que sustituyen
Array.from (Prototype.js, MooTools) se analizan, donde antes el análisis se detenía con PAGE_BUILTINS_BROKEN (consulta la entrada de más abajo). - Algunos selectores son distintos. Los caracteres de control se escapan, un valor de más de 256 caracteres deja paso a la ruta del elemento, y
page-title-present y page-title-patterns apuntan al propio elemento del título, o a <head> cuando no hay ninguno. La identidad de un hallazgo no incluye su selector, así que los baselines siguen coincidiendo. Las reglas de contraste son notApplicable sin ninguna ocurrencia cuando no se pudo calcular ningún contraste. - Los errores se informan en lugar de leerse como nada. Un
contextSelector vacío sigue analizando toda la página, pero avisa; algo que no es un baseline lanza INVALID_BASELINE en lugar de hacer nuevo cada fallo; y con strictOptions, un nombre de perfil desconocido lanza un error. El perfil section508 está obsoleto: usa wcag20-aa, que ejecuta las mismas reglas. - Análisis más rápidos, con los mismos hallazgos: un pequeño porcentaje en Chromium en páginas corrientes, del 10 al 25 % con jsdom, y mucho más donde era peor (miles de enlaces o campos idénticos, tablas largas, muchas reglas de estilo).
Nuevo, y sin cambiar nada salvo que lo uses: los perfiles de WCAG 2.0 y 2.1 (Opciones del motor) y, experimentales hasta la 1.18.0, los estándares como datos, las pruebas bajo los requisitos, los estándares construidos sobre otros y las leyes bajo las que se evalúa un estándar (Packs). La lista completa está en el CHANGELOG.md de core.
"runOnly lanzó un error: no rule or tag named …, o either rule ids or tags"
Desde la 1.10.0, un runOnly dado como array simple o como cadena se lee como ids de regla o como etiquetas (consulta ENGINE_OPTIONS.md). Lanza un error en dos casos:
- Un valor que no nombra ninguna regla ni ninguna etiqueta, normalmente una errata:
runOnly: ['img-alt-presnt']. Comprueba el id con getChecksCatalog(). Las mayúsculas no son la causa: los ids de regla y las etiquetas se comparan sin distinguir mayúsculas y minúsculas, así que IMG-ALT-PRESENT selecciona img-alt-present. - Ids de regla y etiquetas en un mismo array:
runOnly: ['img-alt-present', 'wcag2a']. Usa la forma de objeto para combinarlos:
runOnly: {
includeRuleIds: ['img-alt-present'],
tags: ['wcag2a'],
includeMode: 'or',
}
Antes de la 1.10.0, un array simple se ignoraba y se ejecutaban todas las reglas.
La forma de objeto, { includeRuleIds }, { tags } o { type: 'tag', values }, y engineOptions.rules.include / .tags.include también lanzan un error, con code: 'INVALID_RUN_ONLY', cuando ningún valor de la lista nombra una regla o una etiqueta (runOnly.tags: no tag named "wcag2.2aa".). Antes no ejecutaban ninguna regla, lo que se lee como un análisis sin hallazgos. Un único valor desconocido junto a otros conocidos, o en una lista de exclusión, solo registra un console.warn.
Con el valor predeterminado includeMode: 'and', una selección con etiquetas e ids de regla a la vez ejecuta solo las reglas que coinciden con ambos. .withTags('wcag2a').withRules('region') no ejecuta nada, ya que region es una buena práctica sin la etiqueta wcag2a, y un análisis sin reglas no tiene fallos. El motor avisa en la consola de la página, que una ejecución de pruebas no muestra, y solo lanza INVALID_RUN_ONLY con strictOptions. Para ejecutar cualquiera de las dos, pídelo: .includeMode('or') en las integraciones, includeMode: 'or' en runOnly (arriba), o --include-mode or en la CLI. Desde la versión 1.3.0, la CLI sale con 2 y esa sugerencia cuando las dos no tienen ninguna regla en común.
Para detectar una selección que no elige nada antes de ejecutarla, comprueba el plannedChecks() del builder, las reglas que ejecutará el análisis, calculadas sin página (en Cypress devuelve un chainable):
const builder = new A11yCoreBuilder({ page })
.withTags('wcag2a')
.withRules('region')
.includeMode('or'); // the wcag2a rules, plus region
if (builder.plannedChecks().length === 0) {
throw new Error('This selection runs no rule.');
}
Consulta Opciones del motor para ver cómo se combinan las partes de una selección.
"runOnly.tags: no rules for WCAG 2.2 Level A ("wcag22a")"
Las nueve etiquetas de versión/nivel de WCAG, de wcag2a a wcag22aaa, siempre se conocen, pero tres no llevan ninguna regla: wcag21aaa, wcag22a y wcag22aaa, cuyos criterios no tienen ninguna comprobación automatizada. Nombrar una junto a otras etiquetas registra esa línea con console.info: el resto de la lista se ejecuta, y esos criterios necesitan revisión manual. Pasa engineOptions.logUntestedWcag: false para omitirla, o selecciona por objetivo, que no nombra ninguna etiqueta: runOnly: { wcag: { version: '2.2', level: 'AA' } } (consulta Seleccionar por objetivo de WCAG). Una lista con solo esas etiquetas no ejecutaría nada, así que lanza INVALID_RUN_ONLY con la misma explicación.
"runOnly.wcag.version must be …" o "runOnly.bestPractices must be true or false …"
runOnly.wcag acepta { version, level }, con version igual a '2.0', '2.1' o '2.2' (una cadena: 2.2 como número se rechaza) y level igual a 'A', 'AA' o 'AAA'; runOnly.bestPractices acepta true o false. Cualquier otra cosa lanza INVALID_RUN_ONLY nombrando el campo y el valor, en lugar de ejecutar una selección que no pretendías.
"engineOptions: unknown option "lcoale" (did you mean "locale"?)", o un análisis lanzó INVALID_ENGINE_OPTIONS
Una clave de opción a una o dos letras de una conocida, sin distinguir mayúsculas y minúsculas, genera un aviso y se ignora: el análisis se ejecuta como si no estuviera, así que corrige la ortografía. Las demás claves desconocidas no generan ningún aviso, ya que una regla personalizada puede leer ajustes propios de ctx.engineOptions. Con engineOptions.strictOptions: true, el análisis lanza en cambio un error, con code: 'INVALID_ENGINE_OPTIONS', ante cualquier clave que el motor no lee (incluidas las anidadas) y ante un valor de tipo incorrecto o fuera de su conjunto, nombrando cada una con la clave conocida más parecida; el problems del error las enumera. Consulta Detectar errores en las opciones.
"Mi regla personalizada falla, pero el resultado agregado de WCAG no"
Una regla personalizada cuenta para el resultado agregado de WCAG (rulesResults) de cada criterio al que se asocia: dale meta.wcagSc: ['1.1.1'], o una entrada de WCAG en meta.normativeMappings. Sin ninguna de las dos, no está en ningún resultado agregado. Una regla personalizada que no se ejecutó (listada en skippedCustomRules) tampoco cuenta. Una sustitución de una regla incorporada cuenta solo donde dice su propia asociación, así que una que no declara ninguna deja los resultados agregados para los que contaba su regla incorporada, y un aviso (customRules: "…" overrides a built-in rule but maps to none of the criteria of …) los nombra; dale los criterios de la regla incorporada para que siga ahí.
"Mi análisis acotado informa todo como notApplicable", o "contextSelector lanzó un error: … is not a valid CSS selector"
Desde la 1.10.0, un contextSelector que no coincide con ningún elemento no analiza nada, y uno que el navegador no puede interpretar lanza un error (consulta ENGINE_OPTIONS.md).
- Todo es
notApplicable: mira result.contextMatch. elementCount: 0 significa que el selector no coincidió con nada, así que no se analizó nada: eso no es un resultado sin hallazgos. unmatchedSelectors nombra el selector. Revisa si tiene una errata, o si el elemento ya está en la página cuando analizas (por ejemplo, contenido que un script renderiza después de la carga). - El análisis lanzó un error con
code: 'INVALID_CONTEXT_SELECTOR': el selector del mensaje, y del campo selector del error, no es CSS válido, por ejemplo '#main[' o un combinador >>>. O el ámbito no es un selector en absoluto, como un elemento o un objeto { include, exclude }, y el mensaje dice qué se pasó: pasa un selector que coincida con el elemento, y las exclusiones en engineOptions.excludeSelectors.
Antes, cada uno de estos casos analizaba la página entera: un selector que no coincidía con nada o que no se podía interpretar hasta la 1.10.0, y un ámbito que no es un selector también en la 1.10.0.
"Un análisis lanzó PAGE_BUILTINS_BROKEN"
Los propios scripts de la página cambiaron un objeto integrado de JavaScript del que depende el motor (Array.prototype.filter, Map, JSON.stringify y otros), así que un análisis de ella podría dar un resultado que parece correcto y es erróneo. El mensaje del error y su lista broken nombran cada uno. Analiza la página antes de que sus scripts los cambien (inyecta el bundle antes, o analiza una compilación sin el script que lo hace). Consulta Limitaciones conocidas.
Cuando broken es solo Array.from, la página lo sustituyó (Prototype y MooTools lo hacen) y una regla de un pack o personalizada del análisis lo usa: las reglas propias de core no lo usan, desde la 1.16. Escribe esa regla con spread ([...x], [...x].map(f)), o déjala fuera de la selección. El pack de WAI-ARIA lo hacía hasta su versión 1.0.2: actualízalo.
"Mi análisis nunca termina"
Algo en la página bloquea el análisis: un getter o un script que nunca termina, o un bucle de un pack o de una regla personalizada. Nada dentro de la página puede detener un análisis una vez iniciado, así que pon el límite de tiempo donde lo inicias, y abandona la pestaña cuando pase. Uso independiente muestra cómo hacerlo para Playwright y Puppeteer; en jsdom, ejecuta el análisis en un worker thread o en un proceso hijo.
"Un análisis tarda más tras actualizar"
La mayor parte del tiempo de un análisis es trabajo de estilos y maquetación en el navegador, así que depende de la página, la máquina y el navegador tanto como del motor. Aun así, una versión puede cambiarlo: una regla que ahora comprueba más de la página cuesta más, y el CHANGELOG.md de core indica cuándo una versión cambia lo que cuesta una regla. PERFORMANCE.md, en GitHub, registra cuánto tarda un análisis versión a versión, como proporción respecto a una versión anterior en las mismas páginas, y cómo se mide. Una regla más lenta que encuentra más puede estar pagando por lo que ahora encuentra; una más lenta con los mismos resultados es una regresión que merece la pena comunicar.
Un análisis de varios perfiles a la vez (profile: ['wcag22-aa', 'wai-aria-1.2']) analiza la página una vez por perfil, así que tarda más o menos lo que ese número de análisis.
"Un perfil no se ejecutó", o engine.profilesNotRun no está vacío
En un análisis de varios perfiles, un perfil que no pudo ejecutarse se enumera en engine.profilesNotRun con su motivo, y los demás se siguen ejecutando: unknown-profile (no existe ese perfil: el perfil de un pack necesita su pack en packs), pack-skipped (su pack no se ejecutó, consulta la entrada de más abajo) u overridden-by-selection (un include de runOnly, o ids o etiquetas de reglas en engineOptions, eligieron las reglas en su lugar, para todos los perfiles). Ese análisis juzgó menos de lo que se le pidió, así que SARIF y JUnit informan un error salvo con allowProfilesNotRun: true, la CLI sale con 2 salvo con --allow-profiles-not-run, las integraciones informan una carencia 'profile-not-run', y los test matchers hacen fallar la aserción. Consulta Opciones del motor.
"Un pack no se ejecutó", o skippedPacks no está vacío
Un pack cuyo rango core deja fuera el core instalado, que no es válido, o que no encaja con core (un id de regla fuera de su espacio de nombres, una clave de diccionario que core ya tiene) se omite: el análisis se ejecuta sin él, avisa, y lo enumera en result.skippedPacks con el motivo; con strictOptions lanza un error. En una página, un pack nombrado en engineOptions.packs que ninguna llamada a packScript registró, o que se registró con otra versión de core, se enumera de la misma forma. Las integraciones lo informan como una carencia 'pack-skipped', los test matchers hacen fallar la aserción, y la CLI sale con 2. Instala el pack junto a @surea11y/core y al paquete que lo ejecuta, para que los tres compartan una sola copia de core. Consulta Packs.
"Mi regla personalizada siempre devuelve cantTell sin un motivo claro"
Primero revisa el campo error del resultado: si dice "<something> is not defined", tu runInPage hace referencia a una variable definida fuera del cuerpo de la función (un const de ámbito de módulo, un helper importado, cualquier cosa a la que no se llegue a través de ctx.*). Esta es una trampa real y común: runInPage se serializa a texto fuente y se vuelve a evaluar más tarde en el contexto de la página, así que la compilación nunca detecta esto: el problema solo aparece cuando se ejecuta la regla, y el fallo parece un resultado normal (aunque poco informativo), no un error de ejecución. Consulta RULE_AUTHORING.md §1.1 para ver la explicación completa y la solución (mueve el valor dentro de runInPage o enrútalo a través de ctx.rule/ctx.helpers).
"Una regla que depende de la geometría (por ejemplo, target-size-minimum) siempre indica notApplicable"
jsdom puro (sin un navegador real) no implementa un motor de diseño CSS: getBoundingClientRect() siempre devuelve una geometría de cero. Las reglas que necesitan información real de maquetación devuelven notApplicable al ejecutarse con jsdom en lugar de adivinar. Ejecuta en su lugar a través de un navegador real (Puppeteer/Playwright, consulta INTEGRATION.md Patrón 2) para obtener hallazgos reales de estas reglas. Consulta LIMITATIONS.md.
"Las reglas de título, idioma y regiones de referencia son notApplicable en un frame"
Desde la 1.15, un documento mostrado en un frame no es una página propia: page-title-present, page-title-patterns, html-lang-attr-present, meta-viewport-zoom-enabled, meta-viewport-large, region, bypass-blocks-present, landmark-one-main y page-has-heading-one son notApplicable en él. La página que rodea el frame es la que tiene el título, el idioma y las regiones de referencia que usan las personas, y un navegador ignora el <meta> viewport de un documento en un frame. Un ejecutor de pruebas que muestra la página bajo prueba en un frame propio establece engineOptions.topLevelDocument: true; @surea11y/cypress 1.6.0 lo hace por ti. Consulta Opciones del motor.
"Un componente web devuelve cantTell (name_internals)"
Un elemento personalizado que se da nombre, define sus estados o se asigna un rol mediante un ElementInternals guardado en un campo privado (#internals) queda expuesto por el navegador, pero ningún script de la página puede volver a leerlo. Desde la 1.12, el motor lee los internals guardados en una propiedad (_internals, internals, …), y pregunta por cualquier otro elemento personalizado definido sin un nombre legible o sin un estado obligatorio (name_internals, state_internals) en lugar de hacerlo fallar.
Para que el análisis pueda juzgar esos elementos, instala el hook de internals antes de que se ejecuten los scripts de la página: installInternalsHook() en cada integración (en la página o el contexto en Playwright, la página en Puppeteer, el driver en Selenium, el browser en WebdriverIO, el archivo de soporte u onBeforeLoad en Cypress) y en el archivo de configuración de test-matchers, o internalsHookScript() de core para una página propia. El engine.environment.internalsHook del resultado indica si se ejecutó ('early' o 'late'). El hook permite que cualquier script de la página lea los internals de todos los componentes, así que está pensado para ejecuciones de prueba y auditoría. Consulta Limitaciones conocidas.
"Solo veo apariciones de fail/cantTell. ¿Dónde está la lista de elementos que aprobaron?"
Por diseño, este motor nunca enumera los elementos que una regla aprobó, solo los que señaló. El outcome: 'pass' general de una regla significa "existían uno o más objetivos aplicables y ninguno fue señalado", y occurrences es []. Las reglas de contraste son la excepción: su pass lleva una ocurrencia con un selector vacío que describe el análisis (cuánto texto era elegible y calculable), no un elemento. Si necesitas saber qué elementos concretos se comprobaron y se consideraron correctos, eso actualmente no se expone. Consulta OUTPUT_SCHEMA.md.
"Una regla que esperaba que se activara devolvió notApplicable / no encontró nada en una página que sé que tiene el problema"
Dos causas comunes, en orden de probabilidad:
- El elemento está excluido del árbol de accesibilidad:
aria-hidden="true", display: none, visibility: hidden, hidden o un ancestro inert. La mayoría de las reglas omiten contenido que ya es invisible para la tecnología de asistencia, ya que comprobar un elemento oculto no tendría sentido y podría producir un fail engañoso sobre contenido que ningún usuario encuentra. Algunas reglas se excluyen explícitamente de este filtro cuando no tendría sentido aplicarlo (por ejemplo, no-autoplay-audio: el audio oculto sigue sonando). Revisa el comentario de encabezado del archivo de la regla específica (@applicability) en src/checks/. excludeSelectors: si has configurado esto (directamente o heredado de una configuración compartida), confirma que el elemento en cuestión no coincide con él. Recuerda que esto también se puede limitar a una sola regla mediante engineOptions.rules[ruleId].excludeSelectors (consulta ENGINE_OPTIONS.md). Si una regla que esperas que se active sigue devolviendo notApplicable/pass solo para un elemento, comprueba si esa regla en particular tiene su propia lista de exclusión configurada, no solo la global.
"Todas las comprobaciones se cumplen, ¿por qué cada criterio de WCAG queda en cantTell?"
Desde la 1.14, un resultado agregado de WCAG en rulesResults se cumple solo para un criterio cuyas reglas comprueban todo lo que pide, y todavía no hay ninguno marcado así (COMPLETE_CHECK en src/coverage/complete-applicability.js). Cuando todas las reglas de un criterio se cumplen, su resultado agregado es cantTell con reasonCode composite.rollup.cantTell.partialCheck: las partes que comprueban las reglas se cumplen, y el resto lo comprueba una persona. html-lang-attr-present comprueba que <html lang="fr"> nombra un idioma, no que la página esté en francés. Del mismo modo, un criterio cuyas reglas no encontraron nada es notApplicable solo cuando encuentran todos los casos a los que se aplica, y si no, cantTell con composite.rollup.cantTell.partialCoverage. Una regla que falla sigue haciendo fallar su criterio. Muéstralos como «comprobaciones superadas, requiere revisión» y «nada que comprobar encontrado», nunca como cumplidos; consulta Mapeo de conformidad con WCAG.
No. Consulta WCAG_CONFORMANCE.md. El pass de una regla significa que las comprobaciones que se ejecutaron salieron limpias en la parte de la página que analizaron. Un análisis limitado a una parte de la página, a algunas reglas, o ejecutado bajo jsdom comprueba menos de lo que podría. Una fracción considerable de WCAG requiere juicio humano (texto alternativo preciso, mensajes de error comprensibles) o pruebas dinámicas que la arquitectura de este motor no puede hacer en absoluto (trampas de teclado, reflow al hacer zoom). Consulta LIMITATIONS.md para ver la lista explícita, deliberadamente no exhaustiva. Lo que queda le toca comprobarlo a una persona, y los procedimientos de prueba de core dicen cómo, criterio por criterio.
"¿Debo tratar cantTell como un fallo?"
Trátalo como "necesita que lo revise una persona": por diseño no es ni aprobado ni fallido. Una opción habitual es registrar los hallazgos de cantTell sin hacer fallar la CI por ellos, ya que hacer fallar una compilación por algo que el motor explícitamente no pudo determinar tiende a enseñar a la gente a ignorar la validación. Un equipo que quiera revisar cada uno antes de fusionar puede bloquear por ellos; en cualquier caso, mantenlos separados de los fallos. Entre ambas opciones, una compilación puede bloquearse solo por los hallazgos que apuntan a un fallo, donde la evidencia de la página indica un fallo: leanFailAs en los generadores de informes JUnit y SARIF, o leaningFailures(result) (consulta el esquema de salida). Cada hallazgo cantTell de una regla de core dice cómo responderlo en howToCheck. Consulta POLICY.md si quieres cambiar este comportamiento (por ejemplo, mediante un contrato de política personalizado), y INTEGRATION.md para ver un ejemplo concreto de validación en CI.
"¿Qué pasa si una configuración regional solo está parcialmente traducida?"
Las claves faltantes recurren al inglés por cadena (nunca a un resultado en blanco o roto), de modo que una configuración regional parcial recurre de forma gradual al inglés sin dejar textos vacíos, en lugar de fallar por completo. Consulta I18N.md para ver el mecanismo y la cobertura actual. La paridad de claves se hace cumplir en la propia compilación de core en lugar de darse por hecha: toda clave inglesa nueva o renombrada se traslada a los demás archivos de configuración regional, con el texto en inglés hasta que alguien la traduce, de modo que una configuración regional puede ir atrasada en la redacción sin ir nunca atrasada en las claves.
"runDomRulesInPage frente a runa11yCoreInPage: ¿cuál necesito?"
runDomRulesInPage si la llamas directamente en el mismo proceso de Node (jsdom). runa11yCoreInPage si le entregas la función en sí a un realm de JS diferente: casi siempre page.evaluate en Puppeteer/Playwright, que serializa la función a texto fuente y la vuelve a ejecutar dentro de la pestaña del navegador (que no tiene acceso al ámbito de tus módulos de Node). Consulta INTEGRATION.md para ver ambos patrones desarrollados por completo.
"Tras actualizar, mi baseline indica hallazgos conocidos como nuevos y sus entradas como obsoletas"
La identidad de un hallazgo incluye su código de motivo, y la 1.14 dio códigos a diecisiete reglas que no tenían y dividió algunos códigos según la causa. Un baseline escrito por la 1.13 sigue coincidiendo con esos hallazgos con la 1.14.x, gracias a src/baseline-moves.json, pero no con la 1.15, que quitó esos cambios: allí una entrada con un código antiguo está obsoleta y su hallazgo es nuevo. Reescribe los códigos del archivo con la 1.14.x con migrateBaselineEntries de @surea11y/core/baseline y después actualiza, o regenéralo con la 1.15 y revisa el diff. Ni la 1.15 ni la 1.16 movieron ningún código, así que un baseline escrito por la 1.14 sigue coincidiendo; un hallazgo cuyo resultado cambió con la actualización es nuevo o desaparece igualmente, y el registro de cambios explica por qué. Consulta Baseline / allowlist.
"css-orientation-lock pregunta por STYLESHEETS_NOT_READABLE"
El script de una página no puede leer una hoja de estilos que sirve otro origen (una CDN, un servicio de fuentes), así que las reglas que leen CSS no saben qué contiene. Pásale su texto al análisis en engineOptions.styleSheetTexts: preloadStyleSheets(), o runa11yCoreInPageAsync en el bundle del navegador, descarga las que el servidor comparte, y una herramienta que controla el navegador puede descargar las demás desde fuera de la página. Consulta "Style sheets from another origin" en INTEGRATION.md, la guía de integración en GitHub.
"Mis resultados cambiaron al actualizar a core 1.15"
La 1.15 hace fallar un criterio de WCAG solo donde WCAG falla, y lee los frames como los muestra el navegador. Los cambios que más probablemente se noten en un pipeline:
- Menos fallos de estructura ARIA y HTML. Ocho reglas de ARIA y las reglas de estructura HTML ya no hacen fallar un criterio donde solo se incumple WAI-ARIA o el modelo de contenido de HTML: esos hallazgos son
cantTell, con incertidumbre spec-only y pasos para comprobarlo. Afectadas: aria-role-name-present (grid, tree, radiogroup, meter, progressbar), dialog-name-present, tooltip-name-present, aria-allowed-attr, aria-valid-attr-value (salvo para el estado, el valor o el foco de un control), aria-prohibited-attr, aria-roles-valid (salvo en un elemento enfocable), aria-owns-valid (un ancestro; ahora solo se asocia al 1.3.1), list-children-valid y listitem-parent-valid (salvo donde la página dibuja el elemento defectuoso), definition-list-children-valid, dlitem-parent-valid y nested-interactive-controls-absent (salvo dentro de un control con hijos presentacionales). Cada hallazgo conserva su código de motivo, así que los baselines siguen coincidiendo, pero una validación o un resultado agregado que solo fallaban por estos ahora se cumplen o quedan en cantTell. Para juzgar los mismos hallazgos según WAI-ARIA, donde fallan, añade el pack de WAI-ARIA. - Un documento en un frame no es una página propia. En un frame,
page-title-present, html-lang-attr-present y las reglas de viewport, de bloques que saltar y de regiones de referencia son notApplicable (consulta la entrada de más arriba). Un frame bajo aria-hidden o inert se lee como tal, y uno tras un diálogo modal abierto se deja fuera. - Los roles siguen WAI-ARIA más de cerca.
role="text" no nombra ningún rol válido; una imagen con un rol presentacional y un atributo ARIA global conserva su rol, y falla img-alt-present sin alt; los cuatro globales que WAI-ARIA 1.2 declara obsoletos ya no devuelven su rol a un elemento presentacional. - Un nivel de encabezado saltado es un problema de buenas prácticas, no un fallo del 1.3.1, en los procedimientos de prueba revisados, que también dan los pasos de «Cómo comprobarlo» de seis preguntas nuevas.
- Un baseline de la 1.13 necesita ponerse al día primero. La 1.15 no movió ningún código de motivo, y quitó los cambios de la 1.13 a la 1.14 (consulta la entrada de más arriba).
Nuevo, y sin cambiar nada salvo que lo uses: análisis de varios perfiles a la vez (Opciones del motor), los perfiles wcag22-a y wcag22-aaa, los procedimientos de prueba para evaluar a mano, y «Lo que queda para una persona» en el informe HTML. La lista completa está en el CHANGELOG.md de core.