Ao iniciar este projeto, você concorda com as diretrizes do Código de Ética e Conduta e do Manual da Pessoa Estudante da Trybe.
Você já usa o GitHub diariamente para desenvolver os exercícios, certo? Agora, para desenvolver os projetos, você deverá seguir as instruções a seguir. Fique atento a cada passo, e se tiver qualquer dúvida, nos envie por Slack! #vqv 🚀
Aqui você vai encontrar os detalhes de como estruturar o desenvolvimento do seu projeto a partir deste repositório, utilizando uma branch específica e um Pull Request para colocar seus códigos.
- Boas vindas ao repositório do TFC - Trybe Futebol Clube! ⚽️
- Habilidades
- Entregáveis
- Instruções para entregar seu projeto:
- Como desenvolver
- Requisitos do projeto:
- Antes de começar:
- Configuração Docker:
- Lista de Requisitos:
- 0 - Pré-requisitos
- Sequelize
- 1 - Desenvolva em
/app/backend/src/database
nas pastas correspondentes, uma migration e um model para a tabela deteams
- 2 - Desenvolva em
/app/backend/src/database
nas pastas correspondentes, uma migration e um model para a tabela dematches
- 3 - Desenvolva em
/app/backend/src/database
nas pastas correspondentes, uma migration e um model para a tabelausers
- 1 - Desenvolva em
- Login
- 4 - (
TDD
) Desenvolva testes que cubram no mínimo 5 por cento dos arquivos back-end em/src
com um mínimo de 7 linhas cobertas - 5 - Desenvolva o endpoint
/login
no backend de maneira ele permita o acesso com dados válidos no frontend - 6 - (
TDD
) Desenvolva testes que cubram no mínimo 10 por cento dos arquivos back-end em/src
com um mínimo de 19 linhas cobertas - 7 - Desenvolva o endpoint
/login
no backend de maneira ele não permita o acesso com um email inválido no front-end - 8 - (
TDD
) Desenvolva testes que cubram no mínimo 15 por cento dos arquivos back-end em/src
com um mínimo de 25 linhas cobertas - 9 - Desenvolva o endpoint
/login
no back-end de maneira ele não permita o acesso com uma senha inválida no front-end - 10 - (
TDD
) Desenvolva testes que cubram no mínimo 20 por cento dos arquivos back-end em/src
com um mínimo de 35 linhas cobertas - 11 - Desenvolva o endpoint
/login
no back-end de maneira ele não permita o acesso sem informar um email no front-end - 12 - (
TDD
) Desenvolva testes que cubram no mínimo 30 por cento dos arquivos back-end em/src
com um mínimo de 45 linhas cobertas - 13 - Desenvolva o endpoint
/login
no back-end de maneira ele não permita o acesso sem informar uma senha no front-end - 14 - Desenvolva o endpoint
/login/validate
no back-end de maneira ele retorne os dados corretamente no front-end
- 4 - (
- Jogos
- 15 - (
TDD
) Desenvolva testes que cubram no mínimo 45 por cento dos arquivos back-end em/src
com um mínimo de 70 linhas cobertas - 16 - Desenvolva o endpoint
/teams
no back-end de forma que ele possa retornar todos os times corretamente - 17 - Desenvolva o endpoint
/teams/:id
no back-end de forma que ele possa retornar dados de um time específico - 18 - (
TDD
) Desenvolva testes que cubram no mínimo 60 por cento dos arquivos back-end em/src
com um mínimo de 80 linhas cobertas - 19 - Desenvolva o endpoint
/matches
de forma que os dados apareçam corretamente na tela de partidas no front-end. - 20 - Desenvolva o endpoint
/matches
de forma que seja possível filtrar as partidas em andamento na tela de partidas do front-end - 21 - Desenvolva o endpoint
/matches
de forma que seja possível filtrar as partidas finalizadas na tela de partidas do front-end
- 15 - (
- Adicionar Partidas
- 22 - (
Bônus
;TDD
) Desenvolva testes que cubram no mínimo 80 por cento dos arquivo back-end em/src
com um mínimo de 100 linhas cobertas - 23 - Desenvolva a rota
/matches
de modo que seja possível salvar uma partida com o status de inProgress como true no banco de dados - 24 - Desenvolva a rota
/matches/:id/finish
de modo que seja possível salvar uma partida com o status de inProgress como false no banco de dados - 25 - Desenvolva o endpoint
/matches
de forma que não seja possível inserir uma partida com times iguais - 26 - Desenvolva o endpoint
/matches
de forma que não seja possível inserir uma partida com time que não existe na tabela teams
- 22 - (
- Editar Partidas
- Leaderboards
- Leaderboard Home
- 29 - Desenvolva o endpoint
/leaderboard/home
de forma que seja possível filtrar a classificações dos times quando mandantes na tela de classificação do frontend com os dados iniciais do banco de dados - 30 - Desenvolva o endpoint
/leaderboard/home
, de forma que seja possível filtrar a classificações dos times quando mandantes na tela de classificação do front-end e ao inserir a partida Corinthians 2 X 1 Internacional a tabela será atualizada
- 29 - Desenvolva o endpoint
- Leaderboard away
- 31 - Desenvolva o endpoint
/leaderboard/away
, de forma que seja possível filtrar as classificações dos times na tela de classificação do front-end, com os dados iniciais do banco de dados - 32 - Desenvolva o endpoint
/leaderboard/away
de forma que seja possível filtrar a classificações dos times na tela de classificação do front-end e ao inserir a partida Corinthians 2 X 1 Internacional a tabela seja atualizada
- 31 - Desenvolva o endpoint
- Leaderboard
- 33 - Desenvolva o endpoint
/leaderboard
de forma que seja possível filtrar a classificação geral dos times na tela de classificação do front-end com os dados iniciais do banco de dados - 34 - Desenvolva o endpoint /leaderboard de forma que seja possível filtrar a classificação geral dos times na tela de classificação do front-end e ao inserir a partida Flamengo 3 X 0 Napoli-SC a tabela será atualizada
- 35 - Desenvolva o endpoint /leaderboard de forma que seja possível filtrar a classificação geral dos times na tela de classificação do front-end e ao inserir a partida Minas Brasília 1 X 0 Ferroviária a tabela será atualizada
- 33 - Desenvolva o endpoint
- Leaderboard Home
- Depois de terminar o desenvolvimento
- Avisos Finais
O TFC
é um site informativo sobre partidas e classificações de futebol! ⚽️
No time de desenvolvimento do TFC
, seu squad ficou responsável por desenvolver uma API (utilizando o método TDD
) e também integrar - através do docker-compose - as aplicações para que funcionem consumindo um banco de dados.
Nesse projeto, você vai construir um back-end dockerizado utilizando modelagem de dados através do Sequelize. Seu desenvolvimento deve respeitar regras de negócio providas no projeto e sua API deve ser capaz de ser consumida por um front-end já provido nesse projeto. Você será capaz de:
- Realizar a dockerização dos apps, network, volume e compose;
- Modelar dados com MySQL através do Sequelize;
- Criar e associar tabelas usando
models
dosequelize
; - Construir uma API REST com endpoints para consumir os models criados;
- Fazer um
CRUD
utilizandoORM
;
Para entregar o seu projeto você deverá criar um Pull Request neste repositório.
Lembre-se que você pode consultar nosso conteúdo sobre Git & GitHub sempre que precisar!
Você vai arquitetar e desenvolver uma aplicação responsável pela serie A do campeonato TFC - Trybe Futebol Clube. Começando pela API, você vai desenvolver alguns endpoints (seguindo os princípios REST) que estarão conectados ao seu banco de dados. Lembre-se de aplicar os princípios SOLID!
O seu back-end deverá implementar regras de negócio para popular adequadamente a tabela disponível no front-end que será exibida para a pessoa usuária do sistema.
Você deve desenvolver uma aplicação dockerizada em Node.js + Typescript
usando o pacote sequelize
.
Para adicionar uma partida é necessário usuário e senha, portanto a pessoa deverá estar logada para fazer as alterações. Teremos um relacionamento entre as tabelas teams
e matches
para fazermos as atualizações das partidas.
-
Projeto individual;
-
Serão
4
dias de projeto; -
Data de entrega para avaliação final do projeto:
05/05/2022 14:00
.
- Clone o repositório
git clone https://github.com/tryber/sd-015-b-trybe-futebol-clube.git
.- Entre na pasta do repositório que você acabou de clonar:
cd sd-015-b-trybe-futebol-clube
- Instale as dependências [Caso existam]
npm install
- Crie uma branch a partir da branch
master
- Verifique que você está na branch
master
- Exemplo:
git branch
- Exemplo:
- Se não estiver, mude para a branch
master
- Exemplo:
git checkout master
- Exemplo:
- Agora crie uma branch à qual você vai submeter os
commits
do seu projeto- Você deve criar uma branch no seguinte formato:
nome-de-usuario-nome-do-projeto
- Exemplo:
git checkout -b joaozinho-sd-015-b-trybe-futebol-clube
- Você deve criar uma branch no seguinte formato:
- Adicione as mudanças ao stage do Git e faça um
commit
- Verifique que as mudanças ainda não estão no stage
- Exemplo:
git status
(deve aparecer listada a pasta joaozinho em vermelho)
- Exemplo:
- Adicione o novo arquivo ao stage do Git
- Exemplo:
git add .
(adicionando todas as mudanças - que estavam em vermelho - ao stage do Git)git status
(deve aparecer listado o arquivo joaozinho/README.md em verde)
- Exemplo:
- Faça o
commit
inicial- Exemplo:
git commit -m 'iniciando o projeto x'
(fazendo o primeiro commit)git status
(deve aparecer uma mensagem tipo nothing to commit )
- Exemplo:
- Adicione a sua branch com o novo
commit
ao repositório remoto
- Usando o exemplo anterior:
git push -u origin joaozinho-sd-015-b-trybe-futebol-clube
- Crie um novo
Pull Request
(PR)
- Vá até a página de Pull Requests do repositório no GitHub
- Clique no botão verde "New pull request"
- Clique na caixa de seleção "Compare" e escolha a sua branch com atenção
- Clique no botão verde "Create pull request"
- Adicione uma descrição para o Pull Request e clique no botão verde "Create pull request"
- Não se preocupe em preencher mais nada por enquanto!
- Volte até a página de Pull Requests do repositório e confira que o seu Pull Request está criado
-
Faça
commits
das alterações que você fizer no código regularmente -
Lembre-se de sempre após um (ou alguns)
commits
atualizar o repositório remoto -
Os comandos que você utilizará com mais frequência são:
git status
(para verificar o que está em vermelho - fora do stage - e o que está em verde - no stage)git add
(para adicionar arquivos ao stage do Git)git commit
(para criar um commit com os arquivos que estão no stage do Git)git push -u nome-da-branch
(para enviar o commit para o repositório remoto na primeira vez que fizer opush
de uma nova branch)git push
(para enviar o commit para o repositório remoto após o passo anterior)
⚠️ Para adicionar pacotes adicionais ao backend, utilize o arquivoapp/backend/packages.npm
, separando os pacotes adicionais por espaços ou quebras de linha.⚠️ Não altere o arquivoapp/backend/packages.json
, pois o mesmo está travado para essa avaliação
Para garantir a qualidade do código, usaremos o ESLint para fazer a sua análise estática.
Este projeto já vem com as dependências relacionadas ao linter configuradas nos arquivos package.json
nos seguintes caminhos:
sd-015-b-trybe-futebol-clube/app/backend/package.json
Para rodar o ESLint
em um projeto, basta executar o comando npm install
dentro do projeto e depois npm run lint
. Se a análise do ESLint
encontrar problemas no seu código, tais problemas serão mostrados no seu terminal. Se não houver problema no seu código, nada será impresso no seu terminal.
Você também pode instalar o plugin do ESLint
no VSCode
, bastar ir em extensions e baixar o plugin ESLint
.
⚠ PULL REQUESTS COM ISSUES DE LINTER NÃO SERÃO AVALIADAS. ATENTE-SE PARA RESOLVÊ-LAS ANTES DE FINALIZAR O DESENVOLVIMENTO! ⚠
O não cumprimento de um requisito, total ou parcialmente, impactará em sua avaliação.
Os testes vão utilizar sua aplicação do compose para fazer as validações, por tanto é essencial que ele esteja funcionando corretamente para que os testes passem!
- Para isso, garanta que as aplicações, tanto do back, quanto do front-end, possuem arquivos
Dockerfile
válidos; - Utilize os scripts de apoio
npm run compose:up
/npm run compose:down
, para facilitar a execução do seu compose.
Você irá precisar configurar as variáveis globais do MySQL. Você pode usar esse Conteúdo de variáveis de ambiente com NodeJS como referência.
Faça essas configurações também para as variáveis de ambiente usadas nesses arquivo:
sd-015-b-trybe-futebol-clube/app/backend/src/database/config/database.ts
module.exports = {
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: TRYBE_FUTEBOL_CLUBE,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
dialect: 'mysql',
};
(Neste arquivo é obrigatório deixar o nome do database como "database": 'TRYBE_FUTEBOL_CLUBE'
)
É essencial usar essas 3 variáveis no arquivo acima:
host: process.env.DB_HOST
user: process.env.DB_USER
password: process.env.DB_PASS
Com elas que iremos conseguir conectar ao banco do avaliador automático
JWT
deve ser inserida em app/backend/jwt.evaluation.key
e pode ser carregada no backend com o uso da biblioteca fs
.
bcryptjs
bcryptjs npm. Utilize essa biblioteca, ela pode ser colocada como dependência em app/backend/package.json
para depois instalar todos os pacotes.
A construção de testes de cobertura no backend deve ser feita em TypeScript, utilizando mocha
, chai
e sinon
, na pasta app/backend/src/tests/
, conforme o exemplo em app/backend/src/tests/change.me.test.ts
(aqui considerando um teste de integração):
import * as sinon from 'sinon';
import * as chai from 'chai';
import chaiHttp = require('chai-http');
import { app } from '../app';
import Example from '../database/models/ExampleModel';
import { Response } from 'superagent';
chai.use(chaiHttp);
const { expect } = chai;
describe('Seu teste', () => {
/**
* Exemplo do uso de stubs com tipos
*/
// let chaiHttpResponse: Response;
// before(async () => {
// sinon
// .stub(Example, "findOne")
// .resolves({
// ...<Seu mock>
// } as Example);
// });
// after(()=>{
// (Example.findOne as sinon.SinonStub).restore();
// })
// it('...', async () => {
// chaiHttpResponse = await chai
// .request(app)
// ...
// expect(...)
// });
it('Seu sub-teste', () => {
expect(false).to.be.eq(true);
});
});
Os testes devem cobrir todos os arquivos contidos em app/backend/src
, com exceção daqueles que já foram entregues com o projeto.
Para rodar testes de cobertura no seu back-end, utilize o comando: npm run test:coverage
- Você pode instalar suas aplicações (front e back) rodando o comando
npm run install:apps
; - Você pode rodar o avaliador mostrando as operações que o navegador vai fazer no frontend durante os testes E2E utilizando o comando
npm run test:browser
; - Você pode debugar alguns erros do avaliador (como por exemplo a validação do banco de dados, ou da compilação do TS), onde são printados na tela algumas infos adicionais, utilizando o comando
npm run test:debug
; - Você pode subir ou descer uma aplicação do compose, utilizando os scripts
compose:up
,compose:down
; - Para criação da API com TS + POO, recomenda-se fazer ou relembrar os exercícios do conteúdo de POO e SOLID, especificamente o do dia
SOLID - Introdução e Princípios S, O e D
, nesse link.
Tenha em mente que todas as "respostas" devem respeitar os status do protocolo HTTP com base no que o REST prega.
Alguns exemplos:
-
Requisições que precisam de token mas não o receberam devem retornar um código de
status 401
; -
Requisições que não seguem o formato pedido pelo servidor devem retornar um código de
status 400
; -
Um problema inesperado no servidor deve retornar um código de
status 500
; -
Um acesso ao criar um recurso, no nosso caso usuário ou partida, deve retornar um código de
status 201
.
⚠ O seu docker-compose precisa estar na versão 1.29 ou superior. Veja aqui a documentação para atualizar o docker-compose. ⚠
- As pastas
frontend/
ebackend/
devem possuir um arquivo dockerfile - A pasta
app/
deve possuir um arquivo docker-compose - Os arquivos dockerfile e docker-compose devem estar configurados corretamente
Observação
Em seu projeto vai conter um arquivo docker-compose.example.yml.
Seu service do backend no docker-compose deve ter o depends_on
exatamente igual ao do arquivo docker-compose.example.yml.
Use o modelo de serviço do banco de dados que está no arquivo app/docker-compose.example.yml
, que está igual ao formato abaixo:
Lembre-se, você pode revisitar os conteúdos sobre Docker:
- Dockerfile (Seção Dockerfile - Comandos Básicos)
- docker-compose (Seção Compose File - Parte I)
version: '3.9'
services:
frontend:
build: ./frontend
# ...
depends_on:
backend:
condition: service_healthy
# Os `healthcheck` devem garantir que a aplicação
# está operacional, antes de liberar o container
healthcheck:
test: ["CMD", "lsof", "-t", "-i:3000"] # Caso utilize outra porta interna para o front, altere ela aqui também
timeout: 10s
retries: 5
backend:
build: ./backend
# ...
depends_on:
db:
condition: service_healthy
environment:
- PORT=3001
# Os dados abaixo se referem ao container `db`
# Dica: Relembre aqui da comunicação interna entre containers
- DB_USER=root
- DB_PASS=123456
- DB_HOST=db
- DB_NAME=TRYBE_FUTEBOL_CLUBE
- DB_PORT=3306
healthcheck:
test: ["CMD", "lsof", "-t", "-i:3001"] # Caso utilize outra porta interna para o back, altere ela aqui também
timeout: 10s
retries: 5
db:
image: mysql:8.0.21
container_name: db
ports:
- 3002:3306
environment:
- MYSQL_ROOT_PASSWORD=123456
restart: 'always'
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"] # Deve aguardar o banco ficar operacional
timeout: 10s
retries: 5
cap_add:
- SYS_NICE # Deve omitir alertas menores
Isso porque, o avaliador irá executar um teste de usabilidade E2E (End-to-end, ou Ponto a ponto. Leia mais sobre esse tipo de teste nesse link), acompanhado de validações adicionais (Compilação do TypeScript e inicialização do Sequelize) que podem ser acompanhados pelo uso do script npm run test:debug
;
Considerar, que para TODO REQUISITO, EXCETO os de testes de cobertura:
- Deve existir uma aplicação de back-end rodando em um container de nome
app_backend
;- Considere a leitura do dia de Docker
Manipulação e Criação de Imagens no Docker
nesse link. ⚠️ Caso o nome do container não seja criado automaticamente utilizando os underlines (_
), utilize o parâmetrocontainer_name
no seu serviço para customizar e forçar o nome do mesmo:
- Considere a leitura do dia de Docker
#...
backend:
# ...
container_name: app_backend
# ...
# ...
-
O container
app_backend
deve ser capaz de se comunicar com outro container rodando um banco de dados mysql;- Considere a leitura do dia de Docker
Orquestrando Containers com Docker Compose
nesse link.
- Considere a leitura do dia de Docker
-
Dentro do container
app_backend
, o avaliador irá verificar:- Que é possível rodar o
tsc
("TypeScript Compiler") sem erros, através do scriptbuild
, da própria aplicação back-end; - Que o
tsc
deve gerar um arquivo./build/database/config/database.js
dentro do containerapp_backend
;- Considere a leitura da seção
Bônus: Model com Sequelize
no conteúdo de TypeScript:Tipagem Estática e Generics
nesse link.
- Considere a leitura da seção
- Que é possível restaurar e popular o banco de dados utilizando o
sequelize-cli
, a partir do arquivo de configuração./build/database/config/database.js
, utilizando o scriptdb:reset
, da própria aplicação back-end.⚠️ Note:- Os seeds já foram providos em
./app/backend/src/database/seeders
, porém, precisam ser renomeados (remoção do underline (_
), do final do arquivo) para que possam ser reconhecidos pelosequelize-cli
, a medida que as respectivasmigrations
forem criadas; - Existe uma
migration
com nome./app/backend/src/database/migrations/99999999999999-create-z.js
responsável por indicar que o banco foi criado corretamente e está funcionando, não apague ou renomeie essa migration,
- Os seeds já foram providos em
- Que é possível rodar o
-
Considerando o uso do parâmetro
healthcheck
em cada container do seudocker-compose.yml
, a inicialização dos containers devem aguardar o comando de status de saúde (o que valida se aquele container está operacional ou não):- No container
db
, representado por um comandoping
no banco de dados; - No back-end, representado por um comando
lsof
que vai procurar aplicações ativas na porta definida (por padrão, no caso3001
); - No front-end, representado por um comando
lsof
que vai procurar aplicações ativas na porta definida (por padrão, no caso3000
);
- No container
-
Caso os containers respeitem as premissas anteriores, os mesmos devem ser criados, sem maiores problemas:
- No compose, não há necessidade de parar e/ou reiniciar containers que não tiveram alterações. Em caso de alteração somente da imagem do back-end, basta utilizar, a partir da raiz, o comando
npm run compose:up
.- Na prática, o comando deve rodar, a partir da pasta
./app
(onde deve residir seudocker-compose.yml
), o comandodocker-compose up -d --build
, esse comando forçará o re-build da imagem da aplicaçãoback-end
. O resultado
- Na prática, o comando deve rodar, a partir da pasta
- Em caso de algum problema (no back-end, por exemplo), você deve se deparar com alguma mensagem do tipo:
⚠️ Lembre-se, não cabe ao avaliador de usabilidade dizer qual é o problema específico na sua aplicação, por tanto, cabe aqui investigar o problema, sempre considerando as premissas anteriores.
- Nesse caso, a partir da pasta
./app
(onde está seu docker-compose), é possível rodar o comandodocker-compose logs
(Para ver todos os status) oudocker-compose logs <nome-do-seu-serviço>
(Para mostrar somente o de um escopo específico).⚠️ é indicado remover o parâmetrorestart: 'always'
do seu serviço, para que o mesmo não polua seus logs;- No nosso contexto, rodando o comando
docker-compose logs backend
:
Aqui não houve problema com o
tsc
, porém a senha para acesso do banco pelo sequelize estava errada.
Para o desenvolvimento, o time de produto disponibilizou um Diagrama de Entidade-Relacionamento (DER) para construir a modelagem do banco de dados. Com essa imagem você já consegue saber como:
Dica: Também é possível buscar referências nas seeds providas no projeto em ./app/backend/src/database/seeders
1 - Desenvolva em /app/backend/src/database
nas pastas correspondentes, uma migration e um model para a tabela de teams
- O avaliador consultará os dados da tabela teams, verificando se ela contém os dados iniciais corretos
2 - Desenvolva em /app/backend/src/database
nas pastas correspondentes, uma migration e um model para a tabela de matches
- O avaliador consultará os dados da tabela matches, verificando se ela contém os dados iniciais corretos
3 - Desenvolva em /app/backend/src/database
nas pastas correspondentes, uma migration e um model para a tabela users
- O avaliador consultará os dados da tabela users, verificando se ela contém os dados iniciais corretos
-
A rota deve ser (
/login
). -
A rota deve receber os campos
email
epassword
e esses campos devem ser validados no banco de dados;- O campo
email
deve receber um email válido; - O Campo
password
deve ter mais de 6 caracteres.
- O campo
-
Sua chave
JWT
do back-end, utilizada para assinatura do token, deve ser salva no arquivoapp/backend/jwt.evaluation.key
. Ela pode ser carregada em sua aplicação utilizando a bibliotecafs
e é necessária para passar nos testes; -
O body da requisição deve conterá o seguinte formato:
{ "email": "string", "password": "string" }
4 - (TDD
) Desenvolva testes que cubram no mínimo 5 por cento dos arquivos back-end em /src
com um mínimo de 7 linhas cobertas
Sugestões:
- Se baseando no contrato do endpoint
/login
do próximo requisito, inicie um teste de integração utilizando a metodologiaTDD
, que passará a seguir, com a implementação do requisito seguinte; - Nesse primeiro momento, foque em desenvolver o que pede o requisito, progredindo gradualmente a partir disso;
- Para isso, utilize/altere o arquivo de referência
app/backend
/src/tests/change.me.test.ts
5 - Desenvolva o endpoint /login
no backend de maneira ele permita o acesso com dados válidos no frontend
-
A rota de ser do tipo
POST
-
O avaliador verificará se é possível fazer o login com dados corretos e que após o acesso será redirecionado para a tela de jogos
Se o login foi feito com sucesso o resultado retornado deverá ser conforme exibido abaixo, com um status http 200
:
{
"user": {
"id": 1,
"username": "Admin",
"role": "admin",
"email": "admin@admin.com"
},
"token": "123.456.789" // Aqui deve ser o token gerado pelo backend.
}
6 - (TDD
) Desenvolva testes que cubram no mínimo 10 por cento dos arquivos back-end em /src
com um mínimo de 19 linhas cobertas
Sugestão:
- Evolua os testes de integração da sua rota
/login
, utilizando o métodoTDD
, agora considerando o contrato do próximo requisito;
7 - Desenvolva o endpoint /login
no backend de maneira ele não permita o acesso com um email inválido no front-end
- O avaliador verificará se fazer o login com um email incorreto retornará status não-autorizado
Se o login tiver o "email" inválido o resultado retornado deverá ser conforme exibido abaixo, com um status http 401
:
{ "message": "Incorrect email or password" }
8 - (TDD
) Desenvolva testes que cubram no mínimo 15 por cento dos arquivos back-end em /src
com um mínimo de 25 linhas cobertas
Sugestão:
- Evolua os testes de integração da sua rota
/login
, utilizando o métodoTDD
, agora considerando o contrato do próximo requisito;
9 - Desenvolva o endpoint /login
no back-end de maneira ele não permita o acesso com uma senha inválida no front-end
- O avaliador verificará se fazer o login com uma senha incorreta retornará status não-autorizado
Se o login tiver a "senha" inválida o resultado retornado deverá ser conforme exibido abaixo, com um status http 401
:
{ "message": "Incorrect email or password" }
10 - (TDD
) Desenvolva testes que cubram no mínimo 20 por cento dos arquivos back-end em /src
com um mínimo de 35 linhas cobertas
Sugestão:
- Evolua os testes de integração da sua rota
/login
, utilizando o métodoTDD
, agora considerando o contrato do próximo requisito;
11 - Desenvolva o endpoint /login
no back-end de maneira ele não permita o acesso sem informar um email no front-end
- O avaliador verificará se ao tentar fazer o login sem um email retornará status não-autorizado
Se o login não tiver o campo "email", o resultado retornado deverá ser a mensagem abaixo, com um status http 400
:
{ "message": "All fields must be filled" }
12 - (TDD
) Desenvolva testes que cubram no mínimo 30 por cento dos arquivos back-end em /src
com um mínimo de 45 linhas cobertas
Sugestão:
- Evolua os testes de integração da sua rota
/login
, utilizando o métodoTDD
, agora considerando os contratos dos próximos dois requisitos;`
13 - Desenvolva o endpoint /login
no back-end de maneira ele não permita o acesso sem informar uma senha no front-end
- O avaliador verificará se ao tentar fazer login sem senha retornará status não-autorizado
Se o login não tiver o campo "password" o resultado retornado deverá ser conforme exibido abaixo, com um status http 400
:
{ "message": "All fields must be filled" }
14 - Desenvolva o endpoint /login/validate
no back-end de maneira ele retorne os dados corretamente no front-end
-
Deve ser uma rota
GET
que receba umheader
com parâmetroauthorization
onde ficará armazenado o token gerado no login; -
O avaliador verificará se tentar bater na rota com um token válido, o mesmo retornará o tipo de usuário
A resposta deve ser de status 200
com uma string
contendo a role
do user:
"admin"
- Os requisitos a seguir consideram o consumo da rota
/teams
para retornar os nomes dos times associados a partida na renderização do front-end
15 - (TDD
) Desenvolva testes que cubram no mínimo 45 por cento dos arquivos back-end em /src
com um mínimo de 70 linhas cobertas
Sugestão:
- Crie um novo teste de integração, agora da sua rota
/teams
, utilizando o métodoTDD
, considerando os contratos dos próximos dois requisitos;
16 - Desenvolva o endpoint /teams
no back-end de forma que ele possa retornar todos os times corretamente
- Deve ser uma rota
GET
com resposta com status200
e com umjson
contendo o retorno no seguinte modelo:
[
{
"id": 1,
"teamName": "Avaí/Kindermann"
},
{
"id": 2,
"teamName": "Bahia"
},
{
"id": 3,
"teamName": "Botafogo"
},
...
]
17 - Desenvolva o endpoint /teams/:id
no back-end de forma que ele possa retornar dados de um time específico
- Deve ser uma rota
GET
com resposta com status200
e com umjson
contendo o retorno no seguinte modelo:
{
"id": 5,
"teamName": "Cruzeiro"
}
18 - (TDD
) Desenvolva testes que cubram no mínimo 60 por cento dos arquivos back-end em /src
com um mínimo de 80 linhas cobertas
Sugestão:
- Crie um novo teste de integração, agora da sua rota
/matches
, utilizando o métodoTDD
, agora considerando os contratos dos próximos três requisitos;`
19 - Desenvolva o endpoint /matches
de forma que os dados apareçam corretamente na tela de partidas no front-end.
-
A rota deve ser um
GET
e retorna uma lista de partidas -
Será validado que a página apresentará todos os dados de partidas sem nenhum filtro
Exemplo de retorno:
[ { "id": 1, "homeTeam": 16, "homeTeamGoals": 1, "awayTeam": 8, "awayTeamGoals": 1, "inProgress": false, "teamHome": { "teamName": "São Paulo" }, "teamAway": { "teamName": "Grêmio" } }, ... { "id": 41, "homeTeam": 16, "homeTeamGoals": 2, "awayTeam": 9, "awayTeamGoals": 0, "inProgress": true, "teamHome": { "teamName": "São Paulo" }, "teamAway": { "teamName": "Internacional" } } ]
20 - Desenvolva o endpoint /matches
de forma que seja possível filtrar as partidas em andamento na tela de partidas do front-end
-
A rota deverá ser do tipo
GET
e retornar uma lista de partidas filtradas -
Será validado que ao escolher a opção de partidas em andamento serão filtradas todas as partidas em andamento
-
Essa requisição deverá usar
query string
para definir o parâmetro ex:matches?inProgress=true
Exemplo de retorno da requisição:
[
{
"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"
}
}
]
21 - Desenvolva o endpoint /matches
de forma que seja possível filtrar as partidas finalizadas na tela de partidas do front-end
-
A rota deverá ser do tipo
GET
e retornar uma lista de partidas filtradas -
Será validado que ao escolher a opção de partidas finalizadas serão filtradas todas as partidas finalizadas
-
Essa requisição deverá usar
query string
para definir o parâmetro ex:matches?inProgress=false
Exemplo de retorno da requisição:
[
{
"id": 1,
"homeTeam": 16,
"homeTeamGoals": 1,
"awayTeam": 8,
"awayTeamGoals": 1,
"inProgress": false,
"teamHome": {
"teamName": "São Paulo"
},
"teamAway": {
"teamName": "Grêmio"
}
},
{
"id": 2,
"homeTeam": 9,
"homeTeamGoals": 1,
"awayTeam": 14,
"awayTeamGoals": 1,
"inProgress": false,
"teamHome": {
"teamName": "Internacional"
},
"teamAway": {
"teamName": "Santos"
}
}
]
- Para que os requisitos de criação de partidas, é necessário que a rota
/teams
funcione corretamente
22 - (Bônus
; TDD
) Desenvolva testes que cubram no mínimo 80 por cento dos arquivo back-end em /src
com um mínimo de 100 linhas cobertas
Sugestão:
- Evolua os testes de integração da sua rota
/matches
, utilizando o métodoTDD
, agora considerando o contrato dos próximos requisitos;`
23 - Desenvolva a rota /matches
de modo que seja possível salvar uma partida com o status de inProgress como true no banco de dados
-
A rota deverá ser do tipo
POST
, e retornar a partida inserida no banco de dados -
Será validado que é possível salvar um jogo no banco de dados e ver o jogo na página de jogos
-
A partida só pode ser criada com token JWT validado;
-
O corpo da requisição terá o seguinte formato:
{
"homeTeam": 16, // O valor deve ser o id do time
"awayTeam": 8, // O valor deve ser o id do time
"homeTeamGoals": 2,
"awayTeamGoals": 2,
"inProgress": true // a partida deve ser criada como em progresso
}
- caso a partida seja inserida com sucesso, deve-se retornar os dados da partida:
{
"id": 1,
"homeTeam": 16,
"homeTeamGoals": 2,
"awayTeam": 8,
"awayTeamGoals": 2,
"inProgress": true,
}
24 - Desenvolva a rota /matches/:id/finish
de modo que seja possível salvar uma partida com o status de inProgress como false no banco de dados
-
A rota deve ser do tipo
PATCH
-
Será recebido o
id
pelo parâmetro da URL -
Será validado que ao finalizar uma partida é alterado no banco de dados e na página
25 - Desenvolva o endpoint /matches
de forma que não seja possível inserir uma partida com times iguais
-
Será validado que não é possível inserir uma partida com times iguais
-
Não deve ser possível criar uma partida com o mesmo time, exemplo: Barcelona x Barcelona, caso contrário, deve-se retornar o seguinte erro:
{ "message": "It is not possible to create a match with two equal teams" }
26 - Desenvolva o endpoint /matches
de forma que não seja possível inserir uma partida com time que não existe na tabela teams
-
Será validado que não é possível inserir uma partida com time que não existe na tabela teams
-
caso algum dos times não esteja cadastrado no banco de dados, deve-se retornar o seguinte erro:
{ "message": "Team not found" }
-
O endpoint deve ser do tipo
PATCH
; -
Será recebido o
id
pelo parâmetro da URL; -
Será avaliado que é possível alterar o resultado de uma partida.
-
O corpo da requisição terá o seguinte formato:
{
"homeTeamGoals": 3,
"awayTeamGoals": 1
}
-
O endpoint deve ser do tipo
PATCH
-
Será recebido o
id
pelo parâmetro da url -
Será avaliado que é possível finalizar uma partida em andamento
Para construir as classificação, elas devem seguir as seguintes regras de negócios
-
Em que:
Classificação
: Posição na classificação;Time
: Nome do time;P
: Total de Pontos;J
: Total de Jogos;V
: Total de Vitórias;E
: Total de Empates;D
: Total de Derrotas;GP
: Gols marcados a favor;GC
: Gols marcados contra;SG
: Saldo total de gols;%
: Aproveitamento do time.
-
Toda a regra de negócio e cálculos necessários deverão ser realizados no seu back-end. A aplicação front-end apenas renderizará essas informações;
-
Para calcular o
Total de Pontos
você deve levar em consideração que:- O time
vitorioso
: marcará +3 pontos; - O time
perdedor
: marcará 0 pontos; - Em caso de
empate
: ambos os times marcam +1 ponto.
- O time
-
Para o campo
Aproveitamento do time (%)
que é a porcentagem de jogos ganhos, use a seguinte fórmula:P/(J*3)*100
, onde:P
: Total de Pontos;J
: Total de Jogos.
Obs.: O seu resultado deverá ser limitado a
duas casas decimais
. -
O resultado deverá ser ordenado sempre de forma decrescente, levando em consideração a quantidade de pontos que o time acumulou. Em caso de empate no
Total de Pontos
, você deve levar em consideração os seguintes critérios para desempate:
Ordem para desempate
1º Total de Vitórias; 2º Saldo de gols; 3º Gols a favor; 4º Gols contra.
- Por padrão, as respostas de todos os seus endpoints deverão estar em inglês, mesmo a renderização no front-end estando em português.
- Sua tabela deverá renderizar somente as partidas que já foram finalizadas!
Os seguintes pontos serão avaliados:
- Se a lista de classificação está correta;
- Se a regra de classificação se mantem mesmo com mudanças na classificação
- Se a tabela de classificação tem 10 colunas;
- Se a tabela tem uma linha para cada time;
Exemplo de retorno esperado:
[
{
"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
},
{
"name": "Santos",
"totalPoints": 11,
"totalGames": 5,
"totalVictories": 3,
"totalDraws": 2,
"totalLosses": 0,
"goalsFavor": 12,
"goalsOwn": 6,
"goalsBalance": 6,
"efficiency": 73.33
},
...
]
29 - Desenvolva o endpoint /leaderboard/home
de forma que seja possível filtrar a classificações dos times quando mandantes na tela de classificação do frontend com os dados iniciais do banco de dados
-
O endpoint deverá ser do tipo
GET
e ter o retorno como descrito no exemplo do leaderboard -
Será avaliado que ao fazer a requisição ao endpoint
/leaderboard/home
serão retornados os campos e valores corretos considerando os dados iniciais do banco de dados
30 - Desenvolva o endpoint /leaderboard/home
, de forma que seja possível filtrar a classificações dos times quando mandantes na tela de classificação do front-end e ao inserir a partida Corinthians 2 X 1 Internacional a tabela será atualizada
-
O retorno deve continuar como no leaderboard e ordenar corretamente como na explicação
-
Será avaliado que após acrescentar a partida Botafogo 2 X 1 Grêmio e fazer a requisição ao endpoint
/leaderboard/home
serão retornados os campos e valores corretos
31 - Desenvolva o endpoint /leaderboard/away
, de forma que seja possível filtrar as classificações dos times na tela de classificação do front-end, com os dados iniciais do banco de dados
-
O endpoint deverá ser do tipo
GET
e ter o retorno como descrito no exemplo do leaderboard -
Será avaliado que ao fazer a requisição ao endpoint
/leaderboard/away
serão retornados os campos e valores corretos considerando os dados iniciais do banco de dados
32 - Desenvolva o endpoint /leaderboard/away
de forma que seja possível filtrar a classificações dos times na tela de classificação do front-end e ao inserir a partida Corinthians 2 X 1 Internacional a tabela seja atualizada
-
O retorno deve continuar como no leaderboard e ordenar corretamente como na explicação
-
Será avaliado que após acrescentar a partida Botafogo 2 X 1 Grêmio e fazer a requisição ao endpoint
/leaderboard/away
serão retornados os campos e valores corretos
-
Esse endpoint irá alimentar no front-end uma tabela idêntica ao exemplo abaixo:
Classificação Time P J V E D GP GC SG % 1 Corinthians 38 15 12 2 1 44 13 31 84.4
33 - Desenvolva o endpoint /leaderboard
de forma que seja possível filtrar a classificação geral dos times na tela de classificação do front-end com os dados iniciais do banco de dados
-
O endpoint deverá ser do tipo
GET
e ter o retorno como descrito no exemplo do leaderboard -
Será avaliado que ao fazer a requisição ao endpoint
/leaderboard
serão retornados os campos e valores corretos considerando os dados iniciais do banco de dados
34 - Desenvolva o endpoint /leaderboard de forma que seja possível filtrar a classificação geral dos times na tela de classificação do front-end e ao inserir a partida Flamengo 3 X 0 Napoli-SC a tabela será atualizada
-
O retorno deve continuar como no leaderboard e ordenar corretamente como na explicação
-
Será avaliado que após acrescentar a partida Flamengo 3 X 0 Napoli-SC e fazer a requisição ao endpoint /leaderboard serão retornados os campos e valores corretos
35 - Desenvolva o endpoint /leaderboard de forma que seja possível filtrar a classificação geral dos times na tela de classificação do front-end e ao inserir a partida Minas Brasília 1 X 0 Ferroviária a tabela será atualizada
-
O retorno deve continuar como no leaderboard e ordenar corretamente como na explicação
-
Será avaliado que após acrescentar a partida Minas Brasília 1 X 0 Ferroviária e fazer a requisição ao endpoint /leaderboard serão retornados os campos e valores corretos
Para "entregar" seu projeto, siga os passos a seguir:
- Vá até a página DO SEU Pull Request, adicione a label de "code-review" e marque seus colegas
- No menu à direita, clique no link "Labels" e escolha a label code-review
- No menu à direita, clique no link "Assignees" e escolha o seu usuário
- No menu à direita, clique no link "Reviewers" e digite
students
, selecione o timetryber/students-sd-00
Se ainda houver alguma dúvida sobre como entregar seu projeto, aqui tem um video explicativo.
⚠ Lembre-se que garantir que todas as issues comentadas pelo Lint estão resolvidas! ⚠
À medida que você e as outras pessoas que estudam na Trybe forem entregando os projetos, vocês receberão um alerta via Slack para também fazer a revisão dos Pull Requests dos seus colegas. Fiquem atentos às mensagens do "Pull Reminders" no Slack!
Use o material que você já viu sobre Code Review para te ajudar a revisar os projetos que chegaram para você.
Ao finalizar e submeter o projeto, não se esqueça de avaliar sua experiência preenchendo o formulário. Leva menos de 3 minutos!
Link: FORMULÁRIO DE AVALIAÇÃO DE PROJETO
O avaliador automático não necessariamente avalia seu projeto na ordem em que os requisitos aparecem no readme. Isso acontece para deixar o processo de avaliação mais rápido. Então, não se assuste se isso acontecer, ok?