# Jest

> [Pro egghead lesson on Jest / TypeScript](https://egghead.io/lessons/typescript-getting-started-with-jest-using-typescript)

No testing solution out there is perfect. That said, jest is an excellent unit testing option which provides great TypeScript support.

> Note: We assume you start off with a simple node package.json setup. Also all TypeScript files should be in a `src` folder which is always recommended (even without Jest) for a clean project setup.

## Step 1: Install

Install the following using npm:

```
npm i jest @types/jest ts-jest -D
```

Explanation:

* Install `jest` framework (`jest`)
* Install the types for `jest` (`@types/jest`)
* Install the TypeScript preprocessor for jest (`ts-jest`) which allows jest to transpile TypeScript on the fly and have source-map support built in.
* Save all of these to your dev dependencies (testing is almost always a npm dev-dependency)

## Step 2: Configure Jest

Add the following `jest.config.js` file to the root of your project:

```javascript
module.exports = {
  "roots": [
    "<rootDir>/src"
  ],
  "transform": {
    "^.+\\.tsx?$": "ts-jest"
  },
  "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
  "moduleFileExtensions": [
    "ts",
    "tsx",
    "js",
    "jsx",
    "json",
    "node"
  ],
}
```

Explanation:

* We always recommend having *all* TypeScript files in a `src` folder in your project. We assume this is true and specify this using the `roots` option.
* The `transform` config just tells `jest` to use `ts-jest` for ts / tsx files.
* The `testRegex` tells Jest to look for tests in any `__tests__` folder AND also any files anywhere that use the `(.test|.spec).(ts|tsx)` extension e.g. `asdf.test.tsx` etc.
* The `moduleFileExtensions` tells jest to recognize our file extensions. This is needed as we add `ts`/`tsx` into the defaults (`js|jsx|json|node`).

## Step 3: Run tests

Run `npx jest` from your project root and jest will execute any tests you have.

### Optional: Add script target for npm scripts

Add `package.json`:

```javascript
{
  "test": "jest"
}
```

* This allows you to run the tests with a simple `npm t`.
* And even in watch mode with `npm t -- --watch`.

### Optional: Run jest in watch mode

* `npx jest --watch`

### Example

* For a file `foo.ts`:

```javascript
export const sum
  = (...a: number[]) =>
    a.reduce((acc, val) => acc + val, 0);
```

* A simple `foo.test.ts`:

```javascript
import { sum } from '../';

test('basic', () => {
  expect(sum()).toBe(0);
});

test('basic again', () => {
  expect(sum(1, 2)).toBe(3);
});
```

Notes:

* Jest provides the global `test` function.
* Jest comes prebuilt with assertions in the form of the global `expect`.

### Example async

Jest has built-in async/await support. e.g.

```javascript
test('basic',async () => {
  expect(sum()).toBe(0);
});

test('basic again', async () => {
  expect(sum(1, 2)).toBe(3);
}, 1000 /* optional timeout */);
```

### Example enzyme

> [Pro egghead lesson on Enzyme / Jest / TypeScript](https://egghead.io/lessons/react-test-react-components-and-dom-using-enzyme)

Enzyme allows you to test react components with dom support. There are three steps to setting up enzyme:

1. Install enzyme, types for enzyme, a better snapshot serializer for enzyme, enzyme-adapter-react for your react version `npm i enzyme @types/enzyme enzyme-to-json enzyme-adapter-react-16 -D`
2. Add `"snapshotSerializers"` and `"setupTestFrameworkScriptFile"` to your `jest.config.js`: &#x20;

```javascript
module.exports = {
  // OTHER PORTIONS AS MENTIONED BEFORE

  // Setup Enzyme
  "snapshotSerializers": ["enzyme-to-json/serializer"],
  "setupTestFrameworkScriptFile": "<rootDir>/src/setupEnzyme.ts",
}
```

1. Create `src/setupEnzyme.ts` file.

```javascript
import { configure } from 'enzyme';
import * as EnzymeAdapter from 'enzyme-adapter-react-16';
configure({ adapter: new EnzymeAdapter() });
```

Now here is an example react component and test:

* `checkboxWithLabel.tsx`:

```typescript
import * as React from 'react';

export class CheckboxWithLabel extends React.Component<{
  labelOn: string,
  labelOff: string
}, {
    isChecked: boolean
  }> {
  constructor(props) {
    super(props);
    this.state = { isChecked: false };
  }

  onChange = () => {
    this.setState({ isChecked: !this.state.isChecked });
  }

  render() {
    return (
      <label>
        <input
          type="checkbox"
          checked={this.state.isChecked}
          onChange={this.onChange}
        />
        {this.state.isChecked ? this.props.labelOn : this.props.labelOff}
      </label>
    );
  }
}
```

* `checkboxWithLabel.test.tsx`:

```typescript
import * as React from 'react';
import { shallow } from 'enzyme';
import { CheckboxWithLabel } from './checkboxWithLabel';

test('CheckboxWithLabel changes the text after click', () => {
  const checkbox = shallow(<CheckboxWithLabel labelOn="On" labelOff="Off" />);

  // Interaction demo
  expect(checkbox.text()).toEqual('Off');
  checkbox.find('input').simulate('change');
  expect(checkbox.text()).toEqual('On');

  // Snapshot demo
  expect(checkbox).toMatchSnapshot();
});
```

## Reasons why we like jest

> [For details on these features see jest website](http://facebook.github.io/jest/)

* Built-in assertion library.
* Great TypeScript support.
* Very reliable test watcher.
* Snapshot testing.
* Built-in coverage reports.
* Built-in async/await support.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jorgedacostaza.gitbook.io/typescript-pt/intro-1/jest.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
