From a0f6c7ed419ef38388d9dec3dcf3dcc38bb2f296 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Mon, 2 Mar 2026 12:14:34 +0000 Subject: [PATCH 01/21] updates to Sprint1/fix dedupe function and test --- Sprint-1/fix/median.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index b22590bc6..ac3a25690 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -6,8 +6,24 @@ // or 'list' has mixed values (the function is expected to sort only numbers). function calculateMedian(list) { - const middleIndex = Math.floor(list.length / 2); - const median = list.splice(middleIndex, 1)[0]; + // only operate on non-empty arrays + if (!Array.isArray(list) || list.length === 0) { + return null; + } + + const numbers = list.filter((item) => typeof item === "number"); + if (numbers.length === 0) { + return null; + } + + numbers.sort((a, b) => a - b); + if (numbers.length % 2 === 0) { + const mid1 = numbers.length / 2 - 1; + const mid2 = numbers.length / 2; + return (numbers[mid1] + numbers[mid2]) / 2; + } + const middleIndex = Math.floor(numbers.length / 2); + const median = numbers[middleIndex]; return median; } From ed881926930aafe493a57e444583f737f2863807 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Tue, 10 Mar 2026 15:08:21 +0000 Subject: [PATCH 02/21] updates to sprint 2 debug address --- Sprint-2/debug/address.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..1fb2e5d98 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -5,11 +5,13 @@ // Fix anything that isn't working const address = { - houseNumber: 42, - street: "Imaginary Road", - city: "Manchester", - country: "England", - postcode: "XYZ 123", -}; - -console.log(`My house number is ${address[0]}`); + + houseNumber: 42, + street: "Imaginary Road", + city: "Manchester", + country: "England", + postcode: "XYZ 123", + } + + +console.log(`My house number is ${address.houseNumber}`); From bc4aae52617bf70136bcb0dd86d7bec280eb8400 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Tue, 10 Mar 2026 15:20:29 +0000 Subject: [PATCH 03/21] updates to sprint 2 debug author --- Sprint-2/debug/address.js | 14 ++++++-------- Sprint-2/debug/author.js | 3 ++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 1fb2e5d98..36d2f865d 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -5,13 +5,11 @@ // Fix anything that isn't working const address = { - - houseNumber: 42, - street: "Imaginary Road", - city: "Manchester", - country: "England", - postcode: "XYZ 123", - } - + houseNumber: 42, + street: "Imaginary Road", + city: "Manchester", + country: "England", + postcode: "XYZ 123", +}; console.log(`My house number is ${address.houseNumber}`); diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..8e8bcd053 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -11,6 +11,7 @@ const author = { alive: true, }; -for (const value of author) { +for (const value of Object.values(author)) { console.log(value); } +// The problem is that the code is trying to log out the values of the object using a for...of loop, but it is not using the correct syntax to access the values. The Object.values() method returns an array of the object's values, so we need to use a for...of loop to iterate over that array and log each value. \ No newline at end of file From 9d340fe65b877e3a5ade866db13e8b8be13617c3 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Tue, 10 Mar 2026 15:27:56 +0000 Subject: [PATCH 04/21] updates to sprint 2 debug recipe --- Sprint-2/debug/recipe.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..658667af6 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -10,6 +10,8 @@ const recipe = { ingredients: ["olive oil", "tomatoes", "salt", "pepper"], }; -console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); +console.log(`${recipe.title} serves ${recipe.serves}`); +for (const ingredient of recipe.ingredients) { + console.log(ingredient); +} +// The problem is that the code is trying to log out the ingredients using a for...of loop, but it is not using the correct syntax to access the ingredients. The recipe.ingredients is an array, so we need to use a for...of loop to iterate over that array and log each ingredient. \ No newline at end of file From 95b92bac9957098b4a10485203fd640bdb7a003e Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Tue, 10 Mar 2026 16:32:48 +0000 Subject: [PATCH 05/21] updates to sprint 2 implement Contains and tested ok --- Sprint-2/implement/contains.js | 9 ++++++++- Sprint-2/implement/contains.test.js | 29 ++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..cfa16a4b7 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,10 @@ -function contains() {} +function contains(obj, prop) { + return ( + !!obj && + typeof obj === "object" && + !Array.isArray(obj) && + Object.prototype.hasOwnProperty.call(obj, prop) + ); +} module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..547c8b312 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -16,20 +16,47 @@ as the object doesn't contains a key of 'c' // Given a contains function // When passed an object and a property name // Then it should return true if the object contains the property, false otherwise +test("contains returns true for existing property", () => { + const obj = { a: 1, b: 2 }; + expect(contains(obj, "a")).toBe(true); + expect(contains(obj, "b")).toBe(true); + expect(contains(obj, "c")).toBe(false); +}); // 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 emptyObj = {}; + expect(contains(emptyObj, "a")).toBe(false); + expect(contains(emptyObj, "b")).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 for existing property", () => { + const obj2 = { x: 10, y: 20 }; + expect(contains(obj2, "x")).toBe(true); + expect(contains(obj2, "y")).toBe(true); + expect(contains(obj2, "z")).toBe(false); +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("contains returns false for non-existent property", () => { + const obj3 = { name: "Alice", age: 30 }; + expect(contains(obj3, "name")).toBe(true); + expect(contains(obj3, "age")).toBe(true); + expect(contains(obj3, "gender")).toBe(false); +}); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("contains handles invalid parameters", () => { + expect(contains([], "a")).toBe(false); + expect(contains(null, "a")).toBe(false); + expect(contains(undefined, "a")).toBe(false); +}); From 1af24f24119af0571b744b5879fced9a6069e30f Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Wed, 11 Mar 2026 11:54:52 +0000 Subject: [PATCH 06/21] updates to sprint 2 implement/contains comments added to each line of function to remember key syntax and functionality --- Sprint-2/implement/contains.js | 8 ++++---- Sprint-2/implement/lookup.js | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cfa16a4b7..d4381ffc7 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,9 +1,9 @@ function contains(obj, prop) { return ( - !!obj && - typeof obj === "object" && - !Array.isArray(obj) && - Object.prototype.hasOwnProperty.call(obj, prop) + !!obj && // confirm that obj is not null or undefined. If undefined or null, return false. + typeof obj === "object" && // confirm that obj is an object. If not an object, return false. + !Array.isArray(obj) && // confirm that obj is not an array. If an array, return false. + Object.prototype.hasOwnProperty.call(obj, prop)// check if the object has the property. If it does, return true; otherwise, return false. ); } diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..00eafb38a 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,11 @@ function createLookup() { // implementation here +const lookup = {}; + +lookup.add = function(key, value) { + lookup[key] = value; +}; + } module.exports = createLookup; From 4edc7edbd5ad11cc204bd6b55532f2a372b14f70 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Wed, 11 Mar 2026 12:15:07 +0000 Subject: [PATCH 07/21] restoring Sprint1 files from main for Sprint2 branch --- Sprint-1/fix/median.js | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index ac3a25690..b22590bc6 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -6,24 +6,8 @@ // or 'list' has mixed values (the function is expected to sort only numbers). function calculateMedian(list) { - // only operate on non-empty arrays - if (!Array.isArray(list) || list.length === 0) { - return null; - } - - const numbers = list.filter((item) => typeof item === "number"); - if (numbers.length === 0) { - return null; - } - - numbers.sort((a, b) => a - b); - if (numbers.length % 2 === 0) { - const mid1 = numbers.length / 2 - 1; - const mid2 = numbers.length / 2; - return (numbers[mid1] + numbers[mid2]) / 2; - } - const middleIndex = Math.floor(numbers.length / 2); - const median = numbers[middleIndex]; + const middleIndex = Math.floor(list.length / 2); + const median = list.splice(middleIndex, 1)[0]; return median; } From 0eba06ad7149c43627d436972aa5acd84b38a64a Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Wed, 11 Mar 2026 12:35:55 +0000 Subject: [PATCH 08/21] update to lookup function and test for passing correct array --- Sprint-2/implement/lookup.js | 13 ++++++++----- Sprint-2/implement/lookup.test.js | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index 00eafb38a..a7862d473 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,11 +1,14 @@ -function createLookup() { +function createLookup(pairs) { // implementation here -const lookup = {}; +const lookup = {};// create an empty object to store key-value pairs -lookup.add = function(key, value) { - lookup[key] = value; +for (const pair of pairs) {// iterate through each pair in the input array + const key = pair[0];// extract the first element of the pair as the key + const value = pair[1];// extract the second element of the pair as the value + lookup[key] = value;// add the key-value pair to the lookup object + } + return lookup; }; -} module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..9c0d5553d 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,13 +1,22 @@ const createLookup = require("./lookup.js"); -test.todo("creates a country currency code lookup for multiple codes"); /* Create a lookup object of key value pairs from an array of code pairs - +const countryCurrencyPairs = [['US', 'USD'], ['CA', 'CAD']]; Acceptance Criteria: - +*/ +const countryCurrencyPairs = [['US', 'USD'], ['CA', 'CAD']]; + +test("createLookup returns an object with country codes as keys and currency codes as values", () => { + const lookup = createLookup(countryCurrencyPairs); + expect(lookup).toEqual({ + 'US': 'USD', + 'CA': 'CAD' + }); +}); +/* Given - An array of arrays representing country code and currency code pairs e.g. [['US', 'USD'], ['CA', 'CAD']] From cba30988d60d7552f8f41eb763bfed5ce8fe437c Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Wed, 11 Mar 2026 12:54:41 +0000 Subject: [PATCH 09/21] update to Sprint 2 lookup function and tests including testing of unhappy path --- Sprint-2/implement/lookup.js | 13 ++++++++++-- Sprint-2/implement/lookup.test.js | 35 ++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a7862d473..4ff88e057 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,8 +1,17 @@ function createLookup(pairs) { - // implementation here -const lookup = {};// create an empty object to store key-value pairs + +if (!Array.isArray(pairs)) {// check if the input is an array. If not, throw an error. + throw new Error("Input must be an array of pairs"); + } + + const lookup = {};// create an empty object to store key-value pairs + for (const pair of pairs) {// iterate through each pair in the input array + if (!Array.isArray(pair) || pair.length !== 2) {// check if the current pair is an array of length 2. If not, throw an error. + throw new Error("Each pair must be an array of two elements"); + } + const key = pair[0];// extract the first element of the pair as the key const value = pair[1];// extract the second element of the pair as the value lookup[key] = value;// add the key-value pair to the lookup object diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 9c0d5553d..6daf10981 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,8 +1,8 @@ const createLookup = require("./lookup.js"); - +//test.todo("creates a country currency code lookup for multiple codes");// /* - +Note this test script just tests the happy path of the function. Create a lookup object of key value pairs from an array of code pairs const countryCurrencyPairs = [['US', 'USD'], ['CA', 'CAD']]; Acceptance Criteria: @@ -41,4 +41,33 @@ It should return: 'US': 'USD', 'CA': 'CAD' } -*/ + +These are tests for empty and multiple pairs to test edge cases. + */ + +test("createLookup handles empty input array", () => { + const emptyPairs = []; + const lookup = createLookup(emptyPairs); + expect(lookup).toEqual({}); +}); + +test("createLookup handles multiple pairs", () => { + const morePairs = [['US', 'USD'], ['CA', 'CAD'], ['GB', 'GBP']]; + const lookup = createLookup(morePairs); + expect(lookup).toEqual({ + 'US': 'USD', + 'CA': 'CAD', + 'GB': 'GBP' + }); +}); + +// these test check unexpected input types to ensure the function can handle them gracefully. +test("createLookup handles non-array input", () => { + expect(() => createLookup("not an array")).toThrow(); +}); + +test("createLookup handles array with non-array elements", () => { + const invalidPairs = [['US', 'USD'], 'invalid pair']; + expect(() => createLookup(invalidPairs)).toThrow(); +}); + From 2ee1655bbf8df519555e329a18f03f6bb49897d1 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Wed, 11 Mar 2026 13:20:49 +0000 Subject: [PATCH 10/21] update to Sprint 2 querystring updated function and tests --- Sprint-2/implement/querystring.js | 14 ++++++++------ Sprint-2/implement/querystring.test.js | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..d26ce5902 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,13 +1,15 @@ function parseQueryString(queryString) { - const queryParams = {}; - if (queryString.length === 0) { + const queryParams = {}; // Initialize an empty object to store the key-value pairs + if (queryString.length === 0) {// If the input query string is empty, return the empty object return queryParams; } - const keyValuePairs = queryString.split("&"); + const keyValuePairs = queryString.split("&");// Split the query string into an array of key-value pairs using '&' as the delimiter - for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + for (const pair of keyValuePairs) {// Iterate through each key-value pair in the array + const separatorIndex = pair.indexOf("=");// Find the index of the '=' character in the current pair + const key = separatorIndex === -1 ? pair : pair.slice(0, separatorIndex);// Extract the key from the pair. If there is no '=', the entire pair is the key; otherwise, it's the substring before '=' + const value = separatorIndex === -1 ? "" : pair.slice(separatorIndex + 1);// Extract the value from the pair. If there is no '=', the value is an empty string; otherwise, it's the substring after '=' + queryParams[key] = value;// Add the key and value to the queryParams object } return queryParams; diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..158f8159d 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -10,3 +10,28 @@ test("parses querystring values containing =", () => { "equation": "x=y+1", }); }); + +test("parses querystring with multiple key-value pairs", () => { + expect(parseQueryString("equation1=x=y+1&equation2=z=w+1")).toEqual({ + "equation1": "x=y+1", + "equation2": "z=w+1" + }); +}); + + +test("parses querystring with keys but no values", () => { + expect(parseQueryString("equation1&equation2")).toEqual({ + "equation1": "", + "equation2": "" + }); +}); + +test ("parse querystring with empty string", () => { + expect(parseQueryString("")).toEqual({}); +}); + +test ("parses querystring with values and empty keys", () => { + expect(parseQueryString("z=w+1")).toEqual({ + "": "z=w+1" + }); +}); From b004cf49f064e2f3a0cca4692a2617542ec47bc9 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Wed, 11 Mar 2026 16:46:52 +0000 Subject: [PATCH 11/21] update to Sprint 2 querystring updated function and tests --- Sprint-2/implement/querystring.test.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 158f8159d..0dd2669e4 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -30,8 +30,3 @@ test ("parse querystring with empty string", () => { expect(parseQueryString("")).toEqual({}); }); -test ("parses querystring with values and empty keys", () => { - expect(parseQueryString("z=w+1")).toEqual({ - "": "z=w+1" - }); -}); From 2a7eae59fe6643318f815a09b922365dba00a44a Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Thu, 12 Mar 2026 09:26:35 +0000 Subject: [PATCH 12/21] update to Sprint 2 Contains test update. s --- Sprint-2/implement/contains.test.js | 11 ++++++----- Sprint-2/implement/tally.js | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 547c8b312..b1466695b 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -55,8 +55,9 @@ test("contains returns false for non-existent property", () => { // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error -test("contains handles invalid parameters", () => { - expect(contains([], "a")).toBe(false); - expect(contains(null, "a")).toBe(false); - expect(contains(undefined, "a")).toBe(false); -}); +test("contains returns false for invalid input types", () => { + const arr = [1, 2, 3]; + expect(contains(arr, "0")).toBe(false); // Arrays do not have properties like objects, so it should return false + expect(contains(null, "a")).toBe(false); // null is not an object, so it should return false + expect(contains(undefined, "a")).toBe(false); // undefined is not an object, so it should return false +}); \ No newline at end of file diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..faabde3b4 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,17 @@ function tally() {} +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 + +// Given an empty array, when passed to tally, then it should return an empty object + +for (let i = 0; i < 10; i++) {// Given an array with duplicate items, when passed to tally, then it should return counts for each unique item + + const input = Array.from({ length: Math.floor(Math.random() * 20) + 1 }, () => Math.floor(Math.random() * 10));// Generate a random array of numbers between 0 and 9, with a random length between 1 and 20 + const result = tally(input);// Call the tally function with the generated input array + const expected = input.reduce((acc, val) => {// Use reduce to create an object that counts the occurrences of each unique item in the input array + acc[val] = (acc[val] || 0) + 1;// For each value in the input array, increment the count for that value in the accumulator object. If the value does not exist in the accumulator, initialize it to 0 before incrementing. + return acc; + }, {}); + + }; module.exports = tally; From 07a67c7dccab77e7ed7ab461c22fd492fb7fa407 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Thu, 12 Mar 2026 09:56:51 +0000 Subject: [PATCH 13/21] changes to tally following testing --- Sprint-2/implement/tally.js | 23 +++++++++-------------- Sprint-2/implement/tally.test.js | 20 +++++++++++++++++++- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index faabde3b4..69cb0aa2b 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,17 +1,12 @@ -function tally() {} -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 +function tally(items) { + if (!Array.isArray(items)) { + throw new TypeError("Input must be an array"); + } -// Given an empty array, when passed to tally, then it should return an empty object - -for (let i = 0; i < 10; i++) {// Given an array with duplicate items, when passed to tally, then it should return counts for each unique item - - const input = Array.from({ length: Math.floor(Math.random() * 20) + 1 }, () => Math.floor(Math.random() * 10));// Generate a random array of numbers between 0 and 9, with a random length between 1 and 20 - const result = tally(input);// Call the tally function with the generated input array - const expected = input.reduce((acc, val) => {// Use reduce to create an object that counts the occurrences of each unique item in the input array - acc[val] = (acc[val] || 0) + 1;// For each value in the input array, increment the count for that value in the accumulator object. If the value does not exist in the accumulator, initialize it to 0 before incrementing. - return acc; - }, {}); - - }; + return items.reduce((counts, item) => { + 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..3eece97c7 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -20,10 +20,28 @@ const tally = require("./tally.js"); // When passed an array of items // Then it should return an object containing the count for each unique item +test("tally on an array of items returns counts for each unique item", () => { + const input = ["a"] + const result = tally(input); + const expected = { a: 1 }; + expect(result).toEqual(expected);}); + +const input = ["a", "a", "a"]; +const result = tally(input); +const expected = { a: 3 }; +expect(result).toEqual(expected); + + const input = ["a", "a", "b", "c"]; + const result = tally(input); + const expected = { a: 2, b: 1, c: 1 }; + expect(result).toEqual(expected); + + + // 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.todo("tally on an empty array returns an empty object"); // Given an array with duplicate items // When passed to tally From 24e9bac1dab839266f0ac9929cdd8afe666346eb Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Thu, 12 Mar 2026 10:09:07 +0000 Subject: [PATCH 14/21] update to tally and test for all cases --- Sprint-2/implement/tally.test.js | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 3eece97c7..3e53f98e1 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -20,22 +20,26 @@ const tally = require("./tally.js"); // When passed an array of items // Then it should return an object containing the count for each unique item -test("tally on an array of items returns counts for each unique item", () => { +test("tally on a single-item array returns count for one count", () => { const input = ["a"] const result = tally(input); const expected = { a: 1 }; expect(result).toEqual(expected);}); + +test("tally on an array with duplicate items returns count for each unique item", () => { const input = ["a", "a", "a"]; const result = tally(input); const expected = { a: 3 }; -expect(result).toEqual(expected); +expect(result).toEqual(expected); }); + +test("tally on an array with multiple items returns count for each unique item", () => { const input = ["a", "a", "b", "c"]; const result = tally(input); const expected = { a: 2, b: 1, c: 1 }; expect(result).toEqual(expected); - +}); // Given an empty array @@ -43,10 +47,29 @@ expect(result).toEqual(expected); // 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); + const expected = {}; + expect(result).toEqual(expected); +}); + // Given an array with duplicate items // When passed to tally // Then it should return counts for each unique item +test("tally on an array with duplicate items returns count for each unique item", () => { + const input = ["a", "a","a", "b","b", "c"]; + const result = tally(input); + const expected = { a: 3, b: 2, c: 1 }; + expect(result).toEqual(expected); +}); + // Given an invalid input like a string // When passed to tally // Then it should throw an error + +test("tally on a non-array input throws an error", () => { + const input = "not an array"; + expect(() => tally(input)).toThrow(TypeError); +}); \ No newline at end of file From 728710e1a72a8db324be16921a97622deeb06b3e Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Thu, 12 Mar 2026 10:55:38 +0000 Subject: [PATCH 15/21] update to invert including tests --- Sprint-2/interpret/invert.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..e40810e28 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -10,20 +10,37 @@ 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 } +const currentReturnValue = invert({ a: 1 }); +console.log(currentReturnValue); // Output: { key: 1 } // b) What is the current return value when invert is called with { a: 1, b: 2 } +const currentReturnValue2 = invert({ a: 1, b: 2 }); +console.log(currentReturnValue2); // Output: { key: 2 } // c) What is the target return value when invert is called with {a : 1, b: 2} +const currentReturnValue3 = invert({ a: 1, b: 2 }); +console.log(currentReturnValue3); // Output: { "1": "a", "2": "b" } // c) What does Object.entries return? Why is it needed in this program? +// Object.entries returns an array of a given object's own enumerable string-keyed property [key, value] pairs. It is needed in this program to iterate over the key-value pairs of the input object so that we can swap them and create the inverted object. // d) Explain why the current return value is different from the target output +// The current return value is different from the target output because in the current implementation, we are assigning the value to a property named "key" in the inverted object, instead of using the actual key from the original object. This results in only the last key-value pair being stored in the inverted object, and it does not correctly swap the keys and values as intended. // e) Fix the implementation of invert (and write tests to prove it's fixed!) +// Here's the corrected implementation of the invert function: + +//function invert(obj) { + //const invertedObj = {}; + //for (const [key, value] of Object.entries(obj)) { + //invertedObj[value] = key; + //} + //return invertedObj; +//} From 45dd97693c91a46e3dd067bc63b908de23b7d570 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Thu, 12 Mar 2026 11:09:21 +0000 Subject: [PATCH 16/21] update to invert including tests --- Sprint-2/interpret/invert.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index e40810e28..ec4ecda49 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -29,7 +29,7 @@ const currentReturnValue3 = invert({ a: 1, b: 2 }); console.log(currentReturnValue3); // Output: { "1": "a", "2": "b" } // c) What does Object.entries return? Why is it needed in this program? -// Object.entries returns an array of a given object's own enumerable string-keyed property [key, value] pairs. It is needed in this program to iterate over the key-value pairs of the input object so that we can swap them and create the inverted object. +// Object.entries returns an array of a given object's [key, value] pairs. It is needed in this program to iterate over the key-value pairs of the input object so that we can swap them and create the inverted object. // d) Explain why the current return value is different from the target output // The current return value is different from the target output because in the current implementation, we are assigning the value to a property named "key" in the inverted object, instead of using the actual key from the original object. This results in only the last key-value pair being stored in the inverted object, and it does not correctly swap the keys and values as intended. From f886f54ebf2ae8947ba25257a9ed32bb19426f84 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Mon, 16 Mar 2026 14:36:07 +0000 Subject: [PATCH 17/21] updates to querystringtest --- Sprint-2/implement/querystring.test.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 0dd2669e4..124cce002 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -5,10 +5,12 @@ const parseQueryString = require("./querystring.js") -test("parses querystring values containing =", () => { - expect(parseQueryString("equation=x=y+1")).toEqual({ - "equation": "x=y+1", - }); +test("given a query string with one pair of query params, returns them in object form", function () { + const input = "fruit=banana"; + const currentOutput = parseQueryString(input); + const targetOutput = { fruit: "banana" }; + + expect(currentOutput).toEqual(targetOutput); }); test("parses querystring with multiple key-value pairs", () => { @@ -28,5 +30,10 @@ test("parses querystring with keys but no values", () => { test ("parse querystring with empty string", () => { expect(parseQueryString("")).toEqual({}); + const input="" +const currentOutput=parseQueryString(input) +const targetOutput={} +expect(currentOutput).toEqual(targetOutput) + }); From 7adcbd89147be807ccaebf48a43f8032ec4fcbea Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Tue, 24 Mar 2026 14:34:49 +0000 Subject: [PATCH 18/21] updated recipe.js replacing for loop with .join to simplify code --- Sprint-2/debug/recipe.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 658667af6..db1d2afc3 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -9,9 +9,14 @@ const recipe = { serves: 2, ingredients: ["olive oil", "tomatoes", "salt", "pepper"], }; - +/* Replacing the for loop with Array.prototype.join() to log the ingredients in a single line, separated by new lines. console.log(`${recipe.title} serves ${recipe.serves}`); for (const ingredient of recipe.ingredients) { console.log(ingredient); } +*/ +console.log(`${recipe.title} serves ${recipe.serves}`); +console.log (recipe.ingredients.join("\n")); + + // The problem is that the code is trying to log out the ingredients using a for...of loop, but it is not using the correct syntax to access the ingredients. The recipe.ingredients is an array, so we need to use a for...of loop to iterate over that array and log each ingredient. \ No newline at end of file From 3698abb9e259704fc82988e81e0b4f7884d92c9c Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Tue, 24 Mar 2026 14:43:16 +0000 Subject: [PATCH 19/21] updated contains.js replacing Object.prototype.hasOwnProperty() with just Object.hasOwnProperty() to simplify code --- Sprint-2/implement/contains.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index d4381ffc7..282c8ec76 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -3,7 +3,7 @@ function contains(obj, prop) { !!obj && // confirm that obj is not null or undefined. If undefined or null, return false. typeof obj === "object" && // confirm that obj is an object. If not an object, return false. !Array.isArray(obj) && // confirm that obj is not an array. If an array, return false. - Object.prototype.hasOwnProperty.call(obj, prop)// check if the object has the property. If it does, return true; otherwise, return false. + Object.hasOwnProperty.call(obj, prop)// check if the object has the property. If it does, return true; otherwise, return false. ); } From fbd948cc958e55970adbaf8e7b178abeec682f65 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Tue, 24 Mar 2026 15:01:21 +0000 Subject: [PATCH 20/21] updated lookup.js and resaved to enable Prettier formatting --- Sprint-2/implement/lookup.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index 4ff88e057..33366fb60 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,23 +1,23 @@ function createLookup(pairs) { - -if (!Array.isArray(pairs)) {// check if the input is an array. If not, throw an error. + if (!Array.isArray(pairs)) { + // check if the input is an array. If not, throw an error. throw new Error("Input must be an array of pairs"); } - const lookup = {};// create an empty object to store key-value pairs - + const lookup = {}; // create an empty object to store key-value pairs -for (const pair of pairs) {// iterate through each pair in the input array - if (!Array.isArray(pair) || pair.length !== 2) {// check if the current pair is an array of length 2. If not, throw an error. + for (const pair of pairs) { + // iterate through each pair in the input array + if (!Array.isArray(pair) || pair.length !== 2) { + // check if the current pair is an array of length 2. If not, throw an error. throw new Error("Each pair must be an array of two elements"); - } + } - const key = pair[0];// extract the first element of the pair as the key - const value = pair[1];// extract the second element of the pair as the value - lookup[key] = value;// add the key-value pair to the lookup object + const key = pair[0]; // extract the first element of the pair as the key + const value = pair[1]; // extract the second element of the pair as the value + lookup[key] = value; // add the key-value pair to the lookup object } return lookup; -}; - +} module.exports = createLookup; From 98793906bd9ef3098f550de0379a218ff7459128 Mon Sep 17 00:00:00 2001 From: Damian_Dunkley Date: Tue, 24 Mar 2026 15:17:26 +0000 Subject: [PATCH 21/21] updated tally.js and test to expand testing for strings --- Sprint-2/implement/tally.js | 4 ++-- Sprint-2/implement/tally.test.js | 35 +++++++++++++++++++------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index 69cb0aa2b..800d362e9 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -4,9 +4,9 @@ function tally(items) { } return items.reduce((counts, item) => { - counts[item] = (counts[item] || 0) + 1; + counts[item] = (counts[item] ?? 0) + 1; return counts; - }, {}); + }, Object.create(null)); } module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 3e53f98e1..5295ec3e8 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -21,18 +21,18 @@ const tally = require("./tally.js"); // Then it should return an object containing the count for each unique item test("tally on a single-item array returns count for one count", () => { - const input = ["a"] + const input = ["a"]; const result = tally(input); const expected = { a: 1 }; - expect(result).toEqual(expected);}); - + expect(result).toEqual(expected); +}); test("tally on an array with duplicate items returns count for each unique item", () => { -const input = ["a", "a", "a"]; -const result = tally(input); -const expected = { a: 3 }; -expect(result).toEqual(expected); }); - + const input = ["a", "a", "a"]; + const result = tally(input); + const expected = { a: 3 }; + expect(result).toEqual(expected); +}); test("tally on an array with multiple items returns count for each unique item", () => { const input = ["a", "a", "b", "c"]; @@ -41,25 +41,24 @@ test("tally on an array with multiple items returns count for each unique item", expect(result).toEqual(expected); }); - // 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", () => { +test("tally on an empty array returns an empty object", () => { const input = []; const result = tally(input); const expected = {}; expect(result).toEqual(expected); -}); +}); // Given an array with duplicate items // When passed to tally // Then it should return counts for each unique item -test("tally on an array with duplicate items returns count for each unique item", () => { - const input = ["a", "a","a", "b","b", "c"]; +test("tally on an array with duplicate items returns count for each unique item", () => { + const input = ["a", "a", "a", "b", "b", "c"]; const result = tally(input); const expected = { a: 3, b: 2, c: 1 }; expect(result).toEqual(expected); @@ -72,4 +71,12 @@ test("tally on an array with duplicate items returns count for each unique item" test("tally on a non-array input throws an error", () => { const input = "not an array"; expect(() => tally(input)).toThrow(TypeError); -}); \ No newline at end of file +}); + +test("tally counts keys like toString correctly", () => { + const input = ["toString", "toString"]; + const result = tally(input); + const expected = Object.create(null); + expected.toString = 2; + expect(result).toEqual(expected); +});