CommunityProgramación y desarrollogithub.com

Naki-404/naki-frontend-testing

Pruebas unitarias y de componentes de frontend con Vitest y React Testing Library: pruebas centradas en comportamiento, consultas accesibles, user-event, simulación de red con MSW, hooks, UI asíncrona y cobertura. Úsalo al escribir o corregir pruebas para componentes, hooks o páginas de React, o cuando las pruebas sean lentas, inestables o estén acopladas a detalles de implementación.

¿Qué es naki-frontend-testing?

Este skill proporciona una guía completa para escribir pruebas de frontend robustas y mantenibles con Vitest y React Testing Library, enfatizando un enfoque basado en el comportamiento del usuario en lugar de los detalles de implementación. Es útil para desarrolladores que necesitan crear o corregir pruebas para componentes, hooks o páginas de React, especialmente cuando las pruebas existentes son lentas, inestables o están acopladas a detalles de implementación. El skill cubre consultas accesibles, interacciones con `userEvent`, simulación de red con MSW, y patrones para probar UI asíncrona, hooks, y estados de carga, error y vacío. Además, proporciona un flujo de trabajo detallado, ejemplos prácticos, una lista de verificación y errores comunes para evitar, soportando plataformas como Cursor y Claude Code.

Compatible con~Claude Code~Codex CLI~Cursor
Part ofReact
npx skills add https://github.com/Naki-404/naki-claude-kit/tree/HEAD/kit/skills/naki-frontend-testing

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Pruebas de frontend

Prueba lo que el usuario ve y hace, no cómo está construido el componente. Combínalo con naki-tdd para el ciclo de desarrollo, naki-e2e-playwright para flujos completos del navegador y naki-accessibility para semántica. Sigue el skill de reglas del proyecto si existe (por ejemplo naki-myapp).

Cuándo usarlo

  • Se necesitan pruebas para un nuevo componente, hook o página.
  • Una prueba falla después de una refactorización que no cambió el comportamiento (señal de acoplamiento a implementación).
  • Las pruebas son inestables, usan waitFor en todas partes o simulan la mitad de la aplicación.

Reglas principales

  1. Consulta como un usuario. Prioridad: getByRole (con name), getByLabelText, getByPlaceholderText, getByText, getByDisplayValue. Usa getByTestId solo cuando no exista nada accesible.
  2. Interactúa con userEvent, no con fireEvent. Créalo con const user = userEvent.setup() y espera (await) cada llamada.
  3. Verifica la salida: texto visible, roles, valores de formularios, llamadas a un endpoint de red. Nunca verifiques variables de estado, detalles internos de hooks, nombres de clases CSS o métodos de instancia del componente.
  4. Simula la red, no tus módulos. Usa manejadores de MSW en la capa HTTP. Simula un módulo solo para límites externos reales (tiempo, aleatoriedad, APIs del navegador que no están en jsdom).
  5. Usa findBy* para cosas que aparecen después. Reserva waitFor para verificaciones que no son una consulta, y nunca pongas efectos secundarios dentro de waitFor.
  6. Un comportamiento por prueba, nombrado como una oración: muestra un error cuando el servidor devuelve 500.
  7. Cada prueba configura su propio estado. Sin dependencia de orden; restablece manejadores, temporizadores y almacenamiento en afterEach.
  8. Proporciona proveedores reales a través de un helper renderWithProviders (router, query client con reintentos desactivados, tema) en lugar de simularlos.
  9. La accesibilidad es comprobable. Un getByRole("button", { name: "Guardar" }) que falla a menudo significa un error real de accesibilidad. Opcionalmente, añade comprobaciones de vitest-axe para pantallas clave.
  10. La cobertura es una señal, no un objetivo. Cubre las ramas que importan: estados de error, estados vacíos, permisos.

Hoja de consultas

ElementoConsulta
botóngetByRole("button", { name: /guardar/i })
enlacegetByRole("link", { name: "Documentos" })
entrada de texto con etiquetagetByRole("textbox", { name: "Correo" }) o getByLabelText("Correo")
casilla de verificacióngetByRole("checkbox", { name: "Recordarme" })
encabezadogetByRole("heading", { level: 2, name: "Alertas" })
fila de tablagetAllByRole("row") luego within(row)
diálogogetByRole("dialog", { name: "Eliminar alerta" })
ausenciaexpect(queryByText("Error")).not.toBeInTheDocument()

Flujo de trabajo

  1. Enumera los comportamientos: estados de renderizado (carga, vacío, datos, error) e interacciones.
  2. Añade manejadores de MSW para los endpoints que llama el componente; por defecto, devuelven éxito.
  3. Escribe una prueba por comportamiento, sobrescribiendo manejadores con server.use(...) para casos de error.
  4. Ejecuta npx vitest run ruta/al/archivo.test.tsx, luego toda la suite.
  5. Rompe la implementación a propósito una vez (comenta una línea) para confirmar que la prueba puede fallar.

Configuración

// vitest.setup.ts
import "@testing-library/jest-dom/vitest";
import { afterAll, afterEach, beforeAll } from "vitest";
import { cleanup } from "@testing-library/react";
import { server } from "./src/test/server";

beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
afterEach(() => { server.resetHandlers(); cleanup(); });
afterAll(() => server.close());

onUnhandledRequest: "error" hace que una solicitud no manejada falle de forma notoria en lugar de quedarse colgada.

Ejemplo

import { http, HttpResponse } from "msw";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { server } from "../test/server";
import { AlertList } from "./AlertList";

test("lista alertas y filtra por severidad", async () => {
  server.use(http.get("/api/alerts", () => HttpResponse.json([
    { id: "a1", title: "Ataque de fuerza bruta en vpn", severity: "high" },
    { id: "a2", title: "Nuevo inicio de sesión de administrador", severity: "low" },
  ])));
  const user = userEvent.setup();
  render(<AlertList />);

  expect(await screen.findByText("Ataque de fuerza bruta en vpn")).toBeInTheDocument();
  await user.selectOptions(screen.getByRole("combobox", { name: "Severidad" }), "high");
  expect(screen.queryByText("Nuevo inicio de sesión de administrador")).not.toBeInTheDocument();
});

test("muestra un botón de reintento cuando la carga falla", async () => {
  server.use(http.get("/api/alerts", () => new HttpResponse(null, { status: 500 })));
  render(<AlertList />);
  expect(await screen.findByRole("button", { name: /reintentar/i })).toBeInTheDocument();
});

Hooks y tiempo

  • Prueba un hook a través de un componente pequeño que lo use, o con renderHook cuando no tenga UI.
  • Temporizadores falsos: vi.useFakeTimers() y userEvent.setup({ advanceTimers: vi.advanceTimersByTime }); restáuralos con vi.useRealTimers() en afterEach.
  • Congela fechas con vi.setSystemTime(new Date("2026-01-01T00:00:00Z")) para que las instantáneas y etiquetas sean estables.

Lista de verificación

  • Las consultas están basadas en roles o etiquetas.
  • Todas las llamadas a userEvent tienen await.
  • Red simulada con MSW; las solicitudes no manejadas fallan.
  • Estados de carga, error y vacío cubiertos.
  • Sin verificaciones de detalles internos o nombres de clases.
  • Las pruebas pasan solas y en cualquier orden.
  • Sin advertencias de act(...) en la salida.

Errores comunes

ErrorSolución
getByTestId en todas partesconsultas de rol/etiqueta; añade etiquetas al componente si faltan
await waitFor(() => getByText("x"))await findByText("x")
fireEvent.change para escribirawait user.type(input, "texto")
Simular el hook useAlerts directamentesimula el endpoint HTTP
Instantáneas grandes de páginas completasverificaciones explícitas sobre lo que importa
Query client con reintentos activados, pruebas de error lentasretry: false en el proveedor de prueba
Advertencias act ignoradasespera (await) la actualización de UI asíncrona con findBy*

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills relacionados