-
-
Notifications
You must be signed in to change notification settings - Fork 262
London | 25-ITP-September | Ammad Ur Rehman | Sprint 3 | 03 Complete Sprint 3 practice TDD coursework #815
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
base: main
Are you sure you want to change the base?
Changes from all commits
d110d21
7536db7
fb18946
aac72a4
4002e46
5394a9e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,25 @@ | ||
| function countChar(stringOfCharacters, findCharacter) { | ||
| return 5 | ||
| if (typeof stringOfCharacters !== "string") { | ||
| throw new TypeError( | ||
| "The argument for parameter stringOfCharacters is not a String type" | ||
| ); | ||
| } | ||
|
|
||
| if (typeof findCharacter !== "string") { | ||
| throw new TypeError( | ||
| "The argument for parameter findCharacter is not a String type" | ||
| ); | ||
| } | ||
|
|
||
| if (findCharacter.length !== 1) { | ||
| throw new Error( | ||
| "Parameter findCharacter is must contain a single character" | ||
| ); | ||
| } | ||
|
|
||
| return stringOfCharacters.split("").reduce((accumulator, character) => { | ||
| return accumulator + (character === findCharacter ? 1 : 0); | ||
| }, 0); | ||
| } | ||
|
|
||
| module.exports = countChar; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,3 +22,49 @@ 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 count no occurrences of z characters", () => { | ||
| const str = "aaaaa"; | ||
| const char = "z"; | ||
| const count = countChar(str, char); | ||
| expect(count).toEqual(0); | ||
| }); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @anosidium I think we can add more test cases to cover additional scenarios — such as how the function behaves with an empty string, a single occurrence, or when the character case differs (e.g., 'A' vs 'a'). It’s good practice to include these kinds of edge cases when writing tests to ensure the function handles all possible inputs robustly.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, I've added more test cases. |
||
|
|
||
| test("should return 0 for an empty string and a non-empty character", () => { | ||
| const str = ""; | ||
| const char = "z"; | ||
| const count = countChar(str, char); | ||
| expect(count).toEqual(0); | ||
| }); | ||
|
|
||
| test("should return 0 for an empty string and a whitespace character", () => { | ||
| const str = ""; | ||
| const char = " "; | ||
| const count = countChar(str, char); | ||
| expect(count).toEqual(0); | ||
| }); | ||
|
|
||
| test("should return 0 when the string contains the character in a different case", () => { | ||
| const str = "aBcDeF"; | ||
| const char = "A"; | ||
| const count = countChar(str, char); | ||
| expect(count).toEqual(0); | ||
| }); | ||
|
|
||
| test("throws error when the first argument is not a string", () => { | ||
| expect(() => countChar(1234, "1")).toThrow( | ||
| "The argument for parameter stringOfCharacters is not a String type" | ||
| ); | ||
| }); | ||
|
|
||
| test("throws error when the second argument is not a string", () => { | ||
| expect(() => countChar("1234", 1)).toThrow( | ||
| "The argument for parameter findCharacter is not a String type" | ||
| ); | ||
| }); | ||
|
|
||
| test("throws error when second argument is longer than one character", () => { | ||
| expect(() => countChar("1234", "12")).toThrow( | ||
| "Parameter findCharacter is must contain a single character" | ||
| ); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,28 @@ | ||
| function getOrdinalNumber(num) { | ||
anosidium marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return "1st"; | ||
| if (isNaN(num)) { | ||
| return ""; | ||
| } | ||
|
|
||
| const numberString = String(num); | ||
| const lastDigit = Number(numberString.slice(-1)); | ||
| const lastDigits = Number(numberString.slice(-2)); | ||
| let ordinal; | ||
|
|
||
| if (num === 0) { | ||
| ordinal = ""; | ||
| } else if ([11, 12, 13].includes(lastDigits)) { | ||
| ordinal = "th"; | ||
| } else if (lastDigit === 1) { | ||
| ordinal = "st"; | ||
| } else if (lastDigit === 2) { | ||
| ordinal = "nd"; | ||
| } else if (lastDigit === 3) { | ||
| ordinal = "rd"; | ||
| } else { | ||
| ordinal = "th"; | ||
| } | ||
|
|
||
| return `${num}${ordinal}`; | ||
| } | ||
|
|
||
| module.exports = getOrdinalNumber; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,62 @@ const getOrdinalNumber = require("./get-ordinal-number"); | |
| // When the number is 1, | ||
| // Then the function should return "1st" | ||
|
|
||
| test("should return '1st' for 1", () => { | ||
| expect(getOrdinalNumber(1)).toEqual("1st"); | ||
| test("should return an empty string for a non-numerical character", () => { | ||
| expect(getOrdinalNumber("@")).toEqual(""); | ||
| }); | ||
|
|
||
| test("should return '0' for 0", () => { | ||
| expect(getOrdinalNumber(0)).toEqual("0"); | ||
| }); | ||
|
|
||
| test("should return '11th' for 11", () => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice one!!
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops! |
||
| 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 '-11th' for -11", () => { | ||
anosidium marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| expect(getOrdinalNumber(-11)).toEqual("-11th"); | ||
| }); | ||
|
|
||
| test("should return `22nd` for 22", () => { | ||
| expect(getOrdinalNumber(22)).toEqual("22nd"); | ||
| }); | ||
|
|
||
| test("should return `123rd` for 123", () => { | ||
| expect(getOrdinalNumber(123)).toEqual("123rd"); | ||
| }); | ||
|
|
||
| test("should return '1234th' for 1234", () => { | ||
| expect(getOrdinalNumber(1234)).toEqual("1234th"); | ||
| }); | ||
|
|
||
| test("should return '12345th' for 12345", () => { | ||
| expect(getOrdinalNumber(12345)).toEqual("12345th"); | ||
| }); | ||
|
|
||
| test("should return '123456th' for 123456", () => { | ||
| expect(getOrdinalNumber(123456)).toEqual("123456th"); | ||
| }); | ||
|
|
||
| test("should return '1234567th' for 1234567", () => { | ||
| expect(getOrdinalNumber(1234567)).toEqual("1234567th"); | ||
| }); | ||
|
|
||
| test("should return '12345678th' for 12345678", () => { | ||
| expect(getOrdinalNumber(12345678)).toEqual("12345678th"); | ||
| }); | ||
|
|
||
| test("should return '123456789th' for 123456789", () => { | ||
| expect(getOrdinalNumber(123456789)).toEqual("123456789th"); | ||
| }); | ||
|
|
||
| test("should return '1234567890' for 1234567890th", () => { | ||
| expect(getOrdinalNumber(1234567890)).toEqual("1234567890th"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you know about using describe() blocks in Jest? It can help organize related tests and make your test output cleaner and easier to read. It’s a good practice to group similar tests like this — especially as your test suite grows.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I did not know about |
||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,15 @@ | ||
| function repeat() { | ||
| return "hellohellohello"; | ||
| function repeat(string, count) { | ||
anosidium marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use a different argument name other than
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestion! I named the parameter There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The function name
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestion! The function name There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could also help to add a short comment above the function describing what it does and the expected parameter types — this improves readability for anyone new to the code. |
||
| if (isNaN(count)) { | ||
| throw new Error("count is not a number"); | ||
| } else if (count < 0) { | ||
| throw new Error("negative numbers are not valid"); | ||
| } else if (count === 0) { | ||
| return ""; | ||
| } else if (count === 1) { | ||
| return string; | ||
| } else { | ||
| return string.repeat(count); | ||
| } | ||
| } | ||
|
|
||
| module.exports = repeat; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| function creditCardValidator(cardNumber) { | ||
anosidium marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Check that the card number contains numbers only | ||
| if (isNaN(cardNumber)) return false; | ||
|
|
||
| // Convert the card number to a string so we can check its digits easily | ||
| let cardNumberString = String(cardNumber); | ||
|
|
||
| // Check that the card number has exactly 16 digits | ||
| if (cardNumberString.length != 16) return false; | ||
|
|
||
| // Check that the last digit is even | ||
| if (cardNumberString[15] % 2 != 0) return false; | ||
|
|
||
| // Calculate the sum of all digits | ||
| const sum = cardNumberString | ||
| .split("") | ||
| .reduce((sum, digit) => (sum += Number(digit)), 0); | ||
|
|
||
| // If the sum of all digits is 16 or less, the card is invalid | ||
| if (sum <= 16) return false; | ||
|
|
||
| // Use Set to filter out duplicate digits | ||
| let uniqueDigits = new Set(cardNumberString); | ||
|
|
||
| // Make sure the card number isn’t made up of all the same digit | ||
| if (uniqueDigits.size < 2) return false; | ||
|
|
||
| // If all conditions pass, the card number is valid | ||
| return true; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,16 @@ | ||
| const previousPasswords = []; | ||
|
|
||
| function passwordValidator(password) { | ||
| return password.length < 5 ? false : true | ||
| } | ||
| if (previousPasswords.includes(password)) return false; | ||
| if (password.length < 5) return false; | ||
| if (!/[A-Z]/.test(password)) return false; | ||
anosidium marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (!/[a-z]/.test(password)) return false; | ||
| if (!/[0-9]/.test(password)) return false; | ||
| if (!/[!#$%.*&]/.test(password)) return false; | ||
|
|
||
| previousPasswords.push(password); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| module.exports = passwordValidator; | ||
| module.exports = passwordValidator; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anosidium ✅ Great job! Your countChar function correctly counts occurrences and passes all test scenarios.
Using reduce here is neat and expressive. For clarity or performance, you could also consider a for...of loop, but your current solution is clean and idiomatic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anosidium How should we handle cases where the first argument (stringOfCharacters) is an integer and the second (findCharacter) is a string — essentially when the parameters are of the wrong data types?
I believe adding a check for this would make the function more robust. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree and updated the
countChar()function.