Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
caa5bb0
Fix address object property access to log house number correctly
AkliluMihtsun Nov 9, 2026
e2397d8
Fix for loop to correctly iterate over object properties in author.js
AkliluMihtsun Nov 9, 2026
df238c9
Fix recipe.js to correctly log ingredients and improve comments
AkliluMihtsun Nov 9, 2026
345b355
Add tests for contains function to validate object property checks an…
AkliluMihtsun Nov 10, 2026
2ae7312
Implement contains function to check for property existence in an object
AkliluMihtsun Nov 10, 2026
fd4f6f5
Add jsconfig.json and update package.json for Jest type definitions
AkliluMihtsun Nov 10, 2026
a5c908d
Remove unnecessary TypeScript reference from contains.test.js
AkliluMihtsun Nov 10, 2026
3a2f213
Refactor tests in lookup.test.js to validate createLookup function be…
AkliluMihtsun Nov 10, 2026
4563f09
Implement createLookup function to transform country-currency pairs i…
AkliluMihtsun Nov 10, 2026
64405b5
Implement tally function to count occurrences of items in an array
AkliluMihtsun Nov 11, 2026
c4e3c36
Refactor tally tests to improve clarity and coverage
AkliluMihtsun Nov 11, 2026
6a4db13
Refactor parseQueryString function to improve query parameter handlin…
AkliluMihtsun Nov 11, 2026
7aae036
Fix syntax error in querystring.test.js by adding missing semicolon
AkliluMihtsun Nov 11, 2026
dc40ffc
Fix invert function implementation to correctly swap keys and values …
AkliluMihtsun Nov 11, 2026
2ebc9d0
Add tests for invert function to verify key-value inversion
AkliluMihtsun Nov 11, 2026
69d91ee
Fix author.js to correctly log property values instead of keys
AkliluMihtsun Nov 12, 2026
7ee7105
Refactor contains function to use Object.hasOwn for property checking
AkliluMihtsun Nov 12, 2026
30f8403
Refactor recipe.js to log ingredients in a single console statement
AkliluMihtsun Nov 12, 2026
1d3281e
Refactor createLookup function to improve input validation and error …
AkliluMihtsun Nov 12, 2026
32d1314
Refactor tests in lookup.test.js for clarity and accuracy in error me…
AkliluMihtsun Nov 12, 2026
fba5a72
Update test descriptions in tally.test.js for clarity and accuracy
AkliluMihtsun Nov 12, 2026
fae8185
Fix variable declaration in tally function to use const for objectItem
AkliluMihtsun Nov 12, 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
6 changes: 5 additions & 1 deletion Sprint-2/debug/address.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// Predict and explain first...

// I predict that the code will give undefined result, because objects access properties using the key names not indexes
// And the square bracket will generate a reference error because the houseNumber will be treated
// as a variable name not property key

// 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 +16,4 @@ const address = {
postcode: "XYZ 123",
};

console.log(`My house number is ${address[0]}`);
console.log(`My house number is ${address.houseNumber}`);
10 changes: 8 additions & 2 deletions Sprint-2/debug/author.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
// Predict and explain first...

// I predict the code will generate error, because it has used for of loop which is for looping array,
// instead of for in loop that is for looping objects
Comment thread
AkliluMihtsun marked this conversation as resolved.
Resolved

// 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

// when we run it, it logs out the property key instead of its value because for...in iterates over the property keys (names), not the property values.
// we need to use square brackets [] to access the value associated with that property name

const author = {
firstName: "Zadie",
lastName: "Smith",
Expand All @@ -11,6 +17,6 @@ const author = {
alive: true,
};

for (const value of author) {
console.log(value);
for (const value in author) {
console.log(author[value]);
}
Comment thread
AkliluMihtsun marked this conversation as resolved.
Resolved
10 changes: 6 additions & 4 deletions Sprint-2/debug/recipe.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Predict and explain first...

// I predict the code will not print the ingredients, because the array is not referenced,
// and it does not have loop to go through each element of the array
Comment thread
AkliluMihtsun marked this conversation as resolved.
Resolved

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

console.log(`${recipe.title} serves ${recipe.serves}
ingredients:
${recipe}`);
console.log(
recipe.title + " serves " + recipe.serves + recipe.ingredients.join("\n")
);
10 changes: 8 additions & 2 deletions Sprint-2/implement/contains.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
function contains() {}

function contains(object, name) {
if (typeof object !== "object" || Array.isArray(object) || object === null) {
throw new Error("contains requires an object");
}
// the in Checks own and inherited properties so that is why it returned true when the name is 'toString'
return Object.hasOwn(object, name);
}
//console.log(contains({ a: 1 }, "toString"));
module.exports = contains;
36 changes: 35 additions & 1 deletion Sprint-2/implement/contains.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,52 @@ as an array isn't an object
// Given an empty object
// When passed to contains
// Then it should return false
test.todo("contains on empty object returns false");
test("contains on empty object returns false", () => {
expect(contains({}, "a")).toBe(false);
});

// Given an object with properties
// When passed to contains with an existing property name
// Then it should return true
test("contains name on object returns true", () => {
expect(contains({ a: 1, b: 2, c: 3 }, "a")).toBe(true);
});

// Given an object with properties
// When passed to contains with a non-existent property name
// Then it should return false
test("contains name not on object returns false", () => {
expect(contains({ a: 1, b: 2, c: 3 }, "e")).toBe(false);
});

// Given a value that isn't an object - an array, a string, a number,
// null, or no argument at all
// When passed to contains
// Then it should throw Error("contains requires an object")
// (careful: typeof [] and typeof null are both "object")

describe("when the argument is not an object", () => {
test("throws an error when receiving a string", () => {
expect(() => {
contains("Hello World", "e");
}).toThrow("contains requires an object");
});

test("throws an error when receiving a number", () => {
expect(() => {
contains(1234, "a");
}).toThrow("contains requires an object");
});

test("throws an error when receiving an array", () => {
expect(() => {
contains(["a", "b", "c"], "a");
}).toThrow("contains requires an object");
});

test("throws an error when receiving null", () => {
expect(() => {
contains(null, "a");
}).toThrow("contains requires an object");
});
});
21 changes: 19 additions & 2 deletions Sprint-2/implement/lookup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
function createLookup() {
// implementation here
function createLookup(countryCurrencyPairs) {
if (!Array.isArray(countryCurrencyPairs)) {
throw new Error("createLookup requires an array");
}
for (const keyVlauePairs of countryCurrencyPairs) {
if (!Array.isArray(keyVlauePairs)) {
throw new Error("createLookup requires an array of key value pair");
} else if (keyVlauePairs.length !== 2) {
throw new Error("createLookup requires key value pair");
} else if (keyVlauePairs.some((element) => typeof element !== "string")) {
throw new Error("createLookup requires a string of key value pair");
}
}

let currencyObject = {};
for (const arrayCurrency of countryCurrencyPairs) {
currencyObject[arrayCurrency[0]] = arrayCurrency[1];
}
return currencyObject;
}

module.exports = createLookup;
33 changes: 32 additions & 1 deletion Sprint-2/implement/lookup.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
const createLookup = require("./lookup.js");

test.todo("creates a country currency code lookup for multiple codes");
test("returns an object of country currency pair", () => {
expect(
createLookup([
["US", "USD"],
["CA", "CAD"],
])
).toEqual({ US: "USD", CA: "CAD" });
});

test("Throws an error when there are more strings than key value pairs", () => {
expect(() => {
createLookup([
["US", "USD", "EURO"],
["CA", "CAD"],
]);
}).toThrow("createLookup requires key value pair");
});

test("Throws an error if the input is not an array", () => {
expect(() => {
createLookup(["usd", "cad", "euro"]);
}).toThrow("createLookup requires an array");
});

test("Throws an error if an array has elements that are not string key value pairs", () => {
expect(() => {
createLookup([
[23, "USD"],
["CA", 67],
]);
}).toThrow("createLookup requires a string of key value pair");
});

/*

Expand Down
33 changes: 31 additions & 2 deletions Sprint-2/implement/querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,40 @@ function parseQueryString(queryString) {
if (queryString.length === 0) {
return queryParams;
}
if (queryString.includes("%")) {
queryString = decodeURIComponent(queryString);
}
if (queryString.includes("+")) {
queryString = queryString.replaceAll("+", " ");
}
//const arrayValue = [];
let key = "";
let value = "";

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

for (const pair of keyValuePairs) {
const [key, value] = pair.split("=");
queryParams[key] = value;
if (pair.length === 0) {
continue;
}
const separatorIndex = pair.indexOf("=");
if (separatorIndex === 0) {
value = pair.slice(separatorIndex + 1);
} else if (separatorIndex === pair.length - 1) {
key = pair.slice(0, separatorIndex);
} else if (!pair.includes("=")) {
key = pair;
} else {
key = pair.slice(0, separatorIndex);
value = pair.slice(separatorIndex + 1);
}
if (!queryParams[key]) {
queryParams[key] = value;
} else if (Array.isArray(queryParams[key])) {
queryParams[key].push(value);
} else {
queryParams[key] = [queryParams[key], value];
}
}

return queryParams;
Expand Down
2 changes: 1 addition & 1 deletion 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
15 changes: 14 additions & 1 deletion Sprint-2/implement/tally.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
function tally() {}
function tally(array) {
if (!Array.isArray(array)) {
throw new Error("tally requires an array");
}
const objectItem = {};
for (const item of array) {
if (objectItem[item]) {
objectItem[item] = objectItem[item] + 1;
} else {
objectItem[item] = 1;
}
}
return objectItem;
}

module.exports = tally;
23 changes: 22 additions & 1 deletion Sprint-2/implement/tally.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,37 @@ 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
test("returns count for each unique item in the array", () => {
expect(tally(["a", "b", "b", "a", "c"])).toEqual({ a: 2, b: 2, c: 1 });
});

// 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");
test("returns empty object for given empty array", () => {
expect(tally([])).toEqual({});
});

// Given an array with duplicate items
// When passed to tally
// Then it should return counts for each unique item
test("returns count for each unique item with different type in the array", () => {
expect(tally(["a", "b", 3, "a", "c"])).toEqual({ a: 2, b: 1, 3: 1, c: 1 });
});

// Given an invalid input like a string, a number, or no argument at all
// When passed to tally
// Then it should throw Error("tally requires an array")
test("throws an error when not given an array", () => {
Comment thread
AkliluMihtsun marked this conversation as resolved.
Resolved
expect(() => {
tally("apple");
}).toThrow("tally requires an array");

expect(() => {
tally(234);
}).toThrow("tally requires an array");

expect(() => {
tally();
}).toThrow("tally requires an array");
});
17 changes: 16 additions & 1 deletion Sprint-2/interpret/invert.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,35 @@ function invert(obj) {
const invertedObj = {};

for (const [key, value] of Object.entries(obj)) {
invertedObj.key = value;
invertedObj[value] = key;
}

return invertedObj;
}
//console.log(invert({ f: 34, h: 45, j: "rf" }));
module.exports = invert;

// a) What is the current return value when invert is called with { a : 1 }

// ===> the current return value is { key: 1 }

// b) What is the current return value when invert is called with { a: 1, b: 2 }

// ===> the current return value is { key: 2 }

// c) What is the target return value when invert is called with {a : 1, b: 2}

// ===> the target return value is {"1": "a", "2": "b"}

// c) What does Object.entries return? Why is it needed in this program?

// ===> Object.entries return the key and value of an object, and in this program we used it to go through each key value pair and to put them in an array

// d) Explain why the current return value is different from the target output

// ===> first it used the dot notation instead of square bracket which is accessing the property using a literal name
// ===> second it is not inverted it still uses key value instead of value key so that it returns the inverted one

// e) Fix the implementation of invert (and write tests to prove it's fixed!)

// ===> I have fixed the program
10 changes: 10 additions & 0 deletions Sprint-2/interpret/invert.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const invert = require("./invert.js");

test("checking inversion ", () => {
expect(invert({ x: 10, y: 20 })).toEqual({ 10: "x", 20: "y" });
expect(invert({ f: 34, h: 45, j: "rf" })).toEqual({
34: "f",
45: "h",
rf: "j",
});
});
6 changes: 6 additions & 0 deletions Sprint-2/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"types": ["jest"]
},
"exclude": ["node_modules"]
}
Loading
Loading