# Jest With GitHub Actions

> See how to use Jest alongside GitHub Actions run Jest testing in CI.

- Canonical: https://dennisokeeffe.com/blog/2021-10-27-jest-with-github-actions
- Published: 2021-10-27
- Updated: 2021-10-27
- Tags: jest, javascript

This post will demonstrate how to add a [GitHub Action](https://docs.github.com/en/actions) for running JavaScript test runner jobs on a push event to the repo with the Jest testing framework.

The final project code can be found on my [okeeffed/jest-with-github-actions GitHub repo](https://github.com/okeeffed/jest-with-github-actions).

## Prerequisites

1. Familiarity with [npm](https://www.npmjs.com/).
2. Familiarity with [Jest](https://jestjs.io/).

## Getting started

First, we need to create a project that will host the testing. In our case, let's name that project folder `hello-jest-github-actions`.

```s
$ mkdir hello-jest-github-actions
$ cd hello-jest-github-actions

# Initialise the project with defaults
$ npm init -y

# Install the deps
$ npm install jest

# Recursively create the required folders
$ mkdir -p src/__test__ .github/workflows

# Create a basic file and test file we want tested in CI
$ touch src/math.js src/__test__/math.test.js .github/workflows/jest.yml
```

At this stage, we are ready to start writing our test for the example and then adding our GitHub action.

## Writing the JavaScript tests

We are going to write a simple `add`, `subtract` and `multiply` function with some contrived arithmetic tests to help us demonstrate the testing when we write the code for our GitHub Action.

Inside of `src/main.js`, add the following code:

```js
/**
 * Simple addition.
 *
 * @param {number} x First number.
 * @param {number} y second number.
 * @returns Addition of both arguments.
 */
const add = (x, y) => x + y;

/**
 * Simple subtraction.
 *
 * @param {number} x First number.
 * @param {number} y second number.
 * @returns Subtraction of second argument from the first.
 */
const subtract = (x, y) => x - y;

/**
 * Simple multiplication.
 *
 * @param {number} x First number.
 * @param {number} y second number.
 * @returns Multiplication of both arguments.
 */
const multiply = (x, y) => x * y;

module.exports = {
  add,
  subtract,
  multiply,
};
```

The above is a simple implementation of arithmetic math functions to demonstrate the tests.

As for our Jest tests, update `src/__test__/math.test.js` with the following:

```js
const { add, subtract, multiply } = require("../math");

describe("simple arithmetic", () => {
  describe("addition", () => {
    test("expect 2 + 3 = 5", () => {
      expect(add(2, 3)).toEqual(5);
    });
  });

  describe("subtract", () => {
    test("expect 5 - 2 = 3", () => {
      expect(subtract(5, 2)).toEqual(3);
    });
  });

  describe("multiply", () => {
    test("expect 2 * 3 = 6", () => {
      expect(multiply(2, 3)).toEqual(6);
    });
  });
});
```

I won't go into detail about the Jest tests as I am assuming that you already have knowledge on Jest testing, but the above is simple enough to read through.

In order to run our tests and check they are passing, we first need to update `package.json` to have the correct `test` script:

```json
{
  "name": "hello-jest-github-actions",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest" // UPDATE HERE
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "jest": "^27.3.1"
  }
}
```

At this stage, we can test that our tests are passing as expected by running Jest locally:

```s
$ npm test

> hello-jest-github-actions@1.0.0 test
> jest

 PASS  src/__test__/math.test.js
  simple arithmetic
    addition
      ✓ expect 2 + 3 = 5 (3 ms)
    subtract
      ✓ expect 5 - 2 = 3 (1 ms)
    multiply
      ✓ expect 2 * 3 = 6

Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        0.512 s
Ran all test suites.
```

Tests are green! At this stage, we are ready to set things up for our GitHub action!

## Adding the test script

We can edit the file `.github/workflows/jest.yml` to add the following:

```yml
name: Jest
on: push
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: "12"

      # Speed up subsequent runs with caching
      - name: Cache node modules
        uses: actions/cache@v2
        env:
          cache-name: cache-node-modules
        with:
          # npm cache files are stored in `~/.npm` on Linux/macOS
          path: ~/.npm
          key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-build-${{ env.cache-name }}-
            ${{ runner.os }}-build-
            ${{ runner.os }}-

      # Install required deps for action
      - name: Install Dependencies
        run: npm install

      # Finally, run our tests
      - name: Run the tests
        run: npm test
```

Here we are doing a couple of things:

1. Creating a job call `Jest`.
2. Running this job on a `push` event to the repository. There is also the capability to run this on a pull request, but I will keep it simple for now.
3. Running the job on `ubuntu-latest`.
4. Setting up the Node environment for the latest in version `12.x`. The major versions supported are 12, 14 and 16 but check the [actions/setup-node supported versions](https://github.com/actions/setup-node#supported-version-syntax) for the latest.
5. We then attempt to load a installation cache for the dependencies, with a fallback to create a new cache based on the hash of the `package.json` file.
6. Install dependencies.
7. Running the test suite that we setup the command and tested before.

That is all that we need to be able to push to GitHub and see our action running!

> Be sure at this stage that you have set up your own origin remote for the repo.

All we need to do is commit the code and push the repo and the job will be available under the actions tab in the GitHub UI.

![Action working as expected](https://cdn.dennisokeeffe.com/assets/2021-10-27-jest-with-github-actions/1-jest-github-action.png)

## Summary

Today's post demonstrated how to use GitHub actions to test Jest code on a push to the remote repository. We used the `jest` testing framework to test our code.

## Resources and further reading

1. [Jest](https://jestjs.io/)
2. [GitHub Actions](https://docs.github.com/en/actions)
3. [Caching Dependencies To Speed Up Workflows](https://docs.github.com/en/actions/advanced-guides/caching-dependencies-to-speed-up-workflows)
4. [Final project](https://github.com/okeeffed/jest-with-github-actions)

_Photo credit: [`pawel_czerwinski`](https://unsplash.com/@pawel_czerwinski)_
