Skip to content
Open
Show file tree
Hide file tree
Changes from 14 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
16 changes: 16 additions & 0 deletions Sprint-3/2-practice-tdd/count.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,19 @@ function countChar(stringOfCharacters, findCharacter) {
}

module.exports = countChar;

const countChar = require('../countChar');

describe('countChar()', () => {
test('always returns 5', () => {
expect(countChar('anything', 'a')).toBe(5);
});

test('still returns 5 with empty string', () => {
expect(countChar('', 'z')).toBe(5);
});

test('still returns 5 with special characters', () => {
expect(countChar('!!!', '!')).toBe(5);
});
});
41 changes: 41 additions & 0 deletions Sprint-3/2-practice-tdd/count.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
// implement a function countChar that counts the number of times a character occurs in a string
const countChar = require("./count");

function countChar(stringOfCharacters, findCharacter) {
let count = 0;
for (let char of stringOfCharacters) {
if (char === findCharacter) count++;
}
return count;
}

module.exports = countChar;

// Given a string str and a single character char to search for,
// When the countChar function is called with these inputs,
// Then it should:
Expand All @@ -16,6 +27,36 @@ test("should count multiple occurrences of a character", () => {
const count = countChar(str, char);
expect(count).toEqual(5);
});
test("should return 0 when the character is not found", () => {
const str = "hello";
const char = "z";
const count = countChar(str, char);
expect(count).toEqual(0);
});

// Scenario: Case Sensitivity
// It should be case-sensitive, meaning 'A' != 'a'.
test("should be case-sensitive when counting characters", () => {
const str = "Banana";
expect(countChar(str, "a")).toEqual(3);
expect(countChar(str, "A")).toEqual(0);
});

// Scenario: Empty String
// It should return 0 when the input string is empty.
test("should return 0 when the input string is empty", () => {
const str = "";
const char = "a";
const count = countChar(str, char);
expect(count).toEqual(0);
});

// Scenario: Special Characters
// It should correctly count spaces and punctuation.
test("should count special characters like spaces or punctuation", () => {
expect(countChar("a b a b", " ")).toEqual(2);
expect(countChar("wow!!!", "!")).toEqual(3);
});

// Scenario: No Occurrences
// Given the input string str,
Expand Down
58 changes: 57 additions & 1 deletion Sprint-3/2-practice-tdd/get-ordinal-number.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,61 @@

function getOrdinalNumber(num) {
return "1st";
const remainder10 = num % 10;
const remainder100 = num % 100;

if (remainder100 >= 11 && remainder100 <= 13) {
return `${num}th`;
}

switch (remainder10) {
case 1:
return `${num}st`;
case 2:
return `${num}nd`;
case 3:
return `${num}rd`;
default:
return `${num}th`;
}
}

module.exports = getOrdinalNumber;


const getOrdinalNumber = require("./getOrdinalNumber");

describe("getOrdinalNumber()", () => {
test("should return '1st' for 1", () => {
expect(getOrdinalNumber(1)).toBe("1st");
});

test("should return '2nd' for 2", () => {
expect(getOrdinalNumber(2)).toBe("2nd");
});

test("should return '3rd' for 3", () => {
expect(getOrdinalNumber(3)).toBe("3rd");
});

test("should return '4th' for 4", () => {
expect(getOrdinalNumber(4)).toBe("4th");
});

test("should return '11th', '12th', '13th' for special cases", () => {
expect(getOrdinalNumber(11)).toBe("11th");
expect(getOrdinalNumber(12)).toBe("12th");
expect(getOrdinalNumber(13)).toBe("13th");
});

test("should return correct suffixes for 21, 22, 23", () => {
expect(getOrdinalNumber(21)).toBe("21st");
expect(getOrdinalNumber(22)).toBe("22nd");
expect(getOrdinalNumber(23)).toBe("23rd");
});

test("should return '111th' for numbers ending with 11, 12, 13 even if larger", () => {
expect(getOrdinalNumber(111)).toBe("111th");
expect(getOrdinalNumber(112)).toBe("112th");
expect(getOrdinalNumber(113)).toBe("113th");
});
});
7 changes: 7 additions & 0 deletions Sprint-3/2-practice-tdd/get-ordinal-number.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
const getOrdinalNumber = require("./get-ordinal-number");

function getOrdinalNumber(num) {
return "1st";
}

module.exports = getOrdinalNumber;

// In this week's prep, we started implementing getOrdinalNumber

// continue testing and implementing getOrdinalNumber for additional cases
Expand Down
40 changes: 40 additions & 0 deletions Sprint-3/2-practice-tdd/repeat-str.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ const repeatStr = require("./repeat-str");
// Given a target string str and a positive integer count,
// When the repeatStr function is called with these inputs,
// Then it should:
function repeat(str, count) {
if (count < 0) {
throw new Error("Count must be a non-negative integer");
}
return str.repeat(count);
}

module.exports = repeat;

// case: repeat String:
// Given a target string str and a positive integer count,
Expand Down Expand Up @@ -30,3 +38,35 @@ test("should repeat the string count times", () => {
// Given a target string str and a negative integer count,
// When the repeatStr function is called with these inputs,
// Then it should throw an error or return an appropriate error message, as negative counts are not valid.
const repeat = require("./repeat");

// Case 1: Repeat string multiple times
test("should repeat the string count times", () => {
const str = "hello";
const count = 3;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("hellohellohello");
});

// Case 2: Handle count of 1
test("should return the original string when count is 1", () => {
const str = "world";
const count = 1;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("world");
});

// Case 3: Handle count of 0
test("should return an empty string when count is 0", () => {
const str = "test";
const count = 0;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("");
});

// Case 4: Negative count
test("should throw an error when count is negative", () => {
const str = "oops";
const count = -2;
expect(() => repeat(str, count)).toThrow("Count must be a non-negative integer");
});
11 changes: 11 additions & 0 deletions Sprint-3/2-practice-tdd/repeat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const repeat = require("./repeat");

function repeat() {
return "hellohellohello";
}

module.exports = repeat;

test("should repeat the given word three times", () => {
expect(repeat("hi", 3)).toBe("hihihi");
});
25 changes: 25 additions & 0 deletions Sprint-3/3-stretch/ validateCreditCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
function validateCreditCard(number) {
const numStr = String(number);

// Must be exactly 16 digits, only numbers
if (!/^\d{16}$/.test(numStr)) return false;

// Must contain at least two different digits
const uniqueDigits = new Set(numStr);
if (uniqueDigits.size < 2) return false;

// Last digit must be even
const lastDigit = Number(numStr[numStr.length - 1]);
if (lastDigit % 2 !== 0) return false;

// Sum must be greater than 16
const sum = numStr
.split("")
.map(Number)
.reduce((a, b) => a + b, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would the function still work if line 19 is changed to .reduce((a, b) => a + b);?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function will not work correctly in all cases if you remove the initial value.
You should keep .reduce((a, b) => a + b, 0) to ensure consistent, safe behavior.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was asking, will your function work differently if line 19 is changed from .reduce((a, b) => a + b, 0); to .reduce((a, b) => a + b);?

Can you find an example where your function would work differently?

Suggestion, look up how .reduce() work.

if (sum <= 16) return false;

return true;
}

module.exports = validateCreditCard;
59 changes: 59 additions & 0 deletions Sprint-3/3-stretch/card-validator.md.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Validates a credit card number based on specific rules:
* - Must be 16 digits
* - Must have at least two different digits
* - Final digit must be even
* - Sum of all digits must be greater than 16
*
* @param {string} cardNumber - The credit card number to validate
* @returns {boolean} - true if valid, false if invalid
*/
function validateCreditCard(cardNumber) {
// Rule 1: Check if length is exactly 16 digits and all are numbers
if (!/^\d{16}$/.test(cardNumber)) {
return false;
}

// Convert string to array of numbers
const digits = cardNumber.split('').map(Number);

// Rule 2: Check for at least two different digits
const uniqueDigits = new Set(digits);
if (uniqueDigits.size < 2) {
return false;
}

// Rule 3: Check if the final digit is even
if (digits[digits.length - 1] % 2 !== 0) {
return false;
}

// Rule 4: Check if sum of all digits is greater than 16
const sum = digits.reduce((acc, val) => acc + val, 0);
if (sum <= 16) {
return false;
}

// All rules passed
return true;
}

// Example usage:
console.log(validateCreditCard("9999777788880000")); // true
console.log(validateCreditCard("6666666666661666")); // true
console.log(validateCreditCard("a92332119c011112")); // false
console.log(validateCreditCard("4444444444444444")); // false
console.log(validateCreditCard("1111111111111110")); // false
console.log(validateCreditCard("6666666666666661")); // false

module.exports = validateCreditCard;

const validateCreditCard = require('./credit-card-validator');

test("valid credit card number", () => {
expect(validateCreditCard("9999777788880000")).toBe(true);
});

test("invalid credit card number (all same digits)", () => {
expect(validateCreditCard("4444444444444444")).toBe(false);
});
8 changes: 8 additions & 0 deletions Sprint-3/3-stretch/find.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ console.log(find("code your future", "z"));
// Pay particular attention to the following:

// a) How the index variable updates during the call to find
//The variable index starts at 0 and increases by 1 every time the loop runs (index++).
//It keeps track of the current position in the string.
// b) What is the if statement used to check
//The if statement checks whether the current character (str[index]) is equal to the one we’re searching for (char).
//If it is, we immediately return index.
// c) Why is index++ being used?
//It moves to the next character in the string during each loop iteration.
//Without it, the loop would never move forward — it would keep checking the same character forever (infinite loop 🔁
// d) What is the condition index < str.length used for?
//That’s the loop condition — it keeps the loop running as long as index is less than the length of the string.
//Once index equals str.length, it means we’ve checked every character, and the loop stops.
6 changes: 5 additions & 1 deletion Sprint-3/3-stretch/password-validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@ function passwordValidator(password) {
}


module.exports = passwordValidator;
module.exports = passwordValidator;

// password.length < 5 → rejects short passwords.

// Returns true only if the password passes all checks.
29 changes: 29 additions & 0 deletions Sprint-3/3-stretch/password-validator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,35 @@ To be valid, a password must:

You must breakdown this problem in order to solve it. Find one test case first and get that working
*/
const previousPasswords = [];//Create an array to store previous passwords

function isValidPassword(password) {
// Rule 1: At least 5 characters
if (password.length < 5) return false;

// Rule 2: At least one uppercase letter
if (!/[A-Z]/.test(password)) return false;

// Rule 3: At least one lowercase letter
if (!/[a-z]/.test(password)) return false;

// Rule 4: At least one number
if (!/[0-9]/.test(password)) return false;

// Rule 5: At least one special symbol ! # $ % . * &
if (!/[!#$%.*&]/.test(password)) return false;

// Rule 6: Must not be a previous password
if (previousPasswords.includes(password)) return false;

// If all checks pass, save password and return true
previousPasswords.push(password);
return true;
}

module.exports = isValidPassword;


const isValidPassword = require("./password-validator");
test("password has at least 5 characters", () => {
// Arrange
Expand Down
22 changes: 22 additions & 0 deletions Sprint-3/3-stretch/validateCreditCard.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const validateCreditCard = require("./validateCreditCard");

test("valid credit card numbers should return true", () => {
expect(validateCreditCard("9999777788880000")).toBe(true);
expect(validateCreditCard("6666666666661666")).toBe(true);
});

test("invalid cards with letters should return false", () => {
expect(validateCreditCard("a92332119c011112")).toBe(false);
});

test("invalid cards with all same digits should return false", () => {
expect(validateCreditCard("4444444444444444")).toBe(false);
});

test("invalid cards with sum less than 16 should return false", () => {
expect(validateCreditCard("1111111111111110")).toBe(false);
});

test("invalid cards with odd final digit should return false", () => {
expect(validateCreditCard("6666666666666661")).toBe(false);
});
Loading