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
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@

function getAngleType(angle) {
// TODO: Implement this function
// Check invalid first - angles must be between 0 and 360 (exclusive)
if (angle <= 0 || angle >= 360) return "Invalid angle";
// Check exact values before ranges to avoid overlap
if (angle === 90) return "Right angle";
if (angle === 180) return "Straight angle";
// Now check ranges
if (angle < 90) return "Acute angle";
if (angle < 180) return "Obtuse angle";
return "Reflex angle"; // anything left must be between 180 and 360, which is reflex
}

// The line below allows us to load the getAngleType function into tests in other files.
Expand All @@ -33,5 +42,53 @@ function assertEquals(actualOutput, targetOutput) {

// TODO: Write tests to cover all cases, including boundary and invalid cases.
// Example: Identify Right Angles
// // Right angle: only one possible value
const right = getAngleType(90);
assertEquals(right, "Right angle");

// Acute angles: test a boundary (just above 0), a normal case, and a boundary (just below 90)
const acute1 = getAngleType(1);
assertEquals(acute1, "Acute angle"); // boundary: just above 0

const acute2 = getAngleType(45);
assertEquals(acute2, "Acute angle"); // normal acute angle

const acute3 = getAngleType(89);
assertEquals(acute3, "Acute angle"); // boundary: just below 90

// Obtuse angles: boundary just above 90, normal, boundary just below 180
const obtuse1 = getAngleType(91);
assertEquals(obtuse1, "Obtuse angle"); // boundary: just above 90

const obtuse2 = getAngleType(120);
assertEquals(obtuse2, "Obtuse angle"); // normal obtuse angle

const obtuse3 = getAngleType(179);
assertEquals(obtuse3, "Obtuse angle"); // boundary: just below 180

// Straight angle: only one possible value
const straight = getAngleType(180);
assertEquals(straight, "Straight angle");

// Reflex angles: boundary just above 180, normal, boundary just below 360
const reflex1 = getAngleType(181);
assertEquals(reflex1, "Reflex angle"); // boundary: just above 180

const reflex2 = getAngleType(270);
assertEquals(reflex2, "Reflex angle"); // normal reflex angle

const reflex3 = getAngleType(359);
assertEquals(reflex3, "Reflex angle"); // boundary: just below 360

// Invalid angles: exactly 0, exactly 360, negative, over 360
const invalid1 = getAngleType(0);
assertEquals(invalid1, "Invalid angle"); // boundary: exactly 0

const invalid2 = getAngleType(360);
assertEquals(invalid2, "Invalid angle"); // boundary: exactly 360

const invalid3 = getAngleType(-10);
assertEquals(invalid3, "Invalid angle"); // negative number

const invalid4 = getAngleType(400);
assertEquals(invalid4, "Invalid angle"); // over 360
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

function isProperFraction(numerator, denominator) {
// TODO: Implement this function
// a denominator of 0 is not a proper fraction - it is invalid. divison by 0 undefined.
if (denominator === 0) return false;
// Maths.abs handles negative numbers, -> e.g. -1/2 is a proper fraction, but 1/-2 is not.
return Math.abs(numerator) < Math.abs(denominator);
}

// The line below allows us to load the isProperFraction function into tests in other files.
Expand All @@ -31,3 +35,25 @@ function assertEquals(actualOutput, targetOutput) {

// Example: 1/2 is a proper fraction
assertEquals(isProperFraction(1, 2), true);

// TODO: Write tests to cover all cases.
// What combinations of numerators and denominators should you test?
// Using inline style as the result doesn't need to be stored,
// we only need to check if it equals the expected value

// Example: 1/2 is a proper fraction
assertEquals(isProperFraction(1, 2), true);

// Proper fractions: numerator smaller than denominator
assertEquals(isProperFraction(3, 4), true); // normal proper fraction
assertEquals(isProperFraction(-1, 2), true); // negative numerator - still proper
assertEquals(isProperFraction(0, 5), true); // zero numerator - 0/5 = 0, which is proper

// Improper fractions: numerator greater than or equal to denominator
assertEquals(isProperFraction(2, 1), false); // numerator bigger than denominator
assertEquals(isProperFraction(5, 3), false); // normal improper fraction
assertEquals(isProperFraction(4, 4), false); // boundary: equal - 4/4 = 1, a whole number not proper

// Invalid: zero denominator - division by zero is undefined
assertEquals(isProperFraction(1, 0), false);

Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,49 @@
// After you have implemented the function, write tests to cover all the cases, and
// execute the code to ensure all tests pass.

/**
* Returns the numerical value of a playing card.
*
* A standard deck has 4 suits: ♠ (spades), ♥ (hearts), ♦ (diamonds), ♣ (clubs)
* Each card is written as a rank followed by a suit symbol e.g. "A♠", "10♥", "K♦"
*
* @param {string} card - A string representing a playing card e.g. "A♠", "10♥", "K♦", "7♣"
* @returns {number} - The numerical value of the card:
* - Ace ("A") returns 11
* - Face cards ("J", "Q", "K") return 10
* - Number cards ("2" to "10") return their numeric value
* @throws {Error} - If the card string is not in a valid format e.g. "invalid" or "1♠"
*
* @example
* getCardValue("A♠") // returns 11
* getCardValue("10♥") // returns 10
* getCardValue("K♦") // returns 10
* getCardValue("7♣") // returns 7
*/
function getCardValue(card) {
// TODO: Implement this function
// NEW: The suit symbol (♠ ♥ ♦ ♣) always takes up 2 characters in JavaScript
// slice(0, -2) means "give me everything except the last 2 characters"
// so "A♠" becomes "A", "10♥" becomes "10", "K♦" becomes "K"
// MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice
const rank = card.slice(0, -1);

// ✨ NEW: Ace is always worth 11
if (rank === "A") return 11;

// ✨ NEW: Face cards - Jack, Queen and King are all worth 10
if (rank === "J" || rank === "Q" || rank === "K") return 10;

// ✨ NEW: Number() converts a string like "9" into the actual number 9
// so we can check if it falls in the valid range of 2 to 10
// MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number
const numValue = Number(rank);
if (numValue >= 2 && numValue <= 10) return numValue;

// ✨ NEW: If we reach this line, none of the above matched
// throw stops the function and sends an error back to whoever called it
// MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw
throw new Error(`Invalid card: ${card}`);
}

// The line below allows us to load the getCardValue function into tests in other files.
Expand All @@ -38,17 +79,52 @@ function assertEquals(actualOutput, targetOutput) {
}

// TODO: Write tests to cover all outcomes, including throwing errors for invalid cards.
// Examples:
assertEquals(getCardValue("9♠"), 9);

// Ace cards - always 11 regardless of suit
assertEquals(getCardValue("A♠"), 11);
assertEquals(getCardValue("A♥"), 11);

// Number cards - return their face value as a number
assertEquals(getCardValue("2♦"), 2); // boundary: lowest number card
assertEquals(getCardValue("9♣"), 9);
assertEquals(getCardValue("10♥"), 10); // boundary: highest number card

// Face cards - Jack, Queen and King all return 10
assertEquals(getCardValue("J♣"), 10);
assertEquals(getCardValue("Q♦"), 10);
assertEquals(getCardValue("K♠"), 10);

// Handling invalid cards
// try/catch lets us test that an error IS thrown
// try: runs the code. catch: catches the error if one is thrown
// MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
try {
getCardValue("invalid");

// This line will not be reached if an error is thrown as expected
console.error("Error was not thrown for invalid card 😢");
console.error("Error was not thrown for invalid card ");
} catch (e) {
console.log("Error thrown for invalid card 🎉");
console.log("Error thrown for invalid card ");
}

// What other invalid card cases can you think of?

try {
getCardValue("1♠"); // 1 is not a valid rank - valid ranks are 2 through A
console.error("Error was not thrown for rank 1 ");
} catch (e) {
console.log("Error thrown for rank 1 ");
}

try {
getCardValue("11♥"); // 11 is not a valid rank - valid ranks are 2 through A
console.error("Error was not thrown for rank 11 ");
} catch (e) {
console.log("Error thrown for rank 11 ");
}

try {
getCardValue("A"); // missing suit
console.error("Error was not thrown for missing suit ");
} catch (e) {
console.log("Error thrown for missing suit ");
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// We will use the same function, but write tests for it using Jest in this file.
const getAngleType = require("../implement/1-get-angle-type");

// Jest docs: https://jestjs.io/docs/getting-started
// freeCodeCamp intro to testing: https://www.freecodecamp.org/news/how-to-start-unit-testing-javascript

// TODO: Write tests in Jest syntax to cover all cases/outcomes,
// including boundary and invalid cases.

Expand All @@ -14,7 +17,33 @@ test(`should return "Acute angle" when (0 < angle < 90)`, () => {
});

// Case 2: Right angle
test(`should return "Right angle" when angle is exactly 90`, () => {
expect(getAngleType(90)).toEqual("Right angle");
});

// Case 3: Obtuse angles
test(`should return "Obtuse angle" when (90 < angle < 180)`, () => {
expect(getAngleType(91)).toEqual("Obtuse angle"); // boundary: just above 90
expect(getAngleType(120)).toEqual("Obtuse angle"); // normal obtuse angle
expect(getAngleType(179)).toEqual("Obtuse angle"); // boundary: just below 180
});

// Case 4: Straight angle
test(`should return "Straight angle" when angle is exactly 180`, () => {
expect(getAngleType(180)).toEqual("Straight angle");
});

// Case 5: Reflex angles
test(`should return "Reflex angle" when (180 < angle < 360)`, () => {
expect(getAngleType(181)).toEqual("Reflex angle"); // boundary: just above 180
expect(getAngleType(270)).toEqual("Reflex angle"); // normal reflex angle
expect(getAngleType(359)).toEqual("Reflex angle"); // boundary: just below 360
});

// Case 6: Invalid angles
test(`should return "Invalid angle" for angles outside valid range`, () => {
expect(getAngleType(0)).toEqual("Invalid angle"); // boundary: exactly 0
expect(getAngleType(360)).toEqual("Invalid angle"); // boundary: exactly 360
expect(getAngleType(-10)).toEqual("Invalid angle"); // negative number
expect(getAngleType(400)).toEqual("Invalid angle"); // over 360
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,22 @@ const isProperFraction = require("../implement/2-is-proper-fraction");
test(`should return false when denominator is zero`, () => {
expect(isProperFraction(1, 0)).toEqual(false);
});

// Proper fractions: numerator smaller than denominator
test("should return true for a proper fraction", () => {
expect(isProperFraction(1, 2)).toEqual(true); // basic proper fraction
expect(isProperFraction(3, 4)).toEqual(true);
expect(isProperFraction(-1, 2)).toEqual(true); // negative numerator still proper
expect(isProperFraction(0, 5)).toEqual(true); // 0/5 = 0, which is proper
});

// Improper fractions: numerator greater than denominator
test("should return false for an improper fraction", () => {
expect(isProperFraction(2, 1)).toEqual(false);
expect(isProperFraction(5, 3)).toEqual(false);
});

// Boundary: equal numerator and denominator - 4/4 = 1, a whole number not a fraction
test("should return false when numerator equals denominator", () => {
expect(isProperFraction(4, 4)).toEqual(false);
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const getCardValue = require("../implement/3-get-card-value");
// Case 1: Ace (A)
test(`Should return 11 when given an ace card`, () => {
expect(getCardValue("A♠")).toEqual(11);
expect(getCardValue("A♥")).toEqual(11);
});

// Suggestion: Group the remaining test data into these categories:
Expand All @@ -18,3 +19,25 @@ test(`Should return 11 when given an ace card`, () => {
// please refer to the Jest documentation:
// https://jestjs.io/docs/expect#tothrowerror

// Number cards -> return their numeric value (2-10)
test("should return the numeric value for number cards", () => {
expect(getCardValue("2♦")).toEqual(2); // boundary: lowest number card
expect(getCardValue("9♣")).toEqual(9);
expect(getCardValue("10♥")).toEqual(10); // boundary: highest number card
});

//Face cards -> Jack, Queen and King are all worth 10
test("should return 10 for face cards (J, Q, K)", () => {
expect(getCardValue("J♣")).toEqual(10);
expect(getCardValue("Q♦")).toEqual(10);
expect(getCardValue("K♠")).toEqual(10);
});

// Invalid cards -> function should throw an error
// We wrap the call in () => so Jest can catch the error without crashing the test
// MDN on arrow functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
test("should throw an error for invalid cards", () => {
expect(() => getCardValue("invalid")).toThrow();
expect(() => getCardValue("1♠")).toThrow(); // 1 is not a valid rank
expect(() => getCardValue("")).toThrow(); // empty string
});
Loading