diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..28d70618b 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,5 +1,8 @@ // Predict and explain first... +// Prediction: Error is that address is not an array, so address[0] is undefined. +// Actual output: "My house number is undefined" + // This code should log out the houseNumber from the address object // but it isn't working... // Fix anything that isn't working @@ -12,4 +15,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..1c65dcb60 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,5 +1,8 @@ // Predict and explain first... +// Prediction: The error is that it is trying to iterate over a non-array object. +// Actual output: TypeError: author is not iterable + // 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 +14,6 @@ const author = { alive: true, }; -for (const value of author) { - console.log(value); +for (const key in author) { + console.log(key + ": " + author[key]); } diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..aa3ed75fc 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,5 +1,8 @@ // Predict and explain first... +// Prediction: The error is that recipe is being treated as a string +// Actual output: bruschetta serves 2 [object 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? @@ -11,5 +14,5 @@ const recipe = { }; console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); +ingredients: +${recipe.ingredients.join(", ")}`); diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..ef9793875 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,15 @@ -function contains() {} +function contains(object, name) { + if (object == null || Object.keys(object).length === 0) { + return false; + } + + for (let key in object) { + if (key === name) { + 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..255cce8cf 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -20,7 +20,6 @@ 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"); // Given an object with properties // When passed to contains with an existing property name @@ -33,3 +32,15 @@ test.todo("contains on empty object returns false"); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error + +describe("contains", () => { + [ + { input: [{}, "a"], expected: false }, + { input: [{ a: 1, b: 2 }, "a"], expected: true }, + { input: [{ a: 1, b: 2 }, "c"], expected: false }, + { input: [null, "a"], expected: false }, + ].forEach(({ input, expected }) => + it(`return if object contains the key for ${input[1]}`, () => + expect(contains(...input)).toEqual(expected)) + ); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..7e5f0470f 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,13 @@ -function createLookup() { - // implementation here +function createLookup(countryCurrencyPairs) { + const array = {}; + + for (const pair of countryCurrencyPairs) { + const country = pair[0]; + const currency = pair[1]; + array[country] = currency; + } + + return array; } module.exports = createLookup; 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..5cc6c4684 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -3,10 +3,23 @@ // 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", +describe("parseQueryString", () => { + test("returns an empty object when query is empty", () => { + expect(parseQueryString("")).toEqual({}); + }); + + test("parses query string values containing =", () => { + expect(parseQueryString("equation=x=y+1")).toEqual({ + equation: "x=y+1", + }); + }); + + test("checks for keys without values", () => { + expect(parseQueryString("foo&bar=2")).toEqual({ + foo: "", + bar: "2", + }); }); }); diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..f2ba06655 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,19 @@ -function tally() {} +function tally(itemsList) { + const counts = {}; + + if (itemsList.length === 0) { + return {}; + } + + if (!Array.isArray(itemsList)) { + throw new Error("Input must be an array"); + } + + for (const item of itemsList) { + counts[item] = (counts[item] || 0) + 1; + } + + return counts; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..1ba68ca2f 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -32,3 +32,21 @@ test.todo("tally on an empty array returns an empty object"); // Given an invalid input like a string // When passed to tally // Then it should throw an error + +describe("tally", () => { + test("returns an empty object when given an empty array", () => { + expect(tally([])).toEqual({}); + }); + + test("returns counts for each unique item", () => { + expect(tally(["a", "a", "b", "c"])).toEqual({ + a: 2, + b: 1, + c: 1, + }); + }); + + test("throws an error when input is not an array", () => { + expect(() => tally("abc")).toThrow(); + }); +}); diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..9ec8e150c 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -10,20 +10,28 @@ function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + invertedObj[value] = key; } 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: 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 the key value pairs in an object +// It is needed because without it, iterating over the object is not possible // d) Explain why the current return value is different from the target output +// InvertedObj.key creates a key called 'key' in the object // 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..dcaa0df70 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,23 @@ +const invert = require("./invert"); + +describe("invert", () => { + test("object with numbers as values", () => { + expect(invert({ a: 1, b: 2 })).toEqual({ 1: "a", 2: "b" }); + }); + + test("1 pair in object", () => { + expect(invert({ x: 99 })).toEqual({ 99: "x" }); + }); + + test("number keys with string values", () => { + expect(invert({ 1: "one", 2: "two" })).toEqual({ one: "1", two: "2" }); + }); + + test("empty object returns empty object", () => { + expect(invert({})).toEqual({}); + }); + + test("mixed types", () => { + expect(invert({ a: 1, b: "hello" })).toEqual({ 1: "a", hello: "b" }); + }); +});