Skip to content

O executor de testes do Bun funciona bem com bibliotecas de teste de componentes e DOM existentes, incluindo React Testing Library e happy-dom.

happy-dom

Para escrever testes headless para seu código e componentes de frontend, recomendamos happy-dom. Happy DOM implementa um conjunto completo de APIs HTML e DOM em JavaScript puro, tornando possível simular um ambiente de navegador com alta fidelidade.

Para começar, instale o pacote @happy-dom/global-registrator como dependência de desenvolvimento.

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

Usaremos a funcionalidade de preload do Bun para registrar os globals do happy-dom antes de executar nossos testes. Esta etapa tornará APIs de navegador como document disponíveis no escopo global. Crie um arquivo chamado happydom.ts na raiz do seu projeto e adicione o seguinte código:

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

GlobalRegistrator.register();

Para fazer preload deste arquivo antes de bun test, abra ou crie um arquivo bunfig.toml e adicione as seguintes linhas.

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

Isso executará happydom.ts quando você executar bun test. Agora você pode escrever testes que usam APIs de navegador como document e window.

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

test("teste dom", () => {
  document.body.innerHTML = `<button>Meu botão</button>`;
  const button = document.querySelector("button");
  expect(button?.innerText).toEqual("Meu botão");
});

Suporte a TypeScript

Dependendo da sua configuração tsconfig.json, você pode ver um erro de tipo "Cannot find name 'document'" no código acima. Para "injetar" os tipos para document e outras APIs de navegador, adicione a seguinte diretiva de triple-slash no topo de qualquer arquivo de teste.

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

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

test("teste dom", () => {
  document.body.innerHTML = `<button>Meu botão</button>`;
  const button = document.querySelector("button");
  expect(button?.innerText).toEqual("Meu botão");
});

Vamos executar este teste com bun test:

bash
bun test
bun test v1.3.3

dom.test.ts:
✓ teste dom [0.82ms]

 1 aprovação
 0 falhas
 1 chamada expect()
Executados 1 testes em 1 arquivos. 1 total [125.00ms]

React Testing Library

Bun funciona perfeitamente com React Testing Library para testar componentes React. Após configurar happy-dom como mostrado acima, você pode instalar e 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ão', () => {
  render(<Button>Clique em mim</Button>);
  expect(screen.getByRole('button')).toHaveTextContent('Clique em mim');
});

Teste de DOM Avançado

Elementos Personalizados

Você pode testar elementos personalizados e web components usando a mesma configuração:

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

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

test("elemento personalizado", () => {
  // Definir um elemento personalizado
  class MyElement extends HTMLElement {
    constructor() {
      super();
      this.innerHTML = "<p>Conteúdo do elemento personalizado</p>";
    }
  }

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

  // Usar em testes
  document.body.innerHTML = "<my-element></my-element>";
  const element = document.querySelector("my-element");
  expect(element?.innerHTML).toBe("<p>Conteúdo do elemento personalizado</p>");
});

Teste de Eventos

Teste eventos DOM e interações do usuário:

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

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

test("evento de clique no botão", () => {
  let clicked = false;

  document.body.innerHTML = '<button id="test-btn">Clique em mim</button>';
  const button = document.getElementById("test-btn");

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

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

Dicas de Configuração

Configuração Global

Para configurações de teste de DOM mais complexas, você pode criar um arquivo de preload mais abrangente:

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

// Registrar globals do happy-dom
GlobalRegistrator.register();

// Adicionar qualquer configuração de teste global aqui
global.ResizeObserver = class ResizeObserver {
  observe() {}
  unobserve() {}
  disconnect() {}
};

// Mock de outras APIs conforme necessário
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(),
  })),
});

Então atualize seu bunfig.toml:

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

Solução de Problemas

Problemas Comuns

Erros TypeScript para APIs DOM: Certifique-se de incluir a diretiva /// <reference lib="dom" /> no topo dos seus arquivos de teste.

Globals faltantes: Certifique-se de que @happy-dom/global-registrator está devidamente importado e registrado no seu arquivo de preload.

Problemas de renderização de componentes React: Certifique-se de instalar tanto @testing-library/react e ter happy-dom configurado corretamente.

Considerações de Desempenho

Happy-dom é rápido, mas para suítes de teste muito grandes, você pode querer:

  • Usar beforeEach para redefinir o estado do DOM entre testes
  • Evitar criar muitos elementos DOM em um único teste
  • Considerar usar funções cleanup de bibliotecas de teste
test-setup.ts
ts
import { afterEach } from "bun:test";
import { cleanup } from "@testing-library/react";

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

Bun by www.bunjs.com.cn edit