Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,4 @@ dist
.disclaimer
@assignment*
.dist/
Assignments/
12 changes: 12 additions & 0 deletions .test-summary/TEST_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## 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 | - | ✓ |
46 changes: 32 additions & 14 deletions 3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,46 @@ 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();
});
}

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);
103 changes: 95 additions & 8 deletions 3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +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 fetchData(/* TODO parameter(s) go here */) {
// TODO complete this function

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) {
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;
}

function fetchAndPopulatePokemons(/* TODO parameter(s) go here */) {
// TODO complete this function
async function fetchAndPopulatePokemons(apiUrl, selectEl) {
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;
}

function fetchImage(/* TODO parameter(s) go here */) {
// TODO complete this function
async function fetchImage(detailsUrl, imgEl) {
const pokemon = await fetchData(detailsUrl);
const sprite = pokemon?.sprites?.front_default || '';
imgEl.src = sprite;
imgEl.alt = capitalize(pokemon.name || 'Pokémon');
}

function main() {
// TODO complete this function
async function main() {
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);
26 changes: 13 additions & 13 deletions 3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ import { rollDie } from '../../helpers/pokerDiceRoller.js';
* @param {DieFace} desiredValue
* @returns {Promise<DieFace>}
*/
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 value;
while (value !== desiredValue) {
value = await rollDie();
}
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
Expand Down
26 changes: 16 additions & 10 deletions 3-UsingAPIs/Week2/assignment/ex4-diceRace.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,28 @@ 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((die) => rollDie(die));
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.
*/
11 changes: 8 additions & 3 deletions 3-UsingAPIs/Week2/assignment/ex5-vscDebug.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}`);
Expand Down
22 changes: 18 additions & 4 deletions 3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand Down
17 changes: 17 additions & 0 deletions 3-UsingAPIs/Week2/test-reports/ex1-programmerFun.report.txt
Original file line number Diff line number Diff line change
@@ -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 (134 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: 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.
23 changes: 23 additions & 0 deletions 3-UsingAPIs/Week2/test-reports/ex2-pokemonApp.report.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
*** 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.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.


*** 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)
19 changes: 19 additions & 0 deletions 3-UsingAPIs/Week2/test-reports/ex3-rollAnAce.report.txt
Original file line number Diff line number Diff line change
@@ -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 (1 ms)
✅ 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 (102 ms)

Test Suites: 1 passed, 1 total
Tests: 7 passed, 7 total
Snapshots: 0 total
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.
Loading