diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..caea304ef 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,5 +1,5 @@ // Predict and explain first... - +// The problem is this line:15. address is an object not an array. // This code should log out the houseNumber from the address object // but it isn't working... // Fix anything that isn't working @@ -12,4 +12,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..56ddeaaad 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,5 +1,5 @@ // Predict and explain first... - +// I think we can not use for ... of loop for objects. Object is not iriterable. // 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 +11,10 @@ const author = { alive: true, }; -for (const value of author) { +/*for (const value of author) { + console.log(value); +}*/ + +for (const value of Object.values(author)) { console.log(value); } diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..82b72b6b7 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -10,6 +10,13 @@ const recipe = { ingredients: ["olive oil", "tomatoes", "salt", "pepper"], }; -console.log(`${recipe.title} serves ${recipe.serves} +/*console.log(`${recipe.title} serves ${recipe.serves} ingredients: -${recipe}`); +${recipe}`);*/ + +console.log(`${recipe.title} serves ${recipe.serves}`); +console.log("ingredients:"); + +for (const ingredient of recipe.ingredients) { + console.log(ingredient); +} diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..c0d7f7ecc 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)) { + return false; + } + + return object.hasOwnProperty(propertyName); +} module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..165b128bb 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -20,16 +20,43 @@ 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", () => { + expect(contains({}, "name")).toEqual(false); +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true +test("should return true when the property exists", () => { + const object = { + name: "John", + age: 25, + }; + + expect(contains(object, "name")).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 property does not exist", () => { + const object = { + name: "John", + age: 25, + }; + + expect(contains(object, "city")).toEqual(false); +}); + // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error + +test("should return false for invalid parameters", () => { + expect(contains([], "name")).toEqual(false); + expect(contains(null, "name")).toEqual(false); + expect(contains("hello", "name")).toEqual(false); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..5cc215b6e 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,15 @@ -function createLookup() { +function createLookup(countryCurrencyParis) { // implementation here + const lookup = {}; + + for (const pair of countryCurrencyParis) { + const countryCode = pair[0]; + const currencyCode = pair[1]; + + lookup[countryCode] = currencyCode; + } + + return lookup; } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..8f8544baa 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,7 +1,5 @@ const createLookup = require("./lookup.js"); -test.todo("creates a country currency code lookup for multiple codes"); - /* Create a lookup object of key value pairs from an array of code pairs @@ -10,7 +8,7 @@ Acceptance Criteria: Given - An array of arrays representing country code and currency code pairs - e.g. [['US', 'USD'], ['CA', 'CAD']] + e.g. [['US', 'USD'], ['CA', 'CAD']] When - createLookup function is called with the country-currency array as an argument @@ -33,3 +31,55 @@ It should return: 'CA': 'CAD' } */ + +// Given an array of country-currency pairs +// When createLookup is called +// Then it should return an object with matching key-value pairs +test("creates a country currency code lookup for multiple codes", () => { + const input = [ + ["US", "USD"], + ["CA", "CAD"], + ]; + + const output = createLookup(input); + + expect(output).toEqual({ + US: "USD", + CA: "CAD", + }); +}); + +// Given an empty array +// When createLookup is called +// Then it should return an empty object +test("returns an empty object for an empty array", () => { + expect(createLookup([])).toEqual({}); +}); + +// Given a single country-currency pair +// When createLookup is called +// Then it should return an object with one property +test("creates a lookup for a single code pair", () => { + const input = [["GB", "GBP"]]; + + expect(createLookup(input)).toEqual({ + GB: "GBP", + }); +}); + +// Given multiple country-currency pairs +// When createLookup is called +// Then it should include all pairs in the result +test("creates a lookup for several code pairs", () => { + const input = [ + ["GB", "GBP"], + ["JP", "JPY"], + ["ET", "ETB"], + ]; + + expect(createLookup(input)).toEqual({ + GB: "GBP", + JP: "JPY", + ET: "ETB", + }); +}); diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..201388821 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -6,8 +6,35 @@ function parseQueryString(queryString) { const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + if (pair === "") { + continue; + } + + const index = pair.indexOf("="); + + let key; + let value; + + if (index === -1) { + key = pair; + value = ""; + } else { + key = pair.slice(0, index); + value = pair.slice(index + 1); + } + + key = decodeURIComponent(key.replace(/\+/g, " ")); + value = decodeURIComponent(value.replace(/\+/g, " ")); + + if (queryParams.hasOwnProperty(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..68af13a7a 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,19 @@ -function tally() {} +function tally(items) { + if (!Array.isArray(items)) { + throw new Error("Input must be an array"); + } + + const counts = {}; + + for (const item of items) { + if (counts[item]) { + counts[item]++; + } else { + counts[item] = 1; + } + } + + return counts; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..e781daea5 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -20,15 +20,42 @@ const tally = require("./tally.js"); // When passed an array of items // Then it should return an object containing the count for each unique item +test("should return the count for each unique car brand", () => { + const cars = ["Toyota", "BMW", "Toyota", "Honda", "BMW", "Toyota"]; + + const result = tally(cars); + + expect(result).toEqual({ + Toyota: 3, + BMW: 2, + Honda: 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("should count numbers", () => { + expect(tally([1, 2, 1, 3, 2, 1])).toEqual({ + 1: 3, + 2: 2, + 3: 1, + }); +}); + // Given an invalid input like a string // When passed to tally // Then it should throw an error + +test("should throw an error for invalid input", () => { + expect(() => tally("hello")).toThrow("Input must be an array"); +}); diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..b770b0eab 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -6,7 +6,7 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} -function invert(obj) { +/*function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { @@ -14,16 +14,29 @@ function invert(obj) { } return invertedObj; -} +}*/ // 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(obj) returns an array of key-value pairs. // d) Explain why the current return value is different from the target output - +// The problem is here:invertedObj.key = value; +//JavaScript thinks "key" is literally the property name. // e) Fix the implementation of invert (and write tests to prove it's fixed!) + +function invert(obj) { + const invertedObj = {}; + + for (const [key, value] of Object.entries(obj)) { + invertedObj[value] = key; + } + + return invertedObj; +} + +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..fd230aeab --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,18 @@ +const invert = require("./invert.js"); + +test("should invert an object with one property", () => { + expect(invert({ a: 1 })).toEqual({ + 1: "a", + }); +}); + +test("should invert an object with multiple properties", () => { + expect(invert({ a: 1, b: 2 })).toEqual({ + 1: "a", + 2: "b", + }); +}); + +test("should return an empty object when given an empty object", () => { + expect(invert({})).toEqual({}); +});