Skip to content
Closed
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
47 changes: 47 additions & 0 deletions Sprint-3/1-implement-and-rewrite-tests - Copy/README.md
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -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!");
Original file line number Diff line number Diff line change
@@ -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");
Original file line number Diff line number Diff line change
@@ -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");
Original file line number Diff line number Diff line change
@@ -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");
});
Loading
Loading