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/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js b/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js index a99ca177b..61733b1e0 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 response = await fetch(url); + if (!response.ok) throw new Error('Not found!'); + const data = response.json(); + return data; } function renderImage(data) { - // TODO render the image to the DOM - console.log(data); + const image = document.createElement('img'); + image.src = data.img; + image.alt = data.title; + document.body.appendChild(image); } function renderError(error) { - // TODO render the error to the DOM - console.log(error); + const div = document.createElement('div'); + div.innerHTML = error; + document.body.appendChild(div); } -// 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.message); + } } 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..e657e239e 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 response = await fetch(url); + if (!response.ok) throw new Error('An error occured!'); + const data = await response.json(); + return data; } -function fetchAndPopulatePokemons(/* TODO parameter(s) go here */) { - // TODO complete this function -} +async function fetchAndPopulatePokemons(url) { + //Create the button + const btn = document.createElement('button'); + btn.textContent = 'Show'; + document.body.appendChild(btn); + + //Create the select + try { + const data = await fetchData(url); + + btn.addEventListener('click', () => { + const pokemons = document.createElement('select'); + pokemons.setAttribute('id', 'selected'); + document.body.appendChild(pokemons); + + if (pokemons.options.length === 0) { + data.results.forEach((element) => { + const pokemon = document.createElement('option'); + pokemon.setAttribute('value', element.url); + const optionText = document.createTextNode(element.name); + pokemon.appendChild(optionText); + pokemons.appendChild(pokemon); + }); + } + }); + + pokemons.addEventListener('change', () => { + fetchImage(); + }); -function fetchImage(/* TODO parameter(s) go here */) { - // TODO complete this function + // return pokemons; + } catch (error) { + console.log(error); + } } -function main() { - // TODO complete this function +async function fetchImage() { + const dropdown = document.getElementById('selected'); + const pokemonUrl = dropdown.value; + const data = await fetchData(pokemonUrl); + + const imageUrl = data.sprites.front_default; + + let image = document.querySelector('img'); + if (!image) { + image = document.createElement('img'); + document.body.appendChild(image); + } + + image.src = imageUrl; + image.alt = data.name; } +async function main() { + try { + const result = await fetchAndPopulatePokemons( + 'https://pokeapi.co/api/v2/pokemon?limit=151' + ); + } catch (err) { + console.log(err); + } +} + +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..59e474d90 100644 --- a/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/style.css +++ b/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/style.css @@ -1 +1,24 @@ -/* add your styling here */ +/* add your styling here +body { + text-align: center; + margin-top: 50px; + font-family: Arial, sans-serif; +}*/ +button { + position: fixed; + margin-bottom: 20px; +} +select { + position: fixed; + font-size: 16px; + margin-top: 30px; + margin-bottom: 10px; + padding: 5px; +} + +img { + margin-top: 50px; + margin-bottom: 10px; + width: 250px; + height: 250px; +} diff --git a/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js b/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js index 861b31047..5591e8d91 100644 --- a/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js +++ b/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js @@ -17,21 +17,26 @@ 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); +export async function rollDieUntil(desiredValue) { + while (true) { + try { + const value = await rollDie(); + if (value === desiredValue) { + return value; + } + } catch (err) { + if (err.message.includes('off the table')) throw err; } - return value; - }); + } } -// 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..e119af235 100644 --- a/3-UsingAPIs/Week2/assignment/ex4-diceRace.js +++ b/3-UsingAPIs/Week2/assignment/ex4-diceRace.js @@ -15,15 +15,21 @@ 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 + return Promise.race( + dice.map((ele) => { + return rollDie(ele); + }) + ); } // 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 results = await rollDice(); + console.log('Resolved!', results); + } catch (error) { + console.log('Rejected!', error.message); + } } // ! Do not change or remove the code below @@ -31,4 +37,4 @@ if (process.env.NODE_ENV !== 'test') { main(); } -// TODO Replace this comment by your explanation that was asked for in the assignment description. +//Because Promise.race() only returns when the first promise settles but doesn’t cancel the others. The remaining dice keep rolling because their setTimeout() calls are still running. diff --git a/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js b/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js index a65448e57..72ba6ffd7 100644 --- a/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js +++ b/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js @@ -11,7 +11,9 @@ 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}`); + if (death) { + console.log(`Death: ${death.date}, ${death.place.locationString}`); + } } function renderLaureates(laureates) { @@ -20,12 +22,13 @@ 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); } catch (err) { console.error(`Something went wrong: ${err.message}`); + console.log(err.stack); } } diff --git a/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js b/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js index 91e0402be..7429db50b 100644 --- a/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js +++ b/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js @@ -31,7 +31,9 @@ function renderLaureate(ul, { knownName, birth, death }) { 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}`); + if (death) { + addTableRow(table, 'Death', `${death.date}, ${death.place.locationString}`); + } } function renderLaureates(laureates) { @@ -41,7 +43,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..23fab2322 --- /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 (12.813 s) + api-wk2-ex1-programmerFun + ✅ HTML should be syntactically valid (162 ms) + ✅ should have all TODO comments removed + ✅ should use `fetch()` + ✅ should use async/wait + ✅ should use try/catch (1 ms) + +Test Suites: 1 passed, 1 total +Tests: 5 passed, 5 total +Snapshots: 0 total +Time: 13.562 s +Ran all test suites matching /\/Users\/Alaa\/Desktop\/JavaScript-Cohort54\/.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..f741075d9 --- /dev/null +++ b/3-UsingAPIs/Week2/test-reports/ex2-pokemonApp.report.txt @@ -0,0 +1,21 @@ +*** Unit Test Error Report *** + + PASS .dist/3-UsingAPIs/Week2/unit-tests/ex2-pokemonApp.test.js + api-wk2-ex2-pokemonApp + ✅ HTML should be syntactically valid (158 ms) + ✅ should have all TODO comments removed (1 ms) + ✅ should use `fetch()` + ✅ should use `await fetch()` (1 ms) + ✅ should use try/catch + +Test Suites: 1 passed, 1 total +Tests: 5 passed, 5 total +Snapshots: 0 total +Time: 3.041 s +Ran all test suites matching /\/Users\/Alaa\/Desktop\/JavaScript-Cohort54\/.dist\/3-UsingAPIs\/Week2\/unit-tests\/ex2-pokemonApp.test.js/i. +No linting errors detected. + + +*** Spell Checker Report *** + +3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js:26:47 - Unknown word (occured) fix: (occurred) 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..b522a0fc1 --- /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 (2 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 (23 ms) + ✅ should reject with an Error when a die rolls off the table (10 ms) + +Test Suites: 1 passed, 1 total +Tests: 7 passed, 7 total +Snapshots: 0 total +Time: 0.658 s, estimated 1 s +Ran all test suites matching /\/Users\/Alaa\/Desktop\/JavaScript-Cohort54\/.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..27684922e --- /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 (2 ms) + ✅ should have all TODO comments removed + ✅ `rollDice` should not contain unneeded console.log calls + ✅ should use `dice.map()` (1 ms) + ✅ should use `Promise.race()` + ✅ should resolve as soon as a die settles successfully (10 ms) + ✅ should reject with an Error as soon as a die rolls off the table (30 ms) + +Test Suites: 1 passed, 1 total +Tests: 7 passed, 7 total +Snapshots: 0 total +Time: 0.684 s, estimated 1 s +Ran all test suites matching /\/Users\/Alaa\/Desktop\/JavaScript-Cohort54\/.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. diff --git a/README.md b/README.md index d457d2828..5e5773557 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ We highly recommend that you go through this README in detail before starting to > > This will ensure that the line endings for text files are compatible with those used on MacOS and Linux-based computers. -1. Fork the `HackYourAssignment/Assignments-CohortXX` repository to your own GitHub account. +1. Fork the `HackYourAssignment/JavaScript-CohortXX` repository to your own GitHub account. 2. Clone the fork to your local computer. 3. Open the root folder of the repository in VSCode. 4. When invited to do so, please install the recommended VSCode extensions. @@ -24,7 +24,7 @@ We highly recommend that you go through this README in detail before starting to 10. Fix any reported issues and rerun the test. Repeat until all issues are fixed. 11. When all assignments are done, commit all changed files. This includes the modified exercises, the generated test summary (`TEST_SUMMARY.md`) and test reports (`EXERCISE_NAME.report.txt`). 12. Push the changes to your fork. -13. Create a pull request against the `main` branch of the `HackYourAssignment/Assignments-CohortXX` repository. For the title of your pull request use the same format as the branch name, e.g.: `YOUR_NAME-w2-JavaScript`. +13. Create a pull request against the `main` branch of the `HackYourAssignment/JavaScript-CohortXX` repository. For the title of your pull request use the same format as the branch name, e.g.: `YOUR_NAME-w2-JavaScript`. Repeat steps 6-13 for each week. For subsequent weeks the mandated branch names are: @@ -39,7 +39,7 @@ For more information how to hand in your weekly assignments please refer to the Throughout your [HYF journey](https://github.com/HackYourFuture/curriculum) you will be asked to do certain exercises. This repository contains all of these exercises for the JavaScript modules (JavaScript, Browsers, UsingAPIs). The module repositories will tell you how to hand in the assignment, the curriculum will indicate what week you will need to do. -> Note that a fork of this repository will be created on the [HackYourAssignment](https://github.com/HackYourAssignment) GitHub account specifically for your cohort. The name of the repository will have the format `Assignments-cohortXX` where `XX` is your cohort number, +> Note that a fork of this repository will be created on the [HackYourAssignment](https://github.com/HackYourAssignment) GitHub account specifically for your cohort. The name of the repository will have the format `JavaScript-cohortXX` where `XX` is your cohort number, ## Installation @@ -64,9 +64,9 @@ From the command line, while inside the `Assignments-cohortXX` folder, you can u code . ``` -> When working on your assignments it is strongly recommended to always open the `Assignments-cohortXX` folder in VSCode rather than one of its sub-folders. This gives VSCode and all its extensions the full view on the repository for the best overall developer experience. +> When working on your assignments it is strongly recommended to always open the `JavaScript-cohortXX` folder in VSCode rather than one of its sub-folders. This gives VSCode and all its extensions the full view on the repository for the best overall developer experience. > -> Note that the name of the folder opened in VSCode can always be found in the `EXPLORER` panel ( `ASSIGNMENTS_COHORT49` in the picture below): +> Note that the name of the folder opened in VSCode can always be found in the `EXPLORER` panel ( `ASSIGNMENT_COHORT49` in the picture below): > > ![folder-name](./assets/folder-name.png)