Al utilizar herramientas como Storybook y Cypress para pruebas de accesibilidad en aplicaciones web, los desarrolladores pueden encontrarse con una serie de errores, uno de los más comunes siendo el mensaje "Axe is already running. Use await axe.run() to wait for the previous run to finish before starting a new run." Este artículo aborda cómo resolver este problema en el contexto de pruebas de accesibilidad (a11y) utilizando la biblioteca cypress-axe.
Contexto
En la configuración actual, estamos utilizando Storybook v8.6.7 y Cypress v14.2.0 junto con cypress-axe v1.6.0. En la mayoría de los casos, las pruebas se ejecutan correctamente, pero ocasionalmente surge el error mencionado, lo que interrumpe el flujo de pruebas.
Caso de Prueba
Un caso típico de prueba para una página de calendario podría verse así:
describe('Calendar page a11y', () => {
beforeEach(() => {
cy.visit('/iframe.html?viewMode=story&id=components-calendar-pages--calendar-');
cy.injectAxe();
});
it('single day inline has no detectable a11y violation on load', () => {
cy.get(CALENDAR_PAGE_SELECTORS.SINGLE_DAY_INLINE);
cy.checkA11y(CALENDAR_PAGE_SELECTORS.SINGLE_DAY_INLINE);
});
// Otros casos de prueba...
});
Solución al Problema
Una estrategia para abordar el error "Axe is already running" es utilizar una lógica que verifique si Axe está en ejecución antes de invocar checkA11y
. Aquí hay una implementación que ha demostrado funcionar:
describe('Calendar page a11y', () => {
beforeEach(() => {
cy.visit('/iframe.html?viewMode=story&id=components-calendar-pages--calendar-');
cy.injectAxe();
});
[
{ name: 'single day inline', selector: CALENDAR_PAGE_SELECTORS.SINGLE_DAY_INLINE },
{ name: 'single day no time', selector: CALENDAR_PAGE_SELECTORS.SINGLE_DAY_NO_TIME },
{ name: 'single day with time', selector: CALENDAR_PAGE_SELECTORS.SINGLE_DAY_WITH_TIME },
// Otros selectores...
].forEach(({ name, selector }) => {
it(`${name} has no detectable a11y violation on load`, () => {
cy.get(selector).should('exist').should('be.visible');
cy.window().then(async (win) => {
if (!win.axe) {
throw new Error('Axe is not loaded');
}
while (win.axe._running) {
await new Promise((resolve) => setTimeout(resolve, 50));
}
cy.checkA11y(selector);
});
});
});
});
Explicación del Código
- Uso de
cy.window()
: Esto permite acceder al contexto de la ventana actual, donde podemos acceder a la instancia de Axe. - Comprobación de Ejecución: La condición
while (win.axe._running)
se emplea para comprobar si Axe está en la fase de ejecución. Si lo está, se espera un breve periodo antes de volver a comprobar. - Llamada a
checkA11y
: Una vez que se confirma que no hay otra ejecución en curso, se procede a invocarcy.checkA11y(selector)
para verificar la accesibilidad.
Conclusión
Si bien este método puede parecer poco convencional, es una solución efectiva para manejar el error "Axe is already running". Sin embargo, siempre es recomendable estar atento a las actualizaciones de las bibliotecas y frameworks que se utilizan, ya que las versiones más recientes pueden introducir mejoras y soluciones a problemas comunes. Además, explorar otras alternativas y patrones de diseño en pruebas puede ofrecer soluciones adicionales a los problemas de accesibilidad en sus aplicaciones.