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

London 11 | Pezhman-Azizi | Structuring-and-testing-data | week3 | sprint 3 #214

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
19 changes: 18 additions & 1 deletion Sprint-3/implement/get-angle-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

// Identify Acute Angles:
// When the angle is less than 90 degrees,
// Then the function should return "Acute angle"
// Then the function should return " angle"

// Identify Obtuse Angles:
// When the angle is greater than 90 degrees and less than 180 degrees,
Expand All @@ -25,3 +25,20 @@
// Identify Reflex Angles:
// When the angle is greater than 180 degrees and less than 360 degrees,
// Then the function should return "Reflex angle"

function getAngleType(angel){
if (angel === 90){
return "Right angle";
}else if (angel < 90){
return "Acute angle";
}else if(angel>90 && angel < 10){
return "Obtuse angle";
}else if(angel === 180){
return "Straight angle";
}else if(angel>180 && angel<360){
return "Reflex angle"
}else{
return "invalid angel";
}
}
console.log(getAngleType(180));
Copy link

Choose a reason for hiding this comment

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

Only one test case?

Without using Jest, you can prepare your test as
console.assert(getAngleType(180) === "Right angle", "Right angle");
so that if the function does not return the expected value, you will see the error message "Right angle".

Can you include more test cases to thoroughly test your function? They can help you detect bugs in your code.

19 changes: 18 additions & 1 deletion Sprint-3/implement/get-card-value.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

// Acceptance criteria:

// Given a card string in the format "A♠" (representing a card in blackjack - the last character will always be an emoji for a suit, and all characters before will be a number 2-10, or one letter of J, Q, K, A),
// Given a card string in the format "A♠" (representing a card in blackjack - the last character
// will always be an emoji for a suit, and all characters before will be a number 2-10, or one letter of J, Q, K, A),
// When the function getCardValue is called with this card string as input,
// Then it should return the numerical card value

Expand All @@ -29,3 +30,19 @@
// 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){

const cardValue = card.slice(0, -1); // // Extracts the value of a card by slicing.
// Starts at index 0 (the first character) and excludes the last character (index -1).
const numericValue = Number(cardValue);

if ( numericValue >= 2 && numericValue <= 10){ //insures that the numeric value is valid. For example 13♠ should return "Invalid card rank."
return `your score is: ${numericValue}`;
}else if(["J", "Q", "K"].includes(cardValue)){ //makes sure that the card value includes one of the letters of K, J or Q.
return `your score is: ${10}`;
}else if (cardValue === "A"){
return `your score is: ${11}`;
}else
return `Invalid card rank.`
}
console.log(getCardValue("K♠"));
Copy link

Choose a reason for hiding this comment

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

What do you expect from the following function calls?
Does your function returns the value you expected?

getCardValue("0Q♠");
getCardValue("010♠");
getCardValue("02♠");
getCardValue("0x02♠");
getCardValue("2.1♠")

27 changes: 27 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,30 @@
// 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){
numerator = Math.abs(numerator);
denominator = Math.abs(denominator);

if(denominator === 0){
throw new Error("Denominator cannot be zero");
}else if(numerator === denominator){
Copy link

Choose a reason for hiding this comment

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

This test, if (numerator === denominator), is optional. Can you figure out why?

return false;
}else if(numerator < denominator){
return true;
}else{
return false;
}
}
console.log(isProperFraction(4, 0));


console.assert(isProperFraction(2, 3) === true, "2/3 should be a proper fraction");
Copy link

Choose a reason for hiding this comment

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

Could also test negative values in numerator and/or denominator (for cases when |numerator| < |denominator|).

console.assert(isProperFraction(5, 2) === false, "5/2 should return an improper fraction");
console.assert(isProperFraction(-4, 7) === true, "-7/2 should return a proper fraction");
try {
isProperFraction(4, 0); // Call the function with invalid input
console.assert(false, "4/0 should throw an error"); // Fail the test if no error is thrown
} catch (e) {
console.assert(e.message === "Denominator cannot be zero", "Error message should be 'Denominator cannot be zero'");
}
23 changes: 20 additions & 3 deletions Sprint-3/implement/is-valid-triangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@
// It's also true that b + c > a
// It's also true that a + c > b

// In our function isValidTriangle which takes as parameters the lengths of three sides, we need to invalidate any triangle where the sum of any two sides is less than or equal to the length of the third side.
// In our function isValidTriangle which takes as parameters the lengths of three sides,
// we need to invalidate any triangle where the sum of any two sides is less than or equal to the length of the third side.
// and we need to validate any triangle where the sum of any two sides is greater than the length of the third side.

// Acceptance criteria:

// scenario: invalid triangle
// Given the side lengths a, b, and c,
// When the sum of any two side lengths is less than or equal to the length of the third side (i.e., a + b <= c, a + c <= b, b + c <= a),
// Then it should return false because these conditions violate the Triangle Inequality, which states that the sum of the lengths of any two sides of a triangle must be greater than the length of the third side.
// Then it should return false because these conditions violate the Triangle Inequality,
// which states that the sum of the lengths of any two sides of a triangle must be greater than the length of the third side.

// scenario: invalid triangle
// Check for Valid Input:
Expand All @@ -32,4 +34,19 @@
// When the function is called with these values as input,
// 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.
// 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){
// Checks if the sides are positive
if (a <= 0 || b <= 0 || c <= 0){
Copy link

Choose a reason for hiding this comment

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

Is it necessary to include the if-statement at lines 42-44?
Can you find any values for a, b, and c, such that the function will fail after you removed the if-statement at lines 42-44?
If you cannot find such a, b, and c, that means you probably do not need that if-statement.

I will not go into details why in some programming languages (but not JavaScript) we need also to check if a, b, c are positives.

The main point I would like to make is, you should fully understand what you wrote in your code. An interviewer may ask you questions like what I am asking here, and it would reflect poorly on you if you cannot explain your code.

return false;
}
// Checks to see the sum of two sides is greater than the third one
if (a+b > c && b+c > a && a+c > b){
return true;
}
// Any other cases is false
return false;
}
console.log(isValidTriangle(1,2,3));
60 changes: 50 additions & 10 deletions Sprint-3/implement/rotate-char.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,69 @@
// Scenario: Rotate Lowercase Letters:
// Given a lowercase letter character and a positive integer shift,
// When the function is called with these inputs,
// Then it should rotate the lowercase letter by shift positions within the lowercase alphabet, wrapping around if necessary, and return the rotated lowercase letter as a string.
console.log(rotateCharacter("a", 3)); // Output: "d"
console.log(rotateCharacter("f", 1)); // Output: "g"
// Then it should rotate the lowercase letter by shift positions within the lowercase alphabet, wrapping around if necessary,
// and return the rotated lowercase letter as a string.
// console.log(rotateCharacter("a", 3)); // Output: "d"
// console.log(rotateCharacter("f", 1)); // Output: "g"

// Scenario: Rotate Uppercase Letters:
// Given an uppercase letter character and a positive integer shift,
// When the function is called with these inputs,
// Then it should rotate the uppercase letter by shift positions within the uppercase alphabet, wrapping around if necessary, and return the rotated uppercase letter as a string.
console.log(rotateCharacter("A", 3)); // Output: "D"
console.log(rotateCharacter("F", 1)); // Output: "G"
// Then it should rotate the uppercase letter by shift positions within the uppercase alphabet,
// wrapping around if necessary, and return the rotated uppercase letter as a string.
// console.log(rotateCharacter("A", 3)); // Output: "D"
// console.log(rotateCharacter("F", 1)); // Output: "G"

// Scenario: Leave Non-Letter Characters Unchanged:
// Given a character that is not a letter (neither uppercase nor lowercase) and any positive or negative shift value,
// When the function is called with these inputs,
// Then it should return the character unchanged.
// This specification outlines the behavior of the rotateCharacter function for different input scenarios, including valid and invalid characters, and defines the expected output or action for each case.
console.log(rotateCharacter("7", 5)); // Output: "7" (unchanged, not a letter)
// This specification outlines the behavior of the rotateCharacter function for different input scenarios,
// including valid and invalid characters, and defines the expected output or action for each case.
// console.log(rotateCharacter("7", 5)); // Output: "7" (unchanged, not a letter)

// Scenario: Shifting a Character with Wraparound
// Given a character char within the lowercase alphabet range (e.g., 'z') or the uppercase alphabet range (e.g., 'Z'),
// And a positive integer shift that causes the character to wrap around the alphabet when rotated (e.g., a shift of 3 for 'z' or 'Z'),
// When the rotateCharacter function is called with char and shift as inputs,
// Then it should correctly rotate the character by shift positions within the alphabet while handling the wraparound,
// 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)
// console.log(rotateCharacter("z", 1)); // Output: "a" (preserves case, but wraps around)
// console.log(rotateCharacter("Y", 2)); // Output: "A" (preserves case, but wraps around)





// ------------------------------------------------------------ MY APPROACH------------------------------------------------------------------------------------------
// This approach works with ASCII (American Standard Code for Information Interchange) which assigns a unique numeric code for characters, including
// letters, digits and symbols. In this case we are dealing with letters only.
// Lower case letters range from 97 to 122 and uppercase letters range from 65 to 90.

function rotateCharacter(letter, shift){

const asciiValue = letter.charCodeAt(0); // Gets the ASCII value for each alphabetic letter.

shift = shift % 26; // normalizing shift for large and negative values.

if(asciiValue >= 65 && asciiValue <= 90){ //ASCII code for uppercase
let rotatedAscii = asciiValue + shift;
if(rotatedAscii >= 91){
rotatedAscii -= 26; // Applies the wraparound for upper case letters.
}else if(asciiValue < 65){
rotatedAscii += 26; // Sorts out the negative wraparound
}
}else if (asciiValue >= 97 && asciiValue <= 122){ //ASCII code for lowercase
let rotatedAscii = asciiValue + shift;
if(rotatedAscii>=123){
rotatedAscii -= 26; // Applies the wraparound for lower case letters.
}else if(rotatedAscii < 97){
rotatedAscii += 26; // Sorts out the negative wraparound
}
return String.fromCharCode(rotatedAscii);
}else{
return `Not a valid character`;
Copy link

Choose a reason for hiding this comment

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

The spec says // Scenario: Leave Non-Letter Characters Unchanged:

}
}

console.log(rotateCharacter("z", -1));
30 changes: 30 additions & 0 deletions Sprint-3/revise/implement/count.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// function countChar(str, char){
// let count = 0;
// str.split("").forEach(element => {
// if (element === char){
// count+=1;}
// });
// if (count > 0){
// return `${char} appears ${count} times in ${str}`;
// }else{
// return `no occurrences of the "${char}" were found in the "${str}"`;
// }
// }
// // exports.countChar = {countChar};
// module.exports = { countChar };
function countChar(str, char) {
let count = 0;
str.split("").forEach(element => {
if (element === char) {
count += 1;
}
});

Copy link

Choose a reason for hiding this comment

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

Maybe the spec wasn't clear enough. Usually a function that "count something" would simply return an integer.
I am afraid you may have overdone.

if (count > 0) {
return `${char} appears ${count} times in ${str}`;
} else {
return `no occurrences of the "${char}" were found in the "${str}"`;
}
}

module.exports = { countChar };
30 changes: 30 additions & 0 deletions Sprint-3/revise/implement/count.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,33 @@
// 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.


const { countChar } = require('./count'); // Import the function from count.js

describe('countChar', () => {
test('returns correct count when the character exists in the string', () => {
expect(countChar('hello', 'l')).toBe('l appears 2 times in hello');
});

test('returns correct count when the character appears once', () => {
expect(countChar('world', 'w')).toBe('w appears 1 times in world');
});

test('returns correct message when the character does not exist in the string', () => {
expect(countChar('hello', 'z')).toBe('no occurrences of the "z" were found in the "hello"');
});

test('handles an empty string input', () => {
expect(countChar('', 'a')).toBe('no occurrences of the "a" were found in the ""');
});

test('is case-sensitive and counts only exact matches', () => {
expect(countChar('Hello', 'h')).toBe('no occurrences of the "h" were found in the "Hello"');
});

test('works correctly when the character is a space', () => {
expect(countChar('hello world', ' ')).toBe(' appears 1 times in hello world');
});
});

56 changes: 56 additions & 0 deletions Sprint-3/revise/implement/get-ordinal-number.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,59 @@

// continue testing and implementing getOrdinalNumber for additional cases
// Write your tests using Jest - remember to run your tests often for continual feedback

const getOrdinalNumber = require('./getOrdinalNumber'); // Import the function

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

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

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

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

test('returns "11th" for input 11', () => {
expect(getOrdinalNumber(11)).toBe('11th');
});

test('returns "12th" for input 12', () => {
expect(getOrdinalNumber(12)).toBe('12th');
});

test('returns "13th" for input 13', () => {
expect(getOrdinalNumber(13)).toBe('13th');
});

test('returns "21st" for input 21', () => {
expect(getOrdinalNumber(21)).toBe('21st');
});

test('returns "22nd" for input 22', () => {
expect(getOrdinalNumber(22)).toBe('22nd');
});

test('returns "23rd" for input 23', () => {
expect(getOrdinalNumber(23)).toBe('23rd');
});

test('returns "112th" for input 112', () => {
expect(getOrdinalNumber(112)).toBe('112th');
});

test('returns "101st" for input 101', () => {
expect(getOrdinalNumber(101)).toBe('101st');
});

test('returns "103rd" for input 103', () => {
expect(getOrdinalNumber(103)).toBe('103rd');
});
});
21 changes: 21 additions & 0 deletions Sprint-3/revise/implement/getOrdinalNumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function getOrdinalNumber(number){

let firstDigit = number%10;
Copy link

Choose a reason for hiding this comment

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

A better practice is to use const instead of let to declare variables which do not change. Such practice could lead to less error prone code.

let secondDigit = number%100;

let suffix = "th";

if(secondDigit >= 11 && secondDigit <= 13){
return `${number}${suffix}`;
}else if (firstDigit === 1){
suffix = "st"
}else if (firstDigit === 2){
suffix = "nd";
}else if (firstDigit === 3){
suffix = "rd";
}
return `${number}${suffix}`;
}
console.log(getOrdinalNumber(45));

module.exports = getOrdinalNumber; // Export the function
16 changes: 16 additions & 0 deletions Sprint-3/revise/implement/is-prime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
function isPrime(number){

console.log(number);

if(number<=1) return false;

for (let i = 2; i <= number-1; i++) {
Copy link

Choose a reason for hiding this comment

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

To check if number has a factor that can fully divide it, you can check only odd numbers, and only odd numbers less than or equal to square root number.

Doing so can possibly improve the performance of the function.

You can try Google to find out "how to determine if a number is prime efficiently in JS".

if (number % i === 0) {
return false;
}
}
return true;
}
console.log(isPrime(5));

module.exports = isPrime;
Loading