DEV Community

Michael Rhema
Michael Rhema

Posted on • Edited on

Unit Testing for Gatsby using Jest, Typescript and React Testing Library

My first experience working TDD using React Testing Library with Jest for a Gatsby website in Typescript.

Setting up Jest and React Testing Library for TDD with Gatsby is quite straight forward. It does get a bit tricky because I plan on using Typescript in my tests.
First, I install jest, babel-jest and babel-preset-gatsby to ensure that the babel preset(s) that are used match what are used internally for a Gatsby site.

npm install --save-dev jest babel-jest  babel-preset-gatsby identity-obj-proxy tslint-react @types/jest

Configuring Jest to work with Gatsby

Because Gatsby handles its own Babel configuration, I will need to manually tell Jest to use babel-jest. The gatsby website recommends creating a jest.config.js file. The code below works for me and should work nicely for you.

jest.config.js

const path = require("path")

module.exports = {
  setupFilesAfterEnv: [
    path.resolve(__dirname, "./jest-configs/setup-test-env.js")
  ],
  transform: {
    // "^.+\\.(tsx?|jsx?)$": "ts-jest",
    "\\.svg": "<rootDir>/jest-configs/__mocks__/svgTransform.js" ,
    "^.+\\.(tsx?|jsx?)$": `<rootDir>/jest-configs/jest-preprocess.js`,
  },
  moduleNameMapper: {
    // "\\.svg": `./jest-configs/__mocks__/file-mocks.js`,
    "\\.svg": `<rootDir>/jest-configs/__mocks__/svgTransform.js`,
    "typeface-*": "identity-obj-proxy",
    ".+\\.(css|styl|less|sass|scss)$": `identity-obj-proxy`,
    ".+\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": `<rootDir>/jest-configs/__mocks__/file-mocks.js`,
  },
  testPathIgnorePatterns: [`node_modules`, `.cache`, `public`],
  transformIgnorePatterns: [`node_modules/(?!(gatsby)/)`, `\\.svg`],
  globals: {
    __PATH_PREFIX__: ``,
  },
  testRegex: "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$",
  moduleFileExtensions: [
    "ts",
    "tsx",
    "js"
  ],
  collectCoverage: false,
  coverageReporters: [
    "lcov",
    "text",
    "html"
  ]
}

svgTransform.js

module.exports = {
  process() {
    return 'module.exports = {};';
  },
  getCacheKey() {
    // The output is always the same.
    return 'svgTransform';
  },
};

The transform: option tells Jest that all ts, tsx, js or jsx files need to be transformed using a jest-preprocess.js file. I have created this file in a jest-configs folder at the root of my project.

jest-configs/jest-preprocess.js

const babelOptions = {
  presets: [
    '@babel/preset-react', 
    'babel-preset-gatsby', 
    "@babel/preset-typescript"
  ],
};

module.exports = require("babel-jest").createTransformer(babelOptions)

I also need to put some code in setup-test-env.js .
The Jest Configuration docs explains the setupFilesAfterEnv: .... configuration option if you need to understand what it means along with other available configuration options.

A list of paths to modules that run some code to configure or set up the testing framework before each test.

jest-configs/setup-test-env.js

import "@testing-library/jest-dom/extend-expect"

That should have Jest properly configured. Now, I'll install the testing library and jest-dom as dev-dependencies with npm.

npm install --save-dev @testing-library/react @testing-library/jest-dom

After this I could run npx jest ( Using npx because jest isn't installed globally ) and I got good.

cli

Ok GREAT WORK.

Fingers crossed, I am about to write my first test and run it.
One major reason to love TDD is to fail faster or break things faster. This means, write tests before your write code. Also test should initially fail, always. Read this up from Hackernoon.

I'll create a __tests__ folder on my project root folder. I'll then create a file called test.spec.tsx and paste this code in it. I usually prefer my tests along side my components eg `src/components/-componentName-/-componentName.spec.ts-.
Right now, I am not sure which convention is better accepted.

tests/test.spec.tsx


import React from "react"
import { render } from "@testing-library/react"

// You have to write data-testid
const Title = () => <h1 data-testid="hero-title">Gatsby is awesome!</h1>

test("Displays the correct title", () => {
const { getByTestId } = render(<Title />)
// Assertion
expect(getByTestId("hero-title")).toHaveTextContent("Gatsby is awesome!")
// --> Test will pass
})




Run Yarn or npm install if you get errors like...


Cannot find module 'react' from 'test.spec.tsx'
> 1 | import React from "react"




HURRAY SUCCESSFUL UNIT TESTING WITH TYPESCRIPT AND GATSBY AND JEST AND REACT TESTING LIBRARY

test-passes

I feel really good with this. I am just starting out Typescript with React so this was a lot of fun for me. I'll put up another post about writing real code using TDD for a FAQ website I am building using Gatsby.

Thank you for reading this..

Top comments (3)

Collapse
 
ehrencrona profile image
Andreas Ehrencrona

The tricky part with Gatsby is how to handle testing of code that requires GraphQL queries. I've create a unit testing plugin for Gatsby that makes that possible, so there's no need to extract GraphQL dependencies from every test.

Collapse
 
mikedane profile image
Mike Dane

You're a legend, great guide!

Collapse
 
kdsgyt profile image
Karan Pal Singh

I am still not able to control my Chakra to do web-justu