Guia de setup para um ambiente de desenvolvimento Backend
com Node / TS / Jest
Neste setup vamos utilizar algumas tecnologias para nos ajudar a manter um código bem escrito e organizado seguindo as boas práticas
Lista das dependências que vamos utilizar no setup
prettier
typescript
@types/node
eslint eslint-plugin-promise eslint-plugin-import eslint-plugin-n @typescript-eslint/eslint-plugin eslint-config-standard-with-typescript
lint-staged
husky
commitlint
jest @types/jest ts-jest ts-node
Vamos começar a instalar um por um e explicando cada configuração
Antes de tudo vamos iniciar um projeto com npm
npm init -y
E vamos também criar um repositório git dentro do nosso projeto
git init
Precisamos também do arquivo .gitignore para excluirmos alguns arquivos a serem enviados para o GitHub
Crie um na raiz do projeto e adicione o seguinte conteudo:
node_modules
dist
coverage
A pasta node_modules é muito grande e não precisamos enviar para o GitHub
A pasta dist é onde ficará todo nosso código javascript compilado
E a pasta coverage é onde ficará o coverage dos nossos testes e também não precisamos enviar
Instalação das dependências
prettier
Para formatação e organização do nosso código
npm install -D prettier
Vamos também utilizar um arquivo de configuração para o prettier
Crie na raiz do seu projeto um arquivo chamado .prettierrc.json e adicione o seguinte conteúdo:
{
"tabWidth": 2,
"semi": false,
"useTabs": false,
"endOfLine": "lf",
"printWidth": 120,
"singleQuote": true,
"jsxSingleQuote": true,
"bracketSpacing": true,
"bracketSameLine": true,
"trailingComma": "none"
}
E também vamos criar um arquivo .prettierignore para que ele ignore algumas pastas/arquivos
Adicione o seguinte conteúdo:
node_modules
dist
coverage
typescript
Pacote nescessário para utilização do typescript em nosso projeto
npm install -D typescript
Precisamos de um arquivo de configuração para o typescript
Crie na raiz do projeto um arquivo chamado tsconfig.json e adicione o seguinte conteúdo:
{
"compilerOptions": {
"outDir": "./dist",
"module": "CommonJS",
"target": "ES2020",
"esModuleInterop": true,
"allowJs": true,
"strict": true,
"strictNullChecks": true
}
}
Explicação do arquivo:
outDir: Pasta que será criada para manter todo nosso código compilado
module: Para podermos utilizar import/export mas compilar o código para o formato require
target: Versão para qual o typescript será compilado
esModuleInterop: Converte import/export para require em módulos que ainda usam esse formato
allowJs: Permite incluir arquivos JS na compilação para pasta Dist
strict: Para habilitar o modo estrito do typescript para melhor qualidade do código
strictNullChecks: Habilita uma verificação mais rigorosa para valores null & undefined
@types/node
npm install -D @types/node
Pacote que adiciona tipagens para o Node que nos ajuda a evitar alguns erros bobos
eslint eslint-plugin-promise eslint-plugin-import eslint-plugin-n @typescript-eslint/eslint-plugin eslint-config-standard-with-typescript
npm install -D eslint eslint-plugin-promise eslint-plugin-import eslint-plugin-n @typescript-eslint/eslint-plugin eslint-config-standard-with-typescript
Como vamos utilizar o padrão Standard Javascript precisamos incluir todos esses pacotes para que o eslint consiga configurar esse padrão para o typescript
Precisamos também de mais dois arquivos de configuração para o ESLINT
Crie na raiz do projeto o arquivo chamado .eslintrc.json e adicione o seguinte conteúdo:
{
"extends": "standard-with-typescript",
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
"@typescript-eslint/space-before-function-paren": "off"
}
}
Explicação do arquivo:
extends: Extensão das regras padrões do ESLINT para adicionar mais regras para o typescript
parserOptions: Opções que podemos passar para análise do parser do ESLINT
project: Para usar as configurações definidas no arquivo tsconfig.json do nosso projeto
rules: Onde podemos habilitar ou desabilitar regras do ESLINT
Também precisamos de outro arquivo chamado .eslintignore que vai sinalizar ao ESLINT quais pastas/arquivos ele deve ignorar na análise de código, crie um e adicione o seguinte conteúdo:
node_modules
dist
coverage
lint-staged
Pacote que vamos utilizar para rodar scripts apenas em arquivos modificados na área staged do Git
npm install -D lint-staged
Precisamos de um arquivo de configuração para o lint-staged
Crie na raiz do projeto um arquivo chamado .lintstagedrc.json e adicione o seguinte conteúdo:
{
"*.ts": ["eslint 'src/**/*' --fix"]
}
Fazendo isso estamos dizendo para o lint-staged rodar o comando em qualquer arquivo dentro de qualquer pasta dentro de src que tenha a extensão .ts
husky
Pacote para podermos adicionar hooks ao git fazendo com que ele rode scripts durante alguns estágios que escolhermos
npm install -D husky
Para habilitar os hooks rode o seguinte comando:
npx husky install
Vamos adicionar um hook que vai rodar um script sempre que fizermos um commit
npx husky add .husky/pre-commit "npx lint-staged"
Esse comando cria na raiz do seu projeto uma pasta chamada .husky onde ficará todos os seus hooks e os scripts que vão ser rodados sempre que alguma ação definida acontecer
Vamos utilizar o lint-staged para rodar scripts nos arquivos modificados do git
O lint-staged será o responsável por rodar os scripts que definimos dentro do arquivo .lintstagedrc.json
commitlint
Para padronizar os commits seguindo o Conventional commits
De baixo dos panos é criado um hook que verifica cada commit e valida se estamos seguindo o padrão Conventional commits
npm install -D @commitlint/config-conventional @commitlint/cli
Vamos precisar criar mais um arquivo de configuração para o commitlint
Crie um arquivo chamado .commitlintrc.json e adicione o seguinte código:
{ "extends": ["@commitlint/config-conventional"] }
Após instalar o husky e o commitlint e criado o arquivo de configuração use o seguinte comando:
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'
Feito isso seu linter de commits deve funcionar normalmente
jest @types/jest ts-jest ts-node
Pacotes nescessários para utilização do Jest com Typescript
npm install -D jest @types/jest ts-jest ts-node
Após terminar a instalação dos pacotes vamos rodar o seguinte comando:
npx jest --init
E isso irá iniciar algumas perguntas:
Would you like to use Jest when running "test" script in "package.json"?
Aqui ele está perguntando se queremos criar o script "test": "jest" no nosso arquivo package.json
Escolha a resposta yes porque vamos utilizar esse script
Would you like to use Typescript for the configuration file?
Aqui informamos se queremos criar um arquivo de configuração com typescript
E já que estamos utilizando typescript vamos escolher a resposta yes
Choose the test environment that will be used for testing
Aqui é onde escolhemos o ambiente onde vamos fazer o testes
E como é backend vamos selecionar a resposta node
Do you want Jest to add coverage reports?
Aqui é onde escolhemos se queremos coverage dos nossos arquivos gerado pelo Jest
É uma boa escolha ter o coverage do nosso projeto pra ter uma noção do que falta ser testado
Escolha a resposta yes
Which provider should be used to instrument code for coverage?
Aqui vamos escolher a resposta v8 para instrumentar nosso código
Automatically clear mock calls, instances, contexts and results before every test?
Aqui vamos escolher a resposta no para sinalizar ao Jest que não queremos que ele limpe nossos mocks para termos um melhor controle sobre nossos mocks durante os testes
Após todas as perguntas ele vai criar um arquivo na raiz do nosso projeto chamado jest.config.ts
Dentro desse arquivo substitua o conteúdo por essas opções:
export default {
roots: ['<rootDir>/src'],
coverageProvider: 'v8',
collectCoverage: true,
collectCoverageFrom: ['<rootDir>/src/**/*.ts'],
coverageDirectory: 'coverage',
testEnvironment: 'node',
transform: {
'.+\\.ts$': 'ts-jest'
},
testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[tj]s?(x)']
}
Explicação do arquivo:
roots: Especifica os diretórios que contêm os arquivos de código-fonte do projeto
coverageProvider: Especifica o provedor de cobertura de código que será usado pelo Jest
collectCoverage: Ativa a coleta de informações de cobertura de código
collectCoverageFrom: Especifica os arquivos de código-fonte que serão usados para coletar as informações de cobertura de código.
coverageDirectory: Especifica o diretório onde os resultados da cobertura de código serão armazenados
testEnvironment: Especifica o ambiente em que os testes serão executados
transform: Especifica como os arquivos de código-fonte serão transformados antes de serem executados, vamos utilizar o ts-jest para compilar arquivos para JS apenas para o Jest
testMatch: Especifica os arquivos de teste que serão executados
Agora vamos testar se todo nosso setup está rodando corretamente
Crie na raiz do projeto uma pasta chamada src e dentro dela crie um arquivo controller.spec.ts com o seguinte código:
describe('Controller Test', () => {
test('Should pass the test', () => {
expect(1).toBe(1)
})
})
Após isso rode o comando:
npm run test
Se o setup foi feito corretamente você deverá ver o resultado do seu primeiro teste
Vamos também testar se nossos commits estão padronizados
Rode os seguintes comandos:
git add .
git commit -m "Testando os commits"
E de novo, se o setup foi feito corretamente você deverá ver uma mensagem de erro dizendo que seu commit deve seguir o padrão definido no projeto.