O site é um informativo sobre partidas e classificações de futebol!
Aqui fiquei responsável por desenvolver uma API utilizando o método TDD (Test-Driven Development) e também integrar - através do docker-compose - as aplicações para que elas funcionem consumindo um banco de dados.
Nesse projeto, construi um back-end dockerizado utilizando modelagem de dados através do Sequelize
. O desenvolvimento respeitou regras de negócio providas no projeto e a API construída com as bibliotecas Node.js
, e Express.js
foi capaz de ser consumida por um front-end já provido.
Para adicionar uma partida é necessário ter um token, portanto a pessoa deverá estar logada para fazer as alterações.
{
"email": "[email protected]",
"password": "secret_admin"
}
O banco de dados MySQL
em um relacionamento entre as tabelas teams e matches para fazer as atualizações das partidas.
O back-end está respeitando as regras de negócio para popular adequadamente a tabela disponível no front-end que será exibida para a pessoa usuária do sistema.
Clique para expandir
Clone o projeto
git clone [email protected]:DenisDaros/futebol_clube_repositorio.git
Entre no diretório do projeto
cd futebol_clube_repositorio
Rode com Docker
npm run compose:up
Para acessar Back-End via browser
http://localhost:3001/
Para acessar Front-End via browser
http://localhost:3000/
Clique para expandir
A construção de testes de cobertura no back-end foi feita em TypeScript, utilizando mocha, chai e sinon, na pasta app/backend/src/tests/
Para rodar a cobertura de testes, rode o seguinte comando
npm run test:coverage
Para rodar os testes, entre na pasta app/backend/ e rode
npm test
Clique para expandir
A biblioteca utilizada para criptografar a senha no banco de dados é a `bcryptjs` [bcryptjs npm](https://www.npmjs.com/package/bcryptjs) já veio instalada no projeto. ainda pretendo implementar no projeto para cadastrar um usuário e ao realizar login
Clique para expandir
POST /login
Clique para expandir
{
"email": "[email protected]",
"password": "secret_admin"
}
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6ImFkbWluIiwiaWF0IjoxNjU0NTI3MTg5fQ.XS_9AA82iNoiVaASi0NtJpqOQ_gHSHhxrpIdigiT-fc"
}
Clique para expandir
- email vazio
{ "message": "All fields must be filled" }
- password vazia
{ "message": "All fields must be filled" }
- email inválido
{ "message": "Incorrect email or password" }
- password inválida
{ "message": "Incorrect email or password" }
GET /login/validate
Clique para expandir
{ "role": "admin" }
Clique para expandir
- token vazio
{
"message": "Token not found"
}
- token inválido
{
"message": "Token must be a valid token"
}
GET /teams
Clique para expandir
[
{
"id": 1,
"teamName": "Avaí/Kindermann"
},
{
"id": 2,
"teamName": "Bahia"
},
{
"id": 3,
"teamName": "Botafogo"
}
]
GET /teams/:id
Parâmetro | Tipo | Descrição |
---|---|---|
id | string | Obrigatório. O ID do time que você deseja buscar |
GET /matches
Clique para expandir
[
{
"id": 40,
"homeTeam": 12,
"homeTeamGoals": 4,
"awayTeam": 8,
"awayTeamGoals": 1,
"inProgress": false,
"home_team": 12,
"away_team": 8,
"teamHome": {
"teamName": "Palmeiras"
},
"teamAway": {
"teamName": "Grêmio"
}
},
{
"id": 41,
"homeTeam": 16,
"homeTeamGoals": 2,
"awayTeam": 9,
"awayTeamGoals": 0,
"inProgress": true,
"teamHome": {
"teamName": "São Paulo"
},
"teamAway": {
"teamName": "Internacional"
}
},
{
"id": 42,
"homeTeam": 6,
"homeTeamGoals": 1,
"awayTeam": 1,
"awayTeamGoals": 0,
"inProgress": true,
"teamHome": {
"teamName": "Ferroviária"
},
"teamAway": {
"teamName": "Avaí/Kindermann"
}
}
]
GET /matches?inProgress=true
Clique para expandir
[
{
"id": 41,
"homeTeam": 16,
"homeTeamGoals": 2,
"awayTeam": 9,
"awayTeamGoals": 0,
"inProgress": true,
"home_team": 16,
"away_team": 9,
"teamHome": {
"teamName": "São Paulo"
},
"teamAway": {
"teamName": "Internacional"
}
},
{
"id": 42,
"homeTeam": 6,
"homeTeamGoals": 1,
"awayTeam": 1,
"awayTeamGoals": 0,
"inProgress": true,
"home_team": 6,
"away_team": 1,
"teamHome": {
"teamName": "Ferroviária"
},
"teamAway": {
"teamName": "Avaí/Kindermann"
}
}
]
GET /matches?inProgress=false
Clique para expandir
[
{
"id": 1,
"homeTeam": 16,
"homeTeamGoals": 1,
"awayTeam": 8,
"awayTeamGoals": 1,
"inProgress": false,
"home_team": 16,
"away_team": 8,
"teamHome": {
"teamName": "São Paulo"
},
"teamAway": {
"teamName": "Grêmio"
}
},
{
"id": 2,
"homeTeam": 9,
"homeTeamGoals": 1,
"awayTeam": 14,
"awayTeamGoals": 1,
"inProgress": false,
"home_team": 9,
"away_team": 14,
"teamHome": {
"teamName": "Internacional"
},
"teamAway": {
"teamName": "Santos"
}
}
]
POST /matches
Clique para expandir
{
"homeTeam": 16,
"awayTeam": 8,
"homeTeamGoals": 2,
"awayTeamGoals": 2
}
{
"id": 1,
"homeTeam": 16,
"homeTeamGoals": 2,
"awayTeam": 8,
"awayTeamGoals": 2,
"inProgress": true,
}
Clique para expandir
- token vazio
{
"message": "Token not found"
}
- token inválido
{
"message": "Token must be a valid token"
}
- partida com times iguais
{ "message": "It is not possible to create a match with two equal teams" }
- partida com time não existente
{ "message": "There is no team with such id!" }
PATCH /matches/:id/finish
Parâmetro | Tipo | Descrição |
---|---|---|
id | string | Obrigatório. O ID da partida que você deseja encerrar |
PATCH /matches/:id
Parâmetro | Tipo | Descrição |
---|---|---|
id | string | Obrigatório. O ID da partida em andamento que você deseja alterar |
Clique para expandir
{
"homeTeamGoals": 3,
"awayTeamGoals": 1
}
"Matche updated"
GET /leaderboard
Clique para expandir
[
{
"name": "Palmeiras",
"totalPoints": 13,
"totalGames": 5,
"totalVictories": 4,
"totalDraws": 1,
"totalLosses": 0,
"goalsFavor": 17,
"goalsOwn": 5,
"goalsBalance": 12,
"efficiency": "86.67"
},
{
"name": "Corinthians",
"totalPoints": 12,
"totalGames": 5,
"totalVictories": 4,
"totalDraws": 0,
"totalLosses": 1,
"goalsFavor": 12,
"goalsOwn": 3,
"goalsBalance": 9,
"efficiency": "80.00"
},
{
"name": "Santos",
"totalPoints": 11,
"totalGames": 5,
"totalVictories": 3,
"totalDraws": 2,
"totalLosses": 0,
"goalsFavor": 12,
"goalsOwn": 6,
"goalsBalance": 6,
"efficiency": "73.33"
},
{
"name": "Grêmio",
"totalPoints": 10,
"totalGames": 5,
"totalVictories": 3,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 9,
"goalsOwn": 8,
"goalsBalance": 1,
"efficiency": "66.67"
},
{
"name": "Internacional",
"totalPoints": 10,
"totalGames": 5,
"totalVictories": 3,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 7,
"goalsOwn": 6,
"goalsBalance": 1,
"efficiency": "66.67"
},
{
"name": "Real Brasília",
"totalPoints": 10,
"totalGames": 5,
"totalVictories": 3,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 5,
"goalsOwn": 4,
"goalsBalance": 1,
"efficiency": "66.67"
},
{
"name": "São Paulo",
"totalPoints": 8,
"totalGames": 5,
"totalVictories": 2,
"totalDraws": 2,
"totalLosses": 1,
"goalsFavor": 9,
"goalsOwn": 6,
"goalsBalance": 3,
"efficiency": "53.33"
},
{
"name": "Ferroviária",
"totalPoints": 7,
"totalGames": 5,
"totalVictories": 2,
"totalDraws": 1,
"totalLosses": 2,
"goalsFavor": 7,
"goalsOwn": 7,
"goalsBalance": 0,
"efficiency": "46.67"
},
{
"name": "São José-SP",
"totalPoints": 6,
"totalGames": 5,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 3,
"goalsFavor": 5,
"goalsOwn": 6,
"goalsBalance": -1,
"efficiency": "40.00"
},
{
"name": "Flamengo",
"totalPoints": 5,
"totalGames": 5,
"totalVictories": 1,
"totalDraws": 2,
"totalLosses": 2,
"goalsFavor": 2,
"goalsOwn": 5,
"goalsBalance": -3,
"efficiency": "33.33"
},
{
"name": "Cruzeiro",
"totalPoints": 4,
"totalGames": 5,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 3,
"goalsFavor": 8,
"goalsOwn": 10,
"goalsBalance": -2,
"efficiency": "26.67"
},
{
"name": "Avaí/Kindermann",
"totalPoints": 4,
"totalGames": 5,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 3,
"goalsFavor": 4,
"goalsOwn": 8,
"goalsBalance": -4,
"efficiency": "26.67"
},
{
"name": "Botafogo",
"totalPoints": 4,
"totalGames": 5,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 3,
"goalsFavor": 3,
"goalsOwn": 8,
"goalsBalance": -5,
"efficiency": "26.67"
},
{
"name": "Bahia",
"totalPoints": 2,
"totalGames": 5,
"totalVictories": 0,
"totalDraws": 2,
"totalLosses": 3,
"goalsFavor": 2,
"goalsOwn": 6,
"goalsBalance": -4,
"efficiency": "13.33"
},
{
"name": "Minas Brasília",
"totalPoints": 2,
"totalGames": 5,
"totalVictories": 0,
"totalDraws": 2,
"totalLosses": 3,
"goalsFavor": 4,
"goalsOwn": 9,
"goalsBalance": -5,
"efficiency": "13.33"
},
{
"name": "Napoli-SC",
"totalPoints": 2,
"totalGames": 5,
"totalVictories": 0,
"totalDraws": 2,
"totalLosses": 3,
"goalsFavor": 3,
"goalsOwn": 12,
"goalsBalance": -9,
"efficiency": "13.33"
}
]
GET /leaderboard/home
Clique para expandir
[
{
"name": "Santos",
"totalPoints": 9,
"totalGames": 3,
"totalVictories": 3,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 9,
"goalsOwn": 3,
"goalsBalance": 6,
"efficiency": "100.00"
},
{
"name": "Corinthians",
"totalPoints": 9,
"totalGames": 3,
"totalVictories": 3,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 8,
"goalsOwn": 2,
"goalsBalance": 6,
"efficiency": "100.00"
},
{
"name": "Palmeiras",
"totalPoints": 7,
"totalGames": 3,
"totalVictories": 2,
"totalDraws": 1,
"totalLosses": 0,
"goalsFavor": 10,
"goalsOwn": 5,
"goalsBalance": 5,
"efficiency": "77.78"
},
{
"name": "Grêmio",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 4,
"goalsOwn": 1,
"goalsBalance": 3,
"efficiency": "100.00"
},
{
"name": "Real Brasília",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 2,
"goalsOwn": 0,
"goalsBalance": 2,
"efficiency": "100.00"
},
{
"name": "São Paulo",
"totalPoints": 4,
"totalGames": 2,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 0,
"goalsFavor": 4,
"goalsOwn": 1,
"goalsBalance": 3,
"efficiency": "66.67"
},
{
"name": "Internacional",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 4,
"goalsOwn": 6,
"goalsBalance": -2,
"efficiency": "44.44"
},
{
"name": "Botafogo",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 2,
"goalsOwn": 4,
"goalsBalance": -2,
"efficiency": "44.44"
},
{
"name": "Ferroviária",
"totalPoints": 3,
"totalGames": 2,
"totalVictories": 1,
"totalDraws": 0,
"totalLosses": 1,
"goalsFavor": 3,
"goalsOwn": 2,
"goalsBalance": 1,
"efficiency": "50.00"
},
{
"name": "Napoli-SC",
"totalPoints": 2,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 2,
"totalLosses": 0,
"goalsFavor": 2,
"goalsOwn": 2,
"goalsBalance": 0,
"efficiency": "33.33"
},
{
"name": "Cruzeiro",
"totalPoints": 1,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 2,
"goalsOwn": 3,
"goalsBalance": -1,
"efficiency": "16.67"
},
{
"name": "Flamengo",
"totalPoints": 1,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 1,
"goalsOwn": 2,
"goalsBalance": -1,
"efficiency": "16.67"
},
{
"name": "Minas Brasília",
"totalPoints": 1,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 2,
"goalsFavor": 3,
"goalsOwn": 6,
"goalsBalance": -3,
"efficiency": "11.11"
},
{
"name": "Avaí/Kindermann",
"totalPoints": 1,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 2,
"goalsFavor": 3,
"goalsOwn": 7,
"goalsBalance": -4,
"efficiency": "11.11"
},
{
"name": "São José-SP",
"totalPoints": 0,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 0,
"totalLosses": 3,
"goalsFavor": 2,
"goalsOwn": 5,
"goalsBalance": -3,
"efficiency": "0.00"
},
{
"name": "Bahia",
"totalPoints": 0,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 0,
"totalLosses": 3,
"goalsFavor": 0,
"goalsOwn": 4,
"goalsBalance": -4,
"efficiency": "0.00"
}
]
GET /leaderboard/away
Clique para expandir
[
{
"name": "Palmeiras",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 7,
"goalsOwn": 0,
"goalsBalance": 7,
"efficiency": "100.00"
},
{
"name": "Corinthians",
"totalPoints": 6,
"totalGames": 3,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 1,
"goalsFavor": 6,
"goalsOwn": 2,
"goalsBalance": 4,
"efficiency": "66.67"
},
{
"name": "Internacional",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 3,
"goalsOwn": 0,
"goalsBalance": 3,
"efficiency": "100.00"
},
{
"name": "São José-SP",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 3,
"goalsOwn": 1,
"goalsBalance": 2,
"efficiency": "100.00"
},
{
"name": "São Paulo",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 5,
"goalsOwn": 5,
"goalsBalance": 0,
"efficiency": "44.44"
},
{
"name": "Ferroviária",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 4,
"goalsOwn": 5,
"goalsBalance": -1,
"efficiency": "44.44"
},
{
"name": "Real Brasília",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 3,
"goalsOwn": 4,
"goalsBalance": -1,
"efficiency": "44.44"
},
{
"name": "Grêmio",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 5,
"goalsOwn": 7,
"goalsBalance": -2,
"efficiency": "44.44"
},
{
"name": "Flamengo",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 1,
"goalsOwn": 3,
"goalsBalance": -2,
"efficiency": "44.44"
},
{
"name": "Avaí/Kindermann",
"totalPoints": 3,
"totalGames": 2,
"totalVictories": 1,
"totalDraws": 0,
"totalLosses": 1,
"goalsFavor": 1,
"goalsOwn": 1,
"goalsBalance": 0,
"efficiency": "50.00"
},
{
"name": "Cruzeiro",
"totalPoints": 3,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 0,
"totalLosses": 2,
"goalsFavor": 6,
"goalsOwn": 7,
"goalsBalance": -1,
"efficiency": "33.33"
},
{
"name": "Santos",
"totalPoints": 2,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 2,
"totalLosses": 0,
"goalsFavor": 3,
"goalsOwn": 3,
"goalsBalance": 0,
"efficiency": "33.33"
},
{
"name": "Bahia",
"totalPoints": 2,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 2,
"totalLosses": 0,
"goalsFavor": 2,
"goalsOwn": 2,
"goalsBalance": 0,
"efficiency": "33.33"
},
{
"name": "Minas Brasília",
"totalPoints": 1,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 1,
"goalsOwn": 3,
"goalsBalance": -2,
"efficiency": "16.67"
},
{
"name": "Botafogo",
"totalPoints": 0,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 0,
"totalLosses": 2,
"goalsFavor": 1,
"goalsOwn": 4,
"goalsBalance": -3,
"efficiency": "0.00"
},
{
"name": "Napoli-SC",
"totalPoints": 0,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 0,
"totalLosses": 3,
"goalsFavor": 1,
"goalsOwn": 10,
"goalsBalance": -9,
"efficiency": "0.00"
}
]
Docker |
Sequelize |
Node.js |
Express.js |
TypeScript |