Learn Gatsby - Testing & Quality
Series/Learn Gatsby/Episode 16
Episode 16 of 24

Learn Gatsby - Testing & Quality

This episode covers Gatsby testing and quality assurance: unit testing with Jest and React Testing Library, integration testing for pages, accessibility testing and SEO audits, and static analysis with ESLint.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

A large site can only last if it's backed by automated testing. Gatsby gives you freedom to choose your testing tooling, and the most common pattern is Jest for unit testing plus React Testing Library for rendering and interacting with components.

Episode 16 covers unit testing with Jest and React Testing Library, integration testing for Gatsby pages, accessibility testing and SEO audits, and static analysis with ESLint.

Unit Testing with Jest and React Testing Library

Setting Up Jest in Gatsby

Gatsby provides gatsby-plugin-jest so Jest immediately understands Gatsby's Babel transforms and aliases. Once installed, additional configuration can live in jest.config.js.

Install testing tooling
npm install --save-dev jest @testing-library/react @testing-library/jest-dom gatsby-plugin-jest

The gatsby-plugin-jest plugin injects the transforms Gatsby needs into Jest, including support for the gatsby module inside the components being tested.

Writing Unit Tests for Components

Unit tests verify a component's behavior in isolation. Here's an example button component that displays a click count:

JSCounter component
import { useState } from "react"
 
const Counter = () => {
  const [count, setCount] = useState(0)
  return (
    <button onClick={() => setCount(count + 1)}>
      Klik: {count}
    </button>
  )
}
 
export default Counter

Then write the test in a counter.test.js file:

JSUnit test with React Testing Library
import { render, screen, fireEvent } from "@testing-library/react"
import Counter from "./counter"
 
test("counter bertambah saat tombol diklik", () => {
  render(<Counter />)
 
  const button = screen.getByRole("button", { name: /klik/i })
  fireEvent.click(button)
 
  expect(screen.getByText(/klik: 1/i)).toBeInTheDocument()
})

screen.getByRole and screen.getByText are the recommended ways to select elements in React Testing Library because they encourage testing behavior rather than implementation.

Integration Testing for Gatsby Pages

Mocking Gatsby Modules

Gatsby pages often use useStaticQuery and Link. When testing a page, those modules need to be mocked so the test doesn't require a full build. Create a __mocks__/gatsby.js file at the project root:

JSMock the gatsby module
const React = require("react")
 
exports.useStaticQuery = () => ({
  site: {
    siteMetadata: { title: "Test Site" },
  },
})
 
exports.Link = ({ to, children }) =>
  React.createElement("a", { href: to }, children)

With the mock above, pages using useStaticQuery and Link can render directly inside Jest without running GraphQL.

Rendering the Full Page

Integration tests render an entire page with all of its components, then check the content that appears:

JSIndex page integration test
import { render, screen } from "@testing-library/react"
import IndexPage from "../pages/index"
 
test("halaman index menampilkan judul", () => {
  render(<IndexPage />)
  expect(screen.getByRole("heading", { level: 1 })).toBeInTheDocument()
})

The difference between unit tests and integration tests is scope: unit tests focus on one component, integration tests ensure many components work together as a single page.

Accessibility Testing and SEO Audits

Accessibility with jest-axe

Automated accessibility testing catches issues like contrast, wrong aria attributes, or elements without labels. jest-axe runs axe-core rules on top of the rendered output:

Install jest-axe
npm install --save-dev jest-axe

Inside a test, run the accessibility rules against the rendered output:

JSAccessibility test with jest-axe
import { render } from "@testing-library/react"
import { axe, toHaveNoViolations } from "jest-axe"
import HomePage from "../pages/home"
 
expect.extend(toHaveNoViolations)
 
test("halaman home tidak memiliki pelanggaran aksesibilitas", async () => {
  const { container } = render(<HomePage />)
  expect(await axe(container)).toHaveNoViolations()
})

expect(...).toHaveNoViolations() fails automatically if any accessibility rule violation is found on the rendered page.

SEO Audit with Lighthouse

Lighthouse remains the final audit outside unit tests: run it against a production build and check the SEO, best practices, and accessibility categories. This audit catches things unit tests can't detect, like a missing meta description or an undefined viewport.

Static Analysis with ESLint

ESLint Configuration

Gatsby bundles ESLint with rules from eslint-config-react-app. To add custom rules, add an ESLint config file or adjust package.json. The gatsby develop command also shows lint warnings right in the terminal.

Performance Checks in CI

Combine ESLint with scripts in package.json so any change that breaks the rules fails the pipeline immediately:

Lint and test scripts in package.json
{
  "scripts": {
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
    "test": "jest"
  }
}

npm run lint and npm test can be called in CI before the build. Running both regularly keeps quality in check without relying on manual review alone.

Conclusion

Key takeaways:

  • gatsby-plugin-jest integrates Jest with Gatsby's tooling.
  • React Testing Library encourages behavior-based testing.
  • Mocking the gatsby module enables page tests without a build.
  • jest-axe automatically detects accessibility violations.
  • Lighthouse complements SEO and accessibility audits at the page level.
  • ESLint in CI prevents quality issues from reaching production.

In the next episode, episode 17, we'll discuss progressive web app — making a Gatsby site installable and offline-first via a service worker, web app manifest, and caching strategies.

Learn Gatsby - Testing & Quality | Learn Gatsby