612 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			612 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| id: 5a8b073d06fa14fcfde687aa
 | |
| title: Registrador de exercícios
 | |
| challengeType: 4
 | |
| forumTopicId: 301505
 | |
| dashedName: exercise-tracker
 | |
| ---
 | |
| 
 | |
| # --description--
 | |
| 
 | |
| Crie um aplicativo full stack em JavaScript que seja funcionalmente semelhante a este: <https://exercise-tracker.freecodecamp.rocks/>. Trabalhar nesse projeto vai fazer com que você escreva seu código usando um dos seguintes métodos:
 | |
| 
 | |
| -   Clone [este repositório do GitHub](https://github.com/freeCodeCamp/boilerplate-project-exercisetracker/) e complete o projeto localmente.
 | |
| -   Use [nosso projeto inicial do Replit](https://replit.com/github/freeCodeCamp/boilerplate-project-exercisetracker) para completar o projeto.
 | |
| -   Use um construtor de site de sua escolha para completar o projeto. Certifique-se de incorporar todos os arquivos do nosso repositório no GitHub.
 | |
| 
 | |
| Quando terminar, certifique-se de que uma demonstração funcional do seu projeto está hospedada em algum lugar público. Em seguida, envie o URL para ela no campo `Solution Link`. Como opção, envie também um link para o código-fonte do projeto no campo `GitHub Link`.
 | |
| 
 | |
| # --instructions--
 | |
| 
 | |
| Suas respostas devem ter as seguintes estruturas.
 | |
| 
 | |
| Exercício:
 | |
| 
 | |
| ```js
 | |
| {
 | |
|   username: "fcc_test"
 | |
|   description: "test",
 | |
|   duration: 60,
 | |
|   date: "Mon Jan 01 1990",
 | |
|   _id: "5fb5853f734231456ccb3b05"
 | |
| }
 | |
| ```
 | |
| 
 | |
| Usuário:
 | |
| 
 | |
| ```js
 | |
| {
 | |
|   username: "fcc_test",
 | |
|   _id: "5fb5853f734231456ccb3b05"
 | |
| }
 | |
| ```
 | |
| 
 | |
| Log:
 | |
| 
 | |
| ```js
 | |
| {
 | |
|   username: "fcc_test",
 | |
|   count: 1,
 | |
|   _id: "5fb5853f734231456ccb3b05",
 | |
|   log: [{
 | |
|     description: "test",
 | |
|     duration: 60,
 | |
|     date: "Mon Jan 01 1990",
 | |
|   }]
 | |
| }
 | |
| ```
 | |
| 
 | |
| **Dica:** para a propriedade `date`, o método `toDateString` da API `Date` pode ser usado para conseguir o resultado esperado.
 | |
| 
 | |
| # --hints--
 | |
| 
 | |
| Você deve fornecer seu próprio projeto, não o exemplo de URL.
 | |
| 
 | |
| ```js
 | |
| (getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   assert(
 | |
|     !/.*\/exercise-tracker\.freecodecamp\.rocks/.test(getUserInput('url'))
 | |
|   );
 | |
| };
 | |
| ```
 | |
| 
 | |
| Você pode fazer a solicitação de `POST` para `/api/users` com dados do formulário `username` para criar um novo usuário.
 | |
| 
 | |
| ```js
 | |
| async (getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users', {
 | |
|     method: 'POST',
 | |
|     headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0, 29)
 | |
|   });
 | |
|   assert.isTrue(res.ok);
 | |
|   if(!res.ok) {
 | |
|     throw new Error(`${res.status} ${res.statusText}`)
 | |
|   };
 | |
| };
 | |
| ```
 | |
| 
 | |
| A resposta retornada de `POST /api/users` com dados do formulário `username` será um objeto com as propriedades `username` e `_id`.
 | |
| 
 | |
| ```js
 | |
| async (getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users', {
 | |
|     method: 'POST',
 | |
|     headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0, 29)
 | |
|   });
 | |
|   if (res.ok) {
 | |
|     const { _id, username } = await res.json();
 | |
|     assert.exists(_id);
 | |
|     assert.exists(username);
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   }
 | |
| };
 | |
| ```
 | |
| 
 | |
| Você pode fazer uma solicitação de `GET` a `/api/users` para obter uma lista com todos os usuários.
 | |
| 
 | |
| ```js
 | |
| async(getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users');
 | |
|   assert.isTrue(res.ok);
 | |
|   if(!res.ok) {
 | |
|     throw new Error(`${res.status} ${res.statusText}`)
 | |
|   };
 | |
| };
 | |
| ```
 | |
| 
 | |
| A solicitação de `GET` a `/api/users` retorna um array.
 | |
| 
 | |
| ```js
 | |
| async(getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users');
 | |
|   if(res.ok){
 | |
|     const users = await res.json();
 | |
|     assert.isArray(users);
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   };
 | |
| };
 | |
| ```
 | |
| 
 | |
| Cada elemento do array retornado de `GET /api/users` é um objeto literal que contém o `username` e a `_id` do usuário.
 | |
| 
 | |
| ```js
 | |
| async(getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users');
 | |
|   if(res.ok){
 | |
|     const users = await res.json();
 | |
|     const user = users[0];
 | |
|     assert.exists(user);
 | |
|     assert.exists(user.username);
 | |
|     assert.exists(user._id);
 | |
|     assert.isString(user.username);
 | |
|     assert.isString(user._id);
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   };
 | |
| };
 | |
| ```
 | |
| 
 | |
| Você pode fazer a solicitação de `POST` para `/api/users/:_id/exercises` com os dados do formulário `description`, `duration` e, como opção, `date`. Se nenhuma data for fornecida, a data atual será utilizada.
 | |
| 
 | |
| ```js
 | |
| async (getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users', {
 | |
|     method: 'POST',
 | |
|     headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0, 29)
 | |
|   });
 | |
|   if (res.ok) {
 | |
|     const { _id, username } = await res.json();
 | |
|     const expected = {
 | |
|       username,
 | |
|       description: 'test',
 | |
|       duration: 60,
 | |
|       _id,
 | |
|       date: 'Mon Jan 01 1990'
 | |
|     };
 | |
|     const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}&date=1990-01-01`
 | |
|     });
 | |
|   assert.isTrue(addRes.ok);
 | |
|   if(!addRes.ok) {
 | |
|     throw new Error(`${addRes.status} ${addRes.statusText}`)
 | |
|   };
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   }
 | |
| };
 | |
| ```
 | |
| 
 | |
| A resposta retornada de `POST /api/users/:_id/exercises` será o objeto do usuário com os campos de exercício adicionados.
 | |
| 
 | |
| ```js
 | |
| async (getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users', {
 | |
|     method: 'POST',
 | |
|     headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0, 29)
 | |
|   });
 | |
|   if (res.ok) {
 | |
|     const { _id, username } = await res.json();
 | |
|     const expected = {
 | |
|       username,
 | |
|       description: 'test',
 | |
|       duration: 60,
 | |
|       _id,
 | |
|       date: 'Mon Jan 01 1990'
 | |
|     };
 | |
|     const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}&date=1990-01-01`
 | |
|     });
 | |
|     if (addRes.ok) {
 | |
|       const actual = await addRes.json();
 | |
|       assert.deepEqual(actual, expected);
 | |
|       assert.isString(actual.description);
 | |
|       assert.isNumber(actual.duration);
 | |
|       assert.isString(actual.date);
 | |
|     } else {
 | |
|       throw new Error(`${addRes.status} ${addRes.statusText}`);
 | |
|     }
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   }
 | |
| };
 | |
| ```
 | |
| 
 | |
| Você pode fazer uma solicitação de `GET` a `/api/users/:_id/logs` para obter um registro completo dos exercícios de qualquer usuário.
 | |
| 
 | |
| ```js
 | |
| async (getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users', {
 | |
|     method: 'POST',
 | |
|     headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0, 29)
 | |
|   });
 | |
|   if (res.ok) {
 | |
|     const { _id, username } = await res.json();
 | |
|     const expected = {
 | |
|       username,
 | |
|       description: 'test',
 | |
|       duration: 60,
 | |
|       _id,
 | |
|       date: new Date().toDateString()
 | |
|     };
 | |
|     const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}`
 | |
|     });
 | |
|     if (addRes.ok) {
 | |
|       const logRes = await fetch(url + `/api/users/${_id}/logs`);
 | |
|     assert.isTrue(logRes.ok);
 | |
|     if(!logRes.ok) {
 | |
|       throw new Error(`${logRes.status} ${logRes.statusText}`)
 | |
|     };
 | |
|     } else {
 | |
|       throw new Error(`${addRes.status} ${addRes.statusText}`);
 | |
|     }
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   }
 | |
| };
 | |
| ```
 | |
| 
 | |
| Uma solicitação para o registro (log) de um usuário (`GET /api/users/:_id/logs`) retornará um objeto com uma propriedade `count`, que representa o número de exercícios que pertencem àquele usuário.
 | |
| 
 | |
| ```js
 | |
| async (getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users', {
 | |
|     method: 'POST',
 | |
|     headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0, 29)
 | |
|   });
 | |
|   if (res.ok) {
 | |
|     const { _id, username } = await res.json();
 | |
|     const expected = {
 | |
|       username,
 | |
|       description: 'test',
 | |
|       duration: 60,
 | |
|       _id,
 | |
|       date: new Date().toDateString()
 | |
|     };
 | |
|     const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}`
 | |
|     });
 | |
|     if (addRes.ok) {
 | |
|       const logRes = await fetch(url + `/api/users/${_id}/logs`);
 | |
|       if (logRes.ok) {
 | |
|         const { count } = await logRes.json();
 | |
|         assert(count);
 | |
|       } else {
 | |
|         throw new Error(`${logRes.status} ${logRes.statusText}`);
 | |
|       }
 | |
|     } else {
 | |
|       throw new Error(`${addRes.status} ${addRes.statusText}`);
 | |
|     }
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   }
 | |
| };
 | |
| ```
 | |
| 
 | |
| Uma solicitação de `GET` a `/api/users/:id/logs` retornará o objeto do usuário com um array `log` de todos os exercícios adicionados.
 | |
| 
 | |
| ```js
 | |
| async(getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users', {
 | |
|     method: 'POST',
 | |
|     headers: {
 | |
|       'Content-Type': 'application/x-www-form-urlencoded'
 | |
|     },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0, 29)
 | |
|   })
 | |
|   if(res.ok){
 | |
|     const {_id, username} = await res.json();
 | |
|     const expected = {
 | |
|       username,
 | |
|       description: 'test',
 | |
|       duration: 60,
 | |
|       _id,
 | |
|       date: new Date().toDateString()
 | |
|     };
 | |
|     const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}`
 | |
|     });
 | |
|     if(addRes.ok){
 | |
|       const logRes = await fetch(url + `/api/users/${_id}/logs`);
 | |
|       if(logRes.ok) {
 | |
|         const {log} = await logRes.json();
 | |
|         assert.isArray(log);
 | |
|         assert.equal(1, log.length);
 | |
|       } else {
 | |
|         throw new Error(`${logRes.status} ${logRes.statusText}`);
 | |
|       }
 | |
|     } else {
 | |
|       throw new Error(`${addRes.status} ${addRes.statusText}`);
 | |
|     };
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`)
 | |
|   };
 | |
| };
 | |
| ```
 | |
| 
 | |
| Cada item no array `log` que é retornado de `GET /api/users/:id/logs` é um objeto que deve ter as propriedades `description`, uma `duration` e uma `date`.
 | |
| 
 | |
| ```js
 | |
| async(getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + `/api/users`, {
 | |
|     method: 'POST',
 | |
|     headers: {
 | |
|       'Content-Type': 'application/x-www-form-urlencoded'
 | |
|     },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0, 29)
 | |
|   });
 | |
|   if(res.ok) {
 | |
|     const {_id, username} = await res.json();
 | |
|      const expected = {
 | |
|       username,
 | |
|       description: 'test',
 | |
|       duration: 60,
 | |
|       _id,
 | |
|       date: new Date().toDateString()
 | |
|     };
 | |
|     const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}`
 | |
|     });
 | |
|     if(addRes.ok) {
 | |
|       const logRes = await fetch(url + `/api/users/${_id}/logs`);
 | |
|       if(logRes.ok) {
 | |
|         const {log} = await logRes.json();
 | |
|         const exercise = log[0];
 | |
|         assert.exists(exercise);
 | |
|         assert.exists(exercise.description);
 | |
|         assert.exists(exercise.duration);
 | |
|         assert.exists(exercise.date);
 | |
|       } else {
 | |
|         throw new Error(`${logRes.status} ${logRes.statusText}`);
 | |
|       };
 | |
|     } else {
 | |
|       throw new Error(`${addRes.status} ${addRes.statusText}`);
 | |
|     };
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`)
 | |
|   };
 | |
| };
 | |
| ```
 | |
| 
 | |
| A propriedade `description` de qualquer objeto no array `log` retornada de `GET /api/users/:id/logs` deve ser uma string.
 | |
| 
 | |
| ```js
 | |
| async(getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users/', {
 | |
|     method: 'POST',
 | |
|     headers: {
 | |
|       'Content-Type': 'application/x-www-form-urlencoded',
 | |
|     },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0,29)
 | |
|   });
 | |
|   if(res.ok) {
 | |
|     const {_id, username} = await res.json();
 | |
|     const expected = {
 | |
|       username,
 | |
|       description: 'test',
 | |
|       duration: 60,
 | |
|       _id,
 | |
|       date: new Date().toDateString()
 | |
|     };
 | |
|     const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: {
 | |
|         'Content-Type': 'application/x-www-form-urlencoded',
 | |
|       },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}`
 | |
|     });
 | |
|     if(addRes.ok) {
 | |
|       const logRes = await fetch(url + `/api/users/${_id}/logs`);
 | |
|       if(logRes.ok){
 | |
|         const {log} = await logRes.json();
 | |
|         const exercise = log[0];
 | |
|         assert.isString(exercise.description);
 | |
|         assert.equal(exercise.description, expected.description);
 | |
|       } else {
 | |
|         throw new Error(`${logRes.status} ${logRes.statusText}`);
 | |
|       }
 | |
|     } else {
 | |
|       throw new Error(`${addRes.status} ${addRes.statusText}`);
 | |
|     };
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   };
 | |
| };
 | |
| ```
 | |
| 
 | |
| A propriedade `duration` de qualquer objeto no array `log` que é retornada de `GET /api/users/:id/logs` deve ser um número.
 | |
| 
 | |
| ```js
 | |
| async(getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users/', {
 | |
|     method: 'POST',
 | |
|     headers: {
 | |
|       'Content-Type': 'application/x-www-form-urlencoded',
 | |
|     },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0,29)
 | |
|   });
 | |
|   if(res.ok) {
 | |
|     const {_id, username} = await res.json();
 | |
|     const expected = {
 | |
|       username,
 | |
|       description: 'test',
 | |
|       duration: 60,
 | |
|       _id,
 | |
|       date: new Date().toDateString()
 | |
|     };
 | |
|     const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: {
 | |
|         'Content-Type': 'application/x-www-form-urlencoded',
 | |
|       },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}`
 | |
|     });
 | |
|     if(addRes.ok) {
 | |
|       const logRes = await fetch(url + `/api/users/${_id}/logs`);
 | |
|       if(logRes.ok){
 | |
|         const {log} = await logRes.json();
 | |
|         const exercise = log[0];
 | |
|         assert.isNumber(exercise.duration);
 | |
|         assert.equal(exercise.duration, expected.duration);
 | |
|       } else {
 | |
|         throw new Error(`${logRes.status} ${logRes.statusText}`);
 | |
|       }
 | |
|     } else {
 | |
|       throw new Error(`${addRes.status} ${addRes.statusText}`);
 | |
|     };
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   };
 | |
| };
 | |
| ```
 | |
| 
 | |
| A propriedade `date` de qualquer objeto no array `log` retornada de `GET /api/users/:id/logs` deve ser uma string. Use o formato `dateString` da API `Date`.
 | |
| 
 | |
| ```js
 | |
| async(getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users/', {
 | |
|     method: 'POST',
 | |
|     headers: {
 | |
|       'Content-Type': 'application/x-www-form-urlencoded',
 | |
|     },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0,29)
 | |
|   });
 | |
|   if(res.ok) {
 | |
|     const {_id, username} = await res.json();
 | |
|     const expected = {
 | |
|       username,
 | |
|       description: 'test',
 | |
|       duration: 60,
 | |
|       _id,
 | |
|       date: new Date().toDateString()
 | |
|     };
 | |
|     const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: {
 | |
|         'Content-Type': 'application/x-www-form-urlencoded',
 | |
|       },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}`
 | |
|     });
 | |
|     if(addRes.ok) {
 | |
|       const logRes = await fetch(url + `/api/users/${_id}/logs`);
 | |
|       if(logRes.ok){
 | |
|         const {log} = await logRes.json();
 | |
|         const exercise = log[0];
 | |
|         assert.isString(exercise.date);
 | |
|         assert.equal(exercise.date, expected.date);
 | |
|       } else {
 | |
|         throw new Error(`${logRes.status} ${logRes.statusText}`);
 | |
|       }
 | |
|     } else {
 | |
|       throw new Error(`${addRes.status} ${addRes.statusText}`);
 | |
|     };
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   };
 | |
| };
 | |
| ```
 | |
| 
 | |
| Você pode adicionar os parâmetros `from`, `to` e `limit` a uma solicitação para `GET /api/users/:_id/logs` para recuperar parte do registro de qualquer usuário. `from` e `to` são datas no formato `yyyy-mm-dd`. `limit` é um número inteiro de quantos registros devem ser enviados de volta.
 | |
| 
 | |
| ```js
 | |
| async (getUserInput) => {
 | |
|   const url = getUserInput('url');
 | |
|   const res = await fetch(url + '/api/users', {
 | |
|     method: 'POST',
 | |
|     headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|     body: `username=fcc_test_${Date.now()}`.substr(0, 29)
 | |
|   });
 | |
|   if (res.ok) {
 | |
|     const { _id, username } = await res.json();
 | |
|     const expected = {
 | |
|       username,
 | |
|       description: 'test',
 | |
|       duration: 60,
 | |
|       _id,
 | |
|       date: new Date().toDateString()
 | |
|     };
 | |
|     const addExerciseRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}&date=1990-01-01`
 | |
|     });
 | |
|     const addExerciseTwoRes = await fetch(url + `/api/users/${_id}/exercises`, {
 | |
|       method: 'POST',
 | |
|       headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
 | |
|       body: `description=${expected.description}&duration=${expected.duration}&date=1990-01-02`
 | |
|     });
 | |
|     if (addExerciseRes.ok && addExerciseTwoRes.ok) {
 | |
|       const logRes = await fetch(
 | |
|         url + `/api/users/${_id}/logs?from=1989-12-31&to=1990-01-03`
 | |
|       );
 | |
|       if (logRes.ok) {
 | |
|         const { log } = await logRes.json();
 | |
|         assert.isArray(log);
 | |
|         assert.equal(2, log.length);
 | |
|       } else {
 | |
|         throw new Error(`${logRes.status} ${logRes.statusText}`);
 | |
|       }
 | |
|       const limitRes = await fetch(
 | |
|         url + `/api/users/${_id}/logs?limit=1`
 | |
|       );
 | |
|       if (limitRes.ok) {
 | |
|         const { log } = await limitRes.json();
 | |
|         assert.isArray(log);
 | |
|         assert.equal(1, log.length);
 | |
|       } else {
 | |
|         throw new Error(`${limitRes.status} ${limitRes.statusText}`);
 | |
|       }
 | |
|     } else {
 | |
|       throw new Error(`${res.status} ${res.statusText}`);
 | |
|     }
 | |
|   } else {
 | |
|     throw new Error(`${res.status} ${res.statusText}`);
 | |
|   }
 | |
| };
 | |
| ```
 | |
| 
 | |
| # --solutions--
 | |
| 
 | |
| ```js
 | |
| /**
 | |
|   Backend challenges don't need solutions,
 | |
|   because they would need to be tested against a full working project.
 | |
|   Please check our contributing guidelines to learn more.
 | |
| */
 | |
| ```
 |