diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..36d2f865d 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -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..a8334d54e 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -11,6 +11,9 @@ const author = { alive: true, }; -for (const value of author) { - console.log(value); +for (const value in author) { + console.log(author[value]); } +//author is Object and it is not iterable +//for...of loop excepts array and string but it not working with object type +//we should Use for... in for object diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..691a73cdd 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -2,7 +2,7 @@ // 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? +// How can you fix it? The join() method converts an array into a string. const recipe = { title: "bruschetta", @@ -12,4 +12,4 @@ const recipe = { console.log(`${recipe.title} serves ${recipe.serves} ingredients: -${recipe}`); +${recipe.ingredients.join("\n")}`); diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..cefa84112 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,17 @@ -function contains() {} +function contains(cont, str) { + // if (cont === "") { + // return false; + // } + if (typeof cont !== "object" || cont === null || Array.isArray(cont)) { + throw new Error("contains requires an object"); + } + const keyArray = Object.keys(cont); + for (const item of keyArray) { + if (item === str) { + return true; + } + } + return false; +} module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 719272787..362f87a80 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -16,25 +16,66 @@ as an array isn't an object // Acceptance criteria: -// Given a contains function -// When passed an object and a property name -// Then it should return true if the object contains the property, false otherwise - // Given an empty object // When passed to contains // Then it should return false -test.todo("contains on empty object returns false"); +describe("contains", () => { + test("given an empty object, returns false", function () { + const input = contains({}, ""); + const currentOutput = input; + const targetOutput = false; -// Given an object with properties -// When passed to contains with an existing property name -// Then it should return true + expect(currentOutput).toEqual(targetOutput); + }); + // Given a contains function + // When passed an object and a property name + // Then it should return true if the object contains the property, false otherwise + test("given an object, returns true as the object contains a key of 'a'", function () { + const input = contains({ a: 1, b: 2 }, "a"); + const currentOutput = input; + const targetOutput = true; -// Given an object with properties -// When passed to contains with a non-existent property name -// Then it should return false + expect(currentOutput).toEqual(targetOutput); + }); + // Given an object with properties + // When passed to contains with a non-existent property name + // Then it should return false + test("given an object, returns true as the object contains a key of 'a'", function () { + const input = contains({ a: 1, b: 2 }, "c"); + const currentOutput = input; + const targetOutput = 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") + expect(currentOutput).toEqual(targetOutput); + }); + // 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") + it("throws when given an array containing a value that isn't an object", () => { + expect(() => contains(["banana"])).toThrow( + new Error("contains requires an object") + ); + }); + it("throws when given an array containing a value that isn't an object", () => { + expect(() => contains(123)).toThrow( + new Error("contains requires an object") + ); + }); + + it("throws when given an array containing a value that isn't an object", () => { + expect(() => contains(null)).toThrow( + new Error("contains requires an object") + ); + }); + + it("throws when given an array containing a value that isn't an object", () => { + expect(() => contains()).toThrow(new Error("contains requires an object")); + }); + + it("throws when given an empty array", () => { + expect(() => contains([])).toThrow( + new Error("contains requires an object") + ); + }); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..32c766fad 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,14 @@ -function createLookup() { - // implementation here +function createLookup(countryCurrencyPairs) { + const lookUp = {}; + for (const item of countryCurrencyPairs) { + lookUp[item[0]] = item[1]; + } + return lookUp; } - +console.log( + createLookup([ + ["US", "USD"], + ["CA", "CAD"], + ]) +); module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..18daff60c 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,7 +1,17 @@ const createLookup = require("./lookup.js"); -test.todo("creates a country currency code lookup for multiple codes"); - +describe("lookup", () => { + test("creates a country currency code lookup for multiple codes", function () { + const input = [ + ["US", "USD"], + ["CA", "CAD"], + ]; + const currentOutput = createLookup(input); + const targetOutput = { US: "USD", CA: "CAD" }; + + expect(currentOutput).toEqual(targetOutput); + }); +}); /* Create a lookup object of key value pairs from an array of code pairs diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..a366f4fa6 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,16 +1,44 @@ function parseQueryString(queryString) { - const queryParams = {}; + const queryParams = Object.create(null); + if (queryString.length === 0) { return queryParams; } - const keyValuePairs = queryString.split("&"); + + const newQueryStr = queryString.replaceAll("+", " "); + const keyValuePairs = newQueryStr.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + if (pair.length === 0) { + continue; + } + + const separateIndex = pair.indexOf("="); + + let key; + let value; + + if (separateIndex === -1) { + key = pair; + value = ""; + } else { + key = pair.slice(0, separateIndex); + value = pair.slice(separateIndex + 1); + } + key = decodeURIComponent(key); + value = decodeURIComponent(value); + + if (Object.hasOwn(queryParams, key)) { + if (Array.isArray(queryParams[key])) { + queryParams[key].push(value); + } else { + queryParams[key] = [queryParams[key], value]; + } + } else { + queryParams[key] = value; + } } return queryParams; } - module.exports = parseQueryString; diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 328b8df61..e9e0e9abd 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -3,7 +3,7 @@ // Below are some test cases the implementation doesn't handle well. // Fix the implementation for these tests, 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("should parse values containing '='", () => { expect(parseQueryString("equation=a=b-2")).toEqual({ diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..bd27228cb 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,21 @@ -function tally() {} +function tally(arr) { + const tallyObj = {}; + if (!Array.isArray(arr)) { + throw new Error("tally requires an array"); + } + if (arr.length === 0) { + return {}; + } + let key; + let value; + for (const item of arr) { + if (Object.hasOwn(tallyObj, item)) { + tallyObj[item] = tallyObj[item] + 1; + } else { + tallyObj[item] = 1; + } + } + return tallyObj; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index ca763c296..494a9bda8 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -23,12 +23,43 @@ 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"); +describe("contains", () => { + test("tally on an empty array returns an empty object", function () { + const input = tally([]); + const currentOutput = input; + const targetOutput = {}; -// Given an array with duplicate items -// When passed to tally -// Then it should return counts for each unique item + expect(currentOutput).toEqual(targetOutput); + }); -// 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") + // 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 on aan array of items, returns an object containing the count for each unique item", function () { + expect(tally(["a"])).toEqual({ a: 1 }); + expect(tally(["a", "b", "c"])).toEqual({ a: 1, b: 1, c: 1 }); + expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 }); + }); + + // Given an array with duplicate items + // When passed to tally + // Then it should return counts for each unique item + test("tally with duplicate items returns counts for each unique item", function () { + expect(tally(["a", "a"])).toEqual({ a: 2 }); + expect(tally(["a", "a", "b", "b"])).toEqual({ a: 2, b: 2 }); + expect(tally(["a", "a", "b", "b", "c", "c"])).toEqual({ a: 2, b: 2, c: 2 }); + }); + // 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") + it("throws when given an invalid input like a string, a number, or no argument", () => { + expect(() => tally(123)).toThrow(new Error("tally requires an array")); + expect(() => tally("hello")).toThrow(new Error("tally requires an array")); + expect(() => tally()).toThrow(new Error("tally requires an array")); + }); + test("tally handles object prototype property names", function () { + expect(tally(["toString"])).toEqual({ toString: 1 }); + expect(tally(["constructor"])).toEqual({ constructor: 1 }); + }); +}); diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..f17722554 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -5,25 +5,34 @@ // Then it should swap the keys and values in the object // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} - +const assert = require("node:assert/strict"); function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + invertedObj[value] = key; } return invertedObj; } - +assert.deepEqual(invert({ a: 1, b: 2 }), { 1: "a", 2: "b" }); +console.log(invert({ a: 1, b: 2 })); // 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 containing the object's key-value pairs. +//[["a", 1], ["b", 2]] +// We use Object.entries() because we need to access both the keys and values of an object so we can swap them. // d) Explain why the current return value is different from the target output +// because in this line (invertedObj.key = value;) javascript create a property literally called "key +// it does not use the value stored inside the key, in this case we need to use [] // e) Fix the implementation of invert (and write tests to prove it's fixed!)