En pocas palabras
Pruebas de un componente con sus elementos internos integrados, pero aislado del resto de la aplicación. Buscan validar su comportamiento público con rapidez y estabilidad.
Qué problema resuelve
Dependencia excesiva de pruebas E2E lentas o de pruebas unitarias acopladas a detalles internos que cambian al refactorizar.
Cuándo utilizarlo
Formularios, componentes interactivos y estados de interfaz. Ejemplo: renderizar un formulario, escribir datos y verificar el error visible o el resultado del envío sin levantar todo el sistema.
De la idea a la práctica
Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.
En el Radar compartido: Adopt (valoración de la edición aportada).
Cómo funciona
La prueba monta el componente, simula interacciones y observa el DOM, eventos o efectos públicos. Las dependencias externas se controlan en sus límites, por ejemplo simulando una API, en lugar de acceder al estado privado del componente.
Ejemplo: un error de formulario
Con Vitest configurado para React y jsdom, Testing Library, user-event y un componente Formulario que presenta este comportamiento:
import { expect, test } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Formulario } from './Formulario';
test('muestra el error de un nombre vacío', async () => {
const user = userEvent.setup();
render(<Formulario />);
await user.click(screen.getByRole('button', { name: 'Guardar' }));
expect(await screen.findByText('Escribe tu nombre')).toBeTruthy();
});
Prioridad de consultas
| Prioridad | Consulta | Por qué |
|---|---|---|
| 1 | getByRole (con name) |
Refleja cómo lo perciben usuarios y tecnologías de asistencia |
| 2 | getByLabelText |
Campos de formulario |
| 3 | getByPlaceholderText, getByText |
Contenido visible |
| 4 | getByAltText, getByTitle |
Imágenes y elementos con título |
| Último | getByTestId |
Solo cuando no hay alternativa semántica |
Si un elemento no se puede encontrar por rol y nombre, probablemente tampoco es accesible: la prueba detecta el problema.
Simular la red con MSW
import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { afterAll, afterEach, beforeAll, expect, test } from 'vitest';
import { ResumenCredito } from './ResumenCredito';
const server = setupServer(
http.get('/api/creditos/:id', ({ params }) =>
HttpResponse.json({
id: params.id,
saldo: 1_250_000,
cuota: 250_000,
diasMora: 0,
}),
),
);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
test('muestra el saldo y permite ver el plan de pagos', async () => {
render(<ResumenCredito id="42" />);
expect(await screen.findByText('$ 1.250.000')).toBeInTheDocument();
await userEvent.click(
screen.getByRole('button', { name: 'Ver plan de pagos' }),
);
expect(
screen.getByRole('table', { name: 'Plan de pagos' }),
).toBeInTheDocument();
});
test('informa si el servicio no responde', async () => {
server.use(
http.get(
'/api/creditos/:id',
() => new HttpResponse(null, { status: 503 }),
),
);
render(<ResumenCredito id="42" />);
expect(await screen.findByRole('alert')).toHaveTextContent(
'No pudimos cargar tu crédito',
);
});
MSW intercepta a nivel de red, por lo que el componente usa su cliente HTTP real; los mismos handlers sirven en desarrollo, Storybook y pruebas en navegador.
Qué probar en un componente
| Sí | No |
|---|---|
| Lo que el usuario ve y puede hacer | Estado interno, nombres de funciones privadas |
| Estados de carga, vacío, error y éxito | Detalles de estilo que cambian a menudo (mejor pruebas visuales) |
| Eventos emitidos hacia el padre (props de callback) | Implementación de librerías de terceros |
| Accesibilidad básica (axe-core) | Recorridos entre varias páginas (end-to-end) |
Lugar en la estrategia de pruebas
Las pruebas de componente ofrecen la mayor parte de la confianza de una prueba end-to-end con una fracción del coste y la inestabilidad. Un reparto habitual en frontend: muchas pruebas de componente, pruebas unitarias para lógica pura, pocas end-to-end para los recorridos críticos (solicitar un crédito, pagar), y pruebas en navegador real donde jsdom no basta.
Criterios de implementación
Consulta por roles y nombres accesibles y prueba resultados visibles. Usa un navegador real para layout, foco y APIs que lo requieran. Mantén pruebas E2E para recorridos completos: el alcance del componente y el entorno de ejecución son decisiones distintas.
Continúa en las fuentes
Documentación oficial para verificar detalles y explorar más.