Skip to content

El ejecutor de pruebas de Bun funciona bien con bibliotecas existentes de pruebas de componentes y DOM, incluyendo React Testing Library y happy-dom.

happy-dom

Para escribir pruebas headless para tu código frontend y componentes, recomendamos happy-dom. Happy DOM implementa un conjunto completo de APIs HTML y DOM en JavaScript puro, haciendo posible simular un entorno de navegador con alta fidelidad.

Para comenzar instala el paquete @happy-dom/global-registrator como dependencia de desarrollo.

bash
bun add -d @happy-dom/global-registrator

Estaremos usando la funcionalidad de precarga de Bun para registrar los globales de happy-dom antes de ejecutar nuestras pruebas. Este paso hará que las APIs del navegador como document estén disponibles en el ámbito global. Crea un archivo llamado happydom.ts en la raíz de tu proyecto y agrega el siguiente código:

happydom.ts
ts
import { GlobalRegistrator } from "@happy-dom/global-registrator";

GlobalRegistrator.register();

Para precargar este archivo antes de bun test, abre o crea un archivo bunfig.toml y agrega las siguientes líneas.

bunfig.toml
toml
[test]
preload = ["./happydom.ts"]

Esto ejecutará happydom.ts cuando ejecutes bun test. Ahora puedes escribir pruebas que usan APIs del navegador como document y window.

dom.test.ts
ts
import { test, expect } from "bun:test";

test("prueba de dom", () => {
  document.body.innerHTML = `<button>Mi botón</button>`;
  const button = document.querySelector("button");
  expect(button?.innerText).toEqual("Mi botón");
});

Soporte de TypeScript

Dependiendo de tu configuración de tsconfig.json, podrías ver un error de tipo "Cannot find name 'document'" en el código anterior. Para "inyectar" los tipos para document y otras APIs del navegador, agrega la siguiente directiva de triple barra al principio de cualquier archivo de prueba.

dom.test.ts
ts
/// <reference lib="dom" />

import { test, expect } from "bun:test";

test("prueba de dom", () => {
  document.body.innerHTML = `<button>Mi botón</button>`;
  const button = document.querySelector("button");
  expect(button?.innerText).toEqual("Mi botón");
});

Ejecutemos esta prueba con bun test:

bash
bun test
bun test v1.3.3

dom.test.ts:
✓ prueba de dom [0.82ms]

 1 pass
 0 fail
 1 expect() calls
Ran 1 tests across 1 files. 1 total [125.00ms]

React Testing Library

Bun funciona perfectamente con React Testing Library para probar componentes React. Después de configurar happy-dom como se mostró arriba, puedes instalar y usar React Testing Library normalmente.

bash
bun add -d @testing-library/react @testing-library/jest-dom
component.test.tsx
ts
/// <reference lib="dom" />

import { test, expect } from 'bun:test';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';

function Button({ children }: { children: React.ReactNode }) {
  return <button>{children}</button>;
}

test('renderiza botón', () => {
  render(<Button>Haz clic aquí</Button>);
  expect(screen.getByRole('button')).toHaveTextContent('Haz clic aquí');
});

Pruebas de DOM avanzadas

Elementos personalizados

Puedes probar elementos personalizados y componentes web usando la misma configuración:

custom-element.test.ts
ts
/// <reference lib="dom" />

import { test, expect } from "bun:test";

test("elemento personalizado", () => {
  // Definir un elemento personalizado
  class MyElement extends HTMLElement {
    constructor() {
      super();
      this.innerHTML = "<p>Contenido del elemento personalizado</p>";
    }
  }

  customElements.define("my-element", MyElement);

  // Usarlo en pruebas
  document.body.innerHTML = "<my-element></my-element>";
  const element = document.querySelector("my-element");
  expect(element?.innerHTML).toBe("<p>Contenido del elemento personalizado</p>");
});

Pruebas de eventos

Prueba eventos DOM e interacciones de usuario:

events.test.ts
ts
/// <reference lib="dom" />

import { test, expect } from "bun:test";

test("evento de clic de botón", () => {
  let clicked = false;

  document.body.innerHTML = '<button id="test-btn">Haz clic aquí</button>';
  const button = document.getElementById("test-btn");

  button?.addEventListener("click", () => {
    clicked = true;
  });

  button?.click();
  expect(clicked).toBe(true);
});

Consejos de configuración

Configuración global

Para configuraciones de pruebas DOM más complejas, puedes crear un archivo de precarga más completo:

test-setup.ts
ts
import { GlobalRegistrator } from "@happy-dom/global-registrator";
import "@testing-library/jest-dom";

// Registrar globales de happy-dom
GlobalRegistrator.register();

// Agregar cualquier configuración de prueba global aquí
global.ResizeObserver = class ResizeObserver {
  observe() {}
  unobserve() {}
  disconnect() {}
};

// Mockear otras APIs según sea necesario
Object.defineProperty(window, "matchMedia", {
  writable: true,
  value: jest.fn().mockImplementation(query => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: jest.fn(),
    removeListener: jest.fn(),
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  })),
});

Luego actualiza tu bunfig.toml:

bunfig.toml
toml
[test]
preload = ["./test-setup.ts"]

Solución de problemas

Problemas comunes

Errores de TypeScript para APIs DOM: Asegúrate de incluir la directiva /// <reference lib="dom" /> al principio de tus archivos de prueba.

Globales faltantes: Asegúrate de que @happy-dom/global-registrator esté correctamente importado y registrado en tu archivo de precarga.

Problemas de renderizado de componentes React: Asegúrate de haber instalado tanto @testing-library/react como de tener happy-dom configurado correctamente.

Consideraciones de rendimiento

Happy-dom es rápido, pero para suites de pruebas muy grandes, podrías querer:

  • Usar beforeEach para restablecer el estado del DOM entre pruebas
  • Evitar crear demasiados elementos DOM en una sola prueba
  • Considerar usar funciones cleanup de bibliotecas de pruebas
test-setup.ts
ts
import { afterEach } from "bun:test";
import { cleanup } from "@testing-library/react";

afterEach(() => {
  cleanup();
  document.body.innerHTML = "";
});

Bun por www.bunjs.com.cn editar