rocketseat-education / bootcamp-gostack-desafios Goto Github PK
View Code? Open in Web Editor NEWRepositório contendo todos os desafios dos módulos do Bootcamp Gostack
Home Page: https://pages.rocketseat.com.br/gostack
License: MIT License
Repositório contendo todos os desafios dos módulos do Bootcamp Gostack
Home Page: https://pages.rocketseat.com.br/gostack
License: MIT License
Marcar este repositório como um template, da mesma forma que os repositórios dos desafios anteriores.
const express = require("express");
const cors = require("cors");
const { v4: uuid, validate: isUuid } = require("uuid");
const app = express();
app.use(express.json());
app.use(cors());
const repositories = [];
function validateRepositorieId(request, response, next) {
const { id } = request.params;
if (!isUuid(id)) {
return response.status(400).json({ error: "Invalid repositorie ID" });
}
return next();
}
function validateLikes(request, response, next) {
const { id } = request.params;
if (!isUuid(id)) {
return response.status(400).json({ error: "Invalid repositorie ID" });
}
return next();
}
app.use("/repositories/:id", validateRepositorieId);
app.use("/repositories/:id/likes", validateLikes);
// GET: Fetch backend information
app.get("/repositories", (request, response) => {
return response.json(repositories);
});
// POST: Create information on the backend
app.post("/repositories", (request, response) => {
const { title, url, techs } = request.body;
const repositorie = { id: uuid(), title, url, techs, likes: 0 };
repositories.push(repositorie);
return response.json(repositorie);
});
// PUT: Change information on the backend
app.put("/repositories/:id", (request, response) => {
const { id } = request.params;
const { title, url, techs } = request.body;
const repositorieIndex = repositories.findIndex(
(repositorie) => repositorie.id === id
);
if (repositorieIndex < 0) {
return response.status(400).json({ error: "Repositorie not found" }); // setando o erro caso não encontre o repositorie
}
const repositorie = {
id,
title,
url,
techs,
likes: repositories[repositorieIndex].likes,
};
repositories[repositorieIndex] = repositorie;
return response.json(repositorie);
});
// DELETE: Delete information on the backend
app.delete("/repositories/:id", (request, response) => {
const { id } = request.params;
const repositorieIndex = repositories.findIndex(
(repositorie) => repositorie.id === id
);
if (repositorieIndex < 0) {
return response.status(400).json({ error: "Repositorie not found" });
}
repositories.splice(repositorieIndex, 1);
return response.status(204).send();
});
app.post("/repositories/:id/like", (request, response) => {
const { id } = request.params;
const repositorie = repositories.find((repositorie) => repositorie.id === id);
repositorie.likes += 1;
return response.json(repositorie);
});
module.exports = app;
A descrição da funcionalidade testada no desafio desafio-conceitos-nodejs é:
Para que esse teste passe, você não deve permitir que sua rota de update altere diretamente os likes desse repositório, mantendo o mesmo número de likes que o repositório já possuia antes da atualização. Isso porque o único lugar que deve atualizar essa informação é a rota responsável por aumentar o número de likes.
Porém o teste não valida se é mantida a quantidade original de likes do repositório após atualização.
BootCamp
Não sei se é possível ajustar o teste automatizado para também aceitar o cenário abaixo, mas esse cenário falha no teste mesmo gerando um programa funcional.
Dentro do arquivo src/hooks/cart.tsx:
Em const addToCart
e const increment
e const decrement
:
O código listado abaixo resolve o desafio:
// Everything before //
setProducts(newProductList);
await AsyncStorage.setItem(
'@GoMarketplace:products',
JSON.stringify(newProductList),
);
// Everything after //
Porém caso o Dev prefira gravar inicialmente na memória física e só alterar o estado de produtos após essa gravação o teste falha:
// Everything before //
await AsyncStorage.setItem(
'@GoMarketplace:products',
JSON.stringify(newProductList),
);
setProducts(newProductList);
// Everything after //
Essencialmente para o usuário final do app ambas soluções são indistinguíveis.
Na descrição do README.md está pedindo para criar uma tabela com o campo type
.
- Listar as transações da sua API: Sua página Dashboard deve ser capaz de exibir uma listagem através de uma tabela, com o campo
title
,value
,type
ecategory
de todas as transações que estão cadastradas na sua API.
Porém o correto seria substituir a palavra type
por date
, já que no layout da aplicação GoFinances Web no Figma é o campo data que é utilizado.
Para a exibição de valores na tabela do tipo 'outcome' é necessário formatar o valor para que seja exibido o sinal, exemplo, - R$ 5.500,00
.
Uma indicação para facilitar a formatação é configurar o arquivo presente na pasta Utils que exporta uma função Intl.
Após configurado, se passar por parâmetro um valor negativo, a função retorna e exibe corretamente o sinal antes do R$
. Como os valores são gravados sem sinal no banco de dados, temos que passar para a função o transaction.value * -1
. Na exibição da lista no navegador funciona perfeitamente, porém o teste falha.
Exemplo da passagem do valor por parâmetro(funciona e exibe corretamente na tabela):
Number(transaction.value) * - 1
Para o teste passar, tive que adicionar manualmente o sinal de negativo desta forma:
'- ${formatValue(Number(transaction.value))}'
Em ambiente windows realmente é necessário alterar o components/upload/index.ts de text/csv para application/vnd.ms-excel
Porém o teste falha se deixar com esta alteração.
Portanto para a aplicação funcionar no windows precisa realizar a alteração, mas para entregar o desafio sem erros, precisa desafazer a alteração.
No trecho do README.md que fala sobre o eager loading tem a seguinte descrição:
Para isso, você pode utilizar a funcionalidade de eager loading do TypeORM, adicionando o seguinte na sua model de transactions:
@ManyToOne(() => Category, category => category.transaction, { eager: true }) @JoinColumn({ name: 'category_id' }) category: Category;
Lembre também de fazer o mesmo na model de Category, mas referenciando a tabela de Transaction.
@OneToMany(() => Transaction, transaction => transaction.category) transaction: Transaction;
Acredito que a ideia do trecho era apenas fazer uso do eager loading, nesse caso só precisaria usar o @ManyToOne
, sem o @OneToMany
.
Nesse cenário o código ficaria assim:
@ManyToOne(() => Category, { eager: true })
...
E o model Category não teria o trecho @OneToMany
.
Agora caso ainda queira usar o @OneToMany
ai teria que alterar o trecho do Category para receber um array de Transaction e não apenas uma transação e o restante do código permaneceria o mesmo informado.
Mais detalhes nesse link: https://orkhan.gitbook.io/typeorm/docs/many-to-one-one-to-many-relations
Existe um erro entre as instruções e o teste.
Notem que nas instruções esta:
should be able to give a like to the repository: Para que esse teste passe, sua aplicação deve permitir que um repositório com o id informado possa receber likes. O valor de likes deve ser incrementado em 1 a cada requisição, e como resultado, retornar um json contendo o repositório com o número de likes atualizado.
O problema no meu entendimento é que o teste apenas espera o objeto {likes: 1}. Porem como podem conferir acima, esta solicitando que seja retornado o json contendo o repositório ou seja:
{
id: '6d10d2bf-9905-44e3-8f51-0eaf5cc55935',
title: 'Umbriel',
url: 'https://github.com/Rocketseat/umbriel',
techs: [ 'Node', 'Express', 'TypeScript' ],
likes: 1
}
Porem o teste falha pois o mesmo espera:
expect(response.body).toMatchObject({ likes: 1, });
No arquivo /src/components/Header/index.tsx o comentário // Todo está em camel case. Fora do padrão dos outros arquivos e faz com que não seja listado no plugin Todo Tree.
Ao usar uuid_generate_v4 no default das colunas primárias das migrations do postgre, esse erro (Function uuid_generate_v4() does not exists) acontece e impede que as migrations sejam executadas.
No discord me passaram a solução, que é simplesmente executar CREATE EXTENSION IF NOT EXISTS "uuid-ossp" lá pelo DBeaver no banco gostack_desafio06 que a gente cria (essa parte de criar o banco faz parte do passo-a-passo).
Só que seguindo o fluxo do curso, a gente faz esse desafio do upload logo depois da aula de backend do gobarber. E na aula do gobarber esse step por algum motivo não é necessário então o aluno fica achando que tem algum bug acontecendo. Deveria 'simplesmente funcionar'.
Acho que seria interessante criar uma seção 'problemas frequentes' ou algo assim na descrição desse desafio com essa solução. Eu entendo que 'configurar ambiente' faz parte das tarefas do dev, mas a partir do momento que vocês estão disponibilizando um template pra ser clonado como material do curso (e até agora o yarn install sempre deixou o ambiente pronto pra ser usado), acho válido assumir que não vamos perder muito tempo buscando esse tipo de solução no stackoverflow ou algo do tipo, e que vamos poder simplesmente sentar e 'bora codar', hehe
The Problem
In test "Should be able to list the food plates filtered by name search" the fireEvent.changeText function is called causing malfunctions due to it not going through the setSearchValue function and in consequence searchValue is not updated and the fake api is called with wrong values in the test.
Instead of being called with 'Ao molho' it is called with an empty string due to the issue.
Na descrição da instalação dos types
de cors
, deve-se informar a flag -D
, para instalação apenas em ambiente de desenvolvimento.
Tendo isso em vista, sabemos que a lib cors
será instalada juntamento com a lib de tipos. Então para que o cors
seja instalado como uma dependencia
e não uma dependência de desenvolvimento
, precisamos instalar o cors
antes de instalar os tipos.
Cenário atual:
Antes de tudo, para que seu frontend se conecte corretamente ao backend, vá até a pasta do seu backend e execute o comando
yarn add cors @types/cors
.
Esperado:
Antes de tudo, para que seu frontend se conecte corretamente ao backend, vá até a pasta do seu backend e execute os comandos
yarn add cors
e depoisyarn add cors @types/cors -D
.
Não consigo detectar automaticamente, no frontend, uma deleção no backend, pra que os repositories sejam renderizados novamente.
Ao rodar yarn test
, ambos os testes devem passar sem falhas.
Ao rodar yarn test
, apenas o primeiro teste está passando (should be able to add new repository
). O segundo teste (should be able to remove repository
) falha.
Received:
"<li>Desafio ReactJS<button>Remover</button></li>
O repositório está sendo removido corretamente no backend com o NodeJS...
O problema é que no frontend com o ReactJS, no código que eu fiz, após uma deleção o array repositories
é atualizado fazendo um novo get()
e atualizando o array com um setProjects
:
const [repositories, setRepositories] = useState([]);
async function handleRemoveRepository(id) {
await api.delete(`/repositories/${id}`);
api.get('/repositories').then(response => {
setRepositories(response.data);
});
}
E como o teste faz a requisição delete()
e já verifica se o <ul>
está vazio ou não (ou seja, ele não passa pela mesma lógica implementada em minha deleção):
apiMock.onDelete("repositories/123").reply(204);
await actWait();
fireEvent.click(getByText("Remover"));
await actWait();
expect(getByTestId("repository-list")).toBeEmpty();
Assim, eu não sei de que maneira seria possível que o frontend detectasse automaticamente que uma alteração no backend foi feita e renderizasse a aplicação novamente, sem precisar passar por essa lógica que eu implementei.
Meu useEffect() é esse:
useEffect(() => {
api.get('/repositories').then(response => {
setRepositories(response.data);
});
}, []);
Já tentei colocar um [projects] ali como segundo parâmetro (para que o useEffect sempre atualizasse após uma alteração no estado projects), mas o projects
do frontend não alterou (foi apagado apenas no backend), e o yarn test
trava e fica carregando para sempre.
Eu estava fazendo o desafio 10 e quando foi na parte de editar o available do prato eu passei minha rota como PATCH e ele deu erro na validação porem funcionou normal pois eu usei apenas para alterar o campo available só que no teste pediu para passar PUT, não seria melhor seguir o que foi dito nas aulas e mudar para PATCH no lugar de PUT?
In English we don't use the word food when referring to a meal option in a menu. The same ways as in Portuguese, the word dish (prato) is perfectly suited.
Food is also rarely pluralized. You may say "foods" when referring to categories of food: cereal, legumes, meat, eggs. These are different foods, or different food groups.
A página que LICENSE ao final de README.md (em Desafio-01) direciona, retorna erro 404
Link: https://github.com/rocketseat-education/bootcamp-gostack-desafios/blob/master/desafio-01/LICENSE
The current listed ESLint version seems to have a problem. We should change it to version yarn add -D eslint@^6.8.0
and yarn add -D @typescript-eslint/eslint-plugin@^2.28.0
as Ana Cruz said here: https://skylab.rocketseat.com.br/h/forum/gostack-11/71aca090-903c-4ce2-a9d3-b6302434e58c
Nas especificações dos teste pede para criar um banco de dados com o nome "gostack_desafio06_tests" para que todos os testes possam executar corretamente.
No entanto no arquivo ormconfig.json o "database" esta configurado para acessar o banco de dados "gostack_desafio06".
Faltou adicionar a informação para o usuário alterar a porta caso este utilize uma porta diferente da 5432 para que ele possa executar os testes e antes de enviar o repositório para o github voltar a configuração da porta correta.
Olá pessoal! Vou abrir essa issue pois fiquei preso um bom tempo em função de uma questão boba, logo isso pode vir a atrapalhar alguém também.
Basicamente o meu problema foi: Na rota de upload de arquivos tudo ocorria bem durante o desenvolvimento, ou seja, eu importava uma tabela, para cada linha dessa tabela era criada um transaction
e possivelmente uma category
, no banco de dev tudo tranquilo. Porém nos testes nunca dava certo (retornava que nenhuma category era criada). Hoje acabei encontrado o seguinte problema:
file
;table
;Essa condição foi bem dificil de encontrar.
Acredito que seria interessante adicionar um file
.
segue o print com a diff que fez a feat funcionar:
trecho de código no qual anexa o csv no campo file
:
it('should be able to import transactions', async () => {
const transactionsRepository = getRepository(Transaction);
const categoriesRepository = getRepository(Category);
const importCSV = path.resolve(__dirname, 'import_template.csv');
await request(app).post('/transactions/import').attach('file', importCSV);
Na sessão Preparando o backend o exemplo de retorno do backend possui um erro.
"value"
está definido como String, mas o backend deve retornar um Number, segundo o desafio 06 e segundo a própria Interface do desafio 07.
{
"id": "c0512e43-6589-4dc8-bd0c-2a3f71b347aa",
"title": "Loan",
"type": "income",
///////////////////// O ERRO ESTÁ AQUI //////////////////////////
"value": "1500.00",
////////////////////////////////////////////////////////////////
"category_id": "d93eccc7-64bb-4268-b825-9200103f3a8b",
"created_at": "2020-04-20T00:00:49.620Z",
"updated_at": "2020-04-20T00:00:49.620Z",
"category": {
"id": "d93eccc7-64bb-4268-b825-9200103f3a8b",
"title": "Others",
"created_at": "2020-04-20T00:00:49.594Z",
"updated_at": "2020-04-20T00:00:49.594Z"
}
}
O pacote cors
está salvo dentro de devDependencies
, e isso vai gerar um problema ao enviar a API para produção.
Cenário atual:
"devDependencies": {
// outras dependências
"cors": "^2.8.5",
}
Cenário esperado:
"dependencies": {
// outras dependências
"cors": "^2.8.5",
}
Fala devs, acredito que há um equívoco onde falam sobre testes (https://github.com/rocketseat/bootcamp-gostack-desafios/tree/master/faq-desafios#o-que-s%C3%A3o-os-testes-automatizados).
No texto em questão, é explorado e explicado como interpretar e criar testes para garantir que modificações não afetrão demais partes do código. Porém, no texto são chamados de Testes automatizados
mas os exemplos e explicações são sobre Testes unitários
.
Como podemos ver, Testes automatizados
, em sua maioria, são realizados por softwares desenvolvidos para garantir consistência e funcionamento das aplicações para que sejam validadas antes de irem para um ambiente de produção. Sugiro que deem uma atenção a isso para não confundir a galera!
Obrigado e não entendam isso como uma crítica e sim uma sugestão de melhoria!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.