diff --git a/Sprint-3/1-implement-and-rewrite-tests - Copy/README.md b/Sprint-3/1-implement-and-rewrite-tests - Copy/README.md new file mode 100644 index 0000000000..4658c9423a --- /dev/null +++ b/Sprint-3/1-implement-and-rewrite-tests - Copy/README.md @@ -0,0 +1,47 @@ +# Implement solutions and rewrite tests with Jest + +Before writing any code, please read the [Testing Function Guide](testing-guide.md) to learn how +to choose test values that thoroughly test a function. + +## 1 Implement solutions + +In the `implement` directory you've got a number of functions you'll need to implement. +For each function, you also have a number of different cases you'll need to check for your function. + +Write your implementation and your tests to cover the cases the function should fulfil. + +Here is a recommended order: + +1. `1-get-angle-type.js` +2. `2-is-proper-fraction.js` +3. `3-get-card-value.js` + +## 2 Rewrite tests with Jest + +`console.log` is most often used as a debugging tool. We use to inspect the state of our program during runtime. + +We can use `console.assert` to write assertions: however, it is not very easy to use when writing large test suites. In the first section, Implement, we used a custom "helper function" to make our assertions more readable. + +Jest is a whole library of helper functions we can use to make our assertions more readable and easier to write. + +Your new task is to write the same tests as you wrote in the `implement` directory, but using Jest instead of `console.assert`. + +You shouldn't have to change the contents of `implement` to write these tests. + +There are files for your Jest tests in the `rewrite-tests-with-jest` directory. They will automatically use the functions you already implemented. + +You can run all the tests in this repo by running `npm test` in your terminal. However, VSCode has a built-in test runner that you can use to run the tests, and this should make it much easier to focus on building up your test cases one at a time. + +https://code.visualstudio.com/docs/editor/testing + +1. Go to rewrite-tests-with-jest/1-get-angle-type.test.js +2. Click the green play button to run the test. It's on the left of the test function in the gutter. +3. Read the output in the TEST_RESULTS tab at the bottom of the screen. +4. Explore all the tests in this repo by opening the TEST EXPLORER tab. The logo is a beaker. + +![VSCode Test Runner](../../run-this-test.png) + +![Test Results](../../test-results-output.png) + +> [!TIP] +> You can always run a single test file by running `npm test path/to/test-file.test.js`. diff --git a/Sprint-3/1-implement-and-rewrite-tests - Copy/implement/1-get-angle-type.js b/Sprint-3/1-implement-and-rewrite-tests - Copy/implement/1-get-angle-type.js new file mode 100644 index 0000000000..74daed60d3 --- /dev/null +++ b/Sprint-3/1-implement-and-rewrite-tests - Copy/implement/1-get-angle-type.js @@ -0,0 +1,78 @@ +// Implement a function getAngleType +// +// When given an angle in degrees, it should return a string indicating the type of angle: +// - "Acute angle" for angles greater than 0° and less than 90° +// - "Right angle" for exactly 90° +// - "Obtuse angle" for angles greater than 90° and less than 180° +// - "Straight angle" for exactly 180° +// - "Reflex angle" for angles greater than 180° and less than 360° +// - "Invalid angle" for angles outside the valid range. + +// Assumption: The parameter is a valid number. (You do not need to handle non-numeric inputs.) + +// Acceptance criteria: +// After you have implemented the function, write tests to cover all the cases, and +// execute the code to ensure all tests pass. + +function getAngleType(angle) { + // TODO: Implement this function +} + +// The line below allows us to load the getAngleType function into tests in other files. +// This will be useful in the "rewrite tests with jest" step. +module.exports = getAngleType; + +// This helper function is written to make our assertions easier to read. +// If the actual output matches the target output, the test will pass +function assertEquals(actualOutput, targetOutput) { + console.assert( + actualOutput === targetOutput, + `Expected ${actualOutput} to equal ${targetOutput}` + ); +} + +// TODO: Write tests to cover all cases, including boundary and invalid cases. +// Example: Identify Right Angles +const right = getAngleType(90); +assertEquals(right, "Right angle"); + +// + +function getAngleType(angle) { + if (angle > 0 && angle < 90) { + return "Acute angle"; + } else if (angle === 90) { + return "Right angle"; + } else if (angle > 90 && angle < 180) { + return "Obtuse angle"; + } else if (angle === 180) { + return "Straight angle"; + } else if (angle > 180 && angle < 360) { + return "Reflex angle"; + } else { + return "Invalid angle"; + } +} + +module.exports = getAngleType; + +function assertEquals(actualOutput, targetOutput) { + console.assert( + actualOutput === targetOutput, + `Expected ${actualOutput} to equal ${targetOutput}` + ); +} + +// Tests +assertEquals(getAngleType(45), "Acute angle"); +assertEquals(getAngleType(90), "Right angle"); +assertEquals(getAngleType(120), "Obtuse angle"); +assertEquals(getAngleType(180), "Straight angle"); +assertEquals(getAngleType(270), "Reflex angle"); + +assertEquals(getAngleType(0), "Invalid angle"); +assertEquals(getAngleType(-10), "Invalid angle"); +assertEquals(getAngleType(360), "Invalid angle"); +assertEquals(getAngleType(500), "Invalid angle"); + +console.log("All tests passed!"); diff --git a/Sprint-3/1-implement-and-rewrite-tests - Copy/implement/2-is-proper-fraction.js b/Sprint-3/1-implement-and-rewrite-tests - Copy/implement/2-is-proper-fraction.js new file mode 100644 index 0000000000..cf07ea0c00 --- /dev/null +++ b/Sprint-3/1-implement-and-rewrite-tests - Copy/implement/2-is-proper-fraction.js @@ -0,0 +1,78 @@ +// Implement a function isProperFraction, +// when given two numbers, a numerator and a denominator, it should return true if +// the given numbers form a proper fraction, and false otherwise. + +// Assumption: The parameters are valid numbers (not NaN or Infinity). + +// Note: If you are unfamiliar with proper fractions, please look up its mathematical definition. + +// Acceptance criteria: +// After you have implemented the function, write tests to cover all the cases, and +// execute the code to ensure all tests pass. + +function isProperFraction(numerator, denominator) { + // TODO: Implement this function +} + +// The line below allows us to load the isProperFraction function into tests in other files. +// This will be useful in the "rewrite tests with jest" step. +module.exports = isProperFraction; + +// Here's our helper again +function assertEquals(actualOutput, targetOutput) { + console.assert( + actualOutput === targetOutput, + `Expected ${actualOutput} to equal ${targetOutput}` + ); +} + +// TODO: Write tests to cover all cases. +// What combinations of numerators and denominators should you test? + +// Example: 1/2 is a proper fraction +assertEquals(isProperFraction(1, 2), true); + +// + +function isProperFraction(numerator, denominator) { + if (denominator === 0) { + return false; + } + + return Math.abs(numerator) < Math.abs(denominator); +} + +// Export for later testing +module.exports = isProperFraction; + +// Helper function +function assertEquals(actualOutput, targetOutput) { + console.assert( + actualOutput === targetOutput, + `Expected ${actualOutput} to equal ${targetOutput}` + ); +} + +// TESTS + +// Proper fractions +assertEquals(isProperFraction(1, 2), true); +assertEquals(isProperFraction(3, 4), true); + +// Not proper (equal) +assertEquals(isProperFraction(5, 5), false); + +// Not proper (numerator bigger) +assertEquals(isProperFraction(7, 4), false); + +// Zero numerator +assertEquals(isProperFraction(0, 5), true); + +// Invalid denominator +assertEquals(isProperFraction(1, 0), false); + +// Negative values +assertEquals(isProperFraction(-1, 3), true); +assertEquals(isProperFraction(-5, 2), false); + +console.log("✅ All tests passed"); diff --git a/Sprint-3/1-implement-and-rewrite-tests - Copy/implement/3-get-card-value.js b/Sprint-3/1-implement-and-rewrite-tests - Copy/implement/3-get-card-value.js new file mode 100644 index 0000000000..8243b87c52 --- /dev/null +++ b/Sprint-3/1-implement-and-rewrite-tests - Copy/implement/3-get-card-value.js @@ -0,0 +1,119 @@ +// This problem involves playing cards: https://en.wikipedia.org/wiki/Standard_52-card_deck + +// Implement a function getCardValue, when given a string representing a playing card, +// should return the numerical value of the card. + +// A valid card string will contain a rank followed by the suit. +// The rank can be one of the following strings: +// "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" +// The suit can be one of the following emojis: +// "♠", "♥", "♦", "♣" +// For example: "A♠", "2♥", "10♥", "J♣", "Q♦", "K♦". + +// When the card is an ace ("A"), the function should return 11. +// When the card is a face card ("J", "Q", "K"), the function should return 10. +// When the card is a number card ("2" to "10"), the function should return its numeric value. + +// When the card string is invalid (not following the above format), the function should +// throw an error. + +// Acceptance criteria: +// After you have implemented the function, write tests to cover all the cases, and +// execute the code to ensure all tests pass. + +function getCardValue(card) { + // TODO: Implement this function +} + +// The line below allows us to load the getCardValue function into tests in other files. +// This will be useful in the "rewrite tests with jest" step. +module.exports = getCardValue; + +// Helper functions to make our assertions easier to read. +function assertEquals(actualOutput, targetOutput) { + console.assert( + actualOutput === targetOutput, + `Expected ${actualOutput} to equal ${targetOutput}` + ); +} + +// TODO: Write tests to cover all outcomes, including throwing errors for invalid cards. +// Examples: +assertEquals(getCardValue("9♠"), 9); + +// Handling invalid cards +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 😢"); +} catch (e) { + console.log("Error thrown for invalid card 🎉"); +} + +// What other invalid card cases can you think of? + +function getCardValue(card) { + const cardPattern = /^(A|[2-9]|10|J|Q|K)[♠♥♦♣]$/; + + if (!cardPattern.test(card)) { + throw new Error("Invalid card"); + } + + const rank = card.slice(0, -1); + + if (rank === "A") { + return 11; + } + + if (["J", "Q", "K"].includes(rank)) { + return 10; + } + + return Number(rank); +} + +module.exports = getCardValue; + +// Helper +function assertEquals(actualOutput, targetOutput) { + console.assert( + actualOutput === targetOutput, + `Expected ${actualOutput} to equal ${targetOutput}` + ); +} + +// Tests +assertEquals(getCardValue("2♥"), 2); +assertEquals(getCardValue("9♠"), 9); +assertEquals(getCardValue("10♦"), 10); + +assertEquals(getCardValue("A♣"), 11); + +assertEquals(getCardValue("J♣"), 10); +assertEquals(getCardValue("Q♦"), 10); +assertEquals(getCardValue("K♥"), 10); + +// Invalid tests +try { + getCardValue("invalid"); + console.error("❌ Failed"); +} catch { + console.log("✅ Invalid text"); +} + +try { + getCardValue("1♠"); + console.error("❌ Failed"); +} catch { + console.log("✅ Invalid rank"); +} + +try { + getCardValue("AX"); + console.error("❌ Failed"); +} catch { + console.log("✅ Invalid suit"); +} + +console.log("🎉 Tests completed"); diff --git a/Sprint-3/1-implement-and-rewrite-tests - Copy/rewrite-tests-with-jest/1-get-angle-type.test.js b/Sprint-3/1-implement-and-rewrite-tests - Copy/rewrite-tests-with-jest/1-get-angle-type.test.js new file mode 100644 index 0000000000..3743b0f87c --- /dev/null +++ b/Sprint-3/1-implement-and-rewrite-tests - Copy/rewrite-tests-with-jest/1-get-angle-type.test.js @@ -0,0 +1,62 @@ +// This statement loads the getAngleType function you wrote in the implement directory. +// We will use the same function, but write tests for it using Jest in this file. +const getAngleType = require("../implement/1-get-angle-type"); + +// TODO: Write tests in Jest syntax to cover all cases/outcomes, +// including boundary and invalid cases. + +// Case 1: Acute angles +test(`should return "Acute angle" when (0 < angle < 90)`, () => { + // Test various acute angles, including boundary cases + expect(getAngleType(1)).toEqual("Acute angle"); + expect(getAngleType(45)).toEqual("Acute angle"); + expect(getAngleType(89)).toEqual("Acute angle"); +}); + +// Case 2: Right angle +// Case 3: Obtuse angles +// Case 4: Straight angle +// Case 5: Reflex angles +// Case 6: Invalid angles + +// This statement loads the getAngleType function you wrote in the implement directory. +const getAngleType = require("../implement/1-get-angle-type"); + +// Case 1: Acute angles +test(`should return "Acute angle" when (0 < angle < 90)`, () => { + expect(getAngleType(1)).toEqual("Acute angle"); + expect(getAngleType(45)).toEqual("Acute angle"); + expect(getAngleType(89)).toEqual("Acute angle"); +}); + +// Case 2: Right angle +test(`should return "Right angle" when angle is 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"); + expect(getAngleType(120)).toEqual("Obtuse angle"); + expect(getAngleType(179)).toEqual("Obtuse angle"); +}); + +// Case 4: Straight angle +test(`should return "Straight angle" when angle is 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"); + expect(getAngleType(270)).toEqual("Reflex angle"); + expect(getAngleType(359)).toEqual("Reflex angle"); +}); + +// Case 6: Invalid angles +test(`should return "Invalid angle" for invalid values`, () => { + expect(getAngleType(0)).toEqual("Invalid angle"); + expect(getAngleType(-1)).toEqual("Invalid angle"); + expect(getAngleType(360)).toEqual("Invalid angle"); + expect(getAngleType(500)).toEqual("Invalid angle"); +}); diff --git a/Sprint-3/1-implement-and-rewrite-tests - Copy/rewrite-tests-with-jest/2-is-proper-fraction.test.js b/Sprint-3/1-implement-and-rewrite-tests - Copy/rewrite-tests-with-jest/2-is-proper-fraction.test.js new file mode 100644 index 0000000000..85cbc09fb5 --- /dev/null +++ b/Sprint-3/1-implement-and-rewrite-tests - Copy/rewrite-tests-with-jest/2-is-proper-fraction.test.js @@ -0,0 +1,45 @@ +// This statement loads the isProperFraction function you wrote in the implement directory. +// We will use the same function, but write tests for it using Jest in this file. +const isProperFraction = require("../implement/2-is-proper-fraction"); + +// TODO: Write tests in Jest syntax to cover all combinations of positives, negatives, zeros, and other categories. + +// Special case: numerator is zero +test(`should return false when denominator is zero`, () => { + expect(isProperFraction(1, 0)).toEqual(false); +}); + +// + +// This statement loads the isProperFraction function +const isProperFraction = require("../implement/2-is-proper-fraction"); + +// Case 1: denominator is zero +test(`should return false when denominator is zero`, () => { + expect(isProperFraction(1, 0)).toEqual(false); +}); + +// Case 2: numerator is zero +test(`should return true when numerator is zero and denominator is non-zero`, () => { + expect(isProperFraction(0, 5)).toEqual(true); +}); + +// Case 3: positive proper fractions +test(`should return true for positive proper fractions`, () => { + expect(isProperFraction(1, 2)).toEqual(true); + expect(isProperFraction(3, 4)).toEqual(true); +}); + +// Case 4: positive improper fractions +test(`should return false when numerator is equal or greater`, () => { + expect(isProperFraction(5, 5)).toEqual(false); + expect(isProperFraction(7, 4)).toEqual(false); +}); + +// Case 5: negative fractions +test(`should correctly handle negative values`, () => { + expect(isProperFraction(-1, 3)).toEqual(true); + expect(isProperFraction(-5, 2)).toEqual(false); + expect(isProperFraction(1, -3)).toEqual(true); + expect(isProperFraction(-1, -2)).toEqual(true); +}); diff --git a/Sprint-3/1-implement-and-rewrite-tests - Copy/rewrite-tests-with-jest/3-get-card-value.test.js b/Sprint-3/1-implement-and-rewrite-tests - Copy/rewrite-tests-with-jest/3-get-card-value.test.js new file mode 100644 index 0000000000..f94aa5a144 --- /dev/null +++ b/Sprint-3/1-implement-and-rewrite-tests - Copy/rewrite-tests-with-jest/3-get-card-value.test.js @@ -0,0 +1,57 @@ +// This statement loads the getCardValue function you wrote in the implement directory. +// We will use the same function, but write tests for it using Jest in this file. +const getCardValue = require("../implement/3-get-card-value"); + +// TODO: Write tests in Jest syntax to cover all possible outcomes. + +// Case 1: Ace (A) +test(`Should return 11 when given an ace card`, () => { + expect(getCardValue("A♠")).toEqual(11); +}); + +// Suggestion: Group the remaining test data into these categories: +// Number Cards (2-10) +// Face Cards (J, Q, K) +// Invalid Cards + +// To learn how to test whether a function throws an error as expected in Jest, +// please refer to the Jest documentation: +// https://jestjs.io/docs/expect#tothrowerror + +// + +// This statement loads the getCardValue function +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); +}); + +// Case 2: Number Cards (2–10) +test(`Should return the numeric value for number cards`, () => { + expect(getCardValue("2♦")).toEqual(2); + expect(getCardValue("5♣")).toEqual(5); + expect(getCardValue("10♥")).toEqual(10); +}); + +// Case 3: Face Cards (J, Q, K) +test(`Should return 10 for face cards`, () => { + expect(getCardValue("J♠")).toEqual(10); + expect(getCardValue("Q♦")).toEqual(10); + expect(getCardValue("K♣")).toEqual(10); +}); + +// Case 4: Invalid Cards +test(`Should throw error for invalid cards`, () => { + expect(() => getCardValue("invalid")).toThrow(); + + expect(() => getCardValue("1♠")).toThrow(); + + expect(() => getCardValue("11♥")).toThrow(); + + expect(() => getCardValue("AX")).toThrow(); + + expect(() => getCardValue("")).toThrow(); +}); diff --git a/Sprint-3/1-implement-and-rewrite-tests - Copy/testing-guide.md b/Sprint-3/1-implement-and-rewrite-tests - Copy/testing-guide.md new file mode 100644 index 0000000000..917194e7a9 --- /dev/null +++ b/Sprint-3/1-implement-and-rewrite-tests - Copy/testing-guide.md @@ -0,0 +1,92 @@ +# A Beginner's Guide to Testing Functions + +## 1. What Is a Function? + +``` +Input ──▶ Function ──▶ Output +``` + +A function +- Takes **input** (via **arguments**) +- Does some work +- Produces **one output** (via a **return value**) + +Example: + +``` +sum(2, 3) → 5 +``` + +Important idea: the same input should produce the same output. + + +## 2. Testing Means Predicting + +Testing means: +> If I give this input, what output should I get? + + +## 3. Choosing Good Test Values + +### Step 1: Determining the space of possible inputs +Ask: +- What type of value is expected? +- What values make sense? + - If they are numbers: + - Are they integers or floating-point numbers? + - What is their range? + - If they are strings: + - What are their length and patterns? +- What values would not make sense? + +### Step 2: Choosing Good Test Values + +#### Normal Cases + +These confirm that the function works in normal use. + +- What does a typical, ordinary input look like? +- Are there multiple ordinary groups of inputs? e.g. for an age checking function, maybe there are "adults" and "children" as expected ordinary groups of inputs. + + +#### Boundary Cases + +Test values exactly at, just inside, and just outside defined ranges. +These values are where logic breaks most often. + +#### Consider All Outcomes + +Every outcome must be reached by at least one test. + +- How many different results can this function produce? +- Have I tested a value that leads to each one? + +#### Crossing the Edges and Invalid Values + +This tests how the function behaves when assumptions are violated. +- What happens when input is outside of the expected range? +- What happens when input is not of the expected type? +- What happens when input is not in the expected format? + +## 4. How to Test + +### 1. Using `console.assert()` + +```javascript + // Report a failure only when the first argument is false + console.assert( sum(4, 6) === 10, "Expected 4 + 6 to equal 10" ); +``` + +It is simpler than using `if-else` and requires no setup. + +### 2. Jest Testing Framework + +```javascript + test("Should correctly return the sum of two positive numbers", () => { + expect( sum(4, 6) ).toEqual(10); + ... // Can test multiple samples + }); + +``` + +Jest supports many useful functions for testing but requires additional setup. diff --git a/Sprint-3/1-implement-and-rewrite-tests/implement/1-get-angle-type.js b/Sprint-3/1-implement-and-rewrite-tests/implement/1-get-angle-type.js index 9e05a871e2..74daed60d3 100644 --- a/Sprint-3/1-implement-and-rewrite-tests/implement/1-get-angle-type.js +++ b/Sprint-3/1-implement-and-rewrite-tests/implement/1-get-angle-type.js @@ -35,3 +35,44 @@ function assertEquals(actualOutput, targetOutput) { // Example: Identify Right Angles const right = getAngleType(90); assertEquals(right, "Right angle"); + +// + +function getAngleType(angle) { + if (angle > 0 && angle < 90) { + return "Acute angle"; + } else if (angle === 90) { + return "Right angle"; + } else if (angle > 90 && angle < 180) { + return "Obtuse angle"; + } else if (angle === 180) { + return "Straight angle"; + } else if (angle > 180 && angle < 360) { + return "Reflex angle"; + } else { + return "Invalid angle"; + } +} + +module.exports = getAngleType; + +function assertEquals(actualOutput, targetOutput) { + console.assert( + actualOutput === targetOutput, + `Expected ${actualOutput} to equal ${targetOutput}` + ); +} + +// Tests +assertEquals(getAngleType(45), "Acute angle"); +assertEquals(getAngleType(90), "Right angle"); +assertEquals(getAngleType(120), "Obtuse angle"); +assertEquals(getAngleType(180), "Straight angle"); +assertEquals(getAngleType(270), "Reflex angle"); + +assertEquals(getAngleType(0), "Invalid angle"); +assertEquals(getAngleType(-10), "Invalid angle"); +assertEquals(getAngleType(360), "Invalid angle"); +assertEquals(getAngleType(500), "Invalid angle"); + +console.log("All tests passed!"); diff --git a/Sprint-3/1-implement-and-rewrite-tests/implement/2-is-proper-fraction.js b/Sprint-3/1-implement-and-rewrite-tests/implement/2-is-proper-fraction.js index 970cb9b641..cf07ea0c00 100644 --- a/Sprint-3/1-implement-and-rewrite-tests/implement/2-is-proper-fraction.js +++ b/Sprint-3/1-implement-and-rewrite-tests/implement/2-is-proper-fraction.js @@ -31,3 +31,48 @@ function assertEquals(actualOutput, targetOutput) { // Example: 1/2 is a proper fraction assertEquals(isProperFraction(1, 2), true); + +// + +function isProperFraction(numerator, denominator) { + if (denominator === 0) { + return false; + } + + return Math.abs(numerator) < Math.abs(denominator); +} + +// Export for later testing +module.exports = isProperFraction; + +// Helper function +function assertEquals(actualOutput, targetOutput) { + console.assert( + actualOutput === targetOutput, + `Expected ${actualOutput} to equal ${targetOutput}` + ); +} + +// TESTS + +// Proper fractions +assertEquals(isProperFraction(1, 2), true); +assertEquals(isProperFraction(3, 4), true); + +// Not proper (equal) +assertEquals(isProperFraction(5, 5), false); + +// Not proper (numerator bigger) +assertEquals(isProperFraction(7, 4), false); + +// Zero numerator +assertEquals(isProperFraction(0, 5), true); + +// Invalid denominator +assertEquals(isProperFraction(1, 0), false); + +// Negative values +assertEquals(isProperFraction(-1, 3), true); +assertEquals(isProperFraction(-5, 2), false); + +console.log("✅ All tests passed"); diff --git a/Sprint-3/1-implement-and-rewrite-tests/implement/3-get-card-value.js b/Sprint-3/1-implement-and-rewrite-tests/implement/3-get-card-value.js index ff5c532e1d..8243b87c52 100644 --- a/Sprint-3/1-implement-and-rewrite-tests/implement/3-get-card-value.js +++ b/Sprint-3/1-implement-and-rewrite-tests/implement/3-get-card-value.js @@ -52,3 +52,68 @@ try { } // What other invalid card cases can you think of? + +function getCardValue(card) { + const cardPattern = /^(A|[2-9]|10|J|Q|K)[♠♥♦♣]$/; + + if (!cardPattern.test(card)) { + throw new Error("Invalid card"); + } + + const rank = card.slice(0, -1); + + if (rank === "A") { + return 11; + } + + if (["J", "Q", "K"].includes(rank)) { + return 10; + } + + return Number(rank); +} + +module.exports = getCardValue; + +// Helper +function assertEquals(actualOutput, targetOutput) { + console.assert( + actualOutput === targetOutput, + `Expected ${actualOutput} to equal ${targetOutput}` + ); +} + +// Tests +assertEquals(getCardValue("2♥"), 2); +assertEquals(getCardValue("9♠"), 9); +assertEquals(getCardValue("10♦"), 10); + +assertEquals(getCardValue("A♣"), 11); + +assertEquals(getCardValue("J♣"), 10); +assertEquals(getCardValue("Q♦"), 10); +assertEquals(getCardValue("K♥"), 10); + +// Invalid tests +try { + getCardValue("invalid"); + console.error("❌ Failed"); +} catch { + console.log("✅ Invalid text"); +} + +try { + getCardValue("1♠"); + console.error("❌ Failed"); +} catch { + console.log("✅ Invalid rank"); +} + +try { + getCardValue("AX"); + console.error("❌ Failed"); +} catch { + console.log("✅ Invalid suit"); +} + +console.log("🎉 Tests completed"); diff --git a/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/1-get-angle-type.test.js b/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/1-get-angle-type.test.js index d777f348d3..3743b0f87c 100644 --- a/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/1-get-angle-type.test.js +++ b/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/1-get-angle-type.test.js @@ -18,3 +18,45 @@ test(`should return "Acute angle" when (0 < angle < 90)`, () => { // Case 4: Straight angle // Case 5: Reflex angles // Case 6: Invalid angles + +// This statement loads the getAngleType function you wrote in the implement directory. +const getAngleType = require("../implement/1-get-angle-type"); + +// Case 1: Acute angles +test(`should return "Acute angle" when (0 < angle < 90)`, () => { + expect(getAngleType(1)).toEqual("Acute angle"); + expect(getAngleType(45)).toEqual("Acute angle"); + expect(getAngleType(89)).toEqual("Acute angle"); +}); + +// Case 2: Right angle +test(`should return "Right angle" when angle is 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"); + expect(getAngleType(120)).toEqual("Obtuse angle"); + expect(getAngleType(179)).toEqual("Obtuse angle"); +}); + +// Case 4: Straight angle +test(`should return "Straight angle" when angle is 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"); + expect(getAngleType(270)).toEqual("Reflex angle"); + expect(getAngleType(359)).toEqual("Reflex angle"); +}); + +// Case 6: Invalid angles +test(`should return "Invalid angle" for invalid values`, () => { + expect(getAngleType(0)).toEqual("Invalid angle"); + expect(getAngleType(-1)).toEqual("Invalid angle"); + expect(getAngleType(360)).toEqual("Invalid angle"); + expect(getAngleType(500)).toEqual("Invalid angle"); +}); diff --git a/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/2-is-proper-fraction.test.js b/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/2-is-proper-fraction.test.js index 7f087b2ba1..85cbc09fb5 100644 --- a/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/2-is-proper-fraction.test.js +++ b/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/2-is-proper-fraction.test.js @@ -8,3 +8,38 @@ const isProperFraction = require("../implement/2-is-proper-fraction"); test(`should return false when denominator is zero`, () => { expect(isProperFraction(1, 0)).toEqual(false); }); + +// + +// This statement loads the isProperFraction function +const isProperFraction = require("../implement/2-is-proper-fraction"); + +// Case 1: denominator is zero +test(`should return false when denominator is zero`, () => { + expect(isProperFraction(1, 0)).toEqual(false); +}); + +// Case 2: numerator is zero +test(`should return true when numerator is zero and denominator is non-zero`, () => { + expect(isProperFraction(0, 5)).toEqual(true); +}); + +// Case 3: positive proper fractions +test(`should return true for positive proper fractions`, () => { + expect(isProperFraction(1, 2)).toEqual(true); + expect(isProperFraction(3, 4)).toEqual(true); +}); + +// Case 4: positive improper fractions +test(`should return false when numerator is equal or greater`, () => { + expect(isProperFraction(5, 5)).toEqual(false); + expect(isProperFraction(7, 4)).toEqual(false); +}); + +// Case 5: negative fractions +test(`should correctly handle negative values`, () => { + expect(isProperFraction(-1, 3)).toEqual(true); + expect(isProperFraction(-5, 2)).toEqual(false); + expect(isProperFraction(1, -3)).toEqual(true); + expect(isProperFraction(-1, -2)).toEqual(true); +}); diff --git a/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/3-get-card-value.test.js b/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/3-get-card-value.test.js index cf7f9dae2e..f94aa5a144 100644 --- a/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/3-get-card-value.test.js +++ b/Sprint-3/1-implement-and-rewrite-tests/rewrite-tests-with-jest/3-get-card-value.test.js @@ -18,3 +18,40 @@ test(`Should return 11 when given an ace card`, () => { // please refer to the Jest documentation: // https://jestjs.io/docs/expect#tothrowerror +// + +// This statement loads the getCardValue function +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); +}); + +// Case 2: Number Cards (2–10) +test(`Should return the numeric value for number cards`, () => { + expect(getCardValue("2♦")).toEqual(2); + expect(getCardValue("5♣")).toEqual(5); + expect(getCardValue("10♥")).toEqual(10); +}); + +// Case 3: Face Cards (J, Q, K) +test(`Should return 10 for face cards`, () => { + expect(getCardValue("J♠")).toEqual(10); + expect(getCardValue("Q♦")).toEqual(10); + expect(getCardValue("K♣")).toEqual(10); +}); + +// Case 4: Invalid Cards +test(`Should throw error for invalid cards`, () => { + expect(() => getCardValue("invalid")).toThrow(); + + expect(() => getCardValue("1♠")).toThrow(); + + expect(() => getCardValue("11♥")).toThrow(); + + expect(() => getCardValue("AX")).toThrow(); + + expect(() => getCardValue("")).toThrow(); +});