From 59c786d32fbcf2df035b4046efed33be1754172f Mon Sep 17 00:00:00 2001 From: KK Tech Date: Sat, 21 Mar 2026 13:02:08 +0000 Subject: [PATCH 1/6] I have completed Debug/adress.js --- 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..7eda7d64b 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,4 +1,7 @@ // Predict and explain first... +//if you run this code with console.log('My house number is ${address[0]}'); it well log out 'My house number is undefined' becouse adress is an object and not an array. +// to fix this we need to remove (`My house number is ${address[0]}`); and chnage it to (adress.houseNumber) becouse we need to access the houseNumber property of the address object. +// Then it well log out 42 as expected. // This code should log out the houseNumber from the address object // but it isn't working... @@ -12,4 +15,4 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +console.log(address.houseNumber); From 077f3e4783af9180a11160b38a1b192471919731 Mon Sep 17 00:00:00 2001 From: KK Tech Date: Sat, 21 Mar 2026 15:10:11 +0000 Subject: [PATCH 2/6] Completed Debug tasks --- Sprint-2/debug/author.js | 2 +- Sprint-2/debug/recipe.js | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..7ba8f4c75 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -11,6 +11,6 @@ const author = { alive: true, }; -for (const value of author) { +for (const value of Object.values(author)) { console.log(value); } diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..0788c7620 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -10,6 +10,9 @@ const recipe = { ingredients: ["olive oil", "tomatoes", "salt", "pepper"], }; -console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); +console.log(recipe.title); +console.log(`Serves: ${recipe.serves}`); +console.log("Ingredients:"); +for (const ingredient of recipe.ingredients) { + console.log(ingredient); +} From d28d4cd516731215df17e85d28a5eaa7cb4f746a Mon Sep 17 00:00:00 2001 From: KK Tech Date: Tue, 24 Mar 2026 18:56:24 +0000 Subject: [PATCH 3/6] completed contains.js --- Sprint-2/implement/contains.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..aaaece9a7 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,16 @@ -function contains() {} +function contains(obj, prop) { + if (typeof obj !== "object" || obj === null) { + return false; + } + if (typeof prop !== "string") { + return false; + } + + if (Array.isArray(obj)) { + return false; + } + return obj.hasOwnProperty(prop); +} + module.exports = contains; From b81a1d1ebaac53ee7ae2ca1050fbe020c292cd96 Mon Sep 17 00:00:00 2001 From: KK Tech Date: Fri, 27 Mar 2026 16:05:24 +0000 Subject: [PATCH 4/6] completed some of the Sprint2/Impliment tasks --- Sprint-2/implement/contains.test.js | 13 ++++++++++++- Sprint-2/implement/lookup.js | 9 +++++++-- Sprint-2/implement/lookup.test.js | 5 ++++- Sprint-2/implement/querystring.js | 2 +- Sprint-2/implement/querystring.test.js | 2 ++ 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..0d7f3a169 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -20,16 +20,27 @@ as the object doesn't contains a key of 'c' // Given an empty object // When passed to contains // Then it should return false -test.todo("contains on empty object returns false"); +test("contains an empty object returns false", function () { + 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 returns true when property exists", function () { + expect(contains({ a: 1, b: 2 }, "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 returns false when property does not exist", function () { + expect(contains({ a: 1, b: 2 }, "c")).toBe(false); +}); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("contains returns false when passed an array", function () { + expect(contains([1, 2, 3], "a")).toBe(false); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..0ea659e0c 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,10 @@ -function createLookup() { - // implementation here +function createLookup(countryCurrencyPairs) { + const lookup = {}; + + for (const pair of countryCurrencyPairs) { + lookup[pair[0]] = pair[1]; + } + return lookup; } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..5ab551142 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,9 @@ 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", function() { + expect(createLookup([['US', 'USD'], ['CA', 'CAD']])).toEqual({'US': 'USD', 'CA': 'CAD'}); +}); + /* diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..320efa1ef 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -6,7 +6,7 @@ function parseQueryString(queryString) { const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); + const [key, value] = pair.split(/=(.*)/s); queryParams[key] = value; } diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..9e15d31bc 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -10,3 +10,5 @@ test("parses querystring values containing =", () => { "equation": "x=y+1", }); }); + +const \ No newline at end of file From 3e29bd2805e8d8d232949e9858eb9c1c4a0c4b6e Mon Sep 17 00:00:00 2001 From: KK Tech Date: Fri, 27 Mar 2026 17:32:36 +0000 Subject: [PATCH 5/6] Completed Sprint 2 tasks --- Sprint-2/implement/querystring.test.js | 18 ++++++++++++++- Sprint-2/implement/tally.js | 12 +++++++++- Sprint-2/implement/tally.test.js | 11 ++++++++- Sprint-2/interpret/invert.js | 31 +++++++++++++++++++++++++- Sprint-2/interpret/invert.test.js | 16 +++++++++++++ 5 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 Sprint-2/interpret/invert.test.js diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 9e15d31bc..c972ab099 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -8,7 +8,23 @@ const parseQueryString = require("./querystring.js") test("parses querystring values containing =", () => { expect(parseQueryString("equation=x=y+1")).toEqual({ "equation": "x=y+1", + }); }); -const \ No newline at end of file +test("parses empty querystring", () => { + expect(parseQueryString("")).toEqual({}); +}); + +test("parses querystring with multiple key value pairs", () => { + expect(parseQueryString("name=Karim&age=20")).toEqual({ + "name": "Karim", + "age": "20" + }); +}); + +test("parses querystring with empty value", () => { + expect(parseQueryString("name=")).toEqual({ + "name": "" + }); +}); \ No newline at end of file diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..290aa7345 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,13 @@ -function tally() {} +function tally(items) { + if (!Array.isArray(items)) { + throw new Error('Items must be an array'); + } + const counts = {}; + for (const item of items) { + counts[item] = (counts[item] || 0) + 1; + } + return counts; + +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..82062d24b 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -23,12 +23,21 @@ const tally = require("./tally.js"); // 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("tally counts unique items", () => { + expect(tally(['a', 'a', 'b', 'c'])).toEqual({ a: 2, b: 1, c: 1 }); +}); // Given an invalid input like a string // When passed to tally // Then it should throw an error +test("tally throws an error for invalid input", () => { + expect(() => tally("not an array")).toThrow("Items must be an array"); +}); + diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..f6df76b3f 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -10,7 +10,7 @@ function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + invertedObj[value] = key; } return invertedObj; @@ -18,12 +18,41 @@ function invert(obj) { // a) What is the current return value when invert is called with { a : 1 } +// It returns { key: 1 } because invertedObj.key always writes the word "key" + +//---------------------------------------------------------------------------------------// + // b) What is the current return value when invert is called with { a: 1, b: 2 } +// It returns { key: 2 } because it keeps overwriting the same "key" each time + +//---------------------------------------------------------------------------------------// + // c) What is the target return value when invert is called with {a : 1, b: 2} +// It should return { "1": "a", "2": "b" } because the keys and values are swapped + +//---------------------------------------------------------------------------------------// + // c) What does Object.entries return? Why is it needed in this program? +// Object.entries turns the object into an array like [["a", 1], ["b", 2]] +// We need it so we can loop through each key and value one by one + +//---------------------------------------------------------------------------------------// + // d) Explain why the current return value is different from the target output +// Because invertedObj.key writes the word "key" literally +// instead of using the actual value as the key +// changing it to invertedObj[value] = key fixes this + +//---------------------------------------------------------------------------------------// + // e) Fix the implementation of invert (and write tests to prove it's fixed!) + +// Fixed by changing invertedObj.key = value to invertedObj[value] = key +// Tests are written in invert.test.js + + +module.exports = invert; diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js new file mode 100644 index 000000000..752d559d7 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,16 @@ +const invert = require("./invert.js"); + +// Test 1 swaps the keys and values +test("invert swaps keys and values", () => { + expect(invert({ a: 1, b: 2 })).toEqual({ "1": "a", "2": "b" }); +}); + +// Test 2 empty object should return empty object +test("invert on an empty object returns an empty object", () => { + expect(invert({})).toEqual({}); +}); + +// Test 3 single key value pair +test("invert works with a single pair", () => { + expect(invert({ x: 10 })).toEqual({ "10": "x" }); +}); \ No newline at end of file From e3f0acfd036bcb4e837c805e6b406ae746fcc6b3 Mon Sep 17 00:00:00 2001 From: KK Tech Date: Sun, 29 Mar 2026 16:10:28 +0100 Subject: [PATCH 6/6] Resolved issues following feeback instructions --- Sprint-2/debug/recipe.js | 5 ++--- Sprint-2/implement/contains.js | 3 --- Sprint-2/implement/contains.test.js | 2 +- Sprint-2/implement/querystring.js | 9 ++++++++- Sprint-2/implement/tally.js | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 0788c7620..2abc7c72d 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -13,6 +13,5 @@ const recipe = { console.log(recipe.title); console.log(`Serves: ${recipe.serves}`); console.log("Ingredients:"); -for (const ingredient of recipe.ingredients) { - console.log(ingredient); -} +console.log(recipe.ingredients.join("\n")); + diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index aaaece9a7..61fdab87b 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -2,9 +2,6 @@ function contains(obj, prop) { if (typeof obj !== "object" || obj === null) { return false; } - if (typeof prop !== "string") { - return false; - } if (Array.isArray(obj)) { return false; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 0d7f3a169..bc3dd30f1 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -42,5 +42,5 @@ test("contains returns false when property does not exist", function () { // When passed to contains // Then it should return false or throw an error test("contains returns false when passed an array", function () { - expect(contains([1, 2, 3], "a")).toBe(false); + expect(contains([1, 2, 3], "0")).toBe(false); }); diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 320efa1ef..395e27790 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,12 +1,19 @@ function parseQueryString(queryString) { const queryParams = {}; + if (queryString.length === 0) { return queryParams; } + const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split(/=(.*)/s); + if (!pair) continue; + + const firstEqualsIndex = pair.indexOf("="); + const key = pair.slice(0, firstEqualsIndex); + const value = pair.slice(firstEqualsIndex + 1); + queryParams[key] = value; } diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index 290aa7345..27e3b772b 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -2,7 +2,7 @@ function tally(items) { if (!Array.isArray(items)) { throw new Error('Items must be an array'); } - const counts = {}; + const counts = Object.create(null); for (const item of items) { counts[item] = (counts[item] || 0) + 1; }