Saltar al contenido
Development

Seis ítems pequeños de UI, y los dos casi-desastres escondidos adentro

Por Victor Da Luz
sveltecsstestingdev-loggreenhouse

Un lote de seis ítems pequeños de revisión de UI llegó a Greenhouse: un ícono duplicado, una insignia de conteo inconsistente, un dropdown sin estilo, movimiento de diálogo faltante, un cambio de idioma que descarta la vista actual, y un bloque de CSS con apariencia de muerto. Cinco eran exactamente como se describían. Uno resultó no estar muerto en absoluto, y arreglar uno completamente sin relación casi se lleva puestas treinta y nueve pruebas con él.

Los cinco directos

Un SVG de ícono de carpeta estaba pegado en cuatro lugares distintos repartidos en dos archivos. No tres, como decía la revisión, una vez que hice grep de verdad sobre los datos del path en vez de confiar en el conteo. Lo extraje a un componente pequeño.

Una insignia de conteo en las zonas del dashboard se anunciaba a los lectores de pantalla como un número huérfano sin contexto (“3,” sin nada que diga tres de qué), mientras que la misma insignia en el tablero kanban estaba completamente oculta para los lectores de pantalla. Dos correcciones distintas aplicadas de forma inconsistente con el tiempo. En su lugar, incorporé el conteo al nombre accesible de cada encabezado (“Ripe today, 3 items”), lo que necesitó una cadena traducida y con pluralización real en vez de una codificada directamente, la misma lección que ya había aprendido por las malas del lado de iOS.

Después: le di estilo al único dropdown sin estilo que quedaba en la app, agregué movimiento de fade-in/fade-out a cada diálogo nativo con una sola regla de CSS compartida en vez de copiar y pegar en siete archivos, y arreglé el selector de idioma. Ese último recarga toda la ventana para aplicar un idioma nuevo, y antes siempre volvía a dejar a la persona en la pantalla de inicio sin importar qué tenía abierto. Ahora lo recuerda y lo restaura.

El que en realidad no estaba muerto

El sexto ítem era un bloque de CSS que fuerza el modo claro u oscuro mediante un atributo data-theme, marcado como muerto porque nada en la UI de la app establece jamás ese atributo. Confirmado por grep, incluso.

Salvo que antes de borrarlo corrí la suite de pruebas que lo ejercita, más por costumbre que por sospecha, y encontré una prueba de accesibilidad en navegador real que establece data-theme deliberadamente. Esa es la única forma de revisar el contraste de color tanto en modo claro como oscuro sin depender de cualquier tema en el que resulte estar la máquina que corre las pruebas.

Borrar el CSS no habría lanzado ningún error. Habría hecho que, en silencio, esa prueba dejara de probar el modo oscuro por completo, sin ninguna X roja que lo delatara. “Confirmado muerto por grep” solo revisó código de aplicación. Nunca revisó código de pruebas, y ya había borrado código muerto por el motivo equivocado antes.

El que rompió todo lo demás

La corrección del selector de idioma necesitaba localStorage para recordar la vista abierta a través de una recarga completa de página. Código completamente ordinario, la primera línea que escribí. Rompió treinta y nueve pruebas sin relación repartidas en tres archivos en el instante en que corrió.

Node 25 trae su propio localStorage nativo, activado por defecto. Sin un path de archivo específico configurado para él, esa versión nativa existe pero no funciona en silencio: está presente, pero le falta cada método. Se ubica delante del localStorage propio de jsdom, que sí funciona, en el entorno de pruebas, así que cualquier código que toque el global obtiene el roto.

La solución no fue un flag de configuración de jsdom. Probé eso primero y no ayudó, porque el origen nunca fue el problema real. Fue parchar el archivo de configuración de pruebas con un pequeño sustituto en memoria, de la misma forma en que ya se había parchado ahí una brecha de compatibilidad de <dialog> para una versión más vieja de jsdom.

Lección

Ninguno de esos dos habría aparecido leyendo el diff. Los dos solo aparecieron al correr la suite de pruebas existente antes de asumir que un cambio era seguro, que es el chequeo más barato posible y el más fácil de saltarse en un lote de ítems que a simple vista parecen todos de una sola línea.

Lecturas relacionadas

Development

Cuando el texto importante es el que desaparece

Una tarjeta de kanban con una etiqueta de etapa, un chip de abandono, una insignia Disponible, y sin nombre. Flexbox no sabe que "achicarse con gracia" y "achicarse hasta nada" son resultados distintos.

Leer
Development

El botón de cancelar que no cancelaba

Escape parecía funcionar en cada prueba manual. Escribir la prueba de regresión obligó a ver el orden real de eventos, y el blur perdido que guardaba lo que debía descartarse.

Leer