From b2e70fd9b7434dca825aa44513b41512bb9f0e8e Mon Sep 17 00:00:00 2001 From: Hadidreem17 Date: Wed, 15 Oct 2025 23:05:28 +0200 Subject: [PATCH 1/5] Hadidreem17-w2-UsingAPIs completed all 6 exercises --- .test-summary/TEST_SUMMARY.md | 11 ++++ .../assignment/ex1-programmerFun/index.js | 51 +++++++++++----- .../Week2/assignment/ex2-pokemonApp/index.js | 60 ++++++++++++++++--- 3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js | 34 +++++------ 3-UsingAPIs/Week2/assignment/ex4-diceRace.js | 28 +++++---- 3-UsingAPIs/Week2/assignment/ex5-vscDebug.js | 11 +++- .../assignment/ex6-browserDebug/index.js | 22 +++++-- .../test-reports/ex1-programmerFun.report.txt | 17 ++++++ .../test-reports/ex2-pokemonApp.report.txt | 17 ++++++ .../test-reports/ex4-diceRace.report.txt | 19 ++++++ Assignments | 1 + 11 files changed, 215 insertions(+), 56 deletions(-) create mode 100644 .test-summary/TEST_SUMMARY.md create mode 100644 3-UsingAPIs/Week2/test-reports/ex1-programmerFun.report.txt create mode 100644 3-UsingAPIs/Week2/test-reports/ex2-pokemonApp.report.txt create mode 100644 3-UsingAPIs/Week2/test-reports/ex4-diceRace.report.txt create mode 160000 Assignments diff --git a/.test-summary/TEST_SUMMARY.md b/.test-summary/TEST_SUMMARY.md new file mode 100644 index 000000000..0cc3438f4 --- /dev/null +++ b/.test-summary/TEST_SUMMARY.md @@ -0,0 +1,11 @@ +## 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 | - | ✓ | +| ex4-diceRace | 7 | - | ✓ | diff --git a/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js b/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js index a99ca177b..dedc436bc 100644 --- a/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js +++ b/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js @@ -17,28 +17,51 @@ Full description at: https://github.com/HackYourFuture/Assignments/blob/main/3-U should result in a network (DNS) error. ------------------------------------------------------------------------------*/ function requestData(url) { - // TODO return a promise using `fetch()` + return fetch(url) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + return response.json(); + }) + .catch(error => { + throw new Error(`Network error: ${error.message}`); + }); } function renderImage(data) { - // TODO render the image to the DOM - console.log(data); + const img = document.createElement('img'); + img.src = data.img; + img.alt = data.title; + img.style.maxWidth = '80%'; + img.style.display = 'block'; + img.style.margin = '20px auto'; + + const title = document.createElement('h2'); + title.textContent = data.title; + title.style.textAlign = 'center'; + + document.body.appendChild(title); + document.body.appendChild(img); } function renderError(error) { - // TODO render the error to the DOM - console.log(error); + const h1 = document.createElement('h1'); + h1.textContent = `Something went wrong : ${error.message}`; + h1.style.color = 'red'; + h1.style.textAlign = 'center'; + document.body.appendChild(h1); } -// 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() { + const url = 'https://xkcd.now.sh/?comic=latest'; + try { + const data = await requestData(url); + 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..238adb9b1 100644 --- a/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js +++ b/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js @@ -21,18 +21,62 @@ 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) { + try { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + const data = await response.json(); + return data; + } catch (error) { + console.error(error); + } } -function fetchAndPopulatePokemons(/* TODO parameter(s) go here */) { - // TODO complete this function +async function fetchAndPopulatePokemons(apiUrl, selectEl) { + try { + const data = await fetchData(apiUrl); + const pokemons = data.results; + + pokemons.forEach(pokemon => { + const option = document.createElement('option'); + option.textContent = pokemon.name; + option.value = pokemon.url; + selectEl.appendChild(option); + }); + } catch (error) { + console.error(error); + } } -function fetchImage(/* TODO parameter(s) go here */) { - // TODO complete this function +async function fetchImage(detailsUrl, imgEl) { + try { + const data = await fetchData(detailsUrl); + imgEl.src = data.sprites.front_default; + imgEl.alt = data.name; + } catch (error) { + console.error(error); + } } -function main() { - // TODO complete this function +async function main() { + const selectEl = document.querySelector('#pokemon-select'); + const imgEl = document.querySelector('#pokemon-image'); + const apiUrl = 'https://pokeapi.co/api/v2/pokemon?limit=150'; + + try { + await fetchAndPopulatePokemons(apiUrl, selectEl); + selectEl.addEventListener('change', async e => { + const detailsUrl = e.target.value; + if (detailsUrl) { + await fetchImage(detailsUrl, imgEl); + } + }); + } catch (error) { + console.error(error); + } } + +window.addEventListener('load', main); + diff --git a/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js b/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js index 861b31047..5753f4b08 100644 --- a/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js +++ b/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js @@ -13,28 +13,28 @@ import { rollDie } from '../../helpers/pokerDiceRoller.js'; /** @import {DieFace} from "../../helpers/pokerDiceRoller.js" */ /** - * Rolls a die until the desired value is rolled. - * @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) { + let value; + while (true) { + value = await rollDie(); + if (value === desiredValue) { + return value; } - 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 if (process.env.NODE_ENV !== 'test') { main(); } + diff --git a/3-UsingAPIs/Week2/assignment/ex4-diceRace.js b/3-UsingAPIs/Week2/assignment/ex4-diceRace.js index ddff3242c..198c2b3fc 100644 --- a/3-UsingAPIs/Week2/assignment/ex4-diceRace.js +++ b/3-UsingAPIs/Week2/assignment/ex4-diceRace.js @@ -13,22 +13,30 @@ Full description at: https://github.com/HackYourFuture/Assignments/blob/main/3-U import { rollDie } from '../../helpers/pokerDiceRoller.js'; /** @import {DieFace} from "../../helpers/pokerDiceRoller.js" */ -export function rollDice() { + +export async 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 dicePromises = dice.map(() => rollDie()); + const winner = await Promise.race(dicePromises); + return winner; } -// 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 result = await rollDice(); + console.log('Resolved!', result); + } catch (error) { + console.log('Rejected!', error.message); + } } -// ! Do not change or remove the code below if (process.env.NODE_ENV !== 'test') { main(); } -// TODO Replace this comment by your explanation that was asked for in the assignment description. +/* +Explanation: +Some dice keep rolling because Promise.race() only stops for the first finished promise. +The other promises keep running in the background. +*/ + diff --git a/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js b/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js index a65448e57..c81e1e65e 100644 --- a/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js +++ b/3-UsingAPIs/Week2/assignment/ex5-vscDebug.js @@ -11,18 +11,23 @@ async function getData(url) { function renderLaureate({ knownName, birth, death }) { console.log(`\nName: ${knownName.en}`); console.log(`Birth: ${birth.date}, ${birth.place.locationString}`); +if (death) { console.log(`Death: ${death.date}, ${death.place.locationString}`); } +} + function renderLaureates(laureates) { laureates.forEach(renderLaureate); } async function fetchAndRender() { try { - const laureates = getData( - 'http://api.nobelprize.org/2.0/laureates?birthCountry=Netherlands&format=json&csvLang=en' - ); + const { laureates } = await getData( + 'https://api.nobelprize.org/2.0/laureates?birthCountry=Netherlands&format=json&csvLang=en' +); +renderLaureates(laureates); + renderLaureates(laureates); } catch (err) { console.error(`Something went wrong: ${err.message}`); diff --git a/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js b/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js index 91e0402be..fe3e63525 100644 --- a/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js +++ b/3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js @@ -2,6 +2,7 @@ Full description at:https://github.com/HackYourFuture/Assignments/blob/main/3-UsingAPIs/Week2/README.md#exercise-6-using-the-browser-debugger */ + async function getData(url) { const response = await fetch(url); return response.json(); @@ -29,9 +30,22 @@ function addTableRow(table, label, value) { 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}`); + + const name = knownName?.en ?? '(unknown)'; + const birthPlace = + typeof birth?.place?.locationString === 'string' + ? birth.place.locationString + : birth?.place?.locationString?.en ?? '—'; + addTableRow(table, 'Name', name); + addTableRow(table, 'Birth', `${birth?.date ?? '—'}, ${birthPlace}`); + + if (death) { + const deathPlace = + typeof death?.place?.locationString === 'string' + ? death.place.locationString + : death?.place?.locationString?.en ?? '—'; + addTableRow(table, 'Death', `${death?.date ?? '—'}, ${deathPlace}`); + } } function renderLaureates(laureates) { @@ -41,7 +55,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..86b5fb4a6 --- /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 + api-wk2-ex1-programmerFun + ✅ HTML should be syntactically valid (130 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: 3.652 s, estimated 13 s +Ran all test suites matching /C:\\Users\\Rimha\\Assignments-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..b9373c30b --- /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 (131 ms) + ✅ should have all TODO comments removed + ✅ should use `fetch()` (1 ms) + ✅ should use `await fetch()` + ✅ should use try/catch + +Test Suites: 1 passed, 1 total +Tests: 5 passed, 5 total +Snapshots: 0 total +Time: 3.583 s +Ran all test suites matching /C:\\Users\\Rimha\\Assignments-Cohort54\\.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/ex4-diceRace.report.txt b/3-UsingAPIs/Week2/test-reports/ex4-diceRace.report.txt new file mode 100644 index 000000000..2fc74b72c --- /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 (1 ms) + ✅ `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 (11 ms) + ✅ should reject with an Error as soon as a die rolls off the table (69 ms) + +Test Suites: 1 passed, 1 total +Tests: 7 passed, 7 total +Snapshots: 0 total +Time: 0.876 s +Ran all test suites matching /C:\\Users\\Rimha\\Assignments-Cohort54\\.dist\\3-UsingAPIs\\Week2\\unit-tests\\ex4-diceRace.test.js/i. +No linting errors detected. +No spelling errors detected. diff --git a/Assignments b/Assignments new file mode 160000 index 000000000..c50e3cebe --- /dev/null +++ b/Assignments @@ -0,0 +1 @@ +Subproject commit c50e3cebeac3c278b9994f72695cc11fc2f2f1dc From d01a2057b3e42d782a9bab2ef8cfc331e02be288 Mon Sep 17 00:00:00 2001 From: Hadidreem17 Date: Wed, 15 Oct 2025 23:08:22 +0200 Subject: [PATCH 2/5] Remove accidentally added submodule 'Assignments' --- Assignments | 1 - 1 file changed, 1 deletion(-) delete mode 160000 Assignments diff --git a/Assignments b/Assignments deleted file mode 160000 index c50e3cebe..000000000 --- a/Assignments +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c50e3cebeac3c278b9994f72695cc11fc2f2f1dc From 570bc57efdc8ba575d3e6e282a1fcfbf09b6deb7 Mon Sep 17 00:00:00 2001 From: Hadidreem17 Date: Wed, 15 Oct 2025 23:21:45 +0200 Subject: [PATCH 3/5] Ignore local 'Assignments' folder (avoid embedded repo warning) --- .gitignore | 1 + .test-summary/TEST_SUMMARY.md | 2 ++ 3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js | 10 ++++++---- .../test-reports/ex3-rollAnAce.report.txt | 19 +++++++++++++++++++ .../test-reports/ex5-vscDebug.report.txt | 3 +++ 5 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 3-UsingAPIs/Week2/test-reports/ex3-rollAnAce.report.txt create mode 100644 3-UsingAPIs/Week2/test-reports/ex5-vscDebug.report.txt diff --git a/.gitignore b/.gitignore index c62043e2d..17bfeb34a 100644 --- a/.gitignore +++ b/.gitignore @@ -123,3 +123,4 @@ dist .disclaimer @assignment* .dist/ +Assignments/ diff --git a/.test-summary/TEST_SUMMARY.md b/.test-summary/TEST_SUMMARY.md index 0cc3438f4..d1ee64c7d 100644 --- a/.test-summary/TEST_SUMMARY.md +++ b/.test-summary/TEST_SUMMARY.md @@ -8,4 +8,6 @@ |-------------------|--------|--------|--------| | ex1-programmerFun | 5 | - | ✓ | | ex2-pokemonApp | 5 | - | ✓ | +| ex3-rollAnAce | 7 | - | ✓ | | ex4-diceRace | 7 | - | ✓ | +| ex5-vscDebug | - | - | ✓ | diff --git a/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js b/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js index 5753f4b08..774c2a6dc 100644 --- a/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js +++ b/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js @@ -13,12 +13,13 @@ import { rollDie } from '../../helpers/pokerDiceRoller.js'; /** @import {DieFace} from "../../helpers/pokerDiceRoller.js" */ /** - - + * Rolls a die until the desired value is rolled. + * @param {DieFace} desiredValue + * @returns {Promise} + */ export async function rollDieUntil(desiredValue) { - let value; while (true) { - value = await rollDie(); + const value = await rollDie(); if (value === desiredValue) { return value; } @@ -34,6 +35,7 @@ async function main() { } } +// ! Do not change or remove the code below if (process.env.NODE_ENV !== 'test') { main(); } 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..1d5bc187c --- /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 (3 ms) + ✅ 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 (54 ms) + ✅ should reject with an Error when a die rolls off the table (141 ms) + +Test Suites: 1 passed, 1 total +Tests: 7 passed, 7 total +Snapshots: 0 total +Time: 0.946 s, estimated 1 s +Ran all test suites matching /C:\\Users\\Rimha\\Assignments-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/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. From 2029a0581fa38dc3f9c4eda7e580d6fafb0b721f Mon Sep 17 00:00:00 2001 From: Hadidreem17 Date: Wed, 15 Oct 2025 23:28:07 +0200 Subject: [PATCH 4/5] Add ex6-browserDebug test report --- .test-summary/TEST_SUMMARY.md | 1 + 3-UsingAPIs/Week2/test-reports/ex6-browserDebug.report.txt | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 3-UsingAPIs/Week2/test-reports/ex6-browserDebug.report.txt diff --git a/.test-summary/TEST_SUMMARY.md b/.test-summary/TEST_SUMMARY.md index d1ee64c7d..a5f0d5725 100644 --- a/.test-summary/TEST_SUMMARY.md +++ b/.test-summary/TEST_SUMMARY.md @@ -11,3 +11,4 @@ | ex3-rollAnAce | 7 | - | ✓ | | ex4-diceRace | 7 | - | ✓ | | ex5-vscDebug | - | - | ✓ | +| ex6-browserDebug | - | - | ✓ | 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. From 8dd25d4a258ed2d96822d54cd65a7983d942165d Mon Sep 17 00:00:00 2001 From: Hadidreem17 Date: Tue, 21 Oct 2025 17:26:30 +0200 Subject: [PATCH 5/5] Fix week2 --- .test-summary/TEST_SUMMARY.md | 2 - .../assignment/ex1-programmerFun/index.js | 17 +-- .../Week2/assignment/ex2-pokemonApp/index.js | 133 ++++++++++++------ 3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js | 10 +- 3-UsingAPIs/Week2/assignment/ex4-diceRace.js | 4 +- .../test-reports/ex1-programmerFun.report.txt | 4 +- .../test-reports/ex2-pokemonApp.report.txt | 10 +- .../test-reports/ex3-rollAnAce.report.txt | 10 +- .../test-reports/ex4-diceRace.report.txt | 10 +- 9 files changed, 119 insertions(+), 81 deletions(-) diff --git a/.test-summary/TEST_SUMMARY.md b/.test-summary/TEST_SUMMARY.md index a5f0d5725..2fbbfa948 100644 --- a/.test-summary/TEST_SUMMARY.md +++ b/.test-summary/TEST_SUMMARY.md @@ -10,5 +10,3 @@ | 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 dedc436bc..41dc938af 100644 --- a/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js +++ b/3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js @@ -17,16 +17,12 @@ Full description at: https://github.com/HackYourFuture/Assignments/blob/main/3-U should result in a network (DNS) error. ------------------------------------------------------------------------------*/ function requestData(url) { - return fetch(url) - .then(response => { - if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); - } - return response.json(); - }) - .catch(error => { - throw new Error(`Network error: ${error.message}`); - }); + return fetch(url).then((response) => { + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + return response.json(); + }); } function renderImage(data) { @@ -64,4 +60,3 @@ async function main() { } 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 238adb9b1..54296bf32 100644 --- a/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js +++ b/3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js @@ -21,62 +21,105 @@ 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 createUI() { + const app = document.getElementById('app') || document.body; + + const title = document.createElement('h1'); + title.textContent = 'Pokémon App'; + + const statusEl = document.createElement('p'); + statusEl.id = 'status'; + statusEl.textContent = 'Click "Load Pokémons" to start.'; + + const loadBtn = document.createElement('button'); + loadBtn.id = 'load-btn'; + loadBtn.textContent = 'Load Pokémons'; + + const selectEl = document.createElement('select'); + selectEl.id = 'pokemon-select'; + selectEl.disabled = true; + const placeholder = document.createElement('option'); + placeholder.value = ''; + placeholder.textContent = '-- choose a Pokémon --'; + selectEl.appendChild(placeholder); + + const imgEl = document.createElement('img'); + imgEl.id = 'pokemon-image'; + imgEl.alt = 'Selected Pokémon'; + imgEl.style.maxWidth = '200px'; + imgEl.style.display = 'block'; + imgEl.style.marginTop = '12px'; + + app.append(title, statusEl, loadBtn, selectEl, imgEl); + return { loadBtn, selectEl, imgEl, statusEl }; +} + async function fetchData(url) { - try { - const response = await fetch(url); - if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); - } - const data = await response.json(); - return data; - } catch (error) { - console.error(error); + const response = await fetch(url); + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); } + return response.json(); +} + +function capitalize(s) { + return s ? s[0].toUpperCase() + s.slice(1) : s; } async function fetchAndPopulatePokemons(apiUrl, selectEl) { - try { - const data = await fetchData(apiUrl); - const pokemons = data.results; - - pokemons.forEach(pokemon => { - const option = document.createElement('option'); - option.textContent = pokemon.name; - option.value = pokemon.url; - selectEl.appendChild(option); - }); - } catch (error) { - console.error(error); - } + const data = await fetchData(apiUrl); + selectEl.innerHTML = ''; + const placeholder = document.createElement('option'); + placeholder.value = ''; + placeholder.textContent = '-- choose a Pokémon --'; + selectEl.appendChild(placeholder); + + data.results.forEach((p) => { + const opt = document.createElement('option'); + opt.value = p.url; + opt.textContent = capitalize(p.name); + selectEl.appendChild(opt); + }); + + selectEl.disabled = false; } async function fetchImage(detailsUrl, imgEl) { - try { - const data = await fetchData(detailsUrl); - imgEl.src = data.sprites.front_default; - imgEl.alt = data.name; - } catch (error) { - console.error(error); - } + const pokemon = await fetchData(detailsUrl); + const sprite = pokemon?.sprites?.front_default || ''; + imgEl.src = sprite; + imgEl.alt = capitalize(pokemon.name || 'Pokémon'); } async function main() { - const selectEl = document.querySelector('#pokemon-select'); - const imgEl = document.querySelector('#pokemon-image'); - const apiUrl = 'https://pokeapi.co/api/v2/pokemon?limit=150'; - - try { - await fetchAndPopulatePokemons(apiUrl, selectEl); - selectEl.addEventListener('change', async e => { - const detailsUrl = e.target.value; - if (detailsUrl) { - await fetchImage(detailsUrl, imgEl); - } - }); - } catch (error) { - console.error(error); - } + const API_URL = 'https://pokeapi.co/api/v2/pokemon?limit=150'; + const { loadBtn, selectEl, imgEl, statusEl } = createUI(); + + loadBtn.addEventListener('click', async () => { + loadBtn.disabled = true; + statusEl.textContent = 'Loading pokémons...'; + try { + await fetchAndPopulatePokemons(API_URL, selectEl); + statusEl.textContent = 'Choose a Pokémon from the list.'; + } catch (err) { + statusEl.textContent = `Error: ${err.message}`; + } finally { + loadBtn.disabled = false; + } + }); + + selectEl.addEventListener('change', async (e) => { + const url = e.target.value; + if (!url) return; + statusEl.textContent = 'Loading Pokémon details...'; + try { + await fetchImage(url, imgEl); + statusEl.textContent = 'Loaded!'; + } catch (err) { + statusEl.textContent = `Error: ${err.message}`; + } + }); } window.addEventListener('load', main); - diff --git a/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js b/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js index 774c2a6dc..ec27f5eb3 100644 --- a/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js +++ b/3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js @@ -18,12 +18,11 @@ import { rollDie } from '../../helpers/pokerDiceRoller.js'; * @returns {Promise} */ export async function rollDieUntil(desiredValue) { - while (true) { - const value = await rollDie(); - if (value === desiredValue) { - return value; - } + let value; + while (value !== desiredValue) { + value = await rollDie(); } + return value; } async function main() { @@ -39,4 +38,3 @@ async function main() { if (process.env.NODE_ENV !== 'test') { main(); } - diff --git a/3-UsingAPIs/Week2/assignment/ex4-diceRace.js b/3-UsingAPIs/Week2/assignment/ex4-diceRace.js index 198c2b3fc..6df9c3871 100644 --- a/3-UsingAPIs/Week2/assignment/ex4-diceRace.js +++ b/3-UsingAPIs/Week2/assignment/ex4-diceRace.js @@ -13,10 +13,9 @@ Full description at: https://github.com/HackYourFuture/Assignments/blob/main/3-U import { rollDie } from '../../helpers/pokerDiceRoller.js'; /** @import {DieFace} from "../../helpers/pokerDiceRoller.js" */ - export async function rollDice() { const dice = [1, 2, 3, 4, 5]; - const dicePromises = dice.map(() => rollDie()); + const dicePromises = dice.map((die) => rollDie(die)); const winner = await Promise.race(dicePromises); return winner; } @@ -39,4 +38,3 @@ Explanation: Some dice keep rolling because Promise.race() only stops for the first finished promise. The other promises keep running in the background. */ - diff --git a/3-UsingAPIs/Week2/test-reports/ex1-programmerFun.report.txt b/3-UsingAPIs/Week2/test-reports/ex1-programmerFun.report.txt index 86b5fb4a6..baf490ea8 100644 --- a/3-UsingAPIs/Week2/test-reports/ex1-programmerFun.report.txt +++ b/3-UsingAPIs/Week2/test-reports/ex1-programmerFun.report.txt @@ -2,7 +2,7 @@ PASS .dist/3-UsingAPIs/Week2/unit-tests/ex1-programmerFun.test.js api-wk2-ex1-programmerFun - ✅ HTML should be syntactically valid (130 ms) + ✅ HTML should be syntactically valid (134 ms) ✅ should have all TODO comments removed ✅ should use `fetch()` ✅ should use async/wait @@ -11,7 +11,7 @@ Test Suites: 1 passed, 1 total Tests: 5 passed, 5 total Snapshots: 0 total -Time: 3.652 s, estimated 13 s +Time: 4.131 s Ran all test suites matching /C:\\Users\\Rimha\\Assignments-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 index b9373c30b..e8de18a02 100644 --- a/3-UsingAPIs/Week2/test-reports/ex2-pokemonApp.report.txt +++ b/3-UsingAPIs/Week2/test-reports/ex2-pokemonApp.report.txt @@ -11,7 +11,13 @@ Test Suites: 1 passed, 1 total Tests: 5 passed, 5 total Snapshots: 0 total -Time: 3.583 s +Time: 3.635 s, estimated 4 s Ran all test suites matching /C:\\Users\\Rimha\\Assignments-Cohort54\\.dist\\3-UsingAPIs\\Week2\\unit-tests\\ex2-pokemonApp.test.js/i. No linting errors detected. -No spelling errors detected. + + +*** Spell Checker Report *** + +3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js:33:39 - Unknown word (Pokémons) +3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js:37:31 - Unknown word (Pokémons) +3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js:101:37 - Unknown word (pokémons) diff --git a/3-UsingAPIs/Week2/test-reports/ex3-rollAnAce.report.txt b/3-UsingAPIs/Week2/test-reports/ex3-rollAnAce.report.txt index 1d5bc187c..a5e33e0a3 100644 --- a/3-UsingAPIs/Week2/test-reports/ex3-rollAnAce.report.txt +++ b/3-UsingAPIs/Week2/test-reports/ex3-rollAnAce.report.txt @@ -3,17 +3,17 @@ 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 (3 ms) - ✅ should not include a recursive call + ✅ `rollDieUntil` should not contain unneeded console.log calls + ✅ should not include a recursive call (1 ms) ✅ should use async/wait ✅ should use try/catch - ✅ should resolve as soon as a die settles on an ACE (54 ms) - ✅ should reject with an Error when a die rolls off the table (141 ms) + ✅ 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 (102 ms) Test Suites: 1 passed, 1 total Tests: 7 passed, 7 total Snapshots: 0 total -Time: 0.946 s, estimated 1 s +Time: 0.899 s, estimated 1 s Ran all test suites matching /C:\\Users\\Rimha\\Assignments-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 index 2fc74b72c..4a5dfad7e 100644 --- a/3-UsingAPIs/Week2/test-reports/ex4-diceRace.report.txt +++ b/3-UsingAPIs/Week2/test-reports/ex4-diceRace.report.txt @@ -4,16 +4,16 @@ api-wk2-ex4-diceRace ✅ should exist and be executable (2 ms) ✅ should have all TODO comments removed (1 ms) - ✅ `rollDice` should not contain unneeded console.log calls - ✅ should use `dice.map()` (1 ms) + ✅ `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 (11 ms) - ✅ should reject with an Error as soon as a die rolls off the table (69 ms) + ✅ should resolve as soon as a die settles successfully (12 ms) + ✅ should reject with an Error as soon as a die rolls off the table (71 ms) Test Suites: 1 passed, 1 total Tests: 7 passed, 7 total Snapshots: 0 total -Time: 0.876 s +Time: 0.875 s, estimated 1 s Ran all test suites matching /C:\\Users\\Rimha\\Assignments-Cohort54\\.dist\\3-UsingAPIs\\Week2\\unit-tests\\ex4-diceRace.test.js/i. No linting errors detected. No spelling errors detected.