Skip to content

Le runner de tests de Bun fonctionne bien avec les bibliothèques de test de composants et DOM existantes, y compris React Testing Library et happy-dom.

happy-dom

Pour écrire des tests headless pour votre code frontend et vos composants, nous recommandons happy-dom. Happy DOM implémente un ensemble complet d'APIs HTML et DOM en JavaScript pur, rendant possible la simulation d'un environnement navigateur avec une haute fidélité.

Pour commencer, installez le package @happy-dom/global-registrator comme dépendance de développement.

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

Nous utiliserons la fonctionnalité de préchargement de Bun pour enregistrer les globaux happy-dom avant d'exécuter nos tests. Cette étape rendra les APIs navigateur comme document disponibles dans le scope global. Créez un fichier appelé happydom.ts à la racine de votre projet et ajoutez le code suivant :

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

GlobalRegistrator.register();

Pour précharger ce fichier avant bun test, ouvrez ou créez un fichier bunfig.toml et ajoutez les lignes suivantes.

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

Cela exécutera happydom.ts lorsque vous exécuterez bun test. Vous pouvez maintenant écrire des tests qui utilisent des APIs navigateur comme document et window.

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

test("test dom", () => {
  document.body.innerHTML = `<button>Mon bouton</button>`;
  const button = document.querySelector("button");
  expect(button?.innerText).toEqual("Mon bouton");
});

Prise en charge TypeScript

Selon la configuration de votre tsconfig.json, vous pourriez voir une erreur de type "Cannot find name 'document'" dans le code ci-dessus. Pour "injecter" les types pour document et d'autres APIs navigateur, ajoutez la directive triple-slash suivante en haut de tout fichier de test.

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

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

test("test dom", () => {
  document.body.innerHTML = `<button>Mon bouton</button>`;
  const button = document.querySelector("button");
  expect(button?.innerText).toEqual("Mon bouton");
});

Exécutons ce test avec bun test :

bash
bun test
bun test v1.3.3

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

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

React Testing Library

Bun fonctionne de manière transparente avec React Testing Library pour tester les composants React. Après avoir configuré happy-dom comme indiqué ci-dessus, vous pouvez installer et utiliser React Testing Library normalement.

bash
bun add -d @testing-library/react @testing-library/jest-dom
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('affiche le bouton', () => {
  render(<Button>Cliquez-moi</Button>);
  expect(screen.getByRole('button')).toHaveTextContent('Cliquez-moi');
});

Tests DOM avancés

Éléments personnalisés

Vous pouvez tester les éléments personnalisés et les web components en utilisant la même configuration :

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

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

test("élément personnalisé", () => {
  // Définir un élément personnalisé
  class MyElement extends HTMLElement {
    constructor() {
      super();
      this.innerHTML = "<p>Contenu de l'élément personnalisé</p>";
    }
  }

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

  // L'utiliser dans les tests
  document.body.innerHTML = "<my-element></my-element>";
  const element = document.querySelector("my-element");
  expect(element?.innerHTML).toBe("<p>Contenu de l'élément personnalisé</p>");
});

Tests d'événements

Testez les événements DOM et les interactions utilisateur :

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

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

test("événement clic de bouton", () => {
  let clicked = false;

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

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

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

Conseils de configuration

Configuration globale

Pour des configurations de test DOM plus complexes, vous pouvez créer un fichier de préchargement plus complet :

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

// Enregistrer les globaux happy-dom
GlobalRegistrator.register();

// Ajouter toute configuration de test globale ici
global.ResizeObserver = class ResizeObserver {
  observe() {}
  unobserve() {}
  disconnect() {}
};

// Mock d'autres APIs selon les besoins
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(),
  })),
});

Puis mettez à jour votre bunfig.toml :

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

Dépannage

Problèmes courants

Erreurs TypeScript pour les APIs DOM : Assurez-vous d'inclure la directive /// <reference lib="dom" /> en haut de vos fichiers de test.

Globaux manquants : Assurez-vous que @happy-dom/global-registrator est correctement importé et enregistré dans votre fichier de préchargement.

Problèmes de rendu des composants React : Assurez-vous d'avoir installé à la fois @testing-library/react et d'avoir correctement configuré happy-dom.

Considérations de performance

Happy-dom est rapide, mais pour de très grandes suites de tests, vous pourriez vouloir :

  • Utiliser beforeEach pour réinitialiser l'état du DOM entre les tests
  • Éviter de créer trop d'éléments DOM dans un seul test
  • Envisager d'utiliser des fonctions cleanup des bibliothèques de test
ts
import { afterEach } from "bun:test";
import { cleanup } from "@testing-library/react";

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

Bun édité par www.bunjs.com.cn