Writing tests
Tags: javascript, npm, node, development
Published: 2020-08-18 11:58:09

---
title: Writing tests
published: true
description: write tests for your javascript package
tags: javascript, npm, nodejs, development
series: Building your first JavaScript package
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/tzez8itr381vzljk38bq.jpg
---

Repository for this part is available on git branch `writing-tests`

{% github andrevarandas/mood-sentences no-readme %}

## Writing tests

Our simple package is almost ready. We only need to add some tests. As the package is small, it should be pretty straight forward.

Let's start by creating a special folder under `src` named `__tests__`. Then add a new file and name it `index.test.js`.

In this file, we will write our tests. These will be automatically picked up by `jest` thanks to the configuration we added earlier to the `jestconfig.json` file.

As we are going to use special variables, in order to stop our linter from complaining, we should extend our `.eslintrc.js` file. Start by adding the jest plugin `npm i --save-dev eslint-plugin-jest`.

Then modify the `.eslintrc.js` file to include it:

```javascript
module.exports = {
  env: {
    browser: true,
    es2020: true,
    node: true,
    jest: true // add this line
  },
  extends: [
    'standard'
  ],
  parserOptions: {
    ecmaVersion: 11,
    sourceType: 'module'
  },
  rules: {
  }
}

```

Now we should be able to write our tests without any lint errors.

I usually try to test all the exported methods - so I can have some confidence that the consumer is getting the expected results. In our case, we want to test:

```javascript
module.exports = {
  all: moods,
  anger: moods.anger,
  boredom: moods.boredom,
  excitement: moods.excitement,
  happiness: moods.happiness,
  getRandom,
  list
}
```

Testing all of these properties and methods will give us 100% of code coverage. Pretty neat!

Our test will only have a "test suite" which is basically defined by the keyword `describe`. Inside this test suite, we will add our tests. We can start by adding a test to check if the property .all returns, in fact, all the available mood sentences:

```javascript
// Import our package
const Moods = require('../index')

describe('mood-sentences', () => {
  test('.all should return all sentences', () => {
    const all = require('../mood-sentences.json')
    expect(Moods.all).toMatchObject(all)
  })
})
```

As our property `Moods.all` is nothing more than the contents of the json file, this way we can check that they match.

Let's continue adding all the other properties that should match the json file contents.

```javascript
const Moods = require('../index')

describe('mood-sentences', () => {
  test('.all should return all sentences', () => {
    const all = require('../mood-sentences.json')
    expect(Moods.all).toMatchObject(all)
  })

  test('.anger should return all anger sentences', () => {
    const { anger } = require('../mood-sentences.json')
    expect(Moods.anger).toMatchObject(anger)
  })

  test('.boredom should return all boredom sentences', () => {
    const { boredom } = require('../mood-sentences.json')
    expect(Moods.boredom).toMatchObject(boredom)
  })

  test('.excitement should return all excitement sentences', () => {
    const { excitement } = require('../mood-sentences.json')
    expect(Moods.excitement).toMatchObject(excitement)
  })

  test('.happiness should return all happiness sentences', () => {
    const { happiness } = require('../mood-sentences.json')
    expect(Moods.happiness).toMatchObject(happiness)
  })
})
```

Nothing too fancy, but it assures us that the json contents are being used.

Next, we want to test the `.list` property that should return all the available moods. It is used to get random sentences for a mood.

```javascript
  test('.list should return a list of available moods', () => {
    // Get the json file moods
    const moods = require('../mood-sentences.json')

    // Get all the values defined in the .list property ['anger', 'excitement'...]
    const values = Object.values(Moods.list).sort()

    // Get the json keys ['anger', 'excitement'...]
    const expected = Object.keys(moods).sort()

    expect(values).toEqual(expected)
  })
```

This way we make sure that all the values in the .list property actually exist and match the keys in the json file. If we decide to add one more mood to the json file, we would also have to add a key->value to our list enum.

Lastly, we need to have a test for the `.getRandom` method.

```javascript
 test('.random() should return a random sentence for a mood', () => {
    const randomSentence = Moods.getRandom(Moods.list.HAPPINESS)

    expect(Moods.happiness).toContain(randomSentence)
  })

  // Handle errors (empty call, or non existing mood)
  test('.random() without mood, it throws an error', () => {
    try {
      Moods.getRandom()
    } catch (error) {
      expect(error).toBeInstanceOf(Error)
      expect(error).toHaveProperty('message', 'Requested mood "undefined" is not in the moods list!')
    }
  })
```

With our last test, we should have reached 100% coverage!
Now we can test it, using the script we previously defined in our package.json file: `npm run test`.

You should get a result like the following:

![jest results console screenshot](https://dev-to-uploads.s3.amazonaws.com/i/unz9akw4o6zlsi6i9v00.png)

With this, we have achieved 100% coverage. It's not hard on such a small library. 🤓

We should also add a new `pre-push` hook to husky, so it will run our tests before pushing to Github. This way if the tests are failing, no code will be pushed to our repository, until we fix our code!

Open `package.json` and add the pre-push script:

```json
"husky": {
    "hooks": {
      "pre-commit": "npm run lint:fix && npm run lint",
      "pre-push": "npm run test"
    }
  }
```

Now we can run `git add -A` and `npm run commit` and it will run our lint and test tasks!

You can check this finished chapter on github [https://github.com/AndreVarandas/mood-sentences/tree/writing-tests](https://github.com/AndreVarandas/mood-sentences/tree/writing-tests)

That's all for this part, thanks for reading! In the next part, we will set up our continuous integration (CI) to build our package and publish it into npm!