Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CYF-ITP-South Africa | Rashaad Ebrahim | Module-Structuring-and-Testing-Data | Week 3 #225

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
0655e6d
implement section complete
Rashaad-Ebrahim Dec 11, 2024
35a010c
Installed Jest, package.json and package-lock.json added.
Rashaad-Ebrahim Dec 12, 2024
45701b5
Jest test implemented for get-angle-type.js, with get-angle-type.test.js
Rashaad-Ebrahim Dec 12, 2024
a9860cf
getCardValue function updated to chheck if input is valid string.
Rashaad-Ebrahim Dec 12, 2024
f227570
isProperFraction function updated and isProperFraction jest tests cre…
Rashaad-Ebrahim Dec 12, 2024
548c85e
isValidTriangle function updated and tests created.
Rashaad-Ebrahim Dec 12, 2024
4775eb1
rotateCharacter function updated and tests created.
Rashaad-Ebrahim Dec 12, 2024
3557a56
cardValidator function implemented and tests created.
Rashaad-Ebrahim Dec 12, 2024
7c8723e
countChar function implemented and tests created.
Rashaad-Ebrahim Dec 12, 2024
f7407c9
getOrdinalNumber function implemented and tests created.
Rashaad-Ebrahim Dec 13, 2024
0fb1ed7
isPrime function implemented and tests created.
Rashaad-Ebrahim Dec 13, 2024
c0c428c
validatePassword function created and tests created.
Rashaad-Ebrahim Dec 13, 2024
d4ba005
repeat function implemeted and tests created.
Rashaad-Ebrahim Dec 13, 2024
d3efba7
investigate>find exercise complete.
Rashaad-Ebrahim Dec 14, 2024
ad65cb9
console.logs removed from files after running tests.
Rashaad-Ebrahim Dec 14, 2024
bc8f1b9
Code updated a suggested on PR
Rashaad-Ebrahim Dec 16, 2024
fb6492b
minor changes from feedback from PR
Rashaad-Ebrahim Dec 16, 2024
698e98c
refactored code.
Rashaad-Ebrahim Dec 16, 2024
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
10 changes: 10 additions & 0 deletions Sprint-3/implement/get-angle-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,13 @@
// Identify Reflex Angles:
// When the angle is greater than 180 degrees and less than 360 degrees,
// Then the function should return "Reflex angle"

module.exports = function getAngleType(angle) {
if (angle < 90) return "Acute angle";
Rashaad-Ebrahim marked this conversation as resolved.
Show resolved Hide resolved
if (angle === 90) return "Right angle";
if (angle > 90 && angle < 180) return "Obtuse angle";
if (angle === 180) return "Straight angle";
if (angle > 180 && angle < 360) return "Reflex angle";
return "Not a valid input";
}
// module.exports = getAngleType;
21 changes: 21 additions & 0 deletions Sprint-3/implement/get-angle-type.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const getAngleType = require("./get-angle-type");

test('When the angle is less than 90 degrees, the function should return "Acute angle"', () => {
expect(getAngleType(69)).toBe("Acute angle");
});

test('When the angle is exactly 90 degrees, the function should return "Right angle"', () => {
expect(getAngleType(90)).toBe("Right angle");
});

test('When the angle is greater than 90 degrees and less than 180 degrees, the function should return "Obtuse angle"', () => {
expect(getAngleType(169)).toBe("Obtuse angle");
});

test('When the angle is exactly 180 degrees, the function should return "Straight angle"', () => {
expect(getAngleType(180)).toBe("Straight angle");
});

test('When the angle is greater than 180 degrees and less than 360 degrees, the function should return "Reflex angle"', () => {
Rashaad-Ebrahim marked this conversation as resolved.
Show resolved Hide resolved
expect(getAngleType(246)).toBe("Reflex angle");
});
40 changes: 40 additions & 0 deletions Sprint-3/implement/get-card-value.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,43 @@
// Given a card with an invalid rank (neither a number nor a recognized face card),
// When the function is called with such a card,
// Then it should throw an error indicating "Invalid card rank."

function getCardValue(card) {
if (typeof card !== "string") return "Input should be a sting.";
const cardValue = card
.toUpperCase()
.substring(0, card.indexOf(card.slice(-1)));
Rashaad-Ebrahim marked this conversation as resolved.
Show resolved Hide resolved
const faceCards = ["K", "Q", "J"];

/* If we wanted to exlude cards for not being a suite
const suites = ["♣", "♠", "♦", "♥"];
if (!suites.includes(card.slice(-1))) return "Invalid card rank.";
*/
if (Number(cardValue) && Number(cardValue) >= 2 && Number(cardValue) <= 10)
return Number(cardValue);
if (faceCards.includes(cardValue)) return 10;
if (cardValue === "A") return 11;

return "Invalid card rank.";

/* ### I'm not a fan of if/if else statements so I would have either used ternary operators or short circuiting.
return Number(cardValue)
? Number(cardValue)
: faceCards.includes(cardValue)
? 10
: cardValue === "A"
? 11
: "Invalid card rank.";

OR

return (
(Number(cardValue) && Number(cardValue)) ||
(faceCards.includes(cardValue) && 10) ||
(cardValue === "A" && 11) ||
"Invalid card rank."
);
*/
}

module.exports = getCardValue;
78 changes: 78 additions & 0 deletions Sprint-3/implement/get-card-value.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
const getCardValue = require("./get-card-value");

describe("getCardValue tests", () => {
describe("Acceptance criteria", () => {
test("Handle Number Cards (2-10)", () => {
expect(getCardValue("2♠")).toBe(2);
expect(getCardValue("3♣")).toBe(3);
expect(getCardValue("4♥")).toBe(4);
expect(getCardValue("5♦")).toBe(5);
expect(getCardValue("6♠")).toBe(6);
expect(getCardValue("7♣")).toBe(7);
expect(getCardValue("8♥")).toBe(8);
expect(getCardValue("9♦")).toBe(9);
expect(getCardValue("10♠")).toBe(10);
});

test("Handle Face Cards (J, Q, K)", () => {
expect(getCardValue("K♣")).toBe(10);
expect(getCardValue("Q♥")).toBe(10);
expect(getCardValue("J♦")).toBe(10);
});

test("Handle Ace (A)", () => {
expect(getCardValue("A♠")).toBe(11);
expect(getCardValue("A♣")).toBe(11);
expect(getCardValue("A♥")).toBe(11);
expect(getCardValue("A♦")).toBe(11);
});

test("Handle Invalid Cards", () => {
expect(getCardValue("w♣")).toBe("Invalid card rank.");
expect(getCardValue("W♦")).toBe("Invalid card rank.");
expect(getCardValue("0♠")).toBe("Invalid card rank.");
expect(getCardValue("14♥")).toBe("Invalid card rank.");
expect(getCardValue("?♣")).toBe("Invalid card rank.");
expect(getCardValue("♣")).toBe("Invalid card rank.");
expect(getCardValue(" ♦")).toBe("Invalid card rank.");
expect(getCardValue("card♣")).toBe("Invalid card rank.");
});
});

describe("Other tests", () => {
test("Handle lowercase", () => {
expect(getCardValue("a♠")).toBe(11);
expect(getCardValue("k♣")).toBe(10);
expect(getCardValue("q♥")).toBe(10);
expect(getCardValue("j♦")).toBe(10);
});

test("Handle expression as argument", () => {
expect(getCardValue("2♣ two of clubs".split(" ")[0])).toBe(2);
});
});

describe("Random data", () => {
test.each([
["6♣", 6],
["q♦", 10],
["10♠", 10],
["4♣", 4],
])("Valid values: The %s should be %i ", (input, expected) => {
expect(getCardValue(input)).toBe(expected);
});

test.each([
["/3/4♣", "Invalid card rank."],
["@@$$♦", "Invalid card rank."],
["00000♠", "Invalid card rank."],
["", "Invalid card rank."],
["[]{}♣", "Invalid card rank."],
["let♦", "Invalid card rank."],
["const♠", "Invalid card rank."],
["...♣", "Invalid card rank."],
])("Inalid values: The %s should be %s", (input, expected) => {
expect(getCardValue(input)).toBe(expected);
});
});
Rashaad-Ebrahim marked this conversation as resolved.
Show resolved Hide resolved
});
9 changes: 9 additions & 0 deletions Sprint-3/implement/is-proper-fraction.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,12 @@
// target output: false
// Explanation: The fraction 3/3 is not a proper fraction because the numerator is equal to the denominator. The function should return false.
// These acceptance criteria cover a range of scenarios to ensure that the isProperFraction function handles both proper and improper fractions correctly and handles potential errors such as a zero denominator.

function isProperFraction(numerator, denominator) {
if (denominator === 0) {
throw new Error("Denominator cannot be zero");
}
return Math.abs(numerator) < Math.abs(denominator);
}

module.exports = isProperFraction;
37 changes: 37 additions & 0 deletions Sprint-3/implement/is-proper-fraction.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const isProperFraction = require("./is-proper-fraction");

describe("isProperFraction Tests", () => {
test("Proper Fraction Check", () => {
expect(isProperFraction(2, 3)).toBe(true);
});

test("Improper Fraction Check", () => {
expect(isProperFraction(5, 2)).toBe(false);
});

test("Zero Denominator Check", () => {
expect(() => isProperFraction(3, 0)).toThrow("Denominator cannot be zero");
});

test("Negative Fraction Check", () => {
expect(isProperFraction(-4, 7)).toBe(true);
});

test("Equal Numerator and Denominator Check", () => {
expect(isProperFraction(3, 3)).toBe(false);
});

// Additional tests

test("Negative Denominator Check", () => {
expect(isProperFraction(3, -5)).toBe(true);
});

test("Negative Fraction Improper Check", () => {
expect(isProperFraction(-13, 5)).toBe(false);
});

test("Negative Denominator Improper Check", () => {
expect(isProperFraction(9, -6)).toBe(false);
});
});
6 changes: 6 additions & 0 deletions Sprint-3/implement/is-valid-triangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@
// Then it should return true because the input forms a valid triangle.

// This specification outlines the behavior of the isValidTriangle function for different input scenarios, ensuring it properly checks for invalid side lengths and whether they form a valid triangle according to the Triangle Inequality Theorem.

function isValidTriangle(a, b, c) {
return a + b > c && b + c > a && a + c > b;
}

module.exports = isValidTriangle;
15 changes: 15 additions & 0 deletions Sprint-3/implement/is-valid-triangle.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const isValidTriangle = require("./is-valid-triangle");

describe("isValidTriangle Tests", () => {
test("Invalid triangle", () => {
expect(isValidTriangle(6, 9, -1)).toBe(false);
expect(isValidTriangle(2, 4, 0)).toBe(false);
expect(isValidTriangle(-6, -9, -7)).toBe(false);
});

test("Valid triangle", () => {
expect(isValidTriangle(6, 9, 7)).toBe(true);
expect(isValidTriangle(3, 3, 3)).toBe(true);
expect(isValidTriangle(1200, 1800, 2700)).toBe(true);
});
});
29 changes: 29 additions & 0 deletions Sprint-3/implement/rotate-char.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,32 @@ console.log(rotateCharacter("7", 5)); // Output: "7" (unchanged, not a letter)
// And the function should return the rotated character as a string (e.g., 'z' rotated by 3 should become 'c', 'Z' rotated by 3 should become 'C').
console.log(rotateCharacter("z", 1)); // Output: "a" (preserves case, but wraps around)
console.log(rotateCharacter("Y", 2)); // Output: "A" (preserves case, but wraps around)

function rotateCharacter(char, shift) {
const lettersLowerCase = "abcdefghijklmnopqrstuvwxyz";
const lettersUpperCase = lettersLowerCase.toUpperCase();
if (lettersLowerCase.includes(char)) {
if (lettersLowerCase.indexOf(char) + shift < 25) {
return lettersLowerCase.charAt(lettersLowerCase.indexOf(char) + shift);
}
if (lettersLowerCase.indexOf(char) + shift > 25) {
return lettersLowerCase.charAt(
lettersLowerCase.indexOf(char) - 26 + shift
);
}
}

Rashaad-Ebrahim marked this conversation as resolved.
Show resolved Hide resolved
if (lettersUpperCase.includes(char)) {
if (lettersUpperCase.indexOf(char) + shift < 25) {
return lettersUpperCase.charAt(lettersUpperCase.indexOf(char) + shift);
}
if (lettersUpperCase.indexOf(char) + shift > 25) {
return lettersUpperCase.charAt(
lettersUpperCase.indexOf(char) - 26 + shift
);
}
}
return char;
}

module.exports = rotateCharacter;
23 changes: 23 additions & 0 deletions Sprint-3/implement/rotate-char.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const rotateCharacter = require("./rotate-char");

describe("rotateCharacter Tests", () => {
it("Rotate Lowercase Letters", () => {
expect(rotateCharacter("a", 3)).toBe("d");
expect(rotateCharacter("f", 1)).toBe("g");
});

it("Rotate Uppercase Letters", () => {
expect(rotateCharacter("A", 3)).toBe("D");
expect(rotateCharacter("F", 1)).toBe("G");
});

it("Leave Non-Letter Characters Unchanged", () => {
expect(rotateCharacter("7", 5)).toBe("7");
expect(rotateCharacter("?", 5)).toBe("?");
});

it("Shifting a Character with Wraparound", () => {
expect(rotateCharacter("z", 1)).toBe("a");
expect(rotateCharacter("Y", 2)).toBe("A");
});
});
26 changes: 26 additions & 0 deletions Sprint-3/revise/implement/card-validator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
function cardValidator(ccNumber) {
// Ensure the card number is treated as a string
const ccString = ccNumber.toString();

// Helper variables
const ccNumberArray = ccString.split("").map((dig) => Number(dig)); // Array of card number digits.
const digitsRegex = /^\d+$/; // Regex to check only numeric characters

// Validation checks
const isCorrectLength = ccString.length === 16; // Number must be 16 digits
const hasMultipleDigits = [...new Set(ccNumberArray)].length > 1; // At least two different digits
Rashaad-Ebrahim marked this conversation as resolved.
Show resolved Hide resolved
const hasValidChars = digitsRegex.test(ccString); // All characters are numeric
const endsWithEvenDigit = ccNumberArray[ccNumberArray.length - 1] % 2 === 0; // Last digit is even
const isSumGreaterThan16 = ccNumberArray.reduce((a, c) => a + c, 0) > 16; // Sum of digits greater than 16

// Return true if all conditions are met, false otherwise
return (
isCorrectLength &&
hasMultipleDigits &&
hasValidChars &&
endsWithEvenDigit &&
isSumGreaterThan16
);
}

module.exports = cardValidator;
69 changes: 69 additions & 0 deletions Sprint-3/revise/implement/card-validator.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const cardValidator = require("./card-validator");

describe("cardValidator Tests", () => {
describe("Valid Number Tests", () => {
it.each([
{
input: 9999777788880000,
expected: true,
description: "Number must be 16 digits",
},
{
input: 6666666666661666,
expected: true,
description: "All characters must be numbers",
},

{
input: "8899227766883304",
expected: true,
description: "At least two different digits",
},
{
input: "2265566441861652",
expected: true,
description: "Last digit is even",
},
{
input: "6264561614768652",
expected: true,
description: "Sum of digits greater than 16",
},
])("$description", ({ input, expected }) => {
expect(cardValidator(input)).toBe(expected);
});
});

describe("Invalid Number Tests", () => {
it.each([
{
input: 929673378853830,
expected: false,
description: "Number less than 16 digits",
},
{
input: "495276#896141684",
expected: false,
description: "Invalid characters",
},

{
input: 7777777777777777,
expected: false,
description: "Only one number used",
},
{
input: "2265566441861651",
expected: false,
description: "Last digit is odd",
},
{
input: "1111111111111110",
expected: false,
description: "Sum of digits less than 16",
},
])("$description", ({ input, expected }) => {
expect(cardValidator(input)).toBe(expected);
});
});
});
5 changes: 5 additions & 0 deletions Sprint-3/revise/implement/count.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function countChar(str, char) {
return str.split("").filter((letter) => letter === char).length;
}

module.exports = countChar;
Loading