Head start testing with Jest and Typescript
Tags: jest, testing, beginners, javascript
Published: 2021-01-22 18:22:16

Hello, this post is not a super professional, it is a summary of notes that allow me to remember what I have to do or  quickly explain to a friend how to start with Jest and Typescript. 

Keep in mind it is part 1, so you will to learn basic stuff like jest, configure test a file, import code and use basic asserts.

## Install dependencies for my project with Typescript and Jest

Hi Dany or reader, you want to use Jest because it is help to write tests, is a runner, comes with test cover, provide assertion, mocks more things.

- We are going to create a calculator project directory.
- Create package.json it helps us to define a test task for the future.
- we install the typescript, jest, test-jest packages, the jest types
- Create 2 directories app and tests

_If you want you can copy and paste each line_
```bash
dany@dany:~/Desktop$ mkdir calculator
dany@dany:~/Desktop$ cd calculator/
dany@dany:~/Desktop/calculator$ npm init --y
Wrote to /home/dany/Desktop/calculator/package.json:

{
  "name": "calculator",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
dany@dany:~/Desktop/calculator$ npm install -save-dev typescript jest ts-jest @types/jest

+ jest@26.6.3
+ ts-jest@26.4.4
+ @types/jest@26.0.20
+ typescript@4.1.3

added 514 packages from 377 contributors and audited 515 packages in 16.711s

23 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```

Create src directory and inside add  app and test directory with his files Calculator.ts and Calculator.test.ts

```bash
dany@dany:~/Desktop/calculator$ mkdir src
dany@dany:~/Desktop/calculator$ cd src
dany@dany:~/Desktop/calculator$ mkdir app tests
dany@dany:~/Desktop/calculator$ cd app/
dany@dany:~/Desktop/calculator/app$ touch Calculator.ts
dany@dany:~/Desktop/calculator/app$ cd ..
dany@dany:~/Desktop/calculator$ cd tests/
dany@dany:~/Desktop/calculator/tests$ touch Calculator.test.ts
```
_touch command is only available in osx and linux_ if you are using windows please echo cal  > Calculator.ts_


## Use Describe and it functions.

Jest has 2 main functions Describe and it.

Describe allow to create a suite or group tests, the function expects a name of the group of tests as the first parameter and the callback function. 

Its function allows us to define the test and where we will implement the logic for its validation.

Edit Calculator.test.ts and use *Describe* create a suite of tests related with Calculator and *it* for show a console.log-("jest is running").

Your code should look like: 
```js
describe("Calculator", () => {
 
   it("should print a jest is running", () => {
       console.log("jest is running")
   })
})
```

Edit the package.json and configure be run with npm test in the scripts area.
```js
"main": "index.js",
  "scripts": {
    "test": "jest"
  },
```

If you use VSCode, you can install some extensions that allow you to run test in the same IDE.

https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest

https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner

In our case we run test from terminal

```bash
> calculator@1.0.0 test /home/dany/Desktop/calculator
> jest

 PASS  tests/Calculator.test.ts
  Calculator
    ✓ should return a number (10 ms)

  console.log
    jest is running

      at Object.<anonymous> (tests/Calculator.test.ts:4:17)

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

Stage 0 completed, we know which package install and use describe and it with jest.

_You can download a branch with the current state_
https://github.com/danywalls/jest_typescript_test_calculator/tree/setup-enviroment

## Importing code to our test

We need to test our code in Jest, edit the Calculator.ts and create a class with the Increase method it will increase a number to one.
```js
export class Calculator {
   public static increase(value: number) {
       return value + 1;
   }
}
```

We are going to use the Increase function to get it we need to do the following tasks in Calculator.test.ts

- Import the Calculator into Calculator.test.ts
- Create new test with *it* for Increase function.
- In Increase test define an initialValue variable with 1
- Use the Increase method from calculator and Store the value in resultValue. 
- Print the resultValue (it should be 2).

Your code should look like:
```js
import { Calculator } from "../app/Calculator";

describe("Calculator", () => {
 
    it("should return a number", () => {
        console.log("jest is running")
    })

    it("should increment the number", () => {
        const initValue = 1;
        const resultValue = Calculator.increase(initValue);
        console.log(resultValue);
    })
 })
```

Execute our tests using npm run test, and we got the following error.

```bash
SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (node_modules / jest-runtime / build / index.js: 1350: 14)

Test Suites: 1 failed, 1 total
```
It is because Jest needs to know where our typescript code is and this is set into jest.config.js 

Create jes.confi.js in root path same level of package.json
If you want to learn more about jest.config.js the official website have a (https://jestjs.io/docs/en/configuration)[lot of examples], here you can  get an idea about some of them:

- roots: the path from our archives.
- transform: we say use 'ts-jest'
- testRegex: we tell jest to look for spec files or test 
- moduleFileExtensions: the types of files we will support.
verbose: to show us results in the terminal.

Edit the jest.config.js and add the following settings 
- the path of our code src
```json
module.exports = {
    roots: ['<rootDir>/src'],
    transform: {
        '^.+\\.tsx?$': 'ts-jest'
    },
    testRegex: '(/__test__/.*|(\\.|/)(test|spec))\\.[jt]sx?$',
    moduleFileExtensions: ['ts', 'js'],
    verbose: true
}
```

Run our tests again and jest knows where our files and our code can be read by Jest

```bash
dany@dany:~/Desktop/calculator/tests(import-code-and-configure)$ npm run test

> calculator@1.0.0 test /home/dany/Desktop/calculator
> jest

 PASS  src/tests/Calculator.test.ts
  Calculator
    ✓ should return a number (9 ms)
    ✓ should increment the number (1 ms)

  console.log
    jest is running

      at Object.<anonymous> (src/tests/Calculator.test.ts:7:17)

  console.log
    2

      at Object.<anonymous> (src/tests/Calculator.test.ts:13:17)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        1.76 s
Ran all test suites.
```
Stage 1 completed, we know how to configure jest and call our code :) 


## Using expect and matchers

Expect is function when we you want to test a value, jest provide a lot of "matcher" function to assert values.

toBe and toEquals are 2 great matchers used to variables and objects.

### Using toBe

The ToBe matcher validate primitive types such as strings, numbers or boolean, let to use with our code.

Edit Calculator.test.ts and update the test to use expect and toBe matcher functions.

- Use expect to compare resultValue with Initial using toBe function.

The code will look like this:

```js
it("should increment the number", () => {
       const initialValue = 1;
       const resultValue = Calculator.increase(initValue);
       expect(resultValue).toBe(initialValue + 1);
   })
```

Run test and it works! the expect function get the restul value and compare the primitive value with the expected.
```bash
dany@dany:~/Desktop/calculator(import-code-and-configure)$ npm run test
> calculator@1.0.0 test /home/dany/Desktop/calculator
> jest

 PASS  src/tests/Calculator.test.ts
  Calculator
    ✓ should return a number (11 ms)
    ✓ should increment the number (1 ms)

  console.log
    jest is running

      at Object.<anonymous> (src/tests/Calculator.test.ts:7:17)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.791 s, estimated 2 s
Ran all test suites.
dany@dany:~/Desktop/calculator(import-code-and-configure)$
```

### Using toEquals

First create generateCalcSetting into Calculator.ts it returns an object with some properties from parameters values.

```js
static generateCalcSetting(valueA: number, action: string, valueB: number) {
       let result : number;
       switch (action) {
           case "+":
               result = valueA + valueB;
               break;
           case "-":
               result = valueA - valueB;
               break;
           case "/":
               result = valueA / valueB;
           default:
               result = 0;
       }
      
 
       return  {
           valueA,
           mathAction: action,
           valueB,
           result
       }
   }
```

Create a new test for generateCalcSetting method with the following. 
- Define an object with actualValues to be compared.
- Store the result for generateCalcSetting into resultValue.
- Use expect and toEqual to compare the returned object.

Your code will look like: 
```js
 it('should return a calculation Object logic', () => {
 
        const actualValue = {
            valueA: 1,
            mathAction: '+' ,
            valueB: 5,
            result: 6
        }
  
        const resultValue = Calculator.generateCalcSetting(1,'+',5);
        expect(actualValue).toEqual(resultValue);
    })
```

If you run your tests, everything works we are matching objects that is very useful.

Stage 3 completed!

##Done

This is just part 1, it helps to set up jest, configure, import code and use a basic matcher.

If you liked please share :) 

The final state of project is in https://github.com/danywalls/jest_typescript_test_calculator/tree/master

<span>Photo by <a href="https://unsplash.com/@nci?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">National Cancer Institute</a> on <a href="https://unsplash.com/s/photos/testing?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>