Testing React components with Bun

Learn how to test React components with Bun

Natt Nguyen·December 9, 2024 (a month ago)·2 min read

#bun
#testing
Testing React components with Bun

In my recent exploration of testing React components, I was impressed by how quickly and easily I could set up Bun. The integrated testing functionality in Bun is incredibly fast and works seamlessly with both React and Next.js projects.

To get started, install the necessary packages. Notice that there’s no need to install jest or ts-node with Bun:

bun add -D \
@happy-dom/global-registrator \
@testing-library/react \
@testing-library/dom \
@testing-library/jest-dom
bun add -D \
@happy-dom/global-registrator \
@testing-library/react \
@testing-library/dom \
@testing-library/jest-dom
bun add -D \
@happy-dom/global-registrator \
@testing-library/react \
@testing-library/dom \
@testing-library/jest-dom
bun add -D \
@happy-dom/global-registrator \
@testing-library/react \
@testing-library/dom \
@testing-library/jest-dom

Create the following setup files to configure your testing environment.

// happydom.ts

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

GlobalRegistrator.register()
// happydom.ts

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

GlobalRegistrator.register()
// happydom.ts

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

GlobalRegistrator.register()
// happydom.ts

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

GlobalRegistrator.register()
// testing-library.ts

import * as matchers from "@testing-library/jest-dom/matchers"
import { cleanup } from "@testing-library/react"
import { afterEach, expect } from "bun:test"

expect.extend(matchers)

afterEach(() => {
cleanup()
})
// testing-library.ts

import * as matchers from "@testing-library/jest-dom/matchers"
import { cleanup } from "@testing-library/react"
import { afterEach, expect } from "bun:test"

expect.extend(matchers)

afterEach(() => {
cleanup()
})
// testing-library.ts

import * as matchers from "@testing-library/jest-dom/matchers"
import { cleanup } from "@testing-library/react"
import { afterEach, expect } from "bun:test"

expect.extend(matchers)

afterEach(() => {
cleanup()
})
// testing-library.ts

import * as matchers from "@testing-library/jest-dom/matchers"
import { cleanup } from "@testing-library/react"
import { afterEach, expect } from "bun:test"

expect.extend(matchers)

afterEach(() => {
cleanup()
})
// testing-library.ts

import * as matchers from "@testing-library/jest-dom/matchers"
import { cleanup } from "@testing-library/react"
import { afterEach, expect } from "bun:test"

expect.extend(matchers)

afterEach(() => {
cleanup()
})
// testing-library.ts

import * as matchers from "@testing-library/jest-dom/matchers"
import { cleanup } from "@testing-library/react"
import { afterEach, expect } from "bun:test"

expect.extend(matchers)

afterEach(() => {
cleanup()
})
// testing-library.ts

import * as matchers from "@testing-library/jest-dom/matchers"
import { cleanup } from "@testing-library/react"
import { afterEach, expect } from "bun:test"

expect.extend(matchers)

afterEach(() => {
cleanup()
})
// testing-library.ts

import * as matchers from "@testing-library/jest-dom/matchers"
import { cleanup } from "@testing-library/react"
import { afterEach, expect } from "bun:test"

expect.extend(matchers)

afterEach(() => {
cleanup()
})
# bunfig.toml

[test]
preload = ["./happydom.ts", "./testing-library.ts"]
# bunfig.toml

[test]
preload = ["./happydom.ts", "./testing-library.ts"]
# bunfig.toml

[test]
preload = ["./happydom.ts", "./testing-library.ts"]
# bunfig.toml

[test]
preload = ["./happydom.ts", "./testing-library.ts"]
// matchers.d.ts

import { TestingLibraryMatchers } from "@testing-library/jest-dom/matchers"
import "bun:test"

declare module "bun:test" {
interface Matchers<T>
extends TestingLibraryMatchers<typeof expect.stringContaining, T> {}
interface AsymmetricMatchers extends TestingLibraryMatchers {}
}
// matchers.d.ts

import { TestingLibraryMatchers } from "@testing-library/jest-dom/matchers"
import "bun:test"

declare module "bun:test" {
interface Matchers<T>
extends TestingLibraryMatchers<typeof expect.stringContaining, T> {}
interface AsymmetricMatchers extends TestingLibraryMatchers {}
}
// matchers.d.ts

import { TestingLibraryMatchers } from "@testing-library/jest-dom/matchers"
import "bun:test"

declare module "bun:test" {
interface Matchers<T>
extends TestingLibraryMatchers<typeof expect.stringContaining, T> {}
interface AsymmetricMatchers extends TestingLibraryMatchers {}
}
// matchers.d.ts

import { TestingLibraryMatchers } from "@testing-library/jest-dom/matchers"
import "bun:test"

declare module "bun:test" {
interface Matchers<T>
extends TestingLibraryMatchers<typeof expect.stringContaining, T> {}
interface AsymmetricMatchers extends TestingLibraryMatchers {}
}

With everything set up, you're now ready to test your components.

// button.test.tsx

import Button from "@/components/button"
import { render } from "@testing-library/react"
import { describe, expect, it } from "bun:test"

describe("Button Component", () => {
it("renders a button with the correct default type and class name", () => {
const { getByRole } = render(<Button />)
const button = getByRole("button")
expect(button).toHaveAttribute("type", "button")
})
})
// button.test.tsx

import Button from "@/components/button"
import { render } from "@testing-library/react"
import { describe, expect, it } from "bun:test"

describe("Button Component", () => {
it("renders a button with the correct default type and class name", () => {
const { getByRole } = render(<Button />)
const button = getByRole("button")
expect(button).toHaveAttribute("type", "button")
})
})
// button.test.tsx

import Button from "@/components/button"
import { render } from "@testing-library/react"
import { describe, expect, it } from "bun:test"

describe("Button Component", () => {
it("renders a button with the correct default type and class name", () => {
const { getByRole } = render(<Button />)
const button = getByRole("button")
expect(button).toHaveAttribute("type", "button")
})
})
// button.test.tsx

import Button from "@/components/button"
import { render } from "@testing-library/react"
import { describe, expect, it } from "bun:test"

describe("Button Component", () => {
it("renders a button with the correct default type and class name", () => {
const { getByRole } = render(<Button />)
const button = getByRole("button")
expect(button).toHaveAttribute("type", "button")
})
})

With these steps, you can quickly set up Bun for testing React components and enjoy fast, efficient test runs with minimal configuration.

Subscribe to my blog

I'd love to share my love for design, engineering, and thinking with you when my new articles are published.

You can unsubscribe at any time, no hard feelings.