diff --git a/.test-summary/TEST_SUMMARY.md b/.test-summary/TEST_SUMMARY.md new file mode 100644 index 000000000..a5f0d5725 --- /dev/null +++ b/.test-summary/TEST_SUMMARY.md @@ -0,0 +1,14 @@ +## Test Summary + +**Mentors**: For more information on how to review homework assignments, please refer to the [Review Guide](https://github.com/HackYourFuture/mentors/blob/main/assignment-support/review-guide.md). + +### 3-UsingAPIs - Week2 + +| Exercise | Passed | Failed | ESLint | +|-------------------|--------|--------|--------| +| ex1-programmerFun | 5 | - | ✓ | +| ex2-pokemonApp | 5 | - | ✓ | +| ex3-rollAnAce | 7 | - | ✓ | +| ex4-diceRace | 7 | - | ✓ | +| ex5-vscDebug | - | - | ✓ | +| ex6-browserDebug | - | - | ✓ | diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..6ed567849 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}\\3-UsingAPIs\\Week2\\assignment\\ex5-vscDebug.js" + } + ] +} \ No newline at end of file diff --git a/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js b/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js index a99ca177b..0b6a783d4 100644 --- a/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js +++ b/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js @@ -16,29 +16,33 @@ Full description at: https://github.com/HackYourFuture/Assignments/blob/main/3-U url with `.shx`. There is no server at the modified url, therefore this should result in a network (DNS) error. ------------------------------------------------------------------------------*/ -function requestData(url) { - // TODO return a promise using `fetch()` +async function requestData(url) { + const results = await fetch(url); + if (!results.ok) { + throw new Error('Invalid URL'); + } + return results.json(); } function renderImage(data) { - // TODO render the image to the DOM - console.log(data); + const newImg = document.createElement('img'); + newImg.src = data.img; + document.body.appendChild(newImg); } function renderError(error) { - // TODO render the error to the DOM - console.log(error); + const newMessage = document.createElement('h1'); + newMessage.textContent = error; + document.body.appendChild(newMessage); } -// TODO refactor with async/await and try/catch -function main() { - requestData('https://xkcd.now.sh/?comic=latest') - .then((data) => { - renderImage(data); - }) - .catch((error) => { - renderError(error); - }); +async function main() { + try { + const data = await requestData('https://xkcd.now.sh/?comic=latest'); + renderImage(data); + } catch (error) { + renderError(error); + } } window.addEventListener('load', main); diff --git a/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js b/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js index 262113997..31382df84 100644 --- a/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js +++ b/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js @@ -21,18 +21,73 @@ Use async/await and try/catch to handle promises. Try and avoid using global variables. As much as possible, try and use function parameters and return values to pass data back and forth. ------------------------------------------------------------------------------*/ -function fetchData(/* TODO parameter(s) go here */) { - // TODO complete this function +async function fetchData(url) { + const getData = await fetch(url); + if (!getData.ok) { + throw new Error('Invalid URL'); + } + + return getData.json(); } -function fetchAndPopulatePokemons(/* TODO parameter(s) go here */) { - // TODO complete this function +function fetchAndPopulatePokemons(data) { + const pokemonList = data.results; + + let selector = document.querySelector('select'); + if (!selector) { + selector = document.createElement('select'); + document.body.appendChild(selector); + } + + pokemonList.map((pokemon) => { + const createOption = document.createElement('option'); + createOption.textContent = pokemon.name; + createOption.value = pokemon.name; + selector.appendChild(createOption); + }); + + selector.addEventListener('change', async () => { + try { + const data = await fetchData( + `https://pokeapi.co/api/v2/pokemon/${selector.value}` + ); + fetchImage(data); + } catch (error) { + throw new Error(error); + } + }); + + document.querySelector('button').style.display = 'none'; } -function fetchImage(/* TODO parameter(s) go here */) { - // TODO complete this function +async function fetchImage(data) { + const pokemonImage = data.sprites.other.home.front_default; + + let imgContainer = document.querySelector('#img-container'); + if (!imgContainer) { + imgContainer = document.createElement('img'); + imgContainer.id = 'img-container'; + document.body.appendChild(imgContainer); + } + + imgContainer.src = pokemonImage; } function main() { - // TODO complete this function + const createButton = document.createElement('button'); + createButton.textContent = "Catch 'em all"; + document.body.appendChild(createButton); + + createButton.addEventListener('click', async () => { + try { + const data = await fetchData( + 'https://pokeapi.co/api/v2/pokemon?limit=151' + ); + fetchAndPopulatePokemons(data); + } catch (error) { + throw new Error(error); + } + }); } + +window.addEventListener('load', main); diff --git a/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/style.css b/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/style.css index 44cb05eeb..0aef6d130 100644 --- a/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/style.css +++ b/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/style.css @@ -1 +1,37 @@ -/* add your styling here */ +body { + display: flex; + flex-flow: column nowrap; + align-items: center; + justify-content: center; + height: 100dvh; +} + +button { + width: 300px; + padding: 10px 30px; + background-color: white; + border: 3px solid #3363af; + border-radius: 5px; + font-size: 24px; + font-weight: bold; + color: #3363af; + cursor: pointer; + transition: all 0.3s ease; +} + +button:hover { + background-color: #3363af; + color: #fff; +} + +select { + padding: 10px; + width: 300px; + margin: 20px; + border: 3px solid #3363af; + border-radius: 5px; + font-size: 24px; + font-weight: bold; + color: #3363af; + cursor: pointer; +} diff --git a/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js b/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js index 861b31047..1aafd9475 100644 --- a/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js +++ b/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js @@ -17,21 +17,23 @@ import { rollDie } from '../../helpers/pokerDiceRoller.js'; * @param {DieFace} desiredValue * @returns {Promise} */ -export function rollDieUntil(desiredValue) { - // TODO rewrite this function using async/await - return rollDie().then((value) => { - if (value !== desiredValue) { - return rollDieUntil(desiredValue); - } - return value; - }); +export async function rollDieUntil(desiredValue) { + let roll = await rollDie(); + + while (roll !== desiredValue) { + roll = await rollDie(); + } + + return roll; } -// TODO refactor this function to use try/catch -function main() { - rollDieUntil('ACE') - .then((results) => console.log('Resolved!', results)) - .catch((error) => console.log('Rejected!', error.message)); +async function main() { + try { + const result = await rollDieUntil('ACE'); + console.log('Resolved!', result); + } catch (error) { + console.log('Rejected!', error.message); + } } // ! Do not change or remove the code below diff --git a/3-UsingAPIs/Week2/assignment/ex4-diceRace.js b/3-UsingAPIs/Week2/assignment/ex4-diceRace.js index ddff3242c..479300dcb 100644 --- a/3-UsingAPIs/Week2/assignment/ex4-diceRace.js +++ b/3-UsingAPIs/Week2/assignment/ex4-diceRace.js @@ -15,15 +15,18 @@ import { rollDie } from '../../helpers/pokerDiceRoller.js'; export function rollDice() { const dice = [1, 2, 3, 4, 5]; - // TODO complete this function; use Promise.race() and rollDie() - rollDie(1); // TODO placeholder: modify as appropriate + const promiseMap = dice.map((dice) => rollDie(dice)); + + return Promise.race(promiseMap); } -// Refactor this function to use async/await and try/catch -function main() { - rollDice() - .then((results) => console.log('Resolved!', results)) - .catch((error) => console.log('Rejected!', error.message)); +async function main() { + try { + const roll = await rollDice(); + console.log('Resolved!', roll); + } catch (error) { + console.log('Rejected!', error.message); + } } // ! Do not change or remove the code below @@ -31,4 +34,4 @@ if (process.env.NODE_ENV !== 'test') { main(); } -// TODO Replace this comment by your explanation that was asked for in the assignment description. +// Promise.race() will run all the promises on the same time, but it will only return the result of the fastest promise. And since all the promises has already started, they will keep on executing until they reach their final status. diff --git a/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js b/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js index a65448e57..0017db0cd 100644 --- a/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js +++ b/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js @@ -10,8 +10,10 @@ async function getData(url) { function renderLaureate({ knownName, birth, death }) { console.log(`\nName: ${knownName.en}`); - console.log(`Birth: ${birth.date}, ${birth.place.locationString}`); - console.log(`Death: ${death.date}, ${death.place.locationString}`); + console.log(`Birth: ${birth.date}, ${birth.place.locationString.en}`); + if (death) { + console.log(`Death: ${death.date}, ${death.place.locationString.en}`); + } } function renderLaureates(laureates) { @@ -20,7 +22,7 @@ function renderLaureates(laureates) { async function fetchAndRender() { try { - const laureates = getData( + const { laureates } = await getData( 'http://api.nobelprize.org/2.0/laureates?birthCountry=Netherlands&format=json&csvLang=en' ); renderLaureates(laureates); diff --git a/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js b/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js index 91e0402be..93aae0488 100644 --- a/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js +++ b/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js @@ -30,8 +30,18 @@ function renderLaureate(ul, { knownName, birth, death }) { const li = createAndAppend('li', ul); const table = createAndAppend('table', li); addTableRow(table, 'Name', knownName.en); - addTableRow(table, 'Birth', `${birth.date}, ${birth.place.locationString}`); - addTableRow(table, 'Death', `${death.date}, ${death.place.locationString}`); + addTableRow( + table, + 'Birth', + `${birth.date}, ${birth.place.locationString.en}` + ); + if (death) { + addTableRow( + table, + 'Death', + `${death.date}, ${death.place.locationString.en}` + ); + } } function renderLaureates(laureates) { @@ -41,7 +51,7 @@ function renderLaureates(laureates) { async function fetchAndRender() { try { - const laureates = getData( + const { laureates } = await getData( 'https://api.nobelprize.org/2.0/laureates?birthCountry=Netherlands&format=json&csvLang=en' ); renderLaureates(laureates); diff --git a/3-UsingAPIs/Week2/test-reports/ex1-programmerFun.report.txt b/3-UsingAPIs/Week2/test-reports/ex1-programmerFun.report.txt new file mode 100644 index 000000000..aa2281042 --- /dev/null +++ b/3-UsingAPIs/Week2/test-reports/ex1-programmerFun.report.txt @@ -0,0 +1,17 @@ +*** Unit Test Error Report *** + + PASS .dist/3-UsingAPIs/Week2/unit-tests/ex1-programmerFun.test.js (7.498 s) + api-wk2-ex1-programmerFun + ✅ HTML should be syntactically valid (84 ms) + ✅ should have all TODO comments removed (1 ms) + ✅ should use `fetch()` + ✅ should use async/wait + ✅ should use try/catch + +Test Suites: 1 passed, 1 total +Tests: 5 passed, 5 total +Snapshots: 0 total +Time: 7.842 s +Ran all test suites matching /C:\\Users\\zet_a\\Desktop\\HYF\\Assignments-cohort52\\.dist\\3-UsingAPIs\\Week2\\unit-tests\\ex1-programmerFun.test.js/i. +No linting errors detected. +No spelling errors detected. diff --git a/3-UsingAPIs/Week2/test-reports/ex2-pokemonApp.report.txt b/3-UsingAPIs/Week2/test-reports/ex2-pokemonApp.report.txt new file mode 100644 index 000000000..26fa0a67a --- /dev/null +++ b/3-UsingAPIs/Week2/test-reports/ex2-pokemonApp.report.txt @@ -0,0 +1,17 @@ +*** Unit Test Error Report *** + + PASS .dist/3-UsingAPIs/Week2/unit-tests/ex2-pokemonApp.test.js + api-wk2-ex2-pokemonApp + ✅ HTML should be syntactically valid (78 ms) + ✅ should have all TODO comments removed + ✅ should use `fetch()` + ✅ should use `await fetch()` + ✅ should use try/catch + +Test Suites: 1 passed, 1 total +Tests: 5 passed, 5 total +Snapshots: 0 total +Time: 2.571 s, estimated 3 s +Ran all test suites matching /C:\\Users\\zet_a\\Desktop\\HYF\\Assignments-cohort52\\.dist\\3-UsingAPIs\\Week2\\unit-tests\\ex2-pokemonApp.test.js/i. +No linting errors detected. +No spelling errors detected. diff --git a/3-UsingAPIs/Week2/test-reports/ex3-rollAnAce.report.txt b/3-UsingAPIs/Week2/test-reports/ex3-rollAnAce.report.txt new file mode 100644 index 000000000..066ae83ab --- /dev/null +++ b/3-UsingAPIs/Week2/test-reports/ex3-rollAnAce.report.txt @@ -0,0 +1,19 @@ +*** Unit Test Error Report *** + + PASS .dist/3-UsingAPIs/Week2/unit-tests/ex3-rollAnAce.test.js + api-wk2-ex3-rollAnAce + ✅ should have all TODO comments removed (1 ms) + ✅ `rollDieUntil` should not contain unneeded console.log calls + ✅ should not include a recursive call + ✅ should use async/wait + ✅ should use try/catch + ✅ should resolve as soon as a die settles on an ACE (170 ms) + ✅ should reject with an Error when a die rolls off the table (126 ms) + +Test Suites: 1 passed, 1 total +Tests: 7 passed, 7 total +Snapshots: 0 total +Time: 0.702 s, estimated 1 s +Ran all test suites matching /C:\\Users\\zet_a\\Desktop\\HYF\\Assignments-cohort52\\.dist\\3-UsingAPIs\\Week2\\unit-tests\\ex3-rollAnAce.test.js/i. +No linting errors detected. +No spelling errors detected. diff --git a/3-UsingAPIs/Week2/test-reports/ex4-diceRace.report.txt b/3-UsingAPIs/Week2/test-reports/ex4-diceRace.report.txt new file mode 100644 index 000000000..70cd36816 --- /dev/null +++ b/3-UsingAPIs/Week2/test-reports/ex4-diceRace.report.txt @@ -0,0 +1,19 @@ +*** Unit Test Error Report *** + + PASS .dist/3-UsingAPIs/Week2/unit-tests/ex4-diceRace.test.js + api-wk2-ex4-diceRace + ✅ should exist and be executable (1 ms) + ✅ should have all TODO comments removed + ✅ `rollDice` should not contain unneeded console.log calls (1 ms) + ✅ should use `dice.map()` + ✅ should use `Promise.race()` + ✅ should resolve as soon as a die settles successfully (6 ms) + ✅ should reject with an Error as soon as a die rolls off the table (80 ms) + +Test Suites: 1 passed, 1 total +Tests: 7 passed, 7 total +Snapshots: 0 total +Time: 0.711 s +Ran all test suites matching /C:\\Users\\zet_a\\Desktop\\HYF\\Assignments-cohort52\\.dist\\3-UsingAPIs\\Week2\\unit-tests\\ex4-diceRace.test.js/i. +No linting errors detected. +No spelling errors detected. diff --git a/3-UsingAPIs/Week2/test-reports/ex5-vscDebug.report.txt b/3-UsingAPIs/Week2/test-reports/ex5-vscDebug.report.txt new file mode 100644 index 000000000..d985f405c --- /dev/null +++ b/3-UsingAPIs/Week2/test-reports/ex5-vscDebug.report.txt @@ -0,0 +1,3 @@ +A unit test file was not provided for this exercise. +No linting errors detected. +No spelling errors detected. diff --git a/3-UsingAPIs/Week2/test-reports/ex6-browserDebug.report.txt b/3-UsingAPIs/Week2/test-reports/ex6-browserDebug.report.txt new file mode 100644 index 000000000..d985f405c --- /dev/null +++ b/3-UsingAPIs/Week2/test-reports/ex6-browserDebug.report.txt @@ -0,0 +1,3 @@ +A unit test file was not provided for this exercise. +No linting errors detected. +No spelling errors detected.