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.
bun add -d @happy-dom/global-registratorUsaremos 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:
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.
[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.
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.
/// <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:
bun testbun 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.
bun add -d @testing-library/react @testing-library/jest-dom/// <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:
/// <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:
/// <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:
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:
[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
beforeEachpara redefinir o estado do DOM entre testes - Evitar criar muitos elementos DOM em um único teste
- Considerar usar funções
cleanupde bibliotecas de teste
import { afterEach } from "bun:test";
import { cleanup } from "@testing-library/react";
afterEach(() => {
cleanup();
document.body.innerHTML = "";
});