Skip to content

Средство запуска тестов Bun хорошо работает с существующими библиотеками тестирования компонентов и DOM, включая React Testing Library и happy-dom.

happy-dom

Для написания headless-тестов для вашего фронтенд-кода и компонентов мы рекомендуем happy-dom. Happy DOM реализует полный набор HTML и DOM API на чистом JavaScript, что делает возможным моделирование среды браузера с высокой точностью.

Для начала установите пакет @happy-dom/global-registrator как dev-зависимость.

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

Мы будем использовать функциональность предварительной загрузки Bun для регистрации глобальных объектов happy-dom перед запуском наших тестов. Этот шаг сделает API браузера, такие как document, доступными в глобальной области. Создайте файл с именем happydom.ts в корне вашего проекта и добавьте следующий код:

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

GlobalRegistrator.register();

Для предварительной загрузки этого файла перед bun test откройте или создайте файл bunfig.toml и добавьте следующие строки.

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

Это выполнит happydom.ts при запуске bun test. Теперь вы можете писать тесты, использующие API браузера, такие как document и window.

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

test("тест dom", () => {
  document.body.innerHTML = `<button>Моя кнопка</button>`;
  const button = document.querySelector("button");
  expect(button?.innerText).toEqual("Моя кнопка");
});

Поддержка TypeScript

В зависимости от вашей настройки tsconfig.json вы можете увидеть ошибку типа "Cannot find name 'document'" в приведённом выше коде. Для "внедрения" типов для document и других API браузера добавьте следующую директиву тройной косой черты в начало любого тестового файла.

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

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

test("тест dom", () => {
  document.body.innerHTML = `<button>Моя кнопка</button>`;
  const button = document.querySelector("button");
  expect(button?.innerText).toEqual("Моя кнопка");
});

Давайте запустим этот тест с 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 хорошо работает с React Testing Library для тестирования компонентов React. После настройки happy-dom, как показано выше, вы можете установить и использовать React Testing Library обычным образом.

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('отрисовка кнопки', () => {
  render(<Button>Нажми меня</Button>);
  expect(screen.getByRole('button')).toHaveTextContent('Нажми меня');
});

Продвинутое тестирование DOM

Пользовательские элементы

Вы можете тестировать пользовательские элементы и веб-компоненты, используя ту же настройку:

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

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

test("пользовательский элемент", () => {
  // Определить пользовательский элемент
  class MyElement extends HTMLElement {
    constructor() {
      super();
      this.innerHTML = "<p>Содержимое пользовательского элемента</p>";
    }
  }

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

  // Использовать в тестах
  document.body.innerHTML = "<my-element></my-element>";
  const element = document.querySelector("my-element");
  expect(element?.innerHTML).toBe("<p>Содержимое пользовательского элемента</p>");
});

Тестирование событий

Тестируйте события DOM и взаимодействия с пользователем:

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

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

test("событие клика кнопки", () => {
  let clicked = false;

  document.body.innerHTML = '<button id="test-btn">Нажми меня</button>';
  const button = document.getElementById("test-btn");

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

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

Советы по конфигурации

Глобальная настройка

Для более сложных настроек тестирования DOM вы можете создать более комплексный файл предварительной загрузки:

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

// Зарегистрировать глобальные объекты happy-dom
GlobalRegistrator.register();

// Добавить любую глобальную конфигурацию теста здесь
global.ResizeObserver = class ResizeObserver {
  observe() {}
  unobserve() {}
  disconnect() {}
};

// Мок других API по мере необходимости
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(),
  })),
});

Затем обновите ваш bunfig.toml:

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

Устранение неполадок

Распространённые проблемы

Ошибки TypeScript для API DOM: Убедитесь, что включили директиву /// <reference lib="dom" /> в начало ваших тестовых файлов.

Отсутствующие глобальные объекты: Убедитесь, что @happy-dom/global-registrator правильно импортирован и зарегистрирован в вашем файле предварительной загрузки.

Проблемы отрисовки компонентов React: Убедитесь, что вы установили и @testing-library/react, и правильно настроили happy-dom.

Соображения производительности

Happy-dom быстр, но для очень больших наборов тестов вы можете захотеть:

  • Использовать beforeEach для сброса состояния DOM между тестами
  • Избегать создания слишком большого количества элементов DOM в одном тесте
  • Рассмотреть использование функций cleanup из библиотек тестирования
ts
import { afterEach } from "bun:test";
import { cleanup } from "@testing-library/react";

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

Bun от www.bunjs.com.cn