From eb4db925fc0e5b2b02dcf71fff5386a7e4569d04 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Wed, 9 Jul 2025 14:14:37 +0100 Subject: [PATCH 01/11] address.js is debuged --- Sprint-2/debug/address.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..ddabb97f3 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,5 +1,9 @@ // Predict and explain first... +//The code is trying to access address[0], but address is an object, not an array. +//Objects use keys (like houseNumber) instead of numeric indices. +//So address[0] is undefined, because there is no property with the key "0". + // This code should log out the houseNumber from the address object // but it isn't working... // Fix anything that isn't working @@ -12,4 +16,8 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +console.log(`My house number is ${address.houseNumber}`); + +// The code is correct and will log "My house number is 42" to the console. + +// My house number is 42 From 8cfea902bbd627f4af931375fba733ad3112c2f6 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Wed, 9 Jul 2025 14:29:24 +0100 Subject: [PATCH 02/11] author.js file debuged and tested --- Sprint-2/debug/author.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..9a8d25dad 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,5 +1,10 @@ // Predict and explain first... +//This code tries to use a for...of loop on an object, but objects are not iterable by default. +//for...of works on iterables like arrays, strings, maps, sets — not plain objects. +//Running this will throw: +//TypeError: author is not iterable + // 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 +16,6 @@ const author = { alive: true, }; -for (const value of author) { +for (const value of Object.values(author)) { console.log(value); } From b7a8e42d46aa0c2d6115803b5f9d327ef3b96763 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Wed, 9 Jul 2025 14:41:09 +0100 Subject: [PATCH 03/11] recipe.js file debugged and tested --- Sprint-2/debug/recipe.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..058d6ce0a 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,4 +1,7 @@ // Predict and explain first... +//${recipe} tries to insert the entire object (recipe) directly into the string. +//This will result in something like:[object Object] + // 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 +13,7 @@ const recipe = { ingredients: ["olive oil", "tomatoes", "salt", "pepper"], }; -console.log(`${recipe.title} serves ${recipe.serves} +console.log(`${recipe.title} + serves ${recipe.serves} ingredients: -${recipe}`); +${recipe.ingredients.join("\n")}`); From 6da782c6b820ce2b41f0284ea7a39e682f5c5c7a Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Wed, 9 Jul 2025 14:53:10 +0100 Subject: [PATCH 04/11] added explanation --- Sprint-2/debug/recipe.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 058d6ce0a..e9caad284 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -17,3 +17,5 @@ console.log(`${recipe.title} serves ${recipe.serves} ingredients: ${recipe.ingredients.join("\n")}`); +//recipe.ingredients is an array: ["olive oil", "tomatoes", "salt", "pepper"] +//.join("\n") turns that array into a string, separating each ingredient with a newline (\n) \ No newline at end of file From 95b65e76f24c39cf38852ee34a63f01849e49904 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Wed, 9 Jul 2025 21:36:28 +0100 Subject: [PATCH 05/11] contains function made and tested --- Sprint-2/implement/contains.js | 10 ++++++++-- Sprint-2/implement/contains.test.js | 21 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..79b3442e3 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,9 @@ -function contains() {} +function contains(obj, prop) { + if (typeof obj !== "object" || obj === null || Array.isArray(obj)) { + throw new Error("Invalid input: must be a non-null object"); + } -module.exports = contains; + return obj.hasOwnProperty(prop); +} + +module.exports = contains; \ No newline at end of file diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..895c3598d 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -20,16 +20,35 @@ 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"); + +// Empty object should return false +test("contains on empty object returns false", () => { + const result = contains({}, "a"); + expect(result).toBe(false); }); // Given an object with properties // When passed to contains with an existing property name // Then it should return true +// Object with properties and existing key should return true +test("contains returns true for existing property", () => { + const obj = { a: 1, b: 2 }; + const result = contains(obj, "a"); + expect(result).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 for non-existing property", () => { +const obj = { a: 1, b: 2 }; + const result = contains(obj, "c"); + expect(result).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 or throws when input is not an object", () => { + const obj = ["a", "b"]; + expect(() => contains(["a", "b"], "a")).toThrow(); }); \ No newline at end of file From f72123372c0f9603b4088510b06d913ca22222d2 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Wed, 9 Jul 2025 21:57:55 +0100 Subject: [PATCH 06/11] lookup function is done and tested --- Sprint-2/implement/lookup.js | 8 +++++++- Sprint-2/implement/lookup.test.js | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..20907e476 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,4 +1,10 @@ -function createLookup() { +function createLookup(pairs) { + const lookup= {}; + for (let [countryCode, currencyCode] of pairs) { + lookup[countryCode] = currencyCode; + } + + return lookup; // implementation here } diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..a54284a85 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,8 +1,18 @@ 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 expected = { + US: 'USD', + CA: 'CAD' + }; + expect(createLookup(input)).toEqual(expected); +}); + + /* Create a lookup object of key value pairs from an array of code pairs From 95a40d5676447f82b1cd29074cfa78dd0dacec5f Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Fri, 11 Jul 2025 23:10:11 +0100 Subject: [PATCH 07/11] querystring.js bug is fixed and tested --- Sprint-2/implement/querystring.js | 15 +++++++++------ Sprint-2/implement/querystring.test.js | 26 ++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..274178f2c 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,15 +1,18 @@ function parseQueryString(queryString) { const queryParams = {}; - if (queryString.length === 0) { - return queryParams; - } + if (!queryString) return queryParams; + const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; - } + const [key, ...rest] = pair.split("="); // Grab everything after first '=' + const value = rest.join("="); // Safely join back if value had '=' signs + + const decodedKey = decodeURIComponent((key || "").replace(/\+/g, " ")); + const decodedValue = decodeURIComponent((value || "").replace(/\+/g, " ")); + queryParams[decodedKey] = decodedValue; + } return queryParams; } diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..d2c5e2511 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -5,8 +5,30 @@ const parseQueryString = require("./querystring.js") -test("parses querystring values containing =", () => { - expect(parseQueryString("equation=x=y+1")).toEqual({ +test("parses querystring values containing +", () => { + expect(parseQueryString("equation=x%3Dy%2B1")).toEqual({ "equation": "x=y+1", }); }); + test("returns empty object for empty query string", () => { + expect(parseQueryString("")).toEqual({}); +}); + +test("parses single key with empty value", () => { + expect(parseQueryString("foo=")).toEqual({ foo: "" }); +}); + +test("parses single key with no equals sign", () => { + expect(parseQueryString("foo")).toEqual({ foo: "" }); +}); + +test("parses multiple key-value pairs", () => { + expect(parseQueryString("a=1&b=2")).toEqual({ a: "1", b: "2" }); +}); + +test("decodes URL-encoded characters", () => { + expect(parseQueryString("name=John%20Doe&city=New%20York")).toEqual({ + name: "John Doe", + city: "New York", + }); +}); \ No newline at end of file From 499b60afe1fc1f46c93991516e6b06197ff3762f Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Fri, 11 Jul 2025 23:19:28 +0100 Subject: [PATCH 08/11] tally.js function made and tested --- Sprint-2/implement/tally.js | 22 +++++++++++++++++++++- Sprint-2/implement/tally.test.js | 15 +++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..8e4ad7e25 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,23 @@ -function tally() {} +function tally(items) { + // Validate input: must be an array + if (!Array.isArray(items)) { + throw new Error("Input must be an array"); + } + + // Create an object to hold counts + const counts = {}; + + // Loop through each item and count occurrences + for (const item of items) { + if (counts[item]) { + counts[item] += 1; + } else { + counts[item] = 1; + } + } + + return counts; +} module.exports = tally; + diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..c09a1dc66 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -23,12 +23,23 @@ 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 each unique item correctly", () => { + 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 error on non-array input", () => { + expect(() => tally("not-an-array")).toThrow("Input must be an array"); +}); From 4d3c115355bdece54d4d0ffaa70bfa1fd5a92af8 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Sat, 12 Jul 2025 12:47:39 +0100 Subject: [PATCH 09/11] invert.js fixed and tested --- Sprint-2/interpret/invert.js | 11 ++++++++++- Sprint-2/interpret/invert.test.js | 7 +++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 Sprint-2/interpret/invert.test.js diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..64432ff57 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; } +console.log(invert({ a: 1, b: 2 })); // 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? +//This is a built-in JavaScript method that takes an object and returns an array of key-value pairs as arrays. // d) Explain why the current return value is different from the target output +// it is different because current code is not doing what we was expecting. // e) Fix the implementation of invert (and write tests to prove it's fixed!) + +module.exports = invert; \ 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..d13907664 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,7 @@ +const invert = require("./invert.js"); + +test("inverts a simple object with unique values", () => { + const input = { a: 1, b: 2 }; + const expectedOutput = { 1: "a", 2: "b" }; + expect(invert(input)).toEqual(expectedOutput); +}); \ No newline at end of file From 088b2203c55f9b7a79e6519863543d52ee1ad49b Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Thu, 24 Jul 2025 19:50:20 +0100 Subject: [PATCH 10/11] added new tests --- Sprint-2/implement/lookup.test.js | 42 +++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index a54284a85..873221964 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -3,15 +3,46 @@ const createLookup = require("./lookup.js"); test("creates a country currency code lookup for multiple codes", () => { const input = [ ['US', 'USD'], - ['CA', 'CAD'] + ['CA', 'CAD'], + ['UK', 'GBP'], ]; const expected = { US: 'USD', - CA: 'CAD' + CA: 'CAD', + UK: 'GBP' }; expect(createLookup(input)).toEqual(expected); }); +test("returns an empty object when given an empty array", () => { + expect(createLookup([])).toEqual({}); +}); + +test("overwrites value if a country code appears more than once", () => { + const input = [ + ['UK', 'GBP'], + ['UK', 'POUND'] + ]; + expect(createLookup(input)).toEqual({ UK: 'POUND' }); +}); + +test("ignores extra values in pairs", () => { + const input = [ + ['UK', 'GBP', 'Extra'], + ['US', 'USD'] + ]; + expect(createLookup(input)).toEqual({ UK: 'GBP', US: 'USD' }); +}); + +test("ignores invalid pairs (less than two elements)", () => { + const input = [ + ['UK'], // Invalid + ['US', 'USD'] + ]; + expect(createLookup(input)).toEqual({ US: 'USD' }); +}); + + /* Create a lookup object of key value pairs from an array of code pairs @@ -20,7 +51,7 @@ Acceptance Criteria: Given - An array of arrays representing country code and currency code pairs - e.g. [['US', 'USD'], ['CA', 'CAD']] + e.g. [['US', 'USD'], ['CA', 'CAD'],['UK','GBP']] When - createLookup function is called with the country-currency array as an argument @@ -31,7 +62,7 @@ Then - The values are the corresponding currency codes Example -Given: [['US', 'USD'], ['CA', 'CAD']] +Given: [['US', 'USD'], ['CA', 'CAD'], ['UK', 'GPB']] When createLookup(countryCurrencyPairs) is called @@ -40,6 +71,7 @@ Then It should return: { 'US': 'USD', - 'CA': 'CAD' + 'CA': 'CAD', + 'UK': 'GBP' } */ From 0a95ae92078319aab4348ae6cddcb211ff084ab4 Mon Sep 17 00:00:00 2001 From: HilolaRustamova Date: Wed, 13 Aug 2025 19:54:47 +0100 Subject: [PATCH 11/11] added test containing equal signs --- Sprint-2/implement/querystring.test.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index d2c5e2511..a01416499 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -31,4 +31,10 @@ test("decodes URL-encoded characters", () => { name: "John Doe", city: "New York", }); +}); + +test("parses values containing =", () => { + expect(parseQueryString("token=abc=123")).toEqual({ + token: "abc=123" + }); }); \ No newline at end of file