Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6a0643a
explain and fix the bug in address
edinakurdi Jul 23, 2026
6de1246
debug logging the values of an object
edinakurdi Jul 24, 2026
2488a71
format recipe output to log ingredients on new lines
edinakurdi Jul 24, 2026
0291dfa
implement contains function
edinakurdi Jul 24, 2026
bced4fe
write tests for contains function
edinakurdi Jul 24, 2026
5866558
implement createLookup()
edinakurdi Aug 10, 2026
3423b50
create tests for createLookup()
edinakurdi Aug 10, 2026
2a62f58
implement tally function
edinakurdi Aug 11, 2026
0b6fc65
write tests for tally function
edinakurdi Aug 11, 2026
9c07c98
implement queryString()
edinakurdi Aug 11, 2026
95e7d98
add one extra test
edinakurdi Aug 11, 2026
4de66ef
implement function and answer Qs in the comments
edinakurdi Aug 11, 2026
078648c
add export for testing
edinakurdi Aug 11, 2026
6d32545
create test file and add first test
edinakurdi Aug 11, 2026
1e8685b
add another test
edinakurdi Aug 11, 2026
c0107ff
implement an alternative solution to return the values from the autho…
edinakurdi Aug 13, 2026
a6c0620
shorten code
edinakurdi Aug 13, 2026
0b68a26
shorten code more
edinakurdi Aug 13, 2026
4a89c7d
simplify code
edinakurdi Aug 13, 2026
8ef6662
add a simpler test for valid input to start with
edinakurdi Aug 13, 2026
0ac7c8a
fix bracket that broke the test
edinakurdi Aug 13, 2026
f7b2d6f
break down a test to 3 component tests
edinakurdi Aug 13, 2026
c83a6e2
adjust function to filter out any non-array elements
edinakurdi Aug 13, 2026
cbed42f
add aitional tests to check if input is not an array
edinakurdi Aug 13, 2026
c02c23e
update keyword for variable declaration (tallySet
edinakurdi Aug 13, 2026
b46cc1c
update keyword for variable declaration (filteredValuePairs
edinakurdi Aug 13, 2026
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
5 changes: 4 additions & 1 deletion Sprint-2/debug/address.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Predict and explain first...

// address[0] will not work here as we have an object of key-value pairs. instead of square bracket notation we need the dot notation with the key
// I would think it returns undefined.

// This code should log out the houseNumber from the address object
// but it isn't working...
// Fix anything that isn't working
Expand All @@ -12,4 +15,4 @@ const address = {
postcode: "XYZ 123",
};

console.log(`My house number is ${address[0]}`);
console.log(`My house number is ${address.houseNumber}`);
18 changes: 16 additions & 2 deletions Sprint-2/debug/author.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
// Predict and explain first...
// author is an object. It cannot be accessed through its values, maybe through its key, value pairs instead of "value" -

//update on explanation: objects could be accessed through 3 methods, depending on whether we want the property name or property value, or the pair. :
//1. Object.keys() collects into an array the keys (property names) ignoring the values
//2. Object.values() collects into an array the values ignoring the property names
//3. Object.entries() collects an array of arrays of key-value pairs

// This program attempts to log out all the property values in the object.
// But it isn't working. Explain why first and then fix the problem
Expand All @@ -11,6 +17,14 @@ const author = {
alive: true,
};

for (const value of author) {
console.log(value);
console.log(Object.values(author));
// for (const value of author) {
// console.log(value);
// }
Comment on lines +20 to +23

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A good workaround to print the values of the object.

Question - how could the for loop on lines 21 - 23 be changed (to a different loop for example) to achieve the same effect?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Created an alternative using a loop


//alternative:
let authorValues = [];
for (const value of Object.values(author)) {
authorValues.push(value);
}
console.log(authorValues);
10 changes: 7 additions & 3 deletions Sprint-2/debug/recipe.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Predict and explain first...
//in the template literal the ${recipe}`is referring to the whole object, we want the items in the ingredients of the recipe object, listed line by line.

// This program should log out the title, how many it serves and the ingredients.
// Each ingredient should be logged on a new line
Expand All @@ -10,6 +11,9 @@ const recipe = {
ingredients: ["olive oil", "tomatoes", "salt", "pepper"],
};

console.log(`${recipe.title} serves ${recipe.serves}
ingredients:
${recipe}`);
// const recipeKeys = Object.keys(recipe)
// // console.log(recipeKeys)

console.log(
`${recipe.title} serves ${recipe.serves}${"\n"}ingredients:${"\n"}${recipe.ingredients.join("\n")}`
);
19 changes: 18 additions & 1 deletion Sprint-2/implement/contains.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
function contains() {}
function contains(object, propertyName) {
if (typeof object !== "object" || object === null || Array.isArray(object)) {
throw new Error("Input should be an object");
}
const keysInObject = Object.keys(object);
return keysInObject.includes(propertyName);
}

module.exports = contains;

/*
Implement a function called contains that checks an object contains a
particular property

E.g. contains({a: 1, b: 2}, 'a') // returns true
as the object contains a key of 'a'

E.g. contains({a: 1, b: 2}, 'c') // returns false
as the object doesn't contains a key of 'c'
*/
30 changes: 29 additions & 1 deletion Sprint-2/implement/contains.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,23 @@ as the object doesn't contains a key of 'c'
// When passed an object and a property name
// Then it should return true if the object contains the property, false otherwise

describe("when checking property existence", () => {
test("should return true if the object contains the property", () => {
expect(contains({ a: "apple", b: "hill" }, "a")).toBe(true);
});
test("should return false if the object does not contain the property", () => {
expect(contains({ a: "apple", b: "hill" }, "c")).toBe(false);
});
});

// Given an empty object
// When passed to contains
// Then it should return false
test.todo("contains on empty object returns false");
describe("given an empty object", () => {
test("should return false when passed to contains", () => {
expect(contains({}, "a")).toBe(false);
});
});

// Given an object with properties
// When passed to contains with an existing property name
Expand All @@ -33,3 +46,18 @@ test.todo("contains on empty object returns false");
// Given invalid parameters like an array
// When passed to contains
// Then it should return false or throw an error
describe("when given invalid inputs", () => {
test("should throw an error if the input is not an object", () => {
expect(() => contains([true, 2, "hill"], "2")).toThrow(
"Input should be an object"
);
});

test("should throw an error if the input is not an object", () => {
expect(() => contains(null, "hi")).toThrow("Input should be an object");
});

test("should throw an error if the input is not an object", () => {
expect(() => contains("apple", "a")).toThrow("Input should be an object");
});
});
51 changes: 49 additions & 2 deletions Sprint-2/implement/lookup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,52 @@
function createLookup() {
// implementation here
function createLookup(countryCurrencyPairs) {
//if countryCurrencyPairs is not an array, throw error
if (!Array.isArray(countryCurrencyPairs)) {
throw new Error("Invalid input. It should be an array");
}
//if it is an empty array, throw error
if (countryCurrencyPairs.length === 0) {
throw new Error("Input should not be an empty array");
}

//if not all elements are an array in the array, throw an error
if (!countryCurrencyPairs.every(Array.isArray)) {
throw new Error("Invalid input. All elements should be arrays");
}

return Object.fromEntries(countryCurrencyPairs);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nice choice of method

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

thank you i came across it when learning about iterating through objects. very handy.

}

module.exports = createLookup;

// console.log(
// createLookup([
// ["US", "USD"],
// ["CA", "CAD"],
// ])
// );

// console.log(createLookup([]));

/*
When
- createLookup function is called with the country-currency array as an argument

Then
- It should return an object where:
- The keys are the country codes
- The values are the corresponding currency codes

Example
Given: [['US', 'USD'], ['CA', 'CAD']]

When
createLookup(countryCurrencyPairs) is called

Then
It should return:
{
'US': 'USD',
'CA': 'CAD'
}

*/
44 changes: 42 additions & 2 deletions Sprint-2/implement/lookup.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,46 @@
const createLookup = require("./lookup.js");

test.todo("creates a country currency code lookup for multiple codes");
describe("when given invalid inputs", () => {
test("should return invalid input error, if the input is an empty array", () => {
expect(() => createLookup([])).toThrow(
"Input should not be an empty array"
);
});
test("should return invalid input error, if the input isn't an array of arrays", () => {
expect(() => createLookup(["hi", "hello"])).toThrow(
"Invalid input. All elements should be arrays"
);
});
test("should return invalid input error, if the input isn't an array of arrays", () => {
expect(() => createLookup("hi")).toThrow(
"Invalid input. It should be an array"
);
});
test("should return invalid input error, if the input isn't an array of arrays", () => {
expect(() => createLookup(2)).toThrow(
"Invalid input. It should be an array"
);
});
});

describe("when given valid inputs", () => {
test("should return an object where (Input ==> Output): keys:values ==> country code: corresponding currency", () => {
expect(createLookup([["US", "USD"]])).toEqual({
US: "USD",
});
});
test("should return an object where (Input ==> Output): keys:values ==> country code: corresponding currency", () => {
expect(
createLookup([
["US", "USD"],
["CA", "CAD"],
])
).toEqual({
US: "USD",
CA: "CAD",
});
});
});
Comment on lines +26 to +43

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Could you have included a simpler test to start with for valid inputs?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

i added a simpler input with only one array in the array (one country's data)


/*

Expand All @@ -9,7 +49,7 @@ Create a lookup object of key value pairs from an array of code pairs
Acceptance Criteria:

Given
- An array of arrays representing country code and currency code pairs
- An array of arrays representing when given invalid inputs code pairs
e.g. [['US', 'USD'], ['CA', 'CAD']]

When
Expand Down
33 changes: 29 additions & 4 deletions Sprint-2/implement/querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,37 @@ function parseQueryString(queryString) {
if (queryString.length === 0) {
return queryParams;
}
const keyValuePairs = queryString.split("&");

for (const pair of keyValuePairs) {
const [key, value] = pair.split("=");
queryParams[key] = value;
//replace initial "?" if present
if (queryString.startsWith("?")) {
queryString = queryString.replace("?", "");
}
//replace encoded characters
queryString = decodeURIComponent(queryString);

//replace "+" with " "
queryString = queryString.replaceAll("+", " ");

const keyValuePairs = queryString.split("&");

//filter out empty strings from the keyValuePairs array of strings
const filteredKeyValuePairs = keyValuePairs.filter(
(keyValuePair) => keyValuePair.length > 0
);

//assign key value pairs created by separating on the first "=" sign
filteredKeyValuePairs.forEach((str) => {
//if no "=", then the string should be the key
if (!str.includes("=")) {
const key = str;
queryParams[key] = "";
} else {
const indexOfFirstEqual = str.indexOf("=");
const key = str.slice(0, indexOfFirstEqual);
const value = str.slice(indexOfFirstEqual + 1);
queryParams[key] = value;
}
});

return queryParams;
}
Expand Down
19 changes: 11 additions & 8 deletions Sprint-2/implement/querystring.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Below are some test cases the implementation doesn't handle well.
// Fix the implementation for these tests, and try to think of as many other edge cases as possible - write tests and fix those too.

const parseQueryString = require("./querystring.js")
const parseQueryString = require("./querystring.js");

test("should parse values containing '='", () => {
expect(parseQueryString("equation=a=b-2")).toEqual({
Expand Down Expand Up @@ -37,12 +37,15 @@ test("should replace '+' by ' '", () => {
});
});

test("should delete accidental '?' if first char by accident", () => {
expect(parseQueryString("?colour=teal")).toEqual({ colour: "teal" });
});
// Stretch exercise: Handling query strings that contain identical keys

// Delete this test if you are not working on this optional case
test("should store values of a key in an array when the key has 2 or more values", () => {
expect(parseQueryString("key=value1&key=value2&key=value3&foo=bar")).toEqual({
key: ["value1", "value2", "value3"],
foo: "bar",
});
});
// // Delete this test if you are not working on this optional case
// test("should store values of a key in an array when the key has 2 or more values", () => {
// expect(parseQueryString("key=value1&key=value2&key=value3&foo=bar")).toEqual({
// key: ["value1", "value2", "value3"],
// foo: "bar",
// });
// });
17 changes: 16 additions & 1 deletion Sprint-2/implement/tally.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
function tally() {}
function tally(array) {
if (!Array.isArray(array)) {
throw new Error("Input should be an array");
}

const tallySet = {};

for (let item of array) {
if (!tallySet[item]) {
tallySet[item] = 1;
} else {
tallySet[item] += 1;
}
}
return tallySet;
}

module.exports = tally;
54 changes: 42 additions & 12 deletions Sprint-2/implement/tally.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,46 @@ const tally = require("./tally.js");
// Given a function called tally
// When passed an array of items
// Then it should return an object containing the count for each unique item
describe("tally()", () => {
// Given an array with duplicate items
// When passed to tally
// Then it should return counts for each unique item
describe("when given an array with a single item", () => {
test("should return an object with counts for that item (1)", () => {
expect(tally(["a"])).toEqual({ a: 1 });
});
});
describe("when given an array with duplicate items", () => {
test("should return an object with counts that item", () => {
expect(tally(["a", "a", "a"])).toEqual({ a: 3 });
});
});
describe("when given an array with duplicate items", () => {
test("should return an object with counts for each unique item", () => {
expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 });
Comment on lines +28 to +38

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I actually think these are three different behaviours and so deserve their own test blocks to anyone reading them test suite can see the different behaviours clearly.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

corrected.

});
});
// Given an empty array
// When passed to tally
// Then it should return an empty object
describe("when given an empty array", () => {
test("should return an empty object", () => {
expect(tally([])).toEqual({});
});
});

// Given an empty array
// When passed to tally
// Then it should return an empty object
test.todo("tally on an empty array returns an empty object");

// Given an array with duplicate items
// When passed to tally
// Then it should return counts for each unique item

// Given an invalid input like a string
// When passed to tally
// Then it should throw an error
// Given an invalid input like a string
// When passed to tally
// Then it should throw an error
describe("when given invalid input", () => {
test("should throw an error for a string input", () => {
expect(() => tally("apple")).toThrow("Input should be an array");
});
test("should throw an error for a boolean input", () => {
expect(() => tally(true)).toThrow("Input should be an array");
});
test("should throw an error for a number input", () => {
expect(() => tally(3)).toThrow("Input should be an array");
});
});
});
Loading