From f88a9ac96cb0c7c22a3010feadea6defb3de8d4b Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sat, 7 Nov 2026 14:37:20 +0000 Subject: [PATCH 01/12] Fix bug by using .notation to access address houseNumber --- Sprint-2/debug/address.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..86e425850 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,4 +1,8 @@ // Predict and explain first... +// This will print My house number is undefined +// Because the template literal tries to access the number like it is an array, +// But this is incorrect as it is an object which uses a different way to access +// elements // This code should log out the houseNumber from the address object // but it isn't working... @@ -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}`); From 39abe5dd090c446379cfd70ca7ccbce7d910bbf6 Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sat, 7 Nov 2026 14:58:07 +0000 Subject: [PATCH 02/12] Fix bug by using Object.entries() --- Sprint-2/debug/author.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..a6ae29b10 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,7 +1,9 @@ // Predict and explain first... +// Throw error because I don't think for of works like that for objects // 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 +// Doesn't work because author isn't an iterable, so it can't be looped over const author = { firstName: "Zadie", @@ -11,6 +13,6 @@ const author = { alive: true, }; -for (const value of author) { - console.log(value); +for (const [key, value] of Object.entries(author)) { + console.log(`${key}: ${value}`); } From 3440f8188ead40f42ce750050852f7c899aaced4 Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sat, 7 Nov 2026 15:26:43 +0000 Subject: [PATCH 03/12] Fix printing of ingredients --- Sprint-2/debug/recipe.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..4f0f898e5 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,5 +1,6 @@ // Predict and explain first... - +// This will print "bruschetta serves 2 +// ingredients: " Then not sure, but definitely not the ingredients // 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? @@ -11,5 +12,4 @@ const recipe = { }; console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); + ingredients:\n\t${recipe.ingredients.join("\n\t")}`); From a486ddc3bb425b0398d8d6627059aed0aa29d546 Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sun, 8 Nov 2026 15:50:35 +0000 Subject: [PATCH 04/12] Implement tests for contains.js --- Sprint-2/implement/contains.test.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 719272787..2707664c6 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -23,18 +23,31 @@ 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({})).toEqual(false); +}); // Given an object with properties // When passed to contains with an existing property name -// Then it should return true +// Then it should return true# +test("given object with properties, and wanted property exists, returns true", () => { + expect(contains({ a: 1, b: 2 }, "a")).toEqual(true); +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("given object with properties, and wanted property doesn't exist, returns false", () => { + expect(contains({ a: 1, b: 2 }, "c")).toEqual(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") +test("given something that isn't an object, throw error", () => { + expect(() => contains([1,2,5])).toThrow( + Error("contains requires an object") + ); +}); From d472910f3bb85fbbfc0f68688f4daa778c1d850b Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sun, 8 Nov 2026 15:51:14 +0000 Subject: [PATCH 05/12] Implement contains() and a checkIfObj function --- Sprint-2/implement/contains.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..514b002ac 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,17 @@ -function contains() {} +function checkIfObj(objToCheck) { + if ( + typeof objToCheck !== "object" || + objToCheck === null || + (Object.getPrototypeOf(objToCheck) !== Object.prototype && + Object.getPrototypeOf(objToCheck) !== null) + ) { + throw new Error("contains requires an object"); + } +} + +function contains(objToCheck, keyToSearch) { + checkIfObj(objToCheck); + return Object.keys(objToCheck).includes(keyToSearch); +} module.exports = contains; From 00af9504aca02bcaf2385013204297961bd52681 Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sun, 8 Nov 2026 16:07:22 +0000 Subject: [PATCH 06/12] Add test for createLookUp --- Sprint-2/implement/lookup.test.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..e5bc5f4de 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,16 @@ const createLookup = require("./lookup.js"); -test.todo("creates a country currency code lookup for multiple codes"); +test("creates a country currency code lookup for multiple codes", () => { + expect( + createLookup([ + ["US", "USD"], + ["CA", "CAD"], + ]) + ).toEqual({ + US: "USD", + CA: "CAD", + }); +}); /* From 3c250b620937e9c00db0647995edb741be43da3d Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sun, 8 Nov 2026 16:08:38 +0000 Subject: [PATCH 07/12] Implement createLookUp --- Sprint-2/implement/lookup.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..0e9e8a38f 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,11 @@ -function createLookup() { - // implementation here +function createLookup(countryCurrencyPairs) { + const objCountryCurrencyPairs = {}; + + for (const pair of countryCurrencyPairs) { + objCountryCurrencyPairs[pair[0]] = pair[1]; + } + + return objCountryCurrencyPairs; } module.exports = createLookup; From 24b7c4afb30bd63ce2906c1cde2df6cc1123a586 Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sun, 8 Nov 2026 16:52:26 +0000 Subject: [PATCH 08/12] Implement tests for tally --- Sprint-2/implement/tally.test.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index ca763c296..227fe1cdc 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 +test("Given an array of items, return object contain count for each unique item", () => { + 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 -test.todo("tally on an empty array returns an empty object"); +test("tally on an empty array returns an empty object", () => { + expect(tally([])).toEqual({}); +}); // Given an array with duplicate items // When passed to tally // Then it should return counts for each unique item +test("Given an array of items with duplicates, return object contain count for each unique item", () => { + expect(tally(["a", "a", "b", "c", "d", "b", "a"])).toEqual({ + a: 3, + b: 2, + c: 1, + d: 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("Given something that is not an array, throws error", () => { + expect(() => tally("Not an array")).toThrow(Error("tally requires an array")); +}); From cf0fc0f6e83c49527bcc755b17a5bea87f56412c Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sun, 8 Nov 2026 16:52:44 +0000 Subject: [PATCH 09/12] Implement tally function --- Sprint-2/implement/tally.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..d4ff18bae 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,16 @@ -function tally() {} +function tally(itemList) { + if (!Array.isArray(itemList)) { + throw new Error("tally requires an array"); + } + const talliedItems = {}; + for (const item of itemList) { + if (!Object.keys(talliedItems).includes(item)) { + talliedItems[item] = 1; + } else { + talliedItems[item] += 1; + } + } + return talliedItems; +} module.exports = tally; From 5515ce13ad416dd3efe7b2f1740a655f162269a9 Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sun, 8 Nov 2026 20:55:10 +0000 Subject: [PATCH 10/12] Implement querystring function --- Sprint-2/implement/querystring.js | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..c6460c1da 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -6,10 +6,33 @@ function parseQueryString(queryString) { const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; - } + if (pair === "") { + continue; + } + + if (!pair.includes("=")) { + const key = decodeURIComponent(pair).replace("+", " "); + queryParams[key] = ""; + } else { + const key = decodeURIComponent(pair.slice(0, pair.indexOf("="))).replace( + "+", + " " + ); + const value = decodeURIComponent( + pair.slice(pair.indexOf("=") + 1) + ).replace("+", " "); + if (Object.keys(queryParams).includes(key)) { + if (Array.isArray(queryParams[key])) { + queryParams[key].push(value); + } else { + queryParams[key] = [queryParams[key], value]; + } + } else { + queryParams[key] = value; + } + } + } return queryParams; } From c13d79c8a4a3e1a5cf84e7f89e5676ef866b46a8 Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sun, 8 Nov 2026 22:02:40 +0000 Subject: [PATCH 11/12] Answered questions and fixed invert function --- Sprint-2/interpret/invert.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..e92920d1d 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; } +module.exports = invert; + // a) What is the current return value when invert is called with { a : 1 } +// {key: 1} // b) What is the current return value when invert is called with { a: 1, b: 2 } +// {key: 2} // c) What is the target return value when invert is called with {a : 1, b: 2} +// {"1": "a", "2":"b"} // c) What does Object.entries return? Why is it needed in this program? +// An array of the objects key-value pairs. Used here so we can for loop over all key-value pairs in the object // d) Explain why the current return value is different from the target output +// because the key is a variable, bracket notations has to be used. with .notation it uses the word, not the variable so in this case the +// key is the word 'key'. Also the key and value are the wrong way round, the key of the original object is being given the value of the +// original object, essentially doing nothing // e) Fix the implementation of invert (and write tests to prove it's fixed!) From cfa87df107fcec3bdbe076fe8b2776363ee8ac85 Mon Sep 17 00:00:00 2001 From: Mahir Shah Date: Sun, 8 Nov 2026 22:17:38 +0000 Subject: [PATCH 12/12] Add test to check invert --- Sprint-2/interpret/invert.test.js | 5 +++++ 1 file changed, 5 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..12891e585 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,5 @@ +const invert = require("./invert.js"); + +test("Given object, returns object with inverted values and keys", () => { + expect(invert({ a: 8, b: 2 })).toEqual({ 8: "a", 2: "b" }); +});