diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..66d47dd2b 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -4,6 +4,7 @@ // but it isn't working... // Fix anything that isn't working +// i predict that it will fail straight away as value for houseNumber was not in a string const address = { houseNumber: 42, street: "Imaginary Road", @@ -12,4 +13,6 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +console.log(`My house number is ${address.houseNumber}`); + +// the issue was that it was looking for the property [0] so i changed it to dot notation .houseNumber in the console.log diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..bb7b6049a 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); } +// Objects are not iterable, so for...of can’t be used on them unless you convert them to an array (e.g. with Object.values). diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..07328a666 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -4,12 +4,17 @@ // Each ingredient should be logged on a new line // How can you fix it? +// it should print the recipe title, how many people people it serves and lists the ingredients. + const recipe = { title: "bruschetta", serves: 2, 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")}`); + +// it printed [object Object], this is because ${recipe} tries to print the whole object, which shows as [object Object] instead of useful data. This was fixed by using ${recipe.ingredients} (and .join(", ")) to display the ingredients properly. diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..115c2533e 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,9 @@ -function contains() {} +function contains(object, propertyName) { + if (typeof object !== "object" || object === null || Array.isArray(object)) { + // if user passes something that is not an object, or object is null/array, then return false. + return false; + } + return Object.hasOwn(object, propertyName); +} module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..53ecdc1bd 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -20,16 +20,37 @@ 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"); +test("contains an empty object returns false", () => { + expect(contains({}, "ball")).toEqual(false); +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true - +test("contains an object with properties, returns true", () => { + expect(contains({ foot: "ball" }, "foot")).toEqual(true); +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("should return false when the object does not contain the property", () => { + expect(contains({ foot: "ball" }, "basket")).toEqual(false); +}); // Given invalid parameters like an array // When passed to contains -// Then it should return false or throw an error +// Then it should return false +test("should return false when input is not an object", () => { + expect(contains([], "a")).toEqual(false); +}); + +// Given invalid parameter e.g. null +// When passed to contains +// Then it should return false +test("should return false when input is null", () => { + expect(contains(null, "a")).toEqual(false); +}); + +test("should return false when input is an array even if propertyName is a valid key", () => { + expect(contains(["x", "y"], "0")).toEqual(false); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..a7c08999c 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,19 @@ -function createLookup() { - // implementation here +function createLookup(list) { + // key = country code e.g. 'US' + // value = currency code e.g. 'USD' + // input = array of [country, currency] + // process = go through each pair, add to object + // output = object { country: currency } + + // declare a variable and store empty object + // loop through the array + // while in the loop take each item and add it to the object + let items = {}; + + for (let i = 0; i < list.length; i++) { + items[list[i][0]] = list[i][1]; + } + return items; } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..54851a8e8 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,17 @@ 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 expectedOutput = { + US: "USD", + CA: "CAD", + }; + + expect(createLookup(input)).toEqual(expectedOutput); +}); /* diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..1d36d0ac2 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,12 +1,23 @@ function parseQueryString(queryString) { const queryParams = {}; - if (queryString.length === 0) { - return queryParams; - } - const keyValuePairs = queryString.split("&"); + if (queryString.length === 0) return queryParams; + + const pairs = queryString.split("&"); + + for (const pair of pairs) { + const index = pair.indexOf("="); + // if there is a key but no equals, return empty string for value. + let key; + let value; + if (index === -1) { + key = pair; + value = ""; + } else { + key = pair.slice(0, index).trim(); + value = pair.slice(index + 1).trim(); + } - for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); + if (!key) continue; queryParams[key] = value; } diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..2adfaef8d 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -3,10 +3,47 @@ // 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", + }); + expect(parseQueryString("page=1")).toEqual({ + page: "1", + }); + expect(parseQueryString("name=Ali")).toEqual({ + name: "Ali", + }); +}); + +test("parses querystring values containing &", () => { + expect(parseQueryString("key1=value1&key2=value2")).toEqual({ + key1: "value1", + key2: "value2", + }); + expect(parseQueryString("name=Ayub&colour=blue")).toEqual({ + name: "Ayub", + colour: "blue", + }); +}); + +test("handles malformed querystrings", () => { + // if value is empty, return empty string for value. + expect(parseQueryString("key=")).toEqual({ + key: "", + }); + // if key is empty don't return anything. + expect(parseQueryString("=value")).toEqual({}); + // if there is a key but no equals, return empty string for value. + expect(parseQueryString("key")).toEqual({ key: "" }); + // if key is empty and value is empty, don't return anything for that item + expect(parseQueryString("key1=value1&=&key2=value2")).toEqual({ + key1: "value1", + key2: "value2", + }); + expect(parseQueryString("key1=value1&&key2=value2")).toEqual({ + key1: "value1", + key2: "value2", }); }); diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..5315687c6 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,16 @@ -function tally() {} +function tally(items) { + if (!Array.isArray(items)) { + throw new Error("Input must be an array"); + } + + const plainObject = Object.create(null); + + const itemsObject = items.reduce((acc, item) => { + acc[item] = (acc[item] || 0) + 1; + return acc; + }, plainObject); + + return itemsObject; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..f6e447d87 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -19,16 +19,34 @@ 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 +test("tally returns counts for each unique item", () => { + expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 }); +}); // 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 handles duplicate items", () => { + expect(tally(["a", "a", "a"])).toEqual({ a: 3 }); +}); // Given an invalid input like a string // When passed to tally // Then it should throw an error +test("tally throws an error for invalid input", () => { + expect(() => tally("invalid")).toThrow(); +}); + +// Given an input that has the same name as a prototype method +// When passed to tally +// Then it should return counts for each unique item +test("tally returns correct output for all strings ", () => { + expect(tally(["toString", "toString"])).toEqual({ toString: 2 }); +}); diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..79d324dca 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -10,20 +10,22 @@ 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 }), "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? - +// The Object.entries() static method returns an array of a given object's own enumerable string-keyed property key-value pairs. It returns an array with the object's key-value pairs. e.g. [ [ 'a', 1 ], [ 'b', 2 ] ] // d) Explain why the current return value is different from the target output - +// This is because the function is not correctly inverting the key and value. // e) Fix the implementation of invert (and write tests to prove it's fixed!) + +module.exports = invert; diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js new file mode 100644 index 000000000..7d2c49c7d --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,16 @@ +const invert = require("../interpret/invert"); + +test(`Should return {"10": "x", "20": "y"} when given { x: 10, y: 20 } `, () => { + expect(invert({ x: 10, y: 20 })).toEqual({ 10: "x", 20: "y" }); +}); + +test(`Should return {"2": "bounce", "100": "high"} when given { bounce: 2, high: 100 } `, () => { + expect(invert({ bounce: 2, high: 100 })).toEqual({ + 2: "bounce", + 100: "high", + }); +}); + +test(`Should return {"foot": "ball"} when given { "ball": "foot" } `, () => { + expect(invert({ ball: "foot" })).toEqual({ foot: "ball" }); +});