From 21ac6a2a7ca2d5df05d688d82f206b7481911795 Mon Sep 17 00:00:00 2001
From: d-odumosu
Date: Sun, 26 Jul 2026 21:45:04 +0100
Subject: [PATCH 1/9] The code now logs the correct address
---
Sprint-2/debug/address.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js
index 940a6af83..c59fff5f0 100644
--- a/Sprint-2/debug/address.js
+++ b/Sprint-2/debug/address.js
@@ -1,6 +1,6 @@
// Predict and explain first...
-// This code should log out the houseNumber from the address 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"]}`);
From 31437ab16091f84d97b781f23aa23e29034091c2 Mon Sep 17 00:00:00 2001
From: d-odumosu
Date: Sun, 26 Jul 2026 21:54:46 +0100
Subject: [PATCH 2/9] refactored to use a for..in loop
---
Sprint-2/debug/author.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js
index 8c2125977..87bc6a919 100644
--- a/Sprint-2/debug/author.js
+++ b/Sprint-2/debug/author.js
@@ -10,7 +10,7 @@ const author = {
age: 40,
alive: true,
};
-
-for (const value of author) {
- console.log(value);
+//An object is not directly iterable, if we want to log out the values we can use a for in loop
+for (const value in author) {
+ console.log(`${author[value]}`);
}
From 132dcb48b1eb37f0c12ca7ba0c92f86c5c7d95d4 Mon Sep 17 00:00:00 2001
From: d-odumosu
Date: Mon, 27 Jul 2026 23:09:05 +0100
Subject: [PATCH 3/9] debugged and fixed the recipe file.
---
Sprint-2/debug/recipe.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js
index 6cbdd22cd..88fd8176a 100644
--- a/Sprint-2/debug/recipe.js
+++ b/Sprint-2/debug/recipe.js
@@ -11,5 +11,7 @@ const recipe = {
};
console.log(`${recipe.title} serves ${recipe.serves}
- ingredients:
-${recipe}`);
+ ingredients:`);
+for (const value of Object.values(recipe.ingredients)) {
+ console.log(value);
+}
From bfed0edb58f25f7e297563f29ef9294e0013a01c Mon Sep 17 00:00:00 2001
From: d-odumosu
Date: Tue, 28 Jul 2026 20:09:57 +0100
Subject: [PATCH 4/9] completed all requirements for invert and written tests
to pass.
---
Sprint-2/interpret/invert.js | 17 ++++++++++++++---
Sprint-2/interpret/invert.test.js | 7 +++++++
2 files changed, 21 insertions(+), 3 deletions(-)
create mode 100644 Sprint-2/interpret/invert.test.js
diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js
index bb353fb1f..d828bdd21 100644
--- a/Sprint-2/interpret/invert.js
+++ b/Sprint-2/interpret/invert.js
@@ -9,21 +9,32 @@
function invert(obj) {
const invertedObj = {};
- for (const [key, value] of Object.entries(obj)) {
- invertedObj.key = value;
+ for (let [key, value] of Object.entries(obj)) {
+ invertedObj[value] = key;
}
return invertedObj;
}
-
+module.exports = invert;
// a) What is the current return value when invert is called with { a : 1 }
+// The current value is: { key: 1 }
// b) What is the current return value when invert is called with { a: 1, b: 2 }
+// The current value is: { key: 2 }
// c) What is the target return value when invert is called with {a : 1, b: 2}
+// The target return value should be:
+//{ "1" : "a", "2" : "b"}
// c) What does Object.entries return? Why is it needed in this program?
+//Object.entries returns an array of a key-value pair. we need object.entries
+// because we cannot directly loop over an object, so by using the method
+// it turns it into an array we can loop over
// d) Explain why the current return value is different from the target output
+//The current return uses a dot notation with the variable 'key', when we use a
+// dot notation with a variable it doesn't get the value of the variable but
+// instead uses the literal word as the key. when we change it to a bracket notation
+// it reads the variable and uses that for the key, we however need to swap the return around and return value = key.
// 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..4530cc81b
--- /dev/null
+++ b/Sprint-2/interpret/invert.test.js
@@ -0,0 +1,7 @@
+const invertObj = require("./invert.js");
+
+describe("invertObj", () => {
+ test("when given an object, should swap the keys and values in the object", () => {
+ expect(invertObj({ x: 10, y: 20 })).toEqual({ 10: "x", 20: "y" });
+ });
+});
From 16db858debcd46138397cbf9719200a000dc81db Mon Sep 17 00:00:00 2001
From: d-odumosu
Date: Wed, 29 Jul 2026 14:04:25 +0100
Subject: [PATCH 5/9] completed all requirements for contains and written tests
to pass.
---
Sprint-2/implement/contains.js | 13 ++++++--
Sprint-2/implement/contains.test.js | 50 +++++++++++++++++++++++++++--
2 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js
index cd779308a..d5ce4ce4d 100644
--- a/Sprint-2/implement/contains.js
+++ b/Sprint-2/implement/contains.js
@@ -1,3 +1,12 @@
-function contains() {}
-
+function contains(object, property) {
+ if (Array.isArray(object)) {
+ throw new Error("Expected an object, received an array");
+ }
+ const obj = Object.keys(object);
+ if (obj.length === 0) {
+ return false;
+ }
+ return obj.includes(property);
+}
+console.log(contains({ 1: "o", 2: "k" }, 1));
module.exports = contains;
diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js
index 326bdb1f2..71b8b25d8 100644
--- a/Sprint-2/implement/contains.test.js
+++ b/Sprint-2/implement/contains.test.js
@@ -8,7 +8,7 @@ E.g. contains({a: 1, b: 2}, 'a') // returns true
as the object contains a key of 'a'
E.g. contains({a: 1, b: 2}, 'c') // returns false
-as the object doesn't contains a key of 'c'
+as the object doesn't contain a key of 'c'
*/
// Acceptance criteria:
@@ -17,19 +17,65 @@ as the object doesn't contains a key of 'c'
// When passed an object and a property name
// Then it should return true if the object contains the property, false otherwise
+test(
+ "when passed an object and a property name, should return true if the object " +
+ "contains the property",
+ () => {
+ const obj1 = {
+ name: "dami",
+ age: 34,
+ height: 5.3,
+ location: "London",
+ };
+ const propertyNameCheck1 = "name";
+ const expected1 = true;
+ const result1 = contains(obj1, propertyNameCheck1);
+ expect(result1).toBe(expected1);
+ }
+);
+
// Given an empty object
// When passed to contains
// Then it should return false
-test.todo("contains on empty object returns false");
+test("given an empty object, should return false", () => {
+ const obj2 = {};
+ const propertyNameCheck2 = "a";
+ const expected2 = false;
+ const result2 = contains(obj2, propertyNameCheck2);
+ expect(result2).toBe(expected2);
+});
// Given an object with properties
// When passed to contains with an existing property name
// Then it should return true
+//this test requirement is covered on line 21
// Given an object with properties
// When passed to contains with a non-existent property name
// Then it should return false
+test(
+ "when passed an object and a property name, should return false if the object " +
+ "does not contain the property.",
+ () => {
+ const obj3 = {
+ title: "Things fall apart",
+ year: 1958,
+ publisher: "pan-macmillan",
+ };
+ const propertyNameCheck3 = "location";
+ const expected3 = false;
+ const result3 = contains(obj3, propertyNameCheck3);
+ expect(result3).toBe(expected3);
+ }
+);
// Given invalid parameters like an array
// When passed to contains
// Then it should return false or throw an error
+test("when passed a data type other than an object, throw an error", () => {
+ const arr = [];
+ const propertyNameCheck4 = "name";
+ expect(() => {
+ contains(arr, propertyNameCheck4);
+ }).toThrow("Expected an object, received an array");
+});
From d7c40160c9141acd52981bc48abc1560e328f326 Mon Sep 17 00:00:00 2001
From: d-odumosu
Date: Wed, 29 Jul 2026 17:15:02 +0100
Subject: [PATCH 6/9] completed all requirements for lookup and written tests
to pass.
---
Sprint-2/implement/lookup.js | 29 +++++++++++++++++--
Sprint-2/implement/lookup.test.js | 47 +++++++++++++++++++++++++++++--
2 files changed, 71 insertions(+), 5 deletions(-)
diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js
index a6746e07f..b00652a36 100644
--- a/Sprint-2/implement/lookup.js
+++ b/Sprint-2/implement/lookup.js
@@ -1,5 +1,28 @@
-function createLookup() {
- // implementation here
-}
+function createLookup(arr) {
+ if (!Array.isArray(arr)) {
+ throw new Error("invalid data type entered");
+ }
+ if (arr.length === 0) {
+ throw new Error("country and currency code not entered");
+ }
+
+ const objectLookup = {};
+ for (const pair of arr) {
+ if (!Array.isArray(pair)) {
+ throw new Error("Each item must be an array.");
+ }
+ if (pair.length !== 2) {
+ throw new Error(
+ "Each inner array must contain exactly two elements: a key and a value"
+ );
+ }
+ const [country, currency] = pair;
+ if (country === currency) {
+ throw new Error("Country code and currency code cannot be the same");
+ }
+ objectLookup[country] = currency;
+ }
+ return objectLookup;
+}
module.exports = createLookup;
diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js
index 547e06c5a..92b5bbf2b 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
@@ -33,3 +31,48 @@ It should return:
'CA': 'CAD'
}
*/
+
+test("when passed an empty array, throw an error", () => {
+ expect(() => {
+ createLookup([]);
+ }).toThrow("country and currency code not entered");
+});
+
+test("when given an array of arrays containing two elements, returns an object of key-value pairs", () => {
+ const input = [
+ ["US", "USD"],
+ ["CA", "CAD"],
+ ["NG", "NIG"],
+ ];
+ const expected = {
+ US: "USD",
+ CA: "CAD",
+ NG: "NIG",
+ };
+ const result = createLookup(input);
+ expect(result).toEqual(expected);
+});
+
+test.each(["hello", 123, true, null, undefined, {}])(
+ "throws an error when input is %p",
+ (input) => {
+ expect(() => {
+ createLookup(input);
+ }).toThrow("invalid data type entered");
+ }
+);
+
+test("when given an array containing more than 2 elements, throw error", () => {
+ const input = [["US", "USD", "U"]];
+ expect(() => {
+ createLookup(input);
+ }).toThrow(
+ "Each inner array must contain exactly two elements: a key and a value"
+ );
+});
+
+test("when given an array, if country code !=== currency code, throw an error", () => {
+ expect(() => {
+ createLookup([["US", "US"]]);
+ }).toThrow("Country code and currency code cannot be the same");
+});
From ec2b1d080a4b5324d5a7563e7caee4f6f8d9dc98 Mon Sep 17 00:00:00 2001
From: d-odumosu
Date: Thu, 30 Jul 2026 19:18:42 +0100
Subject: [PATCH 7/9] completed all requirements of tally
---
Sprint-2/implement/tally.js | 14 ++++++++++++--
Sprint-2/implement/tally.test.js | 30 ++++++++++++++++++++++++++++--
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js
index f47321812..29b90544d 100644
--- a/Sprint-2/implement/tally.js
+++ b/Sprint-2/implement/tally.js
@@ -1,3 +1,13 @@
-function tally() {}
-
+function tally(arr) {
+ if (!Array.isArray(arr)) {
+ throw new Error('Invalid data type entered"');
+ }
+ if (arr.length === 0) {
+ return {};
+ }
+ return arr.reduce((acc, cur) => {
+ acc[cur] = (acc[cur] || 0) + 1;
+ return acc;
+ }, {});
+}
module.exports = tally;
diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js
index 2ceffa8dd..75fe70a70 100644
--- a/Sprint-2/implement/tally.test.js
+++ b/Sprint-2/implement/tally.test.js
@@ -19,16 +19,42 @@ const tally = require("./tally.js");
// 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("", () => {
+ const input = ["hey", "hi", "hello", "hi", "word", "picnic", "book"];
+ const expected = {
+ hey: 1,
+ hi: 2,
+ hello: 1,
+ word: 1,
+ picnic: 1,
+ book: 1,
+ };
+ const result = tally(input);
+ expect(result).toEqual(expected);
+});
// 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", () => {
+ const input = [];
+ const expected = {};
+ const result = tally(input);
+ expect(result).toEqual(expected);
+});
// Given an array with duplicate items
// When passed to tally
// Then it should return counts for each unique item
+//Test on line 22 covers this
// Given an invalid input like a string
// When passed to tally
// Then it should throw an error
+test.each([undefined, null, {}, "hello", 123, true])(
+ "throws when input is %p",
+ (input) => {
+ expect(() => {
+ tally(input).toThrow("Invalid data type entered");
+ });
+ }
+);
From 928a880ab20dd2ec7ca1529312b67c18c1f067ec Mon Sep 17 00:00:00 2001
From: d-odumosu
Date: Thu, 30 Jul 2026 22:02:59 +0100
Subject: [PATCH 8/9] completed all requirements of invert
---
Sprint-2/interpret/invert.js | 9 ++++--
Sprint-2/interpret/invert.test.js | 53 +++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js
index d828bdd21..30fc6f16a 100644
--- a/Sprint-2/interpret/invert.js
+++ b/Sprint-2/interpret/invert.js
@@ -7,12 +7,17 @@
// E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"}
function invert(obj) {
- const invertedObj = {};
+ if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
+ throw new Error("Enter a valid object");
+ }
+ if (Object.keys(obj).length === 0) {
+ return {};
+ }
+ const invertedObj = {};
for (let [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
index 4530cc81b..26dead034 100644
--- a/Sprint-2/interpret/invert.test.js
+++ b/Sprint-2/interpret/invert.test.js
@@ -4,4 +4,57 @@ describe("invertObj", () => {
test("when given an object, should swap the keys and values in the object", () => {
expect(invertObj({ x: 10, y: 20 })).toEqual({ 10: "x", 20: "y" });
});
+
+ test("when passed an object with one key-value pair, should swap the key and value", () => {
+ expect(invertObj({ a: 1 })).toEqual({ 1: "a" });
+ });
+
+ test("when passed an empty object, should return an empty object", () => {
+ expect(invertObj({})).toEqual({});
+ });
+
+ test("when passed string values, should swap the keys and values", () => {
+ expect(invertObj({ first: "apple", second: "banana" })).toEqual({
+ apple: "first",
+ banana: "second",
+ });
+ });
+
+ test("when passed boolean values, should swap the keys and values", () => {
+ expect(invertObj({ yes: true, no: false })).toEqual({
+ true: "yes",
+ false: "no",
+ });
+ });
+
+ test("when passed a null value, should use 'null' as the key", () => {
+ expect(invertObj({ a: null })).toEqual({
+ null: "a",
+ });
+ });
+
+ test("when passed an undefined value, should use 'undefined' as the key", () => {
+ expect(invertObj({ a: undefined })).toEqual({
+ undefined: "a",
+ });
+ });
+
+ //error
+ test.each([null, undefined, [], "cat", 4, true])(
+ "Throws an error when input is %p",
+ (input) => {
+ expect(() => {
+ invertObj(input);
+ }).toThrow("Enter a valid object");
+ }
+ );
+
+ test("when value is swapped and keys are identical", () => {
+ const input = { a: 1, b: 1 };
+ const expected = {
+ 1: "b",
+ };
+ const result = invertObj(input);
+ expect(result).toEqual(expected);
+ });
});
From 330582e2dbdaa0ad5072dd41e1dc219ee6b328c2 Mon Sep 17 00:00:00 2001
From: d-odumosu
Date: Fri, 31 Jul 2026 22:33:46 +0100
Subject: [PATCH 9/9] completed all requirements of queryString
---
Sprint-2/implement/querystring.js | 15 ++++++++++++---
Sprint-2/implement/querystring.test.js | 12 +-----------
2 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js
index 45ec4e5f3..fa69f9af4 100644
--- a/Sprint-2/implement/querystring.js
+++ b/Sprint-2/implement/querystring.js
@@ -6,10 +6,19 @@ function parseQueryString(queryString) {
const keyValuePairs = queryString.split("&");
for (const pair of keyValuePairs) {
- const [key, value] = pair.split("=");
- queryParams[key] = value;
+ const indexOfFirst = pair.indexOf("=");
+ if (indexOfFirst === -1) {
+ queryParams[pair] = "";
+ } else {
+ let key = decodeURIComponent(
+ pair.slice(0, indexOfFirst).replaceAll("+", " ")
+ );
+ let value = decodeURIComponent(
+ pair.slice(indexOfFirst + 1).replaceAll("+", " ")
+ );
+ queryParams[key] = value;
+ }
}
-
return queryParams;
}
diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js
index 328b8df61..a2f400262 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({
@@ -36,13 +36,3 @@ test("should replace '+' by ' '", () => {
"full name": "John Doe",
});
});
-
-// 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"],
- foo: "bar",
- });
-});