diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..3fff53389 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,6 @@ -function contains() {} +function contains(obj, prop) { + if (typeof obj !== "object" || obj === null || Array.isArray(obj)) return false; + return Object.hasOwn(obj, prop); +} module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..5f8755aa2 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -1,35 +1,17 @@ const contains = require("./contains.js"); -/* -Implement a function called contains that checks an object contains a -particular property +test("contains on empty object returns false", () => { + expect(contains({}, "a")).toBe(false); +}); -E.g. contains({a: 1, b: 2}, 'a') // returns true -as the object contains a key of 'a' +test("returns true when object has the property", () => { + expect(contains({ a: 1, b: 2 }, "a")).toBe(true); +}); -E.g. contains({a: 1, b: 2}, 'c') // returns false -as the object doesn't contains a key of 'c' -*/ +test("returns false when object does not have the property", () => { + expect(contains({ a: 1, b: 2 }, "c")).toBe(false); +}); -// Acceptance criteria: - -// 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 - -// Given an empty object -// When passed to contains -// Then it should return false -test.todo("contains on empty object returns false"); - -// Given an object with properties -// When passed to contains with an existing property name -// Then it should return true - -// Given an object with properties -// When passed to contains with a non-existent property name -// Then it should return false - -// Given invalid parameters like an array -// When passed to contains -// Then it should return false or throw an error +test("returns false for array input", () => { + expect(contains([1, 2, 3], "0")).toBe(false); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..81db95cb0 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,5 @@ -function createLookup() { - // implementation here +function createLookup(pairs) { + return Object.fromEntries(pairs); } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..ecf63947d 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,35 +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", () => { + expect(createLookup([["US", "USD"], ["CA", "CAD"]])).toEqual({ US: "USD", CA: "CAD" }); +}); -/* +test("returns empty object for empty array", () => { + expect(createLookup([])).toEqual({}); +}); -Create a lookup object of key value pairs from an array of code pairs - -Acceptance Criteria: - -Given - - An array of arrays representing country code and currency code pairs - e.g. [['US', 'USD'], ['CA', 'CAD']] - -When - - createLookup function is called with the country-currency array as an argument - -Then - - It should return an object where: - - The keys are the country codes - - The values are the corresponding currency codes - -Example -Given: [['US', 'USD'], ['CA', 'CAD']] - -When -createLookup(countryCurrencyPairs) is called - -Then -It should return: - { - 'US': 'USD', - 'CA': 'CAD' - } -*/ +test("creates lookup for a single pair", () => { + expect(createLookup([["GB", "GBP"]])).toEqual({ GB: "GBP" }); +}); diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..98f1bdab0 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,13 +1,26 @@ function parseQueryString(queryString) { const queryParams = {}; - if (queryString.length === 0) { - return queryParams; - } - const keyValuePairs = queryString.split("&"); + if (queryString.length === 0) return queryParams; + + const keyValuePairs = queryString.split("&").filter(pair => pair.length > 0); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + const eqIndex = pair.indexOf("="); + const rawKey = eqIndex === -1 ? pair : pair.slice(0, eqIndex); + const rawValue = eqIndex === -1 ? "" : pair.slice(eqIndex + 1); + + const key = decodeURIComponent(rawKey.replace(/\+/g, " ")); + const value = decodeURIComponent(rawValue.replace(/\+/g, " ")); + + if (Object.prototype.hasOwnProperty.call(queryParams, key)) { + if (Array.isArray(queryParams[key])) { + queryParams[key].push(value); + } else { + queryParams[key] = [queryParams[key], value]; + } + } else { + queryParams[key] = value; + } } return queryParams; diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..ed0a93c1e 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,9 @@ -function tally() {} +function tally(arr) { + if (!Array.isArray(arr)) throw new Error("Input must be an array"); + return arr.reduce((acc, item) => { + acc[item] = (acc[item] || 0) + 1; + return acc; + }, Object.create(null)); +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..801856203 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -1,34 +1,21 @@ const tally = require("./tally.js"); -/** - * tally array - * - * In this task, you'll need to implement a function called tally - * that will take a list of items and count the frequency of each item - * in an array - * - * For example: - * - * tally(['a']), target output: { a: 1 } - * tally(['a', 'a', 'a']), target output: { a: 3 } - * tally(['a', 'a', 'b', 'c']), target output: { a : 2, b: 1, c: 1 } - */ +test("tally on an empty array returns an empty object", () => { + expect(tally([])).toEqual({}); +}); -// Acceptance criteria: +test("tally counts a single item", () => { + expect(tally(["a"])).toEqual({ a: 1 }); +}); -// Given a function called tally -// When passed an array of items -// Then it should return an object containing the count for each unique item +test("tally counts duplicate items", () => { + expect(tally(["a", "a", "a"])).toEqual({ a: 3 }); +}); -// 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 counts multiple unique items", () => { + expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 }); +}); -// Given an array with duplicate items -// When passed to tally -// Then it should return counts for each unique item - -// Given an invalid input like a string -// When passed to tally -// Then it should throw an error +test("throws an error for invalid input like a string", () => { + expect(() => tally("invalid")).toThrow(); +});