diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..17666fae1 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,5 +1,16 @@ // Predict and explain first... +/* +Predict +The function is calling index 0 but there is not an index 0 +Console.log will show a ref error +To fix this we need to change the index to [houseNumber] +What actually happened +Console.log showed undefined for that index +Changed index to [houseNumber] this gave us a ref err +Therefore it must be address.houseNumber +This works +*/ // This code should log out the houseNumber from the address object // but it isn't working... // Fix anything that isn't working @@ -12,4 +23,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..05796952b 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,5 +1,11 @@ // Predict and explain first... - +/* +Predict +for of loops work on iteration and we cant iterate objects +To fix this we use for in loop +This loops over the keys +Now we can use author[value] to get values +*/ // 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 +17,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..141083710 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,5 +1,9 @@ // Predict and explain first... - +/* +The ${recipe}`); line does not call the object correctly and shows [object Object] +This is because it tries to convert the whole object to a string but it doesnt know how to display the information +to fix this i used a for loop and iterated through the ingredients key's array to print each ingredient on a new line +*/ // 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? @@ -11,5 +15,9 @@ const recipe = { }; console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); +ingredients: `) + +for (let i=0; i < recipe.ingredients.length; i++) { + console.log(`${recipe.ingredients[i]}`) +} + diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..8c1ca08f2 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,11 @@ -function contains() {} - +function contains(input, key) { + if (input === null || typeof input !== "object") { + throw new Error("contains requires an object") + } else {for (const keys in input){ + if (keys === key) { + return true + } + }} return false +} +console.log(contains({a: 1}, 'a')) module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 719272787..057e0df27 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -23,18 +23,40 @@ as an array isn't an object // 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 input = {}; + const key = 'a' + const result = contains(input, key); + expect(result).toEqual(false) +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true +test("given: object with keys and values & key within object returns true", () => { + const input = {a: 1, b: 2, c: 3}; + const key = 'a' + const result = contains(input, key); + expect(result).toEqual(true) +}); // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("given: object with keys and values & key not within object returns true", () => { + const input = {a: 1, b: 2, c: 3}; + const key = 'k' + const result = contains(input, key); + expect(result).toEqual(false) +}); // Given a value that isn't an object - an array, a string, a number, // null, or no argument at all // When passed to contains // Then it should throw Error("contains requires an object") // (careful: typeof [] and typeof null are both "object") +test("given: value that is not an object throws error: 'contains requires an object'", () => { + const input = "tooth"; + const key = 'k' + expect(() => contains(input, key)).toThrow("contains requires an object") +}); \ No newline at end of file diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..6ccefee0b 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,6 @@ -function createLookup() { - // implementation here +function createLookup(input) { + return Object.fromEntries(input) + } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..057edf56c 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +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", () => { + const input = [['US', 'USD'], ['CA', 'CAD']] + const result = createLookup(input) + expect(result).toEqual({ + 'US': 'USD', + 'CA': 'CAD' + }) +}); /* diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..87c06591f 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -4,12 +4,27 @@ function parseQueryString(queryString) { return queryParams; } const keyValuePairs = queryString.split("&"); - - for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + let keyValuePair = keyValuePairs; + if (queryString.includes("+")) { + keyValuePair = keyValuePairs.map((keyValuePair) => + keyValuePair.replaceAll("+", " ") + ); + } else if(queryString.includes("%")) { + keyValuePair = keyValuePairs.map((keyValuePair) => + decodeURIComponent(keyValuePair)) + }; + + for (const pair of keyValuePair) { + if (pair === "") continue; + const eqIndex = pair.indexOf("="); + if (eqIndex === -1) { + queryParams[pair] = ""; + } else { + const key = pair.slice(0, eqIndex); + const value = pair.slice(eqIndex + 1); + queryParams[key] = value; + } } - return queryParams; } diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 328b8df61..f4e075f3d 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -40,9 +40,9 @@ test("should replace '+' by ' '", () => { // Stretch exercise: Handling query strings that contain identical keys // Delete this test if you are not working on this optional case -test("should store values of a key in an array when the key has 2 or more values", () => { - expect(parseQueryString("key=value1&key=value2&key=value3&foo=bar")).toEqual({ - key: ["value1", "value2", "value3"], - foo: "bar", - }); -}); +// test("should store values of a key in an array when the key has 2 or more values", () => { +// expect(parseQueryString("key=value1&key=value2&key=value3&foo=bar")).toEqual({ +// key: ["value1", "value2", "value3"], +// foo: "bar", +// }); +// }); diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..3d3b650bd 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,16 @@ -function tally() {} +function tally(array) { + if (!Array.isArray(array)){ + throw new Error('tally requires an array') + } + const result = {}; + for (const item of array){ + if (Object.hasOwn(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 ca763c296..c0e408378 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -23,12 +23,24 @@ 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 input = []; + const result = tally(input); + expect(result).toEqual({}); +}); // Given an array with duplicate items // When passed to tally // Then it should return counts for each unique item +test("given array with duplicate items, return object with counts for each unique item", () => { + const input = ['a', 'a', 'b', 'c', 'c', 'c']; + const result = tally(input); + expect(result).toEqual({a: 2, b: 1, c: 3}) +}) // Given an invalid input like a string, a number, or no argument at all // When passed to tally // Then it should throw Error("tally requires an array") +test("given invalid input (str, num, no arg), throw error: 'tally requires an array'", () => { + expect(() => tally('meaf')).toThrow('tally requires an array') +}) \ No newline at end of file diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..42da88512 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -7,23 +7,36 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} function invert(obj) { + if (typeof obj !== "object"){ + throw new Error('invert requires an object.') + } const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + invertedObj[value] = key; } return invertedObj; } -// a) What is the current return value when invert is called with { a : 1 } +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 } +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} +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? +c) What does Object.entries return? Why is it needed in this program? +It returns an array of key value pairs from the object. +It is needed because we cannot iterate over objects with for..of. We convert the obj to array (key-value pairs) using Object.entries and then we can iterate. -// d) Explain why the current return value is different from the target output +d) Explain why the current return value is different from the target output +We dont swop the key value pairs after they are in array form, we only place them back into the object as they were before. +invertedObj also returns uses key as a property name, not a placeholder. When we call the function key is overwritten with more than one key-value pair as well so only the last k-v pair shows but with "key" as the key name. -// e) Fix the implementation of invert (and write tests to prove it's fixed!) +e) Fix the implementation of invert (and write tests to prove it's fixed!) +*/ \ 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..a5feb4394 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,21 @@ +const invert = require("./invert.js"); + +test("object with 1 key-value pair. returns object with key-value pairs swopped.", () => { + expect(invert({a: 1})).toEqual({'1': 'a'}) +}) + +test("object with 2 key-value pairs. returns object with key-value pairs swopped.", () => { + expect(invert({a: 1, b: 2})).toEqual({'1': 'a', '2': 'b'}) +}) + +test("object with 3 key-value pairs. returns object with key-value pairs swopped.", () => { + expect(invert({a: 1, b: 2, z: 12})).toEqual({'1': 'a', '2': 'b', '12': 'z'}) +}) + +test("object with 0 key-value pair. returns empty object.", () => { + expect(invert({})).toEqual({}) +}) + +test("object with invalid input. throw error: 'invert requires an object.", () => { + expect(() => invert("bones")).toThrow('invert requires an object.') +}) \ No newline at end of file