From 2baf830ae575af2d229c5205914e65f7bd7916d3 Mon Sep 17 00:00:00 2001 From: Arunkumar Akilan Date: Tue, 17 Mar 2026 09:13:15 +0000 Subject: [PATCH 1/5] feat: clean Sprint-2 implementation and tests --- Sprint-2/debug/address.js | 2 +- Sprint-2/debug/author.js | 13 +++++++---- Sprint-2/debug/recipe.js | 14 +++++++---- Sprint-2/implement/contains.js | 20 +++++++++++++++- Sprint-2/implement/contains.test.js | 32 ++++++++++++++++++++++++++ Sprint-2/implement/lookup.js | 10 ++++++-- Sprint-2/implement/lookup.test.js | 9 ++++++++ Sprint-2/implement/querystring.js | 6 +++-- Sprint-2/implement/querystring.test.js | 15 ++++++++++++ Sprint-2/implement/tally.js | 17 +++++++++++++- Sprint-2/implement/tally.test.js | 9 ++++++++ Sprint-2/interpret/invert.js | 11 +++++++-- Sprint-2/interpret/invert.test.js | 10 ++++++++ 13 files changed, 151 insertions(+), 17 deletions(-) create mode 100644 Sprint-2/interpret/invert.test.js diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..fde180d6d 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -12,4 +12,4 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +console.log(`My house number is ${address["houseNumber"]}`); diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..876962002 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,5 +1,6 @@ // Predict and explain first... - +// The program throws an error because a for...of loop only works with iterable values like arrays or strings. +// The author variable is an object, which is not iterable by default, so JavaScript cannot loop through it. // 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 @@ -10,7 +11,11 @@ const author = { age: 40, alive: true, }; - -for (const value of author) { - console.log(value); +const values = Object.values(author); +for(const item of values) +{ + console.log(item); } + + + diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..15a450935 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,5 +1,6 @@ // Predict and explain first... - +//The title and serves values print correctly because the properties are accessed directly using +// recipe.title and recipe.serves. // 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? @@ -10,6 +11,11 @@ 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 ingredients of recipe.ingredients) +{ + console.log(`*${ingredients}`) +} + +//The program prints the recipe title and number of servings. +// Then it loops through the ingredients array and logs each ingredient on a new line so they are displayed individually instead of printing the whole object. \ No newline at end of file diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..8cee952a2 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,21 @@ -function contains() {} +function contains(object, propertyName) { + if(typeof object !== 'object' || Array.isArray(object) || object=== null) + { + throw new Error("It is a invalid object") + } + const newArray = Object.keys(object); + for(let item of newArray) + { + if (item === propertyName) + { + return true + } + + + + } + return false; +} + module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..b64015f11 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -11,6 +11,38 @@ E.g. contains({a: 1, b: 2}, 'c') // returns false as the object doesn't contains a key of 'c' */ +test("An empty object should return false",()=>{ + const object = {}; + const propertyName = "a"; + expect(contains(object, propertyName)).toEqual(false); +}); + + +test("returns true when the object contains an existing property name", () => { + const object = { a: 1, b: 2, c: 3 }; + const propertyName = "a"; + expect(contains(object, propertyName)).toEqual(true); +}); +test("returns false when the object not contains an existing property name", () => { + const object = { a: 1, b: 2, c: 3 }; + const propertyName = "d"; + expect(contains(object, propertyName)).toEqual(false); +}); +test("Should throw an error for an invalid parameters", () => { + const object = [1,2,3,4,5,6,7]; + const propertyName = "a"; + expect(() => contains(object, propertyName)).toThrow(); +}); +test("Should throw an error for an invalid parameters", () => { + const object = null; + const propertyName = "a"; + expect(() => contains(object, propertyName)).toThrow(); +}); +test("Should throw an error for an invalid parameters", () => { + const object = "hi"; + const propertyName = "a"; + expect(() => contains(object, propertyName)).toThrow(); +}); // Acceptance criteria: // Given a contains function diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..e5f1addc0 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 countryCurrencyLookup = {}; + + for (let item of countryCurrencyPairs) { + const [key, value] = [item[0], item[1]]; + countryCurrencyLookup[key] = value; + } + return countryCurrencyLookup; } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..a1b82e864 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -2,6 +2,15 @@ const createLookup = require("./lookup.js"); test.todo("creates a country currency code lookup for multiple codes"); +test("An array of arrays representing country code and currency code should return an object where the keys are country code values are currency code",()=>{ + const countryCurrencyPairs = [['IND', 'INR'], ['US', 'USD'], ['UK', 'GBR'], ['CA','CAD'] ]; + expect(createLookup(countryCurrencyPairs)).toEqual({ + IND: "INR", + US: "USD", + UK: "GBR", + CA: "CAD", + }); +}) /* Create a lookup object of key value pairs from an array of code pairs diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..118a27b53 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -5,8 +5,10 @@ function parseQueryString(queryString) { } const keyValuePairs = queryString.split("&"); - for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); + for (const item of keyValuePairs) { + const pair = item.split("="); + const key = pair.shift(); + const value = pair.join("="); queryParams[key] = value; } diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..c5681bec4 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -10,3 +10,18 @@ test("parses querystring values containing =", () => { "equation": "x=y+1", }); }); +test("An empty string should return an empty object",()=>{ + expect(parseQueryString("")).toEqual({}); +}); +test("parses querystring parameters with an empty value",()=>{ + expect(parseQueryString("name=")).toEqual({name :""}); +}); +test("handles querystring parameters that have no = sign",()=>{ + expect(parseQueryString("flag")).toEqual({flag:""}) +}); +test("parses querystring values containing multiple = characters",()=>{ + expect(parseQueryString("token=a=b=c=d")).toEqual({token:"a=b=c=d"}); +}); +test("handles multiple querystring parameters when one value contains =",()=>{ + expect(parseQueryString("a=1&equation=x=y+1")).toEqual({a:"1", equation:"x=y+1"}); +}); diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..88ff23bb1 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,18 @@ -function tally() {} +function tally(arr) { + const object = {}; + if(!Array.isArray(arr)) + { + throw new Error("Invalid input: tally expects an array"); + } + if(arr.length === 0) + { + return object; + } + arr.forEach(ele =>{ + object[ele] =(object[ele] || 0) + 1; + + }); + return object; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..691b622be 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -13,6 +13,15 @@ const tally = require("./tally.js"); * tally(['a', 'a', 'a']), target output: { a: 3 } * tally(['a', 'a', 'b', 'c']), target output: { a : 2, b: 1, c: 1 } */ +test("throws an error when the input is not an array", ()=>{ + expect(()=>tally("hi")).toThrow(); +}); +test("returns an empty object when the input array is empty",()=>{ + expect(tally([])).toEqual({}); +}); +test("returns the count of each unique item in the array", ()=>{ + expect(tally(['a','b','a','c','b','a'])).toEqual({a:3,b:2,c:1}) +}); // Acceptance criteria: diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..0cdc4da5e 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -9,21 +9,28 @@ function invert(obj) { const invertedObj = {}; - for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + for (const [value, key] of Object.entries(obj)) { + invertedObj[key] = value; } 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:1, 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? +// Object.entries() returns an array of [key, value] pairs from an object. It is used here to loop through the object and access both the key and value in each iteration. // d) Explain why the current return value is different from the target output +// The return value is different because the program uses dot notation with a variable instead of bracket notation. +// Also, the object needs to be inverted, so the key and value must be swapped when iterating through the entries. // e) Fix the implementation of invert (and write tests to prove it's fixed!) diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js new file mode 100644 index 000000000..a5d0a564b --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,10 @@ +const invert = require("./invert"); + +test("returns an object with the key and value swapped when given a single key-value pair", ()=>{ + expect(invert({a:1})).toEqual({'1':'a'}) +}); + +test("returns an object with all keys and values swapped for multiple key-value pairs",()=>{ + + expect(invert({a:1, b:2})).toEqual({'1':'a','2':'b'}) +}); \ No newline at end of file From a149a4c062998ac28872c7d7ca155da82fb00a0e Mon Sep 17 00:00:00 2001 From: Arunkumar Akilan Date: Mon, 23 Mar 2026 10:14:03 +0000 Subject: [PATCH 2/5] style: format Sprint-2 with Prettier --- Sprint-2/debug/author.js | 10 +++------- Sprint-2/debug/recipe.js | 11 +++++------ Sprint-2/implement/contains.js | 25 +++++++++---------------- Sprint-2/implement/contains.test.js | 11 +++++------ Sprint-2/implement/lookup.js | 2 +- Sprint-2/implement/lookup.test.js | 23 ++++++++++++++--------- Sprint-2/implement/querystring.test.js | 25 ++++++++++++++----------- Sprint-2/implement/tally.js | 23 ++++++++++------------- Sprint-2/implement/tally.test.js | 12 ++++++------ Sprint-2/interpret/invert.test.js | 11 +++++------ 10 files changed, 72 insertions(+), 81 deletions(-) diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 876962002..0e7093954 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,5 +1,5 @@ // Predict and explain first... -// The program throws an error because a for...of loop only works with iterable values like arrays or strings. +// The program throws an error because a for...of loop only works with iterable values like arrays or strings. // The author variable is an object, which is not iterable by default, so JavaScript cannot loop through it. // 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 @@ -12,10 +12,6 @@ const author = { alive: true, }; const values = Object.values(author); -for(const item of values) -{ - console.log(item); +for (const item of values) { + console.log(item); } - - - diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 15a450935..ef6de51a0 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,5 +1,5 @@ // Predict and explain first... -//The title and serves values print correctly because the properties are accessed directly using +//The title and serves values print correctly because the properties are accessed directly using // recipe.title and recipe.serves. // This program should log out the title, how many it serves and the ingredients. // Each ingredient should be logged on a new line @@ -12,10 +12,9 @@ const recipe = { }; console.log(`${recipe.title} serves ${recipe.serves}`); -for(const ingredients of recipe.ingredients) -{ - console.log(`*${ingredients}`) +for (const ingredients of recipe.ingredients) { + console.log(`*${ingredients}`); } -//The program prints the recipe title and number of servings. -// Then it loops through the ingredients array and logs each ingredient on a new line so they are displayed individually instead of printing the whole object. \ No newline at end of file +//The program prints the recipe title and number of servings. +// Then it loops through the ingredients array and logs each ingredient on a new line so they are displayed individually instead of printing the whole object. diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index 8cee952a2..5c5d94b89 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,21 +1,14 @@ function contains(object, propertyName) { - if(typeof object !== 'object' || Array.isArray(object) || object=== null) - { - throw new Error("It is a invalid object") + if (typeof object !== "object" || Array.isArray(object) || object === null) { + throw new Error("It is a invalid object"); + } + const newArray = Object.keys(object); + for (let item of newArray) { + if (item === propertyName) { + return true; } - const newArray = Object.keys(object); - for(let item of newArray) - { - if (item === propertyName) - { - return true - } - - - - } - return false; + } + return false; } - module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index b64015f11..79aba2ce1 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -11,12 +11,11 @@ E.g. contains({a: 1, b: 2}, 'c') // returns false as the object doesn't contains a key of 'c' */ -test("An empty object should return false",()=>{ - const object = {}; - const propertyName = "a"; - expect(contains(object, propertyName)).toEqual(false); +test("An empty object should return false", () => { + const object = {}; + const propertyName = "a"; + expect(contains(object, propertyName)).toEqual(false); }); - test("returns true when the object contains an existing property name", () => { const object = { a: 1, b: 2, c: 3 }; @@ -29,7 +28,7 @@ test("returns false when the object not contains an existing property name", () expect(contains(object, propertyName)).toEqual(false); }); test("Should throw an error for an invalid parameters", () => { - const object = [1,2,3,4,5,6,7]; + const object = [1, 2, 3, 4, 5, 6, 7]; const propertyName = "a"; expect(() => contains(object, propertyName)).toThrow(); }); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index e5f1addc0..683a2a9c5 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -3,7 +3,7 @@ function createLookup(countryCurrencyPairs) { for (let item of countryCurrencyPairs) { const [key, value] = [item[0], item[1]]; - countryCurrencyLookup[key] = value; + countryCurrencyLookup[key] = value; } return countryCurrencyLookup; } diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index a1b82e864..7c2a25575 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -2,15 +2,20 @@ const createLookup = require("./lookup.js"); test.todo("creates a country currency code lookup for multiple codes"); -test("An array of arrays representing country code and currency code should return an object where the keys are country code values are currency code",()=>{ - const countryCurrencyPairs = [['IND', 'INR'], ['US', 'USD'], ['UK', 'GBR'], ['CA','CAD'] ]; - expect(createLookup(countryCurrencyPairs)).toEqual({ - IND: "INR", - US: "USD", - UK: "GBR", - CA: "CAD", - }); -}) +test("An array of arrays representing country code and currency code should return an object where the keys are country code values are currency code", () => { + const countryCurrencyPairs = [ + ["IND", "INR"], + ["US", "USD"], + ["UK", "GBR"], + ["CA", "CAD"], + ]; + expect(createLookup(countryCurrencyPairs)).toEqual({ + IND: "INR", + US: "USD", + UK: "GBR", + CA: "CAD", + }); +}); /* Create a lookup object of key value pairs from an array of code pairs diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index c5681bec4..939c0a0cb 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -3,25 +3,28 @@ // Below is one test case for an edge case the implementation doesn't handle well. // Fix the implementation for this test, and try to think of as many other edge cases as possible - write tests and fix those too. -const parseQueryString = require("./querystring.js") +const parseQueryString = require("./querystring.js"); test("parses querystring values containing =", () => { expect(parseQueryString("equation=x=y+1")).toEqual({ - "equation": "x=y+1", + equation: "x=y+1", }); }); -test("An empty string should return an empty object",()=>{ +test("An empty string should return an empty object", () => { expect(parseQueryString("")).toEqual({}); }); -test("parses querystring parameters with an empty value",()=>{ - expect(parseQueryString("name=")).toEqual({name :""}); +test("parses querystring parameters with an empty value", () => { + expect(parseQueryString("name=")).toEqual({ name: "" }); }); -test("handles querystring parameters that have no = sign",()=>{ - expect(parseQueryString("flag")).toEqual({flag:""}) +test("handles querystring parameters that have no = sign", () => { + expect(parseQueryString("flag")).toEqual({ flag: "" }); }); -test("parses querystring values containing multiple = characters",()=>{ - expect(parseQueryString("token=a=b=c=d")).toEqual({token:"a=b=c=d"}); +test("parses querystring values containing multiple = characters", () => { + expect(parseQueryString("token=a=b=c=d")).toEqual({ token: "a=b=c=d" }); }); -test("handles multiple querystring parameters when one value contains =",()=>{ - expect(parseQueryString("a=1&equation=x=y+1")).toEqual({a:"1", equation:"x=y+1"}); +test("handles multiple querystring parameters when one value contains =", () => { + expect(parseQueryString("a=1&equation=x=y+1")).toEqual({ + a: "1", + equation: "x=y+1", + }); }); diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index 88ff23bb1..ab9d546ec 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,18 +1,15 @@ function tally(arr) { - const object = {}; - if(!Array.isArray(arr)) - { - throw new Error("Invalid input: tally expects an array"); - } - if(arr.length === 0) - { - return object; - } - arr.forEach(ele =>{ - object[ele] =(object[ele] || 0) + 1; - - }); + const object = {}; + if (!Array.isArray(arr)) { + throw new Error("Invalid input: tally expects an array"); + } + if (arr.length === 0) { return object; + } + arr.forEach((ele) => { + object[ele] = (object[ele] || 0) + 1; + }); + return object; } module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 691b622be..e07cdfe03 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -13,14 +13,14 @@ const tally = require("./tally.js"); * tally(['a', 'a', 'a']), target output: { a: 3 } * tally(['a', 'a', 'b', 'c']), target output: { a : 2, b: 1, c: 1 } */ -test("throws an error when the input is not an array", ()=>{ - expect(()=>tally("hi")).toThrow(); +test("throws an error when the input is not an array", () => { + expect(() => tally("hi")).toThrow(); }); -test("returns an empty object when the input array is empty",()=>{ - expect(tally([])).toEqual({}); +test("returns an empty object when the input array is empty", () => { + expect(tally([])).toEqual({}); }); -test("returns the count of each unique item in the array", ()=>{ - expect(tally(['a','b','a','c','b','a'])).toEqual({a:3,b:2,c:1}) +test("returns the count of each unique item in the array", () => { + expect(tally(["a", "b", "a", "c", "b", "a"])).toEqual({ a: 3, b: 2, c: 1 }); }); // Acceptance criteria: diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js index a5d0a564b..813a644b8 100644 --- a/Sprint-2/interpret/invert.test.js +++ b/Sprint-2/interpret/invert.test.js @@ -1,10 +1,9 @@ const invert = require("./invert"); -test("returns an object with the key and value swapped when given a single key-value pair", ()=>{ - expect(invert({a:1})).toEqual({'1':'a'}) +test("returns an object with the key and value swapped when given a single key-value pair", () => { + expect(invert({ a: 1 })).toEqual({ 1: "a" }); }); -test("returns an object with all keys and values swapped for multiple key-value pairs",()=>{ - - expect(invert({a:1, b:2})).toEqual({'1':'a','2':'b'}) -}); \ No newline at end of file +test("returns an object with all keys and values swapped for multiple key-value pairs", () => { + expect(invert({ a: 1, b: 2 })).toEqual({ 1: "a", 2: "b" }); +}); From 900dfb7df0e816cd336af607f4ac327787b03bcf Mon Sep 17 00:00:00 2001 From: Arunkumar Akilan Date: Mon, 23 Mar 2026 11:21:50 +0000 Subject: [PATCH 3/5] refactor: improve invert readability by using [key, value] destructuring --- Sprint-2/interpret/invert.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index 0cdc4da5e..af8f43837 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -9,8 +9,8 @@ function invert(obj) { const invertedObj = {}; - for (const [value, key] of Object.entries(obj)) { - invertedObj[key] = value; + for (const [key, value ] of Object.entries(obj)) { + invertedObj[value] = key; } return invertedObj; From 3fee122f69da5afa331b57b45749024598fdfd0b Mon Sep 17 00:00:00 2001 From: Arunkumar Akilan Date: Mon, 23 Mar 2026 11:55:11 +0000 Subject: [PATCH 4/5] feat: complete tally implementation and handle special keys like toString --- Sprint-2/implement/tally.js | 2 +- Sprint-2/implement/tally.test.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index ab9d546ec..f267735da 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,5 +1,5 @@ function tally(arr) { - const object = {}; + const object = Object.create(null); if (!Array.isArray(arr)) { throw new Error("Invalid input: tally expects an array"); } diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index e07cdfe03..a42cff6b4 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -22,6 +22,9 @@ test("returns an empty object when the input array is empty", () => { test("returns the count of each unique item in the array", () => { expect(tally(["a", "b", "a", "c", "b", "a"])).toEqual({ a: 3, b: 2, c: 1 }); }); +test("handles special keys like toString", () => { + expect(tally(["toString", "toString"])).toEqual({ "toString": 2 }); +}); // Acceptance criteria: @@ -32,7 +35,7 @@ test("returns the count of each unique item in the array", () => { // 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"); + // Given an array with duplicate items // When passed to tally From 5930937d8c210e7e5ce96d4e7ae1397b4e1315fc Mon Sep 17 00:00:00 2001 From: Arunkumar Akilan Date: Mon, 23 Mar 2026 12:18:44 +0000 Subject: [PATCH 5/5] test: add edge case tests for parseQueryString and handle invalid query pairs --- Sprint-2/implement/querystring.js | 1 + Sprint-2/implement/querystring.test.js | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 118a27b53..566456f03 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -9,6 +9,7 @@ function parseQueryString(queryString) { const pair = item.split("="); const key = pair.shift(); const value = pair.join("="); + if (!key) continue; queryParams[key] = value; } diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 939c0a0cb..b5571848e 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -28,3 +28,27 @@ test("handles multiple querystring parameters when one value contains =", () => equation: "x=y+1", }); }); +test("ignores pairs with missing key (=b)", () => { + expect(parseQueryString("=b")).toEqual({}); +}); + +test("ignores empty pairs (double &&)", () => { + expect(parseQueryString("a=b&&c=d")).toEqual({ + a: "b", + c: "d", + }); +}); +test("ignores empty key and value (=)", () => { + expect(parseQueryString("=")).toEqual({}); +}); +test("ignores invalid pairs but keeps valid ones", () => { + expect(parseQueryString("a=b&=&c=d")).toEqual({ + a: "b", + c: "d", + }); +}); +test("keeps key with empty value", () => { + expect(parseQueryString("a=")).toEqual({ + a: "", + }); +}); \ No newline at end of file