Configurando Jest no seu projeto com Angular
Tags: jest, angular, testing, javascript
Published: 2020-08-18 19:55:42

Eu estou criando este artigo pois ao começar meus estudos no mundo dos testes, me deparei com o seguinte problema, vou utilizar Angular para criar uma aplicação e por padrão ele utiliza *Karma* e *Jasmine*, porém não vou utilizar estes caras para testar e sim o tal do *Jest*.

Não vou falar sobre quem é melhor ou pior(~~até por que eu nem sei~~), mas o fato é que eu preciso do *Jest* configurado no meu projeto para iniciar meus testes com teste(~~HAHAHAHAHA~~).

Porém dei uma olhada no *State Of JS* e o nível de interesse e satisfação a respeito do Jest se encontra assim:

![State of js test](https://dev-to-uploads.s3.amazonaws.com/i/jbwps27m3l3ky9tjd0i0.png)

Caso queira saber mais é só entrar neste link: [*State of js*](https://2019.stateofjs.com/testing/)

## 🔥 Introdução

Para configurar o *Jest* em seu projeto com *Angular*(~~e até mesmo rodar o projeto~~), vamos precisar dos seguintes programas instalados:

- npm
- node
- npx

**npm**: Gerenciador de pacotes para a linguagem de programação *JavaScript*;

**node**: Trata-se de um *software* *open-source*, *cross-platform* e *runtime* para *JavaScript*;

**npx**: *Package runner* que permite executar código criado com *Node.js* e publicado por meio do registro *NPM*;

## 💊 Cenário do projeto

Primeiro vamos entender o cenário do seu projeto, possivelmente você deve estar usando *Karma* e *Jasmine* e quer mudar para o *Jest*, caso seja isto continue a leitura do artigo. 

Se você criou sua aplicação *Angular* utilizando o parâmetro `--minimal=true`, [clique aqui](#minimal) para pular algumas etapas desnecessárias.

## 🚀 Iniciando

Então vamos separar este artigo em diversas parte:

✔️ Removendo o *Karma* e o *Jasmine* do seu projeto;
✔️ Adicionando as dependências do *Jest*
✔️ Configurando o *Jest* no projeto
✔️ BÔNUS: Configurando o *Jest* no comando `ng` do *Angular*

## 💣 Removendo Karma e Jasmine do seu projeto

Como não vamos mais utilizar algumas dependências, precisamos remover toda configuração e arquivos que se encontra no projeto que é desnecessário.

### 📌 Removendo as dependências
```javascript
npm uninstall karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter @types/jasmine @types/jasminewd2 jasmine-core jasmine-spec-reporter protractor
```

Ao rodar o comando acima você vai remover *Karma* e *Jasmine* das *devDependencies* do `package.json`

### 📌 Removendo arquivos e pastas

Os arquivos `karma.conf.js`, `test.ts` e a pasta `e2e` não são mais necessários, podemos deletar os três.

`Karma.conf.js` se encontra na raiz da aplicação:
```javascript
./karma.conf.js
```

`test.ts` se encontra dentro da pasta `src` que está na raiz da aplicação:
```javascript
./src/test.ts
```

A pasta `e2e` se encontra na raiz do projeto:
```javascript
./e2e
```

O arquivo `tsconfig.spec.json` vai ser necessário, então vamos apenas apagar o seu conteúdo.

### 📌 Removendo o comando *test* e *e2e* no arquivo `angular.json`
```javascript
"test": {
  "builder": "@angular-devkit/build-angular:karma",
  "options": {
    "main": "src/test.ts",
    "polyfills": "src/polyfills.ts",
    "tsConfig": "tsconfig.spec.json",
    "karmaConfig": "karma.conf.js",
    "assets": [
      "src/favicon.ico",
      "src/assets"
    ],
    "styles": [
      "src/styles.css"
    ],
    "scripts": []
  }
}
"e2e": {
  "builder": "@angular-devkit/build-angular:protractor",
  "options": {
    "protractorConfig": "e2e/protractor.conf.js",
    "devServerTarget": "project-with-test:serve"
  },
  "configurations": {
    "production": {
      "devServerTarget": "project-with-test:serve:production"
    }
  }
}
```
Os caras acima são responsáveis por fazer funcionar o comando:
```javascript
ng test
```
e 
```javascript
ng e2e
```

Pelo que eu vi(~~mas posso estar errado~~) uma prática normal é criar no `package.json` um script novo para rodar o *Jest*, exemplo:

```javascript
"test": "jest --passWithNoTests",
"test:watch": "jest --watch --passWithNoTests",
"test:watchAll": "jest --watchAll --passWithNoTests",
```

Porém vamos configurar o *Jest* no `angular.json` para suportar o uso do comando `ng`:
```javascript
"test": "ng test --passWithNoTests",
"test:watch": "ng test --watch --passWithNoTests",
"test:watchAll": "ng test --watchAll --passWithNoTests",
```

Mas não agora, vamos deixar isto por ultimo e usar o comando:
```javascript
npx jest
```

deixando o comando do jeito que ele veio:  
```javascript
"test": "ng test",
```

Ele não irá funcionar, provavelmente dando o seguinte erro:

```javascript
An unhandled exception occurred: No projects support the 'test' target.
```

Pois você removeu a configuração no `angular.json`.

Legal, se você vem de um projeto com *Karma* e *Jasmine* configurado, agora não tem mais nada de teste no seu projeto e se iguala a um projeto criado com o argumento `--minimal=true`

Exemplo:
```javascript
ng new project-without-test-and-more --minimal=true
```

## 🐸 Adicionando as dependências do *Jest* <a name="minimal"></a>

Com o comando abaixo instalaremos as dependências para o *Jest* funcionar:
```javascript
npm install --save-dev jest @types/jest jest-preset-angular
```

- jest
- @types/jest
- jest-preset-angular

**jest**:  *Framework* de testes em *JavaScript* com um foco na simplicidade;

**@types/jest**: Tipos do *Jest* para o *TypeScript* poder funcionar corretamente;

**jest-preset-angular**: Predefinições para o *Jest*;

Após as dependências do *Jest* instaladas vamos iniciar a configuração no projeto.

## 👻 Configurando o *Jest* no projeto

### 📌 Criando o arquivo `setupJest.ts`

Crie o arquivo na raiz do seu projeto chamado `setupJest.ts` e importe o modulo `jest-preset-angular`, vai ficar assim o arquivo:
```javascript
import 'jest-preset-angular';
```

### 📌 Configurando `tsconfig.spec.json`

Altere o arquivo `tsconfig.spec.json`, caso não tenha, crie ele na raiz do seu projeto.
```javascript
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./out-tsc/spec",
    "types": [
      "jest",
      "node"
    ]
  },
  "files": [
    "src/polyfills.ts"
  ],
  "include": [
    "src/**/*.spec.ts",
    "src/**/*.d.ts"
  ]
}
```

### 📌 Configurando `package.json`

Adicione o código abaixo dentro do arquivo `package.json`:
```javascript
"jest": {
    "preset": "jest-preset-angular",
    "setupFilesAfterEnv": [
      "<rootDir>/setupJest.ts"
    ],
    "testPathIgnorePatterns": [
      "<rootDir>/node_modules/",
      "<rootDir>/dist/",
      "<rootDir>/src/test.ts"
    ],
    "globals": {
      "ts-jest": {
        "tsConfig": "<rootDir>/tsconfig.spec.json",
        "stringifyContentPathRegex": "\\.html$"
      }
    }
  }
```

OK, *Jest* configurado agora é só rodar o seguinte comando para ver a magia acontecer:

```javascript
npx jest
```

## 🏃 Configurando o *Jest* no comando `ng` do *Angular*

Agora vamos adicionar a execução do *Jest* junto ao comando:
```javascript
npm run test
```

Para isso precisamos instalar a dependência: 
```javascript
npm install --save-dev @angular-builders/jest
```

e configurar o arquivo `angular.json` adicionando o seguinte código:
```javascript
"test": {
  "builder": "@angular-builders/jest:run"
}
```

Com isso agora é só rodar o comando:
```javascript
npm run test
```

e sua aplicação está apta a rodar o *Jest* utilizando o *Angular*.

## 🍦 exemplo

Caso queira ver na prática, segue o projeto com a remoção do *Karma* e *Jasmine* e a adição e configuração do *Jest*.

{% github lucasdeoliveiradev/configurando-jest-no-angular %}

## 🐧 Criticas e Sugestões

Caso eu não tenha abordado algum problema deixa nos comentários que eu vou estudar e adicionar no artigo(ou não)