Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
2c2b0f3
Add test for countChar when character occurs zero times
Iswanna Oct 23, 2025
6db0981
Implement countChar function to count occurrences of a character in a…
Iswanna Oct 23, 2025
7362e86
Add test cases using jest for function getOrdinalNumber
Iswanna Oct 23, 2025
1f72b49
Add the implementation for the function getOrdinalNumber
Iswanna Oct 23, 2025
ed1a393
Add test cases using jest for the function repeat
Iswanna Oct 23, 2025
93d9cb6
Add implementation for the function repeat
Iswanna Oct 23, 2025
9bc1c34
Add test to verify countChar returns 1 when the character appears once
Iswanna Oct 27, 2025
01cb978
Add unit test to verify countChar returns 0 when given an empty string
Iswanna Oct 27, 2025
86311c7
Add a test case for multi-character input in countChar
Iswanna Oct 27, 2025
bd7847f
Add test cases for countChar to check expected outputs in various sce…
Iswanna Oct 27, 2025
1c66099
Update countChar implementation to correctly count character occurrences
Iswanna Oct 27, 2025
03b238e
Fix indentation in count.js and count.test.js
Iswanna Oct 27, 2025
14306cc
Add test cases to ensure correct ordinal output for 12, and 13
Iswanna Oct 27, 2025
a6bbe86
Fix getOrdinalNumber to handle integers correctly and reject invalid …
Iswanna Oct 28, 2025
aaa3da4
Add integer, negative, zero, and invalid input test cases for getOrdi…
Iswanna Oct 28, 2025
4548cb5
Update repeat function to handle positive, zero, negative, non-intege…
Iswanna Oct 28, 2025
4027919
Add test cases for repeat function to cover edge cases and various in…
Iswanna Oct 28, 2025
2b82934
Refactor countChar function to return early for invalid inputs and re…
Iswanna Oct 29, 2025
4153632
Refactor getOrdinalNumber function to return early for invalid input …
Iswanna Oct 29, 2025
2957d4b
Fix inconsitent icode indentation
Iswanna Oct 30, 2025
95ba4bf
Refactor repeat function to return early for invalid input and remove…
Iswanna Oct 30, 2025
d0b6378
Update expected output for negative float to 'Invalid count: count sh…
Iswanna Oct 30, 2025
3243748
Update error message for numOfTimes validation to "Invalid numOfTimes…
Iswanna Oct 30, 2025
adb9421
Fix function to allow only string for valueToRepeat and positive inte…
Iswanna Oct 30, 2025
f6115be
Update test descriptions and expected output values in test cases
Iswanna Oct 30, 2025
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
20 changes: 19 additions & 1 deletion Sprint-3/2-practice-tdd/count.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
function countChar(stringOfCharacters, findCharacter) {
return 5
// Check both inputs are strings
if (
Copy link
Contributor

Choose a reason for hiding this comment

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

It's usually better to return early if inputs are invalid, it's called early return. Can you think of a way to implement this in your function?

typeof stringOfCharacters !== "string" ||
typeof findCharacter !== "string"
) {
return "Invalid input: input should be a string";
Copy link
Contributor

@jennethydyrova jennethydyrova Oct 30, 2025

Choose a reason for hiding this comment

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

It's okay to return error message like this as you are just at the beginning of learning js, but there is a better way of doing it. This is optional but can you think of how you can make use of the following https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw in the context of error handling in your functions?

Copy link
Author

Choose a reason for hiding this comment

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

Member

Hi @jennethydyrova.

I will read through the resource you have provided and update the code. Thank you.

Copy link
Contributor

Choose a reason for hiding this comment

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

You don’t need to act on optional comments right now, this one was optional, but feel free to if you’d like!

Copy link
Author

Choose a reason for hiding this comment

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

You don’t need to act on optional comments right now, this one was optional, but feel free to if you’d like!

Thank you for clarifying! I’ll keep the optional comments in mind and may try them out later to improve the code further.

}

// Convert both to lowercase for case-insensitive matching
const str = stringOfCharacters.toLowerCase();
const char = findCharacter.toLowerCase();

// Check that only one character is passed
if (char.length !== 1) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is optional but you can do this check before L10

return "invalid input: Input just one character";
}

// Return count (0 for empty strings works naturally)
return str.split(char).length - 1;
}

module.exports = countChar;
68 changes: 68 additions & 0 deletions Sprint-3/2-practice-tdd/count.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,71 @@ test("should count multiple occurrences of a character", () => {
// And a character char that does not exist within the case-sensitive str,
// When the function is called with these inputs,
// Then it should return 0, indicating that no occurrences of the char were found in the case-sensitive str.
test("should return 0 occurence of a character", () => {
Copy link
Contributor

@jennethydyrova jennethydyrova Oct 26, 2025

Choose a reason for hiding this comment

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

This is a good start but this is would not be considered as a good test suite as it covers just one behavior. Good test suite should cover different scenarios based on what type of arguments you pass to the function.

const str = "happy";
const char = "z";
const count = countChar(str, char);
expect(count).toEqual(0);
});

// Scenario: One occurrence
// Given an input string `str`,
// And a character `char` that occurs once within `str` (e.g., 'a' in 'boat'),
// When the function is called with these inputs,
// Then it should correctly return the count of `char` (e.g., 'a' appears once in 'boat').

test("should return 1 occurence of a character", () => {
const str = "boat";
const char = "a";
const count = countChar(str, char);
expect(count).toEqual(1);
});

test("should return 0 occurrence of character in an empty string", () => {
const str = "";
const char = "b";
const count = countChar(str, char);
expect(count).toEqual(0);
});

test("should throw an error when more than one string is passed as char", () => {
const str = "jump";
const char = "pp";
const count = countChar(str, char);
expect(count).toEqual("invalid input: Input just one character");
});

test("should count characters regardless of case (treat 'a' and 'A' as equal)", () => {
const str = "JUMP";
const char = "m";
const count = countChar(str, char);
expect(count).toEqual(1);
});

test("should return correct count of space characters", () => {
const str = "F r o NT";
const char = " ";
const count = countChar(str, char);
expect(count).toEqual(3);
});

test("should count numeric characters correctly in the string", () => {
const str = "2Languages6";
const char = "2";
const count = countChar(str, char);
expect(count).toEqual(1);
});

test("should correctly count characters in a very long string", () => {
const str = "b".repeat(500) + "abB";
const char = "b";
const count = countChar(str, char);
expect(count).toEqual(502);
});

test("should count numeric characters correctly in the string", () => {
const str = "2Languages6";
const char = 2;
const count = countChar(str, char);
expect(count).toEqual("Invalid input: input should be a string");
});
29 changes: 28 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,32 @@
function getOrdinalNumber(num) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Unfortunately, this function is not passing the acceptance criteria. Please try to pass different values to the function and see if it returns what you expect.

return "1st";
// Early return for invalid inputs
if (!Number.isInteger(num)) {
return "Invalid input: Input is an integer";
}

const absNum = Math.abs(num);
const lastTwo = absNum % 100;
const lastDigit = absNum % 10;

// Handle special cases: 11th, 12th, 13th
if (lastTwo === 11 || lastTwo === 12 || lastTwo === 13) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Optional again, can you think of ways to make this if condition simpler?

return `${num}th`;
}

// Handle regular suffixes
if (lastDigit === 1) {
return `${num}st`;
}

if (lastDigit === 2) {
return `${num}nd`;
}

if (lastDigit === 3) {
return `${num}rd`;
}
// Default suffix
return `${num}th`;
}

module.exports = getOrdinalNumber;
78 changes: 78 additions & 0 deletions Sprint-3/2-practice-tdd/get-ordinal-number.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,81 @@ const getOrdinalNumber = require("./get-ordinal-number");
test("should return '1st' for 1", () => {
expect(getOrdinalNumber(1)).toEqual("1st");
});

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

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

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

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

test("should return '11th' for 11", () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as a previous comment regarding very slim test suite. Try to think of more test cases.

expect(getOrdinalNumber(11)).toEqual("11th");
});

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

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

test("should return '21st' for 21", () => {
expect(getOrdinalNumber(21)).toEqual("21st");
});

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

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

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

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

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

test("should return '-111th' for -111", () => {
expect(getOrdinalNumber(-111)).toEqual("-111th");
});

test("should return 'Invalid input: Input is an integer' for 1.52", () => {
expect(getOrdinalNumber(1.52)).toEqual("Invalid input: Input is an integer");
});

test("should return 'Invalid input: Input is an integer' for null", () => {
expect(getOrdinalNumber(null)).toEqual("Invalid input: Input is an integer");
});

test("should return 'Invalid input: Input is an integer' for undefined", () => {
expect(getOrdinalNumber(undefined)).toEqual(
"Invalid input: Input is an integer"
);
});

test("should return 'Invalid input: Input is an integer' for 'a'", () => {
expect(getOrdinalNumber("a")).toEqual("Invalid input: Input is an integer");
});

test("should return 'Invalid input: Input is an integer' for {}", () => {
expect(getOrdinalNumber({})).toEqual("Invalid input: Input is an integer");
});
29 changes: 27 additions & 2 deletions Sprint-3/2-practice-tdd/repeat.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
function repeat() {
return "hellohellohello";
function repeat(valueToRepeat, numOfTimes) {
// Validate count
if (!Number.isInteger(numOfTimes)) {
return "Invalid count: count should be an integer";
Copy link
Contributor

Choose a reason for hiding this comment

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

You should ideally have your error message to mention the actual argument that is incorrect. Here you have numOfTimes but say count in the error message. This can be confusing when you try to debug your function.

Copy link
Author

Choose a reason for hiding this comment

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

I have fixed my code to reflect your correction. Thank you.

}
if (numOfTimes < 0) {
return "Negative number invalid";
}
Comment on lines 7 to 13
Copy link
Contributor

Choose a reason for hiding this comment

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

One more optional comment, you should try to keep your error messages consistent in style. If you say Invalid x: x must be an integer, then you should have Invalid x: x must be a positive integer. Here you might see that perhaps you can combine this if condition into something that would return Invalid x: x must be a positive integer.

if (numOfTimes === 0) {
return "";
}

// Convert arrays to empty string
if (Array.isArray(valueToRepeat)) {
valueToRepeat = "";
}

// Convert other types to string
const strValue = String(valueToRepeat);

// Repeat the string
let repeatedValue = "";
for (let i = 0; i < numOfTimes; i++) {
repeatedValue += strValue;
}

return repeatedValue;
}

module.exports = repeat;
85 changes: 85 additions & 0 deletions Sprint-3/2-practice-tdd/repeat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,98 @@ test("should repeat the string count times", () => {
// Given a target string str and a count equal to 1,
// When the repeat function is called with these inputs,
// Then it should return the original str without repetition, ensuring that a count of 1 results in no repetition.
test("should return the original input with no repetition", () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

These unit tests are good, great job on writing them! Now I would like you to think of more test cases, where the values passed to the function are not what you expected. What if you pass integer 3 as valueToRepeat or undefined as numOfTimes, etc.?

const str = "milk";
const count = 1;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual(str);
})

// case: Handle Count of 0:
// Given a target string str and a count equal to 0,
// When the repeat function is called with these inputs,
// Then it should return an empty string, ensuring that a count of 0 results in an empty output.
test("should return an empty string for zero count times", () => {
const str = "rice";
const count = 0;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("");
})

// case: Negative Count:
// Given a target string str and a negative integer count,
// When the repeat function is called with these inputs,
// Then it should throw an error or return an appropriate error message, as negative counts are not valid.
test("should return an error message", () => {
const str = "food";
const count = -2;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("Negative number invalid");
})

test("should return an empty string when empty string is expected count number of times", () => {
const str = "";
const count = 23;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("");
})

test("should repeat the number count times as a string", () => {
const str = 1;
const count = 3;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("111");
});

test("should repeat boolean count times as a string", () => {
const str = true;
const count = 2;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("truetrue");
});

test("should repeat null count times as a string", () => {
const str = null;
const count = 2;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("nullnull");
});

test("should repeat undefined count times as a string", () => {
const str = undefined;
const count = 2;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("undefinedundefined");
});

// case: array input
test("should repeat [] count times as a string", () => {
const str = [];
const count = 2;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("");
});

// case: Non-integer positive count
test("should return an error message for non-integer positive count", () => {
const str = "apple";
const count = 2.5;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("Invalid count: count should be an integer");
});

// case: Non-integer negative count
test("should return an error message for non-integer negative count", () => {
const str = "banana";
const count = -1.7;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("Invalid count: count should be an integer");
});

// case: Object input
test("should repeat an object count times as a string", () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, I am not sure if you want to repeat empty object like this. I don't see value in doing so. I think the requirement of this function is to repeat string n times. If what you pass is not a string, should it perhaps return an error as you did in other functions?

Copy link
Author

Choose a reason for hiding this comment

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

Hmm, I am not sure if you want to repeat empty object like this. I don't see value in doing so. I think the requirement of this function is to repeat string n times. If what you pass is not a string, should it perhaps return an error as you did in other functions?

Hi @jennethydyrova.

I am trying to fix my code. Please, I would like your opinion. Should I let the number input (e.g. 2) repeat or return an error message?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the function requirement is a bit vague, that also stems from an unclear function name (this is about the importance of a good and descriptive fn names!). I would say to keep it simpler, assume that only string should be accepted as an input to be repeated, the rest should throw an error.

Copy link
Author

Choose a reason for hiding this comment

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

I think the function requirement is a bit vague, that also stems from an unclear function name (this is about the importance of a good and descriptive fn names!). I would say to keep it simpler, assume that only string should be accepted as an input to be repeated, the rest should throw an error.

Thank you for your suggestion. I agree that the function name is a bit vague. It would have been clearer if it were something like repeatString instead of just repeat. I will update the function to only allow strings to be repeated and update the tests accordingly.

const str = {};
const count = 2;
const repeatedStr = repeat(str, count);
expect(repeatedStr).toEqual("[object Object][object Object]");
});
Loading