Skip to content

Bun 의 테스트 러너는 React Testing Library 와 happy-dom 을 포함한 기존 구성요소 및 DOM 테스트 라이브러리와 잘 작동합니다.

happy-dom

프론트엔드 코드와 구성요소에 대한 헤드리스 테스트를 작성하려면 happy-dom 을 권장합니다. Happy DOM 은 HTML 과 DOM API 의 완전한 세트를 일반 JavaScript 로 구현하여 높은 충실도로 브라우저 환경을 시뮬레이션할 수 있게 합니다.

시작하려면 @happy-dom/global-registrator 패키지를 dev dependency 로 설치하세요.

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

테스트 실행 전에 happy-dom globals 를 등록하기 위해 Bun 의 프리로드 기능을 사용할 것입니다. 이 단계는 document 와 같은 브라우저 API 를 전역 범위에서 사용할 수 있게 합니다. 프로젝트 루트에 happydom.ts 라는 파일을 생성하고 다음 코드를 추가하세요.

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

GlobalRegistrator.register();

bun test 전에 이 파일을 프리로드하려면 bunfig.toml 파일을 열거나 생성하고 다음 줄을 추가하세요.

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

이것은 bun test 를 실행할 때 happydom.ts 를 실행합니다. 이제 documentwindow 와 같은 브라우저 API 를 사용하는 테스트를 작성할 수 있습니다.

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 에 대한 타입을 "주입"하려면 테스트 파일 상단에 다음 triple-slash 지시문을 추가하세요.

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 구성요소 테스트를 위해 React Testing Library 와 원활하게 작동합니다. 위에서 보여준 대로 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 globals 등록
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"]

문제 해결

일반적인 문제

DOM API 에 대한 TypeScript 오류: 테스트 파일 상단에 /// <reference lib="dom" /> 지시문을 포함했는지 확인하세요.

누락된 globals: @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 by www.bunjs.com.cn 편집