From 6a0643acbc7dea51fe7be4e4475b88529e3ad870 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Fri, 24 Jul 2026 00:48:48 +0100 Subject: [PATCH 01/15] explain and fix the bug in address --- Sprint-2/debug/address.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..286933cb0 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -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 @@ -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}`); From 6de12461fffb257b250fc72bf1b8c2780e0fed2a Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Fri, 24 Jul 2026 18:07:46 +0100 Subject: [PATCH 02/15] debug logging the values of an object --- Sprint-2/debug/author.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..8ed2f72df 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -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 @@ -11,6 +17,7 @@ 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); +// } From 2488a71b61cbf61a618cfb59c846b185619f1912 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Fri, 24 Jul 2026 18:44:33 +0100 Subject: [PATCH 03/15] format recipe output to log ingredients on new lines --- Sprint-2/debug/recipe.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..415b730b9 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -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 @@ -10,6 +11,20 @@ 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) + +const recipeValues = Object.values(recipe); +// ["bruschetta", 2, ["olive oil", "tomatoes", "salt", "pepper"]] + +const ingredients = recipeValues.slice(-1)[0]; +// ["olive oil","tomatoes","salt","pepper"] + +//create a function to log line by line the elements of an array +function logItemised(items) { + return items.join("\n"); +} + +console.log( + `${recipe.title} serves ${recipe.serves}${"\n"}ingredients:${"\n"}${logItemised(ingredients)}` +); From 0291dfaea561716eea1163e43e1fa1af3d584aa1 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Fri, 24 Jul 2026 21:48:09 +0100 Subject: [PATCH 04/15] implement contains function --- Sprint-2/implement/contains.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..819d10ea2 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,24 @@ -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); + if (keysInObject.includes(propertyName)) { + return true; + } else { + return false; + } +} 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' +*/ From bced4fe2424b2317d6ef381294449011643c64ab Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Fri, 24 Jul 2026 21:48:34 +0100 Subject: [PATCH 05/15] write tests for contains function --- Sprint-2/implement/contains.test.js | 30 ++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..3030c13ea 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -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 @@ -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"); + }); +}); From 58665581578642e2e42b08933d30cb44d0ed1e71 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Mon, 10 Aug 2026 21:44:19 +0100 Subject: [PATCH 06/15] implement createLookup() --- Sprint-2/implement/lookup.js | 51 ++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..46ef9b8d0 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -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); } 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' + } + +*/ From 3423b50d987bc76ba6792e172c06de18548a7c23 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Mon, 10 Aug 2026 21:45:11 +0100 Subject: [PATCH 07/15] create tests for createLookup() --- Sprint-2/implement/lookup.test.js | 39 +++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..1d6ea5fb3 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,41 @@ 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"], + ["CA", "CAD"], + ]) + ).toEqual({ + US: "USD", + CA: "CAD", + }); + }); +}); /* @@ -9,7 +44,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 From 2a62f584df9c397d6d64a5bf47bed55d6c9a1473 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Tue, 11 Aug 2026 10:17:10 +0100 Subject: [PATCH 08/15] implement tally function --- Sprint-2/implement/tally.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..8cfb2f508 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,18 @@ -function tally() {} +function tally(array) { + if (typeof array === "string") { + throw new Error("Input should be an array"); + } + + let tallySet = {}; + + for (let item of array) { + if (!tallySet[item]) { + tallySet[item] = 1; + } else { + tallySet[item] += 1; + } + } + return tallySet; +} module.exports = tally; From 0b6fc652394f15a252ed0f3d1a297de235db774c Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Tue, 11 Aug 2026 10:17:33 +0100 Subject: [PATCH 09/15] write tests for tally function --- Sprint-2/implement/tally.test.js | 40 ++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..96584d86c 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -19,16 +19,32 @@ 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 duplicate items", () => { + test("should return an object with counts for each unique item", () => { + expect(tally(["a"])).toEqual({ a: 1 }); + expect(tally(["a", "a", "a"])).toEqual({ a: 3 }); + expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 }); + }); + }); + // 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 such as a string", () => { + test("should throw an error", () => { + expect(() => tally("apple")).toThrow("Input should be an array"); + }); + }); +}); From 9c07c980ff6cf980bd3df712cdda7642adf52ac1 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Tue, 11 Aug 2026 17:11:30 +0100 Subject: [PATCH 10/15] implement queryString() --- Sprint-2/implement/querystring.js | 33 +++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..b8030a627 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -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 + let 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; } From 95e7d98a5583e1c379baf7fe07e31d384a45ce40 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Tue, 11 Aug 2026 17:12:07 +0100 Subject: [PATCH 11/15] add one extra test --- Sprint-2/implement/querystring.test.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 328b8df61..4853e9094 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -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({ @@ -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", +// }); +// }); From 4de66ef04d61f9598d1f7561caf6442f5adf5442 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Tue, 11 Aug 2026 17:52:36 +0100 Subject: [PATCH 12/15] implement function and answer Qs in the comments --- Sprint-2/interpret/invert.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..6b45d9db2 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -10,20 +10,29 @@ function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + invertedObj[value] = key; } - return invertedObj; } // a) What is the current return value when invert is called with { a : 1 } +console.log(invert({ a: 1 })); +//return value is { key : 1 } // b) What is the current return value when invert is called with { a: 1, b: 2 } +console.log(invert({ a: 1, b: 2 })); +//return value is { key : 2 } // c) What is the target return value when invert is called with {a : 1, b: 2} +// target return value: {"1" : "a", "2": "b"} // c) What does Object.entries return? Why is it needed in this program? +//each key-value pair will form an array in a bigger array (array of arrays of key-value pairs) // d) Explain why the current return value is different from the target output +/* issues: +- .key notation naming the key "key" +- we only assign the key to value, but not reversing it +*/ // e) Fix the implementation of invert (and write tests to prove it's fixed!) From 078648cf1302653e8c72171be690582a911f3978 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Tue, 11 Aug 2026 18:05:06 +0100 Subject: [PATCH 13/15] add export for testing --- Sprint-2/interpret/invert.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index 6b45d9db2..4c4127d1e 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -36,3 +36,5 @@ console.log(invert({ a: 1, b: 2 })); */ // e) Fix the implementation of invert (and write tests to prove it's fixed!) + +module.exports = invert; From 6d32545af395c15ab3c784141f49a7d50caa41ed Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Tue, 11 Aug 2026 18:05:32 +0100 Subject: [PATCH 14/15] create test file and add first test --- Sprint-2/interpret/invert.test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Sprint-2/interpret/invert.test.js diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js new file mode 100644 index 000000000..470d8f3f6 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,10 @@ +const invert = require("./invert.js"); +// Given an object +// When invert is passed this object +// Then it should swap the keys and values in the object + +describe("invert function", () => { + test("should swap the keys and values in the object", () => { + expect(invert({ a: 1 })).toEqual({ 1: "a" }); + }); +}); From 1e8685b3faf0546dde84a74e010d8f40bc28d170 Mon Sep 17 00:00:00 2001 From: Edina Kurdi Date: Tue, 11 Aug 2026 21:10:13 +0100 Subject: [PATCH 15/15] add another test --- Sprint-2/interpret/invert.test.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js index 470d8f3f6..c5d841e1e 100644 --- a/Sprint-2/interpret/invert.test.js +++ b/Sprint-2/interpret/invert.test.js @@ -2,9 +2,17 @@ const invert = require("./invert.js"); // Given an object // When invert is passed this object // Then it should swap the keys and values in the object +describe("invert()", () => { + describe("invert function", () => { + test("should swap the keys and values in the object", () => { + expect(invert({ a: 1 })).toEqual({ 1: "a" }); + expect(invert({ x: 10, y: 20 })).toEqual({ 10: "x", 20: "y" }); + }); + }); -describe("invert function", () => { - test("should swap the keys and values in the object", () => { - expect(invert({ a: 1 })).toEqual({ 1: "a" }); + describe("given an empty object is passed into the function", () => { + test("should return and empty object", () => { + expect(invert({})).toEqual({}); + }); }); });