diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..775abe36c 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,4 +1,6 @@ // Predict and explain first... +// The variable 'address' is an object, not an array, +// so the code won't give the house number. // This code should log out the houseNumber from the address object // but it isn't working... @@ -12,4 +14,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..4b7bfc304 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,7 +1,10 @@ // Predict and explain first... +// - I predict that it won't work, because the variable 'value' isn't defined. // 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 +// - I was wrong, the error that it gives is that the variable 'author' is not iterable. +// Checking for a solution... const author = { firstName: "Zadie", @@ -11,6 +14,6 @@ const author = { alive: true, }; -for (const value of author) { - console.log(value); +for (const key in author) { + console.log(author[key]); } diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..cf64108d8 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,8 +1,15 @@ // Predict and explain first... +// - The program will give the recipe title and serves, +// but the ingredients will be undefined +// because it calls the whole object at the end, instead of the key 'ingredients' of the object. // 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? +// - First, I was wrong. The ingredients came out as 'object', not undefined. +// - To fix it, I removed the object recipe from the first console.log, +// and I used forEach to go through the 'recipe.ingredients' array and list all elements, +// each on a new line. const recipe = { title: "bruschetta", @@ -11,5 +18,8 @@ const recipe = { }; console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); + ingredients:`); + +recipe.ingredients.forEach((element) => { + console.log(element); +}); diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..d7fe7b128 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,22 @@ -function contains() {} +function contains(object1, prop1) { + if ( + typeof object1 !== "object" || + object1 === null || + Array.isArray(object1) + ) { + console.log("Error: object1 must be a non-null object and not an array."); + return false; + } + + if (prop1 in object1) { + return true; + } else { + return false; + } +} + +const myObject = [15, 20, 30]; + +console.log(contains(myObject, "test2")); module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..3e65326ca 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -20,16 +20,59 @@ 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 on empty object returns false", () => { + const object = {}; + + expect(contains(object, "cat")).toBe(false); +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true +test("Given object with properties, should return true if the property name is in the object", () => { + const object1 = { + test1: 56, + test2: "cat", + test3: "dog", + }; + expect(contains(object1, "test2")).toBe(true); +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("When the property name isn't in the object, should return false", () => { + const object2 = { + test4: 52, + test5: "mango", + test6: "banana", + }; + expect(contains(object2, "test7")).toBe(false); +}); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("Given invalid parameters, should return false or an error", () => { + const array1 = ["duo", "mono", 105]; + + expect(contains(array1, "mono")).toBe(false); +}); + +//Given a string as an object +//When passed to contains +//Then it should return false +test("Given a string as an object, should return false or an error", () => { + const string1 = "hello"; + + expect(contains(string1, "mono")).toBe(false); +}); + +//Given an object that's 'null' +//When passed to contains +//Then it should return false +test("Given a null object, should return false or an error", () => { + const object3 = null; + + expect(contains(object3, "mono")).toBe(false); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..c5a5c6c2c 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,15 @@ -function createLookup() { - // implementation here +function createLookup(nestedArray) { + let finalObject = {}; + + nestedArray.forEach((pair) => { + const key = pair[0]; + const value = pair[1]; + finalObject[key] = value; + }); + + return finalObject; } +console.log(createLookup([["NG", "Naira"]])); + module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..a41ed7fb9 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,12 @@ 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", () => { + testArray1 = [ + ["US", "USD"], + ["DRC", "CDF"], + ]; + expect(createLookup(testArray1)).toStrictEqual({ US: "USD", DRC: "CDF" }); +}); /* diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..53399af0e 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -6,7 +6,8 @@ function parseQueryString(queryString) { const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); + const [key, ...rest] = pair.split("="); + const value = rest.join("="); queryParams[key] = value; } diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..403c07f1e 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -3,10 +3,26 @@ // 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("parses an empty string", () => { + expect(parseQueryString("")).toEqual({}); +}); + +test("parses querystring with missing value", () => { + expect(parseQueryString("key=")).toEqual({ key: "" }); +}); + +test("parses querystring with no equal sign", () => { + expect(parseQueryString("lonely")).toStrictEqual({ lonely: "" }); +}); + +test("parses querystring with repeated values", () => { + expect(parseQueryString("a=1&a=2")).toEqual({ a: "2" }); +}); diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..a2167e2a9 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,19 @@ -function tally() {} +function tally(array) { + if (!Array.isArray(array)) { + throw new Error("Input must be an array"); + } + + const result = {}; + + for (const item of array) { + if (result[item]) { + result[item] = result[item] + 1; + } else { + result[item] = 1; + } + } + + return result; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..5e33f6b49 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -23,12 +23,27 @@ 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", () => { + const testArray = []; + + expect(tally(testArray)).toStrictEqual({}); +}); // 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 counts for each item", () => { + const testArray1 = ["a", "a", "b", "c"]; + + expect(tally(testArray1)).toStrictEqual({ 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 on an invalid input throws an error", () => { + const testArray2 = "mango"; + const invalidInput = () => tally(testArray2); + + expect(invalidInput).toThrow("Input must be an array"); +}); diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..c398b9aa0 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -10,20 +10,34 @@ function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + invertedObj[value] = key; } return invertedObj; } +const testObj = { a: 1, b: 2 }; +console.log(invert(testObj)); + +module.exports = invert; + // a) What is the current return value when invert is called with { a : 1 } +// - The current return value is { key: 1 } // b) What is the current return value when invert is called with { a: 1, b: 2 } +// - The current return value is { key: 2 } // c) What is the target return value when invert is called with {a : 1, b: 2} +// - The target return value is {"1": "a", "2": "b"} // c) What does Object.entries return? Why is it needed in this program? +// - Object.entries returns an array of arrays, +// where each inner array represents a [key, value] pair from the input object. +// - It is needed to transform the given object into a nested array of the key-value pairs. +// Then use that array to invert the object's key and value. // d) Explain why the current return value is different from the target output +// - Because this line 13 creates a property named "key", +// instead of inverting the original key and value. // 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..b2c44992f --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,21 @@ +const objectInvert = require("./invert.js"); + +test("Inverting an object with one key and value", () => { + const test1 = { a: 1 }; + expect(objectInvert(test1)).toEqual({ 1: "a" }); +}); + +test("Inverting an object with two keys and values", () => { + const test2 = { a: 1, b: 2 }; + expect(objectInvert(test2)).toEqual({ 1: "a", 2: "b" }); +}); + +test("Inverting an empty object", () => { + const test3 = {}; + expect(objectInvert(test3)).toEqual({}); +}); + +test("Inverting an object with duplicate values", () => { + const test4 = { a: 1, b: 1, c: 2 }; + expect(objectInvert(test4)).toEqual({ 1: "b", 2: "c" }); +});