Requisitos do projeto

01 - Crie endpoints para listar produtos

💡Dica: Comece criando pelo menos um teste do mocha para que os testes do avaliador funcionem.

  • O endpoint para listar produtos deve ser acessível através do caminho GET /products e GET /products/:id;
  • Através do caminho GET /products, todos os produtos devem ser retornados;
  • Através do caminho GET /products/:id, apenas o produto com o id presente na URL deve ser retornado;
  • O resultado da listagem deve ser ordenado de forma crescente pelo campo id;
  • Crie testes que garantem a funcionalidade implementada;
O que será testado:
  • Será validado que é possível listar todos os produtos

    Ao fazer uma requisição para GET /products, o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:

    [
      {
        "id": 1,
        "name": "Martelo de Thor"
      },
      {
        "id": 2,
        "name": "Traje de encolhimento"
      }
      /* ... */
    ]
  • Será validado que não é possível listar um produto que não existe

    Ao fazer uma requisição para GET /products/:id, se não existir um produto com o id presente na URL, o resultado retornado deverá ser conforme exibido abaixo, com um status http 404:

    { "message": "Product not found" }
  • Será validado que é possível listar um produto específico com sucesso

    Ao fazer uma requisição para GET /products/:id, caso exista um produto com o id presente na URL, o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:

    {
      "id": 1,
      "name": "Martelo de Thor"
    }
  • Será validado que os testes estão cobrindo:

    • Pelo menos 30% das linhas e possíveis mutações em código
    • Pelo menos 6 funções do código
💡Se quiser buscar os 100% de cobertura de testes, veja esta dica!

Se quiser incluir as rotas na sua cobertura de testes, lembre-se que testes unitários testam funções - e o router só faz chamadas, ele não implementa nenhuma função. O teste mais adequado para ele é de integração - fique à vontade para fazê-los para complementar seus testes unitários!

02 - Crie endpoints para listar vendas

  • O endpoint para listar vendas deve ser acessível através do caminho GET /sales e GET /sales/:id;
  • Através do caminho GET /sales, todas as vendas devem ser retornadas;
  • Através do caminho GET /sales/:id, apenas a venda com o id presente na URL deve ser retornada;
  • O resultado deve ser ordenado de forma crescente pelo campo saleId, em caso de empate, ordenar também de forma crescente pelo campo productId;
O que será testado:
  • Será validado que é possível listar todas as vendas

    Ao fazer uma requisição para GET /sales, o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:

    [
      {
        "saleId": 1,
        "date": "2021-09-09T04:54:29.000Z",
        "productId": 1,
        "quantity": 2
      },
      {
        "saleId": 1,
        "date": "2021-09-09T04:54:54.000Z",
        "productId": 2,
        "quantity": 2
      }
    
      /* ... */
    ]
  • Será validado que não é possível listar uma venda que não existe

    Ao fazer uma requisição para GET /sales/:id, se não existir uma venda com o id presente na URL, o resultado retornado deverá ser conforme exibido abaixo, com um status http 404:

    { "message": "Sale not found" }
  • Será validado que é possível listar uma venda específica com sucesso

    Ao fazer uma requisição para GET /sales/:id, caso exista uma venda com o id presente na URL, o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:

    [
      {
        "date": "2021-09-09T04:54:29.000Z",
        "productId": 1,
        "quantity": 2
      },
      {
        "date": "2021-09-09T04:54:54.000Z",
        "productId": 2,
        "quantity": 2
      }
    
      /* ... */
    ]
  • Será validado que os testes estão cobrindo:

    • Pelo menos 30% das linhas e possíveis mutações em código
    • Pelo menos 12 funções do código

💡 Dica: Você vai precisar buscar dados de mais de uma tabela para este requisito. Relembre o conteúdo sobre JOIN nas seções sobre MySQL caso necessário.

03 - Crie endpoint para cadastrar produtos

  • O endpoint deve ser acessível através do caminho POST /products;
  • Os produtos enviados devem ser salvos na tabela products do banco de dados;
  • O corpo da requisição deverá seguir o formato abaixo:
{
  "name": "ProdutoX"
}
O que será testado:
  • Será validado que é possível cadastrar um produto com sucesso

    Ao fazer uma requisição válida para POST /products, o resultado retornado deverá ser conforme exibido abaixo, com um status http 201:

    {
      "id": 4,
      "name": "ProdutoX"
    }
  • Será validado que os testes estão cobrindo:

    • Pelo menos 30% das linhas e possíveis mutações em código
    • Pelo menos 15 funções do código

04 - Crie validações para o cadastro de produtos

  • O endpoint de cadastro de produtos deve retornar mensagens de erro para requisições com dados inválidos;
  • Lembre-se, o banco de dados não deve ser acessado nas validações iniciais do corpo da requisição;
O que será testado:
  • Será validado que não é possível cadastrar um produto sem o campo name

    Se a requisição para POST /products não tiver o campo name, o resultado retornado deverá ser conforme exibido abaixo, com um status http 400 :

    { "message": "\"name\" is required" }
  • Será validado que não é possível cadastrar um produto com o campo name menor que 5 caracteres

    Se a requisição para POST /products não tiver name com pelo menos 5 caracteres, o resultado retornado deverá ser conforme exibido abaixo, com um status http 422

    { "message": "\"name\" length must be at least 5 characters long" }
  • Será validado que os testes estão cobrindo:

    • Pelo menos 40% das linhas e possíveis mutações em código
    • Pelo menos 15 funções do código
💡 Dica: Para testar middlewares, você pode mockar a função next como no exemplo a seguir:
// ...
const next = sinon.stub().returns(); // crie um stub
>
myMiddlewares.validateMiddleware(req, res, next); // passe o `next` para o middleware junto com o `req` e `res`
>
expect(next).to.have.been.calledWith(); // verifica se o `next` foi chamado pelo middleware
// ...

05 - Crie endpoint para cadastrar vendas

  • O endpoint de vendas deve ser acessível através do caminho POST /sales;
  • As vendas enviadas devem ser salvas nas tabelas sales e sales_products do banco de dados;
  • Deve ser possível cadastrar a venda de vários produtos através da uma mesma requisição;
  • O corpo da requisição deverá seguir o formato abaixo:
[
  {
    "productId": 1,
    "quantity": 1
  },
  {
    "productId": 2,
    "quantity": 5
  }
]
O que será testado:
  • Será validado que é possível cadastrar uma venda com sucesso

    Ao fazer uma requisição válida para POST /sales, o resultado retornado deverá ser conforme exibido abaixo, com um status http 201:

    {
      "id": 3,
      "itemsSold": [
        {
          "productId": 1,
          "quantity": 1
        },
        {
          "productId": 2,
          "quantity": 5
        }
      ]
    }
  • Será validado que os testes estão cobrindo:

    • Pelo menos 40% das linhas e possíveis mutações em código
    • Pelo menos 18 funções do código

06 - Crie validações para o cadastro de vendas

  • O endpoint de cadastro de vendas deve retornar mensagens de erro para requisições com dados inválidos;
  • Lembre-se, o banco de dados não deve ser acessado nas validações iniciais do corpo da requisição;
O que será testado:
  • Será validado que não é possível cadastrar uma venda sem o campo productId

    Se algum dos itens da requisição para POST /sales não tiver o campo productId, o resultado retornado deverá ser conforme exibido abaixo, com um status http 400:

    { "message": "\"productId\" is required" }
  • Será validado que não é possível cadastrar uma venda sem o campo quantity

    Se algum dos itens da requisição para POST /sales não tiver o campo quantity, o resultado retornado deverá ser conforme exibido abaixo, com um status http 400 :

    { "message": "\"quantity\" is required" }
  • Será validado que não é possível cadastrar uma venda com o campo quantity menor ou igual a 0 (Zero)

    Se a requisição para POST /sales tiver algum item em que o campo quantity seja menor ou igual a zero, o resultado retornado deverá ser conforme exibido abaixo, com um status http 422

    { "message": "\"quantity\" must be greater than or equal to 1" }
  • Será validado que não é possível cadastrar uma venda com o campo productId inexistente, em uma requisição com um único item

    Se o campo productId do item da requisição para POST /sales não existir no banco de dados, o resultado retornado deverá ser conforme exibido abaixo, com um status http 404

    { "message": "Product not found" }
  • Será validado que não é possível cadastrar uma venda com o campo productId inexistente, em uma requisição com vários items

    Se a requisição para POST /sales tiver algum item cujo campo productId não existe no banco de dados, o resultado retornado deverá ser conforme exibido abaixo, com um status http 404

    { "message": "Product not found" }
  • Será validado que os testes estão cobrindo:

    • Pelo menos 50% das linhas e possíveis mutações em código
    • Pelo menos 18 funções do código

07 - Crie endpoint para atualizar um produto

  • O endpoint deve ser acessível através do caminho PUT /products/:id;
  • Apenas o produto com o id presente na URL deve ser atualizado;
  • O corpo da requisição deve ser validado igual no cadastro;
  • O corpo da requisição deverá seguir o formato abaixo:
{
  "name": "Martelo do Batman"
}
O que será testado:
  • Será validado que não é possível alterar um produto sem o campo name

    Se a requisição para PUT /products/:id não tiver o campo name, o resultado retornado deverá ser conforme exibido abaixo, com um status http 400 :

    { "message": "\"name\" is required" }
  • Será validado que não é possível alterar um produto com o campo name menor que 5 caracteres

    Se a requisição para PUT /products/:id não tiver name com pelo menos 5 caracteres, o resultado retornado deverá ser conforme exibido abaixo, com um status http 422

    { "message": "\"name\" length must be at least 5 characters long" }
  • Será validado que não é possível alterar um produto que não existe

    Se a requisição para PUT /products/:id informar o id de um produto inexistente, o resultado retornado deverá ser conforme exibido abaixo, com um status http 404:

      { "message": "Product not found" }
  • Será validado que é possível alterar um produto com sucesso

    Ao fazer uma requisição válida para PUT /products/:id, o resultado retornado deverá ser conforme exibido abaixo, com um status http200:

    {
      "id": 1,
      "name": "Martelo do Batman"
    }

    Também será verificado que o produto foi alterado corretamente no banco de dados.

  • Será validado que os testes estão cobrindo:

    • Pelo menos 50% das linhas e possíveis mutações em código
    • Pelo menos 21 funções do código

08 - Crie endpoint para deletar um produto

  • O endpoint deve ser acessível através do caminho DELETE /products/:id;
  • Apenas o produto com o id presente na URL deve ser deletado;
O que será testado:
  • Será validado que não é possível deletar um produto que não existe

    Se a requisição para DELETE /products/:id informar o id de um produto inexistente, o resultado retornado deverá ser conforme exibido abaixo, com um status http 404:

      { "message": "Product not found" }
  • Será validado que é possível deletar um produto com sucesso

    Ao fazer uma requisição válida para DELETE /products/:id, não deve ser retornada nenhuma resposta, apenas um status http 204;

    Também será verificado que o produto foi removido corretamente no banco de dados.

  • Será validado que os testes estão cobrindo:

    • Pelo menos 60% das linhas e possíveis mutações em código
    • Pelo menos 24 funções do código

Requisitos Bônus

09 - Crie endpoint para deletar uma venda

  • O endpoint deve ser acessível através do caminho DELETE /sales/:id;
  • Apenas a venda com o id presente na URL deve ser deletada;
O que será testado:
  • Será validado que não é possível deletar uma venda que não existe

    Se a requisição para DELETE /sales/:id informar o id de uma venda inexistente, o resultado retornado deverá ser conforme exibido abaixo, com um status http 404:

      { "message": "Sale not found" }
  • Será validado que é possível deletar uma venda com sucesso

    Ao fazer uma requisição válida para DELETE /sales/:id, não deve ser retornada nenhuma resposta, apenas um status http 204;

    Também será verificado que a venda foi removida corretamente no banco de dados.

  • Será validado que os testes estão cobrindo:

    • Pelo menos 70% das linhas e possíveis mutações em código
    • Pelo menos 27 funções do código

10 - Crie endpoint para atualizar a quantidade de um produto em uma venda

  • O endpoint deve ser acessível através do caminho /sales/:saleId/product/:productId/quantity;
  • Apenas a quantidade do produto vendido com o productId na URL deve ser atualizada;
  • O corpo da requisição receberá um valor quantity, que:
    • Deverá ser validado como o valor quantity para produtos recebidos na requisição de cadastro de venda;
    • Substituirá o valor atual de quantity do produto com o productId na venda;
  • O corpo da requisição deverá seguir o formato abaixo:
{
  "quantity": 20
}
O que será testado:
  • Será validado que não é possível realizar alterações em uma venda sem o campo quantity

    Se a requisição para PUT /sales/:saleId/product/:productId/quantity não tiver o campo quantity, o resultado retornado deverá ser conforme exibido abaixo, com um status http 400:

    { "message": "\"quantity\" is required" }
  • Será validado que não é possível realizar alterações em uma venda com o campo quantity menor ou igual a 0 (Zero)

    Se a requisição para PUT /sales/:saleId/product/:productId/quantity tiver o campo quantity menor que zero, o resultado retornado deverá ser conforme exibido abaixo, com um status http 422:

    { "message": "\"quantity\" must be greater than or equal to 1" }
  • Será validado que não é possível realizar alterações em uma venda com productId inexistente

    Se a requisição para PUT /sales/:saleId/product/:productId/quantity tiver o campo productId com um valor não existente no banco, o resultado retornado deverá ser conforme exibido abaixo, com um status http 404:

    { "message": "Product not found in sale" }
  • Será validado que não é possível alterar uma venda que não existe

    Se a requisição para PUT /sales/:saleId/product/:productId/quantity informar o saleId de uma venda inexistente, o resultado retornado deverá ser conforme exibido abaixo, com um status http 404:

      { "message": "Sale not found" }
  • Será validado que é possível alterar a quantidade de um produto de uma venda com sucesso

    Ao fazer uma requisição válida para PUT /sales/:saleId/product/:productId/quantity, o produto atualizado deverá ser retornado conforme exibido abaixo, com um status http 200:

    {
      "date": "2023-05-06T03:14:28.000Z",
      "productId": 2,
      "quantity": 20,
      "saleId": 1
    }

    Também será verificado que a quantidade do produto foi alterada corretamente no banco de dados.

  • Será validado que os testes estão cobrindo:

    • Pelo menos 50% das linhas e possíveis mutações em código
    • Pelo menos 21 funções do código

11 - Crie endpoint para pesquisar produtos

  • O endpoint deve ser acessível através do URL GET /products/search;
  • O endpoint deve ser capaz de trazer todos os produtos no banco de dados contendo o valor da query q em name, se existirem;
  • Sua aplicação deve ser capaz de retornar um array de produtos que contenham em seu nome o termo passado na URL;
  • Sua aplicação deve ser capaz de retornar todos os produtos caso query params q esteja vazia;
  • Sua aplicação deve ser capaz de retornar um array vazio caso nenhum nome satisfaça a busca;
  • O query params da requisição deverá seguir o formato abaixo:
  http://localhost:PORT/products/search?q=Martelo
O que será testado:
  • Será validado que é possível buscar um produto pelo name

    Se a requisição para GET /products/search for feita com um query params q cujo valor exista no atributo name de algum produto, o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:

    // GET /products/search?q=Martelo
    
    [
      {
        "id": 1,
        "name": "Martelo de Thor"
      }
    ]
  • Será validado que é possível buscar todos os produtos quando passa a busca vazia

    Se a requisição para GET /products/search foi feita com um query params q vazio, o resultado retornado deverá ser conforme exibido abaixo, com um status http 200:

    // GET /products/search?q=
    
    [
      {
        "id": 1,
        "name": "Martelo de Thor",
      },
      {
        "id": 2,
        "name": "Traje de encolhimento",
      }
      /* ... */
    ]
  • Será validado que a busca retorna um array vazio quando não há produtos correspondentes

    Se a requisição para GET /products/search for feita com um query params q cujo valor não exista no atributo name de nenhum produto, o resultado retornado deverá ser um array vazio, com um status http 200:

    // GET /products/search?q=ProdutoInexistente
    
    []
  • Será validado que os testes estão cobrindo:

    • Pelo menos 70% das linhas e possíveis mutações em código
    • Pelo menos 33 funções do código

🗣 Nos dê feedbacks sobre o projeto!

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!

Formulário de avaliação do projeto

🗂 Compartilhe seu portfólio!

Você sabia que o LinkedIn é a principal rede social profissional e compartilhar o seu aprendizado lá é muito importante para quem deseja construir uma carreira de sucesso? Compartilhe esse projeto no seu LinkedIn, marque o perfil da Trybe (@trybe) e mostre para a sua rede toda a sua evolução.