Simplifying Gatsby Unit Testing using a Jest Preset

Published August 03, 2019

Recently I have been expanding the codebase for this website and blog in order to have a more robust web presence. Part of this of course includes unit testing the source code using Jest. This code base’s test suite is primarilly composed of Jest Snapshot Tests to ensure components and the pages they build are behaving and rendering as expected. Like any codebase, creating robust unit tests like this has many advantages; the primary ones for this code base being automated dependency updates using Dependabot and mutation testing (to ensure tests are working effectively) using Stryker.

I’ve used Jest for many projects before, and have built a few Jest plugins to improve the experience. I’ve built Jest runners to run linters alongside unit tests (jest-runner-prettier, jest-runner-stylelint, and jest-runner-tslint) and I’ve built a transformer module to make working with webpack projects easier jest-raw-loader. So when I saw room for improvement in testing my Gatsby codebase I knew exactly what to do.

Using Jest’s Preset Functionality to Reduce Configuration Boilerplate

The Gatsby documentation on unit testing is fantastic and incredibly helpful (like the rest of the Gatsby documentation.) It runs you through the ropes of unit testing your site’s code and gets you up and running quickly with little friction. However, it has one flaw: the config it requires you create inadvertantly creates a lot of boilerplate. Thankfully, Jest has functionality built in to abstract away boilerplate behind a preset.

Jest presets are found throughout the Jest documentation as a reccomended method to make testing easier in known environments. They’re used to test React Native projects, run tests with Puppeteer, and make testing MongoDB and DynamoDB easier. Given this, let’s abstract away the boilerplate needed to configure Jest to run Gatsby code and make life just a bit easier for us.

I’ve created a module which exports the default Jest config from the Gatsby documentation as a Jest preset. By using it our Jest config goes from this:

module.exports = {
  transform: {
    "^.+\\.jsx?$": "<rootDir>/.jest/gatsby-preprocess.js"
  },
  testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?)$",
  moduleNameMapper: {
    ".+\\.(css|styl|less|sass|scss)$": "identity-obj-proxy",
    ".+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
      "jest-raw-loader"
  },
  moduleFileExtensions: ["js", "jsx", "json", "node"],
  testPathIgnorePatterns: ["node_modules", ".cache"],
  transformIgnorePatterns: ["node_modules/(?!(gatsby)/)"],
  globals: { __PATH_PREFIX__: "" },
  testURL: "http://localhost",
  setupFiles: ["<rootDir>/.jest/loadershim.js"]
};

To this:

module.exports = { preset: "jest-preset-gatsby" };

TypeScript, too!

Abstracting this boiler plate has the added benefit of making life easier for us TypeScript users too. Configuring Jest to run in your Gatsby+TypeScript project becomes as easy as setting the following in your Jest config:

module.exports = { preset: "jest-preset-gatsby/typescript" };

Installation From Scratch

Interested in testing your Gatsby project, and haven’t configured it yet? Now’s a great time to start!

JavaScript Projects

Install jest, react-test-renderer, and jest-preset-gatsby using npm:

npm install --save-dev jest react-test-renderer jest-preset-gatsby

or Yarn:

yarn add --dev jest react-test-renderer jest-preset-gatsby

And configure Jest to use the preset in your package.json:

{
  "jest": {
    "preset": "jest-preset-gatsby"
  }
}

Or jest.config.js:

module.exports = { preset: "jest-preset-gatsby" };

And just like that you’re ready to write your tests! Please see the Gatsby documentation on writing your first test.

TypeScript Projects

Install jest, react-test-renderer, jest-preset-gatsby, and the relevant type definitions using npm:

npm install --save-dev jest react-test-renderer jest-preset-gatsby @types/jest @types/react-test-renderer

or Yarn:

yarn add --dev jest react-test-renderer jest-preset-gatsby @types/jest @types/react-test-renderer

And configure Jest to use the preset in your package.json:

{
  "jest": {
    "preset": "jest-preset-gatsby/typescript"
  }
}

Or jest.config.js:

module.exports = { preset: "jest-preset-gatsby/typescript" };

And just like that you’re ready to write your tests! Please see the Gatsby documentation on writing your first test.

Caveats

While this does make configuring Jest for Gatsby easier, it does come with one caveat. This project does not provide mocks for the gatsby module. Please see the Gatsby documentation on mocking gatsby in order to effectively test your code.