diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..65c3b5ecd 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,5 +1,5 @@ // Predict and explain first... - +// i think its because the address is not used as an array but as an object // 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..2a37e796d 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,8 +1,8 @@ // Predict and explain first... - +//i think its because value is not used as a parameter of an object, and author is an object not an ordered list Array. // 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 found that object literals are not iterative because they have no orders const author = { firstName: "Zadie", lastName: "Smith", @@ -11,6 +11,6 @@ const author = { alive: true, }; -for (const value of author) { +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..8b6bca89a 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,5 +1,9 @@ // Predict and explain first... - +/* +console.log(`${recipe.title} serves ${recipe.serves} + ingredients: +${recipe}`);// here it misses recipe.ingredients +*/ // 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? @@ -12,4 +16,4 @@ const recipe = { console.log(`${recipe.title} serves ${recipe.serves} ingredients: -${recipe}`); +${recipe.ingredients.join("\n")}`); // this make the list to be logged on a new line - not predicted at first diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..575136836 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,14 @@ -function contains() {} +function contains(keyInput, valueInput) { + if (Array.isArray(keyInput) == true) { + return false; + } else { + for (const key in keyInput) { + if (key == valueInput) { + 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..b7180cf13 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -1,35 +1,21 @@ const contains = require("./contains.js"); -/* -Implement a function called contains that checks an object contains a -particular property +test("Give a contains with object and property and if the object contains the property returns true", () => { + expect(contains({ a: 1, b: 2 }, "b")).toEqual(true); +}); -E.g. contains({a: 1, b: 2}, 'a') // returns true -as the object contains a key of 'a' +test("Give a contains with empty object and when passed to contains it returns false", () => { + expect(contains({}, "y")).toEqual(false); +}); -E.g. contains({a: 1, b: 2}, 'c') // returns false -as the object doesn't contains a key of 'c' -*/ +test("Give a contains with object and property and if the object contains the property returns true", () => { + expect(contains({ a: 1, b: 2 }, "a")).toEqual(true); +}); -// Acceptance criteria: +test("Give a contains with object and property and if the property is non-existent returns false", () => { + expect(contains({ a: 1, b: 2 }, "z")).toEqual(false); +}); -// 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"); - -// Given an object with properties -// When passed to contains with an existing property name -// Then it should return true - -// Given an object with properties -// When passed to contains with a non-existent property name -// Then it should return false - -// Given invalid parameters like an array -// When passed to contains -// Then it should return false or throw an error +test("Give invalid parameter in this case array when passed to contains it returns false", () => { + expect(contains(["a", 2, "b", 3, 2], 2)).toEqual(false); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..9abdaa661 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,9 @@ -function createLookup() { - // implementation here +function createLookup(countryCurrencyPairs) { + pairs = {}; + for (const [country, currency] of countryCurrencyPairs) { + pairs[country] = currency; + } + return pairs; } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..28cd9e52e 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,35 +1,17 @@ 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 - -Acceptance Criteria: - -Given - - An array of arrays representing country code and currency code pairs - e.g. [['US', 'USD'], ['CA', 'CAD']] - -When - - createLookup function is called with the country-currency array as an argument - -Then - - It should return an object where: - - The keys are the country codes - - The values are the corresponding currency codes - -Example -Given: [['US', 'USD'], ['CA', 'CAD']] - -When -createLookup(countryCurrencyPairs) is called - -Then -It should return: - { - 'US': 'USD', - 'CA': 'CAD' - } -*/ +test("create a country currency code lookup for a single codes", () => { + expect(createLookup([["UK", "GBP"]])).toEqual({ UK: "GBP" }); +}); +test("creates an empty country currency code returns empty lookup", () => { + expect(createLookup([])).toEqual({}); +}); +test("creates a country currency code lookup for multiple codes", () => { + expect( + createLookup([ + ["US", "USD"], + ["CA", "CAD"], + ["UK", "GBP"], + ]) + ).toEqual({ US: "USD", CA: "CAD", UK: "GBP" }); +}); diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..7d2691657 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,13 +1,39 @@ function parseQueryString(queryString) { const queryParams = {}; - if (queryString.length === 0) { + if (!queryString) { return queryParams; } + + // 1. Split on '&' to get individual key-value pairs const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + // Skip completely empty segments from '&&' or trailing '&' + if (!pair) continue; + + // 2. Split on '=' separating key and value + const eqIndex = pair.indexOf("="); + let rawKey, rawValue; + + if (eqIndex === -1) { + // Key with no '=' (e.g. "key") + rawKey = pair; + rawValue = ""; + } else { + rawKey = pair.slice(0, eqIndex); + rawValue = pair.slice(eqIndex + 1); + } + + // 3. Replace '+' with ' ' first, then decode URL percent-encoded values + const key = decodeURIComponent(rawKey.replace(/\+/g, " ")); + const value = decodeURIComponent(rawValue.replace(/\+/g, " ")); + + // 4. Handle identical keys (stretch goal) + if (Object.hasOwn(queryParams, key)) { + queryParams[key] = [].concat(queryParams[key], value); + } else { + queryParams[key] = value; + } } return queryParams; diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 328b8df61..76e6111c0 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -1,9 +1,4 @@ -// In the prep, we implemented a function to parse query strings. -// Unfortunately, it contains several bugs! -// 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({ @@ -37,9 +32,6 @@ 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"], diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..670bfb839 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,13 @@ -function tally() {} +function tally(items) { + if (!Array.isArray(items)) { + throw new Error("Invalid input!"); + } + const result = {}; + for (const item of items) { + result[item] = (result[item] || 0) + 1; + } + + return result; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..799e3240d 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -1,34 +1,22 @@ const tally = require("./tally.js"); -/** - * tally array - * - * In this task, you'll need to implement a function called tally - * that will take a list of items and count the frequency of each item - * in an array - * - * For example: - * - * tally(['a']), target output: { a: 1 } - * tally(['a', 'a', 'a']), target output: { a: 3 } - * tally(['a', 'a', 'b', 'c']), target output: { a : 2, b: 1, c: 1 } - */ +test("given an array of items an object containing the counter for each item", () => { + expect(tally(["a", "a"])).toEqual({ a: 2 }); +}); -// Acceptance criteria: +test("tally on an empty array returns an empty object", () => { + expect(tally([])).toEqual({}); +}); -// 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("given an array of items an object containing the counter for each item", () => { + expect(tally(["a", "a", "c", "b", "b", "d"])).toEqual({ + a: 2, + c: 1, + b: 2, + d: 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"); - -// Given an array with duplicate items -// When passed to tally -// Then it should return counts for each unique item - -// Given an invalid input like a string -// When passed to tally -// Then it should throw an error +test("tally on an empty array returns an empty object", () => { + expect(() => tally("string")).toThrow("Invalid input!"); +}); diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..4c21c3cda 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -1,29 +1,30 @@ -// Let's define how invert should work - -// Given an object -// When invert is passed this object -// Then it should swap the keys and values in the object - -// E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} - function invert(obj) { const invertedObj = {}; for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; + //invertedObj.key = value; + invertedObj[value] = key; } 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} - -// c) What does Object.entries return? Why is it needed in this program? - -// d) Explain why the current return value is different from the target output - -// e) Fix the implementation of invert (and write tests to prove it's fixed!) +// {"1":"a", "2":"b"} +// d) What does Object.entries return? Why is it needed in this program? +//object.entries takes an objecet and returns an array of its key-value pairs. +// e) Explain why the current return value is different from the target output +//because we use .key notation we are setting a property named "key" on our Object. +// f) Fix the implementation of invert (and write tests to prove it's fixed!) +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..4004fe604 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,9 @@ +const invert = require("./invert.js"); + +test("swap key with value", () => { + expect(invert({ a: 1 })).toEqual({ 1: "a" }); +}); + +test("swap key with value", () => { + expect(invert({ a: 1, b: 2 })).toEqual({ 1: "a", 2: "b" }); +});