DEV Community

Silviu Technology
Silviu Technology

Posted on

React: un inbox de prueba que explica cada espera

Un inbox de prueba en una app React no debería limitarse a mostrar un spinner. Cuando esperamos un correo de verificación, la interfaz necesita explicar que está pasando, que puede hacer la persona y cuando conviene volver a intentar. Este enfoque reduce la incertidumbre y hace que un flujo de pruebas con correo temporal sea mucho más fácil de depurar.

El problema: una espera que parece un fallo

En mis flujos de frontend, el fallo más costoso no siempre está en la API. A veces el endpoint responde bien, pero la pantalla deja al usuario ante un botón desactivado y un indicador que gira sin contexto. Después de unos segundos, la pregunta es inevitable: ¿el email no llegó, la bandeja está vacía o la aplicación se rompió?

Un inbox de prueba tiene varios momentos distintos:

  • todavía no se ha solicitado el mensaje;
  • la solicitud está en curso;
  • la bandeja está esperando un mensaje nuevo;
  • el mensaje llegó y puede abrirse;
  • la espera expiró o devolvió un error.

Me gusta tratar cada momento como un estado de producto, no como un detalle interno de la petición. Así se puede probar un fake email generator, un buzón local o una integración real sin cambiar la expectativa de la interfaz.

Modelar el inbox como estados visibles

Un modelo pequeño evita que los componentes acumulen condiciones contradictorias. Por ejemplo, waiting no significa lo mismo que empty: en el primero hay una consulta activa; en el segundo, la consulta terminó y no encontró nada.

type InboxState =
  | { kind: "idle" }
  | { kind: "waiting"; startedAt: number }
  | { kind: "empty"; checkedAt: number }
  | { kind: "ready"; subject: string; receivedAt: number }
  | { kind: "error"; message: string };
Enter fullscreen mode Exit fullscreen mode

Con esta separación, el texto de la pantalla puede ser preciso. “Buscando el correo” comunica una acción en progreso; “Aún no hay mensajes” comunica un resultado. Parece una diferencia pequeña, pero ayuda a que el equipo de QA y quien desarrolla hablen del mismo escenario.

Un componente React con feedback útil

El componente no necesita conocer todos los detalles del proveedor de correo. Solo recibe el estado y expone una acción que se pueda repetir de forma segura.

function TestInbox({ state, onRefresh }: Props) {
  const label = {
    idle: "El inbox está listo",
    waiting: "Buscando el correo de prueba",
    empty: "Aún no hay mensajes",
    ready: "Correo recibido",
    error: "No pudimos consultar el inbox"
  }[state.kind];

  return (
    <section aria-labelledby="inbox-title" aria-live="polite">
      <h2 id="inbox-title">Inbox de prueba</h2>
      <p>{label}</p>
      {state.kind === "waiting" && <progress aria-label="Esperando correo" />}
      {state.kind === "ready" && <p>{state.subject}</p>}
      {(state.kind === "empty" || state.kind === "error") && (
        <button type="button" onClick={onRefresh}>Volver a consultar</button>
      )}
    </section>
  );
}
Enter fullscreen mode Exit fullscreen mode

aria-live="polite" anuncia los cambios sin interrumpir una lectura. El botón sigue siendo un botón real, con foco visible y un nombre que explica la acción. Si el chequeo tarda, mantengo el texto “Buscando” cerca del indicador; un spinner por sí solo no ayuda a una persona que navega con lector de pantalla.

También conviene mostrar el tiempo de la última consulta. No hace falta prometer una entrega instantánea: una frase como “Última revisión hace unos segundos” da contexto y evita clics repetidos. En pruebas con tp mail so o con otra fuente, ese dato permite distinguir una demora del proveedor de un problema de renderizado.

Accesibilidad y rendimiento en la misma revisión

La accesibilidad no es una capa para añadir al final. Un estado explícito mejora el rendimiento percibido porque la persona entiende la espera antes de decidir si abandona o pulsa otra vez. En mi revisión de CSS compruebo tres cosas:

  1. El layout no salta cuando aparece el botón o el asunto del mensaje. Reservo espacio para esos elementos y evito cambios bruscos.
  2. El foco no desaparece al actualizar la lista. Si se abre un detalle, lo devuelvo a un encabezado útil o al control que inició la acción.
  3. La animación es opcional. Con prefers-reduced-motion, desactivo el giro y mantengo un indicador textual.
@media (prefers-reduced-motion: reduce) {
  .inbox-spinner {
    animation: none;
  }
}
Enter fullscreen mode Exit fullscreen mode

En móvil, reviso que el mensaje de estado y el botón queden juntos, sin obligar a desplazarse para entender el resultado. Es un ajuste simple, pero se nota mucho en una interacion corta de verificación.

Checklist para probar el flujo

Antes de dar por terminado el componente, pruebo estos casos:

  • solicitud lenta: el estado cambia rápido y explica la espera;
  • respuesta vacía: no se presenta como un error del sistema;
  • mensaje recibido: el asunto y la hora son legibles;
  • error de red: existe un camino claro para reintentar;
  • doble clic: no se generan consultas duplicadas sin control;
  • lector de pantalla: cada transición tiene una etiqueta entendible;
  • pantalla estrecha: el contenido no se desborda ni se superpone.

Para investigar mensajes de activación en un producto SaaS, puede servir revisar emails de activación en un SaaS. Y si la validación vive dentro de un formulario, recomiendo validar emails sin fricción visual antes de añadir más lógica al inbox.

Hay un detalle de documentación que suele olvidarse: registrar los nombres usados por el equipo. Un test puede buscar “tepm mail com” o “tempail” por una razón histórica, pero esos terminos no deberian convertirse en etiquetas visibles ni en enlaces. Los dejo como alias de fixture, con una nota breve, para que nadie confunda un typo de prueba con una funcionalidad.

Conclusión

Un inbox de prueba útil no intenta ocultar la espera. La hace legible, medible y recuperable. En React, un modelo de estados pequeño, un mensaje accesible y un layout estable suelen aportar más que otra animación o un botón de reintento colocado sin contexto.

Cuando el frontend explica si está esperando, vacío, listo o bloqueado, el flujo de verificación deja de sentirse misterioso. Y esa claridad sirve tanto para la persona que prueba la app como para quien debe diagnosticarla a las nueve de la mañana, aun con poca paciencia y menos contexto.

Top comments (0)