Skip to content

Commit 23f1985

Browse files
committed
chore(sprint-2): create clean branch with Sprint-2 files
1 parent 4222cda commit 23f1985

15 files changed

Lines changed: 259 additions & 40 deletions

File tree

‎Sprint-2/debug/address.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Predict and explain first...
2+
// that it will throw a undefined error because the address object is not defined in the code snippet. The code snippet is missing the definition of the address object, which is necessary for the console.log statement to work correctly.
23

34
// This code should log out the houseNumber from the address object
45
// but it isn't working...
@@ -12,4 +13,4 @@ const address = {
1213
postcode: "XYZ 123",
1314
};
1415

15-
console.log(`My house number is ${address[0]}`);
16+
console.log(`My house number is ${address.houseNumber}`);

‎Sprint-2/debug/author.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Predict and explain first...
2+
// will throw a TypeError because Object.values() is not a function. The correct way to get the values of an object is to use Object.values(author) instead of Object.values(author). The code is trying to call Object.values() on the author object, which is not a function, hence the error.
23

34
// This program attempts to log out all the property values in the object.
45
// But it isn't working. Explain why first and then fix the problem
@@ -11,6 +12,6 @@ const author = {
1112
alive: true,
1213
};
1314

14-
for (const value of author) {
15+
for (const value of Object.values(author)) {
1516
console.log(value);
1617
}

‎Sprint-2/debug/recipe.js‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Predict and explain first...
2+
// will log out the title and how many it serves, but it will not log out the ingredients on new lines. The ingredients are in an array, and the current code does not iterate over that array to log each ingredient on a new line.
23

34
// This program should log out the title, how many it serves and the ingredients.
45
// Each ingredient should be logged on a new line
@@ -10,6 +11,7 @@ const recipe = {
1011
ingredients: ["olive oil", "tomatoes", "salt", "pepper"],
1112
};
1213

13-
console.log(`${recipe.title} serves ${recipe.serves}
14-
ingredients:
15-
${recipe}`);
14+
console.log(`${recipe.title} serves ${recipe.serves}`);
15+
for (const ingredient of recipe.ingredients) {
16+
console.log(ingredient);
17+
}

‎Sprint-2/implement/contains.js‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1-
function contains() {}
1+
function contains(obj, prop) {
2+
if (typeof obj !== "object" || obj === null) {
3+
return false;
4+
}
5+
return obj.hasOwnProperty(prop);
6+
}
27

38
module.exports = contains;

‎Sprint-2/implement/contains.test.js‎

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,44 @@ as the object doesn't contains a key of 'c'
1616
// Given a contains function
1717
// When passed an object and a property name
1818
// Then it should return true if the object contains the property, false otherwise
19+
describe("contains", () => {
20+
test("should return true if the object contains the property, false otherwise", () => {
21+
expect(contains({ a: 1, b: 2 }, 'a')).toBe(true);
22+
expect(contains({ a: 1, b: 2 }, 'b')).toBe(true);
23+
expect(contains({ a: 1, b: 2 }, 'c')).toBe(false);
24+
expect(contains({}, 'a')).toBe(false);
25+
});
26+
});
1927

2028
// Given an empty object
2129
// When passed to contains
2230
// Then it should return false
23-
test.todo("contains on empty object returns false");
31+
test("contains returns false for empty object", () => {
32+
expect(contains({}, 'a')).toBe(false);
33+
});
34+
35+
2436

2537
// Given an object with properties
2638
// When passed to contains with an existing property name
2739
// Then it should return true
40+
test("contains returns true for existing keys", () => {
41+
expect(contains({ a: 1, b: 2 }, 'a')).toBe(true);
42+
expect(contains({ a: 1, b: 2 }, 'b')).toBe(true);
43+
});
2844

2945
// Given an object with properties
3046
// When passed to contains with a non-existent property name
3147
// Then it should return false
48+
test("contains returns false for non-existent property name", () => {
49+
expect(contains({ a: 1, b: 2 }, 'c')).toBe(false);
50+
});
3251

3352
// Given invalid parameters like an array
3453
// When passed to contains
3554
// Then it should return false or throw an error
55+
test("contains with invalid parameters returns false", () => {
56+
expect(contains([], 'a')).toBe(false);
57+
expect(contains(null, 'a')).toBe(false);
58+
expect(contains(undefined, 'a')).toBe(false);
59+
});

‎Sprint-2/implement/lookup.js‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
1-
function createLookup() {
2-
// implementation here
1+
function createLookup(countryCurrencyPairs) {
2+
let lookUp = {};
3+
if (!Array.isArray(countryCurrencyPairs)) {
4+
throw new Error("Input must be an array of arrays");
5+
}
6+
countryCurrencyPairs.forEach(pair => {
7+
if (Array.isArray(pair) && pair.length === 2) {
8+
lookUp[pair[0]] = pair[1];
9+
} else {
10+
throw new Error("Each element of the input array must be an array of two elements");
11+
}
12+
});
13+
14+
return lookUp;
315
}
416

517
module.exports = createLookup;

‎Sprint-2/implement/lookup.test.js‎

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,49 @@
11
const createLookup = require("./lookup.js");
22

3-
test.todo("creates a country currency code lookup for multiple codes");
3+
describe("createLookup", () => {
4+
test("creates a country currency code lookup for multiple codes", () => {
5+
const countryCurrencyPairs = [['US', 'USD'], ['CA', 'CAD']];
6+
const expectedLookup = {
7+
'US': 'USD',
8+
'CA': 'CAD'
9+
};
10+
expect(createLookup(countryCurrencyPairs)).toEqual(expectedLookup);
11+
});
12+
});
13+
14+
test("creates a country currency code lookup for a single code", () => {
15+
const countryCurrencyPairs = [['GB', 'GBP']];
16+
const expectedLookup = {
17+
'GB': 'GBP'
18+
};
19+
expect(createLookup(countryCurrencyPairs)).toEqual(expectedLookup);
20+
});
21+
22+
test("creates an empty lookup for an empty array", () => {
23+
const countryCurrencyPairs = [];
24+
const expectedLookup = {};
25+
expect(createLookup(countryCurrencyPairs)).toEqual(expectedLookup);
26+
});
27+
28+
test("creates a country currency code lookup for multiple codes with different currencies", () => {
29+
const countryCurrencyPairs = [['JP', 'JPY'], ['AU', 'AUD'], ['IN', 'INR']];
30+
const expectedLookup = {
31+
'JP': 'JPY',
32+
'AU': 'AUD',
33+
'IN': 'INR'
34+
};
35+
expect(createLookup(countryCurrencyPairs)).toEqual(expectedLookup);
36+
});
37+
38+
test("creates an array of array representing country code and currency code pairs", () => {
39+
const countryCurrencyPairs = [['FR', 'EUR'], ['DE', 'EUR'], ['IT', 'EUR']];
40+
const expectedLookup = {
41+
'FR': 'EUR',
42+
'DE': 'EUR',
43+
'IT': 'EUR'
44+
};
45+
expect(createLookup(countryCurrencyPairs)).toEqual(expectedLookup);
46+
});
447

548
/*
649
@@ -11,6 +54,8 @@ Acceptance Criteria:
1154
Given
1255
- An array of arrays representing country code and currency code pairs
1356
e.g. [['US', 'USD'], ['CA', 'CAD']]
57+
tes
58+
1459
1560
When
1661
- createLookup function is called with the country-currency array as an argument

‎Sprint-2/implement/querystring.js‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,30 @@
11
function parseQueryString(queryString) {
2-
const queryParams = {};
3-
if (queryString.length === 0) {
4-
return queryParams;
2+
const params = {};
3+
if (!queryString) {
4+
return params;
55
}
6-
const keyValuePairs = queryString.split("&");
76

8-
for (const pair of keyValuePairs) {
9-
const [key, value] = pair.split("=");
10-
queryParams[key] = value;
11-
}
7+
const pairs = queryString.split("&");
8+
for (const pair of pairs) {
9+
if (!pair) continue; // Ignore empty key-value pairs
10+
11+
const [key, ...valueParts] = pair.split("=");
12+
const value = valueParts.join("="); // Join back in case value contains '='
1213

13-
return queryParams;
14+
const decodedKey = decodeURIComponent(key.replace(/\+/g, " "));
15+
const decodedValue = decodeURIComponent(value.replace(/\+/g, " "));
16+
17+
if (params.hasOwnProperty(decodedKey)) {
18+
if (Array.isArray(params[decodedKey])) {
19+
params[decodedKey].push(decodedValue);
20+
} else {
21+
params[decodedKey] = [params[decodedKey], decodedValue];
22+
}
23+
} else {
24+
params[decodedKey] = decodedValue;
25+
}
26+
}
27+
return params;
1428
}
1529

1630
module.exports = parseQueryString;

‎Sprint-2/implement/tally.js‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1-
function tally() {}
1+
function tally(items) {
2+
if (!Array.isArray(items)) {
3+
throw new Error('tally expects an array');
4+
}
5+
6+
const counts = {};
7+
for (const item of items) {
8+
// Use the item as the key; this will stringify non-string keys
9+
const key = String(item);
10+
counts[key] = (counts[key] || 0) + 1;
11+
}
12+
13+
return counts;
14+
}
215

316
module.exports = tally;

‎Sprint-2/implement/tally.test.js‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,31 @@ const tally = require("./tally.js");
1919
// Given a function called tally
2020
// When passed an array of items
2121
// Then it should return an object containing the count for each unique item
22+
test("tally returns an object containing the count for each unique item", () => {
23+
const input = ["a"];
24+
const expected = { a: 1 };
25+
expect(tally(input)).toEqual(expected);
26+
});
2227

2328
// Given an empty array
2429
// When passed to tally
2530
// Then it should return an empty object
26-
test.todo("tally on an empty array returns an empty object");
31+
test("tally on an empty array returns an empty object", () => {
32+
expect(tally([])).toEqual({});
33+
});
2734

2835
// Given an array with duplicate items
2936
// When passed to tally
3037
// Then it should return counts for each unique item
38+
test("tally should return counts for each unique item", () => {
39+
const input = ["a", "a", "b", "c"];
40+
const expected = { a: 2, b: 1, c: 1 };
41+
expect(tally(input)).toEqual(expected);
42+
});
3143

3244
// Given an invalid input like a string
3345
// When passed to tally
3446
// Then it should throw an error
47+
test("tally should throw on invalid input", () => {
48+
expect(() => tally("not-an-array")).toThrow();
49+
});

0 commit comments

Comments
 (0)