Infinite Jest: toBe or not.toBe
Tags: testing, javascript, beginners
Published: 2020-01-26 02:49:53

## What is Jest?

Jest is an open source JavaScript testing framework and is used by lots of different companies including Facebook, Twitter, Spotify, and more. Jest is fast and intuitive to learn and set up.

To install using npm, navigate to the directory you want to add tests for (`mkdir david-foster-wallace` and then `cd david-foster-wallace`) create a package.json file (`npm init -y`) and enter `npm install --save-dev jest` in your terminal.

## What is Infinite Jest?

Infinite Jest is a book by David Foster Wallace I have never read but have decided to reference numerous times to make this blog vaguely themed.

## Let's write a Jest test

Once you've installed Jest you'll need to make a quick change to your package.json file and then you can start writing your first test.

1) Change the `"test":` value in the `"scripts":` object to "jest"
```javascript
{
  "name": "david-foster-wallace",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest" // <-- this line!
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "jest": "^25.1.0"
  }
}
```
2) Create a new file named pageCount.js 
3) Write a function pageCount in this file

```javascript
const pageCount = () => {
  return 1079 + ' pages';
// try this with 'pages' and the test in step 7 will fail!
}

module.exports = pageCount; 
// export your function to access from your test file
```

4) Create a new file named pageCount.test.js or pageCount.spec.js

*Tests should be written in files ending in .test.js or .spec.js.*

5) Make sure to require your pageCount.js file in your test file

```javascript
const pageCount = require('./pageCount');
```

6) Write the test (we'll cover the terms and syntax in **Anatomy of a test** below)

```javascript
describe('these tests are all about the page count of Infinite Jest', () => {
    test('pageCount should return the page count of Infinite Jest', () => {
        expect(pageCount()).toBe('1079 pages');
    })
})
```

7) Run your tests with `npm run test` in your terminal

![Terminal output showing the test is passing](https://thepracticaldev.s3.amazonaws.com/i/zbv00nj8yc18ajc2t2qv.png)

*Did `npm run test` get stuck for you? (more like Infinite Test, am I right??) It happened to me too! I was able to solve it by running `brew uninstall watchman` in my terminal. Checkout this GitHub issue for more information on [npm run test hangs](https://github.com/facebook/create-react-app/issues/960).*

## Anatomy of a test

We'll briefly cover the following terms from the test we wrote above:

* Describe -- logically group your tests together
* Test -- this will hold your test
* Expect -- this is your assertion that checks to see if your test passes or fails

Describe is used to group tests together. If we wanted to write a few more tests all about the page count of Infinite Jest we could add them under the describe we wrote above. Describe takes 2 arguments, your summary of the tests included in describe and a function that holds the tests.

```javascript
describe('these tests are all about the page count of Infinite Jest', () => {
    test('pageCount should return the page count of Infinite Jest', () => {
        expect(pageCount()).toBe('1079 pages');
    })
    test('endnotesPageCount should return the page count of the endnotes in Infinite Jest', () => {
        expect(endnotesPageCount()).toBe('too many...');
    })
    test('tooLong should return a boolean indicating if Infinite Jest is too long', () => {
        expect(tooLong()).toBe(true);
    })
})
```
Test takes 3 arguments, your summary of conditions to test, a function that holds your "expect", and an optional timeout. For the purposes of this tutorial I won't cover the optional timeout argument. A test does not need to be written inside a describe method.

```javascript
test('timeToReadThisBook returns how long it takes to read I.J. based on reading speed', () => {
    expect(timeToReadThisBook('medium speed')).toBe('~50 hours');
})
```
Expect is where you write what should happen when you test for different scenarios. Expect is where you can think about different scenarios and edge cases that could arise for your code and how you want to handle them. For example, for our timeToReadThisBook function you could write an expect for when 'null' is provided as the reading speed.

```javascript
test('timetoReadThisBook...', () => {
    expect(timeToReadThisBook(null).toBe(
      'You will haunt your local public library.
       Your unfinished business is to read Infinite Jest.
       Ghosts do not have ghost library cards. Sad!'
    );
})
```
>The expect function is used every time you want to test a value. You will rarely call expect by itself. Instead, you will use expect along with a "matcher" function to assert something about a value. - [Jest Docs](https://jestjs.io/docs/en/expect#expectvalue)

## Jest matchers

Matchers are used to check the values in your expect methods. I've listed some of the most common matches below:

* .toBe -- used for checking strict equality
* .toEqual -- used for checking objects and arrays
* .not -- `expect(pageCount()).not.toBe('1 page')`
* .toContain -- used to check if an array contains an item
* .toMatch -- used to check for regex matches

*[Complete list of matchers](https://jestjs.io/docs/en/expect)*

### .toBe vs .toEqual

The distinction between .toBe and .toEqual methods is that .toBe checks for strict equality (works for primitive types like strings and numbers) whereas 'toEqual recursively checks every field of an object or array' (thanks [Jest Docs](https://jestjs.io/docs/en/using-matchers)!).

![David Tennant as Hamlet holding the skull](https://thepracticaldev.s3.amazonaws.com/i/1f7on7rm8r9je0ajtad2.jpg)

## In conclusion...

The novel Infinite Jest by David Foster Wallace was named for a line from Shakespeare's Hamlet and that is a fact I definitely knew before today.

>Alas, poor Yorick! I knew him, Horatio: a fellow of **infinite jest**, of most excellent fancy: he hath borne me on his back a thousand times; and now, how abhorred in my imagination it is! - *Straight outta Hamlet's mouth*

.toBe and not.toBe are methods for Jest. Coincidence? I think not.

>To be, or not to be, that is the question - *Also straight outta Hamlet's mouth*

![Laurence Olivier as Hamlet holding the skull](https://thepracticaldev.s3.amazonaws.com/i/1on9nbv8rc59i3wubdwc.jpg)

I hope my blog has inspired you to learn how to write tests with Jest and maybe even read Inifinite Jest or at least read one paragraph of the Infinite Jest Wikipedia page like I did.

## Sources

* [Jest Docs](https://jestjs.io/docs/en/getting-started)
* [Test Automation University - Jest Tutorial (really helpful)](https://testautomationu.applitools.com/jest-testing-tutorial/)
* [npm run test hangs](https://github.com/facebook/create-react-app/issues/960)
* [Inifinite Jest on Wikipedia](https://en.wikipedia.org/wiki/Infinite_Jest)