En pocas palabras
Prueba componentes aislados en un navegador real para observar su comportamiento en el entorno de ejecución.
Qué problema resuelve
Diferencias entre DOM emulado y navegador en foco, CSS, eventos y APIs web.
Cuándo utilizarlo
Componentes interactivos sensibles al navegador. Ejemplo: comprobar teclado y foco de un diálogo.
De la idea a la práctica
Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.
En el Radar compartido: Trial (valoración de la edición aportada).
Cómo funciona
Herramientas como Vitest Browser Mode montan componentes y ejecutan interacciones en motores reales. Las dependencias externas se controlan para delimitar el comportamiento probado.
Ejemplo de uso
Montar un selector con datos de prueba, abrirlo con teclado, elegir una opción y verificar el valor emitido y el foco. Ejecutar la misma prueba en los navegadores necesarios para el producto.
Por qué un navegador real
jsdom simula el DOM en Node, pero no implementa layout, estilos computados, foco real, eventos de puntero completos, IntersectionObserver fiel ni APIs como el portapapeles. Pruebas que pasan en jsdom pueden fallar en el navegador (y al revés). Un navegador real elimina esa clase de falsos resultados a cambio de algo más de tiempo de ejecución.
Configuración con Vitest
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: {
browser: {
enabled: true,
provider: 'playwright', // en versiones recientes se importa el provider como función
headless: true,
instances: [
{ browser: 'chromium' },
{ browser: 'firefox' },
{ browser: 'webkit' },
],
},
},
});
Ejemplo de prueba
import { expect, test } from 'vitest';
import { render } from 'vitest-browser-react';
import { SelectorPlazo } from './SelectorPlazo';
test('se elige un plazo con el teclado', async () => {
const onChange = vi.fn();
const screen = render(
<SelectorPlazo opciones={[6, 12, 24]} onChange={onChange} />,
);
await screen.getByRole('combobox', { name: 'Plazo' }).click();
await expect.element(screen.getByRole('listbox')).toBeVisible();
await screen.getByRole('option', { name: '12 meses' }).click();
expect(onChange).toHaveBeenCalledWith(12);
await expect.element(screen.getByRole('combobox')).toHaveFocus();
});
expect.element reintenta hasta que la condición se cumple, lo que evita esperas fijas.
Comparativa de opciones
| Herramienta | Rasgos |
|---|---|
| Vitest Browser Mode | Misma API de Vitest, reutiliza la configuración de Vite |
| Playwright Component Testing | Ecosistema de Playwright, varios navegadores |
| Cypress Component Testing | Ejecución visual interactiva |
| Storybook + pruebas de interacción | Las historias son a la vez documentación y casos de prueba |
Qué probar aquí y qué no
| En pruebas de componente en navegador | En otro nivel |
|---|---|
| Interacción, foco, teclado, accesibilidad (axe-core) | Lógica pura: pruebas unitarias |
| Comportamiento responsive y visual | Recorridos completos entre páginas: end-to-end |
| Integración con librerías que dependen del navegador | Contratos con el backend: Pact |
Mantén la red simulada (MSW) y el reloj controlado para que los resultados sean deterministas. La técnica general está en component testing.
Criterios de implementación
Esperar condiciones observables, evitar pausas fijas y controlar reloj y red. Medir estabilidad y duración antes de decidir qué casos migrar desde jsdom.
Continúa en las fuentes
Documentación oficial para verificar detalles y explorar más.