From 6ec28c5f693ba8412983309d577793f1118d73c6 Mon Sep 17 00:00:00 2001 From: Tyler-leigh Date: Fri, 6 Nov 2026 00:23:39 +0200 Subject: [PATCH 01/10] Predict and explain with object dot notation --- Sprint-2/debug/address.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..17666fae1 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,5 +1,16 @@ // Predict and explain first... +/* +Predict +The function is calling index 0 but there is not an index 0 +Console.log will show a ref error +To fix this we need to change the index to [houseNumber] +What actually happened +Console.log showed undefined for that index +Changed index to [houseNumber] this gave us a ref err +Therefore it must be address.houseNumber +This works +*/ // This code should log out the houseNumber from the address object // but it isn't working... // Fix anything that isn't working @@ -12,4 +23,4 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +console.log(`My house number is ${address.houseNumber}`); From 8c3b5176f64a220cd2b5936430d5372ea82e91d7 Mon Sep 17 00:00:00 2001 From: Tyler-leigh Date: Fri, 6 Nov 2026 00:37:02 +0200 Subject: [PATCH 02/10] Predict and explain with for in loop --- Sprint-2/debug/author.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..05796952b 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,5 +1,11 @@ // Predict and explain first... - +/* +Predict +for of loops work on iteration and we cant iterate objects +To fix this we use for in loop +This loops over the keys +Now we can use author[value] to get values +*/ // 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,6 @@ const author = { alive: true, }; -for (const value of author) { - console.log(value); +for (const key in author) { + console.log(author[key]); } From 28469a633fd7dcdc2861e129ddd6a657ac205f25 Mon Sep 17 00:00:00 2001 From: Tyler-leigh Date: Fri, 6 Nov 2026 01:09:57 +0200 Subject: [PATCH 03/10] Predict and explain: converting an object to a str but default format displays label --- Sprint-2/debug/recipe.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..141083710 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,5 +1,9 @@ // Predict and explain first... - +/* +The ${recipe}`); line does not call the object correctly and shows [object Object] +This is because it tries to convert the whole object to a string but it doesnt know how to display the information +to fix this i used a for loop and iterated through the ingredients key's array to print each ingredient on a new line +*/ // 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 +15,9 @@ const recipe = { }; console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); +ingredients: `) + +for (let i=0; i < recipe.ingredients.length; i++) { + console.log(`${recipe.ingredients[i]}`) +} + From 5117a51a0a8c9a5f4bd9805291c6091371ea2869 Mon Sep 17 00:00:00 2001 From: Tyler-leigh Date: Fri, 6 Nov 2026 01:46:22 +0200 Subject: [PATCH 04/10] Implemented function contains to check if an object contains a key. Implemented tests. All tests pass --- Sprint-2/implement/contains.js | 12 ++++++++++-- Sprint-2/implement/contains.test.js | 24 +++++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..8c1ca08f2 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,11 @@ -function contains() {} - +function contains(input, key) { + if (input === null || typeof input !== "object") { + throw new Error("contains requires an object") + } else {for (const keys in input){ + if (keys === key) { + return true + } + }} return false +} +console.log(contains({a: 1}, 'a')) module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 719272787..057e0df27 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -23,18 +23,40 @@ 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", () => { + const input = {}; + const key = 'a' + const result = contains(input, key); + expect(result).toEqual(false) +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true +test("given: object with keys and values & key within object returns true", () => { + const input = {a: 1, b: 2, c: 3}; + const key = 'a' + const result = contains(input, key); + expect(result).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 keys and values & key not within object returns true", () => { + const input = {a: 1, b: 2, c: 3}; + const key = 'k' + const result = contains(input, key); + expect(result).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: value that is not an object throws error: 'contains requires an object'", () => { + const input = "tooth"; + const key = 'k' + expect(() => contains(input, key)).toThrow("contains requires an object") +}); \ No newline at end of file From 76e3bb4b936b96ca1b20f6739575a62a60afcb8f Mon Sep 17 00:00:00 2001 From: Tyler-leigh Date: Fri, 6 Nov 2026 02:05:57 +0200 Subject: [PATCH 05/10] Implement function createLookup that unpacks array of arrays into a single object with key value pairs (each array being a k-v pair). Implemented test. Test passes. Using Object method --- Sprint-2/implement/lookup.js | 5 +++-- Sprint-2/implement/lookup.test.js | 9 ++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..6ccefee0b 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,6 @@ -function createLookup() { - // implementation here +function createLookup(input) { + return Object.fromEntries(input) + } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..057edf56c 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,13 @@ 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", () => { + const input = [['US', 'USD'], ['CA', 'CAD']] + const result = createLookup(input) + expect(result).toEqual({ + 'US': 'USD', + 'CA': 'CAD' + }) +}); /* From 0b1de93c79ce93f4cfb90e0dd4cece8241291f94 Mon Sep 17 00:00:00 2001 From: Tyler-leigh Ross Date: Fri, 6 Nov 2026 14:24:42 +0200 Subject: [PATCH 06/10] Implemented queryParser that takes a query string and passes it into an object with key and value pairs, using guidance from already written test cases. All tests pass --- Sprint-2/implement/querystring.js | 25 ++++++++++++++++++++----- Sprint-2/implement/querystring.test.js | 12 ++++++------ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..87c06591f 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -4,12 +4,27 @@ function parseQueryString(queryString) { return queryParams; } const keyValuePairs = queryString.split("&"); - - for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + let keyValuePair = keyValuePairs; + if (queryString.includes("+")) { + keyValuePair = keyValuePairs.map((keyValuePair) => + keyValuePair.replaceAll("+", " ") + ); + } else if(queryString.includes("%")) { + keyValuePair = keyValuePairs.map((keyValuePair) => + decodeURIComponent(keyValuePair)) + }; + + for (const pair of keyValuePair) { + if (pair === "") continue; + const eqIndex = pair.indexOf("="); + if (eqIndex === -1) { + queryParams[pair] = ""; + } else { + const key = pair.slice(0, eqIndex); + const value = pair.slice(eqIndex + 1); + queryParams[key] = value; + } } - return queryParams; } diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 328b8df61..f4e075f3d 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -40,9 +40,9 @@ test("should replace '+' by ' '", () => { // 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", - }); -}); +// 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 87d5708d004b4a35bec9a64efa9b0e85729ef44d Mon Sep 17 00:00:00 2001 From: Tyler-leigh Ross Date: Fri, 6 Nov 2026 14:28:27 +0200 Subject: [PATCH 07/10] wrote 1st test case failing appropriately. --- Sprint-2/implement/tally.test.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index ca763c296..0bdcc9565 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -23,7 +23,11 @@ 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", () => { + const input = []; + const result = tally(input); + expect(result).toEqual({}); +}); // Given an array with duplicate items // When passed to tally From a349638ce27e5cf46637701745e5498bec785786 Mon Sep 17 00:00:00 2001 From: Tyler-leigh Ross Date: Fri, 6 Nov 2026 14:28:58 +0200 Subject: [PATCH 08/10] changed comments to multi line to make answering questions easier. --- Sprint-2/interpret/invert.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..b0ff2ff3b 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -16,14 +16,17 @@ function invert(obj) { return invertedObj; } -// a) What is the current return value when invert is called with { a : 1 } +/* +a) What is the current return value when invert is called with { a : 1 } -// b) What is the current return value when invert is called with { a: 1, b: 2 } +b) What is the current return value when invert is called with { a: 1, b: 2 } -// c) What is the target return value when invert is called with {a : 1, b: 2} +c) What is the target return value when invert is called with {a : 1, b: 2} -// c) What does Object.entries return? Why is it needed in this program? +c) What does Object.entries return? Why is it needed in this program? -// d) Explain why the current return value is different from the target output +d) Explain why the current return value is different from the target output -// e) Fix the implementation of invert (and write tests to prove it's fixed!) +e) Fix the implementation of invert (and write tests to prove it's fixed!) + +*/ From c43a62edbca7e91dede41e2d39c360ff8a972854 Mon Sep 17 00:00:00 2001 From: Tyler-leigh Date: Sat, 7 Nov 2026 01:53:02 +0200 Subject: [PATCH 09/10] Implemented function tally that takes an array and counts the frequency of each item then returns an object with each item-frequency pair. Implemented tests and all tests pass. --- Sprint-2/implement/tally.js | 15 ++++++++++++++- Sprint-2/implement/tally.test.js | 8 ++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..3d3b650bd 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,16 @@ -function tally() {} +function tally(array) { + if (!Array.isArray(array)){ + throw new Error('tally requires an array') + } + const result = {}; + for (const item of array){ + if (Object.hasOwn(result, item)) { + result[item] = result[item] + 1 + } else { + result[item] = 1 + } + } + return result +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 0bdcc9565..c0e408378 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -32,7 +32,15 @@ test("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 +test("given array with duplicate items, return object with counts for each unique item", () => { + const input = ['a', 'a', 'b', 'c', 'c', 'c']; + const result = tally(input); + expect(result).toEqual({a: 2, b: 1, c: 3}) +}) // 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 invalid input (str, num, no arg), throw error: 'tally requires an array'", () => { + expect(() => tally('meaf')).toThrow('tally requires an array') +}) \ No newline at end of file From 80fc275f344f6c2561b41e4ce8b0fbd1b75a645f Mon Sep 17 00:00:00 2001 From: Tyler-leigh Date: Sat, 7 Nov 2026 02:43:42 +0200 Subject: [PATCH 10/10] Fixed function invert: added error handling for non-object input, used bracket notation to assign propeties which handles swopping key-value pairs. Added test file and tests. all tests pass --- Sprint-2/interpret/invert.js | 16 +++++++++++++--- Sprint-2/interpret/invert.test.js | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 Sprint-2/interpret/invert.test.js diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index b0ff2ff3b..42da88512 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -7,26 +7,36 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} function invert(obj) { + if (typeof obj !== "object"){ + throw new Error('invert requires an object.') + } 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? +It returns an array of key value pairs from the object. +It is needed because we cannot iterate over objects with for..of. We convert the obj to array (key-value pairs) using Object.entries and then we can iterate. d) Explain why the current return value is different from the target output +We dont swop the key value pairs after they are in array form, we only place them back into the object as they were before. +invertedObj also returns uses key as a property name, not a placeholder. When we call the function key is overwritten with more than one key-value pair as well so only the last k-v pair shows but with "key" as the key name. e) Fix the implementation of invert (and write tests to prove it's fixed!) - -*/ +*/ \ No newline at end of file diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js new file mode 100644 index 000000000..a5feb4394 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,21 @@ +const invert = require("./invert.js"); + +test("object with 1 key-value pair. returns object with key-value pairs swopped.", () => { + expect(invert({a: 1})).toEqual({'1': 'a'}) +}) + +test("object with 2 key-value pairs. returns object with key-value pairs swopped.", () => { + expect(invert({a: 1, b: 2})).toEqual({'1': 'a', '2': 'b'}) +}) + +test("object with 3 key-value pairs. returns object with key-value pairs swopped.", () => { + expect(invert({a: 1, b: 2, z: 12})).toEqual({'1': 'a', '2': 'b', '12': 'z'}) +}) + +test("object with 0 key-value pair. returns empty object.", () => { + expect(invert({})).toEqual({}) +}) + +test("object with invalid input. throw error: 'invert requires an object.", () => { + expect(() => invert("bones")).toThrow('invert requires an object.') +}) \ No newline at end of file