From d964e18339d84b08e04a23c469b2da4028a4675a Mon Sep 17 00:00:00 2001 From: Noor Fakhry <65724923+NoorFakhry@users.noreply.github.com> Date: Thu, 26 Aug 2021 13:27:52 +0200 Subject: [PATCH] fix(curriculum): exercise-tracker test and description improvement (#43205) * fix(curriculum): clarify exercise tracker * feat:separatetest steps for logs endpoint * feat:separate test steps for logs endpoint, refactored a description sentence * feat:separate-test-steps-for-users-endpoint * added string checks on last commit * feat:separate-test-steps-for-exercises-endpoint * feat:separate-test-steps-for-users-endpoint * feat:separate test steps * feat:separate test steps * feat:explicitly specify prop returned from 'GET /api/users' * feat:explicitly specify obj returned from * feat:explicitly specify returned responses from 'GET/api/users/:_id/logs' * feat:separate test steps * feat:separate test steps(apply req changes) * feat:spearate test steps(made more req changes) * feat:separate test steps(apply more req changes) * feat:separate test steps(modified clarification of return from POST api/users) * feat:separate test changes(added / after 'url') * feat:separate test changes(applied more req changes) * feat:spearate test steps(removed unwanted space) * feat:separate test steps --- .../exercise-tracker.md | 352 +++++++++++++++++- 1 file changed, 333 insertions(+), 19 deletions(-) diff --git a/curriculum/challenges/english/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md b/curriculum/challenges/english/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md index cde690bfa6..d22ca8c0ed 100644 --- a/curriculum/challenges/english/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md +++ b/curriculum/challenges/english/05-back-end-development-and-apis/back-end-development-and-apis-projects/exercise-tracker.md @@ -47,7 +47,7 @@ Log: { username: "fcc_test", count: 1, - _id: "5fd01a41c5b5cf05d080502f", + _id: "5fb5853f734231456ccb3b05", log: [{ description: "test", duration: 60, @@ -71,7 +71,24 @@ You should provide your own project, not the example URL. }; ``` -You can `POST` to `/api/users` with form data `username` to create a new user. The returned response will be an object with `username` and `_id` properties. +You can `POST` to `/api/users` with form data `username` to create a new user. + +```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}`) + }; +}; +``` + +The returned response from `POST /api/users` with form data `username` will be an object with `username` and `_id` properties. ```js async (getUserInput) => { @@ -91,24 +108,89 @@ async (getUserInput) => { }; ``` -You can make a `GET` request to `/api/users` to get an array of all users. Each element in the array is an object containing a user's `username` and `_id`. +You can make a `GET` request to `/api/users` to get a list of all users. + +```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}`) + }; +}; +``` + +The `GET` request to `/api/users` returns an 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}`); + }; +}; +``` + +Each element in the array returned from `GET /api/users` is an object literal containing a user's `username` and `_id`. + +```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}`); + }; +}; +``` + +You can `POST` to `/api/users/:_id/exercises` with form data `description`, `duration`, and optionally `date`. If no date is supplied, the current date will be used. ```js async (getUserInput) => { const url = getUserInput('url'); - const res = await fetch(url + '/api/users'); + 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 data = await res.json(); - assert.isArray(data); - assert.isString(data[0].username); - assert.isString(data[0]._id); + 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}`); } }; ``` -You can `POST` to `/api/users/:_id/exercises` with form data `description`, `duration`, and optionally `date`. If no date is supplied, the current date will be used. The response returned will be the user object with the exercise fields added. +The response returned from `POST /api/users/:_id/exercises` will be the user object with the exercise fields added. ```js async (getUserInput) => { @@ -135,6 +217,9 @@ async (getUserInput) => { 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}`); } @@ -144,7 +229,7 @@ async (getUserInput) => { }; ``` -You can make a `GET` request to `/api/users/:_id/logs` to retrieve a full exercise log of any user. The returned response will be the user object with a `log` array of all the exercises added. Each log item has the `description`, `duration`, and `date` properties. +You can make a `GET` request to `/api/users/:_id/logs` to retrieve a full exercise log of any user. ```js async (getUserInput) => { @@ -170,13 +255,10 @@ async (getUserInput) => { }); 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}`); - } + assert.isTrue(logRes.ok); + if(!logRes.ok) { + throw new Error(`${logRes.status} ${logRes.statusText}`) + }; } else { throw new Error(`${addRes.status} ${addRes.statusText}`); } @@ -186,7 +268,7 @@ async (getUserInput) => { }; ``` -A request to a user's log (`/api/users/:_id/logs`) returns an object with a `count` property representing the number of exercises returned. +A request to a user's log `GET /api/users/:_id/logs` returns a user object with a `count` property representing the number of exercises that belong to that user. ```js async (getUserInput) => { @@ -227,7 +309,239 @@ async (getUserInput) => { }; ``` -You can add `from`, `to` and `limit` parameters to a `/api/users/:_id/logs` request to retrieve part of the log of any user. `from` and `to` are dates in `yyyy-mm-dd` format. `limit` is an integer of how many logs to send back. +A `GET` request to `/api/users/:id/logs` will return the user object with a `log` array of all the exercises added. + +```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}`) + }; +}; +``` + +Each item in the `log` array that is returned from `GET /api/users/:id/logs` is an object that should have a `description`, `duration`, and `date` properties. + +```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}`) + }; +}; +``` + +The `description` property of any object in the `log` array that is returned from `GET /api/users/:id/logs` should be a 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}`); + }; +}; +``` + +The `duration` property of any object in the `log` array that is returned from `GET /api/users/:id/logs` should be a number. + +```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}`); + }; +}; +``` + +The `date` property of any object in the `log` array that is returned from `GET /api/users/:id/logs` should be a string.. Use the `dateString` format of the `Date` API. + +```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}`); + }; +}; +``` + +You can add `from`, `to` and `limit` parameters to a `GET /api/users/:_id/logs` request to retrieve part of the log of any user. `from` and `to` are dates in `yyyy-mm-dd` format. `limit` is an integer of how many logs to send back. ```js async (getUserInput) => {