Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Sprint-2/debug/address.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Predict and explain first...

// address[0] will not work here as we have an object of key-value pairs. instead of square bracket notation we need the dot notation with the key
// I would think it returns undefined.

// This code should log out the houseNumber from the address object
// but it isn't working...
// Fix anything that isn't working
Expand All @@ -12,4 +15,4 @@ const address = {
postcode: "XYZ 123",
};

console.log(`My house number is ${address[0]}`);
console.log(`My house number is ${address.houseNumber}`);
13 changes: 10 additions & 3 deletions Sprint-2/debug/author.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
// Predict and explain first...
// author is an object. It cannot be accessed through its values, maybe through its key, value pairs instead of "value" -

//update on explanation: objects could be accessed through 3 methods, depending on whether we want the property name or property value, or the pair. :
//1. Object.keys() collects into an array the keys (property names) ignoring the values
//2. Object.values() collects into an array the values ignoring the property names
//3. Object.entries() collects an array of arrays of key-value pairs

// 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
Expand All @@ -11,6 +17,7 @@ const author = {
alive: true,
};

for (const value of author) {
console.log(value);
}
console.log(Object.values(author));
// for (const value of author) {
// console.log(value);
// }
Comment on lines +20 to +23

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good workaround to print the values of the object.

Question - how could the for loop on lines 21 - 23 be changed (to a different loop for example) to achieve the same effect?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created an alternative using a loop

21 changes: 18 additions & 3 deletions Sprint-2/debug/recipe.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Predict and explain first...
//in the template literal the ${recipe}`is referring to the whole object, we want the items in the ingredients of the recipe object, listed line by line.

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

console.log(`${recipe.title} serves ${recipe.serves}
ingredients:
${recipe}`);
// const recipeKeys = Object.keys(recipe)
// // console.log(recipeKeys)

const recipeValues = Object.values(recipe);
// ["bruschetta", 2, ["olive oil", "tomatoes", "salt", "pepper"]]

const ingredients = recipeValues.slice(-1)[0];
// ["olive oil","tomatoes","salt","pepper"]

Comment on lines +17 to +22

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good use of methods but how could we reduce the amount of code we're writing here?

Is there a more direct way to access the ingredients so you can join them on line 25?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, i seem to have created more work for myself than needed. corrected now

//create a function to log line by line the elements of an array
function logItemised(items) {
return items.join("\n");
}

console.log(
`${recipe.title} serves ${recipe.serves}${"\n"}ingredients:${"\n"}${logItemised(ingredients)}`
);
23 changes: 22 additions & 1 deletion Sprint-2/implement/contains.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
function contains() {}
function contains(object, propertyName) {
if (typeof object !== "object" || object === null || Array.isArray(object)) {
throw new Error("Input should be an object");
}
const keysInObject = Object.keys(object);
if (keysInObject.includes(propertyName)) {
return true;
} else {
return false;
}
}
Comment on lines +6 to +11

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could you refactor these lines to be more concise?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, since it returns a boolean, I dont have to write if else statement. done.


module.exports = contains;

/*
Implement a function called contains that checks an object contains a
particular property

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'
*/
30 changes: 29 additions & 1 deletion Sprint-2/implement/contains.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,23 @@ 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

describe("when checking property existence", () => {
test("should return true if the object contains the property", () => {
expect(contains({ a: "apple", b: "hill" }, "a")).toBe(true);
});
test("should return false if the object does not contain the property", () => {
expect(contains({ a: "apple", b: "hill" }, "c")).toBe(false);
});
});

// Given an empty object
// When passed to contains
// Then it should return false
test.todo("contains on empty object returns false");
describe("given an empty object", () => {
test("should return false when passed to contains", () => {
expect(contains({}, "a").toBe(false));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line fails - please correct it

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh those brackets... fixed now.

});
});

// Given an object with properties
// When passed to contains with an existing property name
Expand All @@ -33,3 +46,18 @@ test.todo("contains on empty object returns false");
// Given invalid parameters like an array
// When passed to contains
// Then it should return false or throw an error
describe("when given invalid inputs", () => {
test("should throw an error if the input is not an object", () => {
expect(() => contains([true, 2, "hill"], "2")).toThrow(
"Input should be an object"
);
});

test("should throw an error if the input is not an object", () => {
expect(() => contains(null, "hi")).toThrow("Input should be an object");
});

test("should throw an error if the input is not an object", () => {
expect(() => contains("apple", "a")).toThrow("Input should be an object");
});
});
51 changes: 49 additions & 2 deletions Sprint-2/implement/lookup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,52 @@
function createLookup() {
// implementation here
function createLookup(countryCurrencyPairs) {
//if countryCurrencyPairs is not an array, throw error
if (!Array.isArray(countryCurrencyPairs)) {
throw new Error("Invalid input. It should be an array");
}
//if it is an empty array, throw error
if (countryCurrencyPairs.length === 0) {
throw new Error("Input should not be an empty array");
}

//if not all elements are an array in the array, throw an error
if (!countryCurrencyPairs.every(Array.isArray)) {
throw new Error("Invalid input. All elements should be arrays");
}

return Object.fromEntries(countryCurrencyPairs);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice choice of method

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you i came across it when learning about iterating through objects. very handy.

}

module.exports = createLookup;

// console.log(
// createLookup([
// ["US", "USD"],
// ["CA", "CAD"],
// ])
// );

// console.log(createLookup([]));

/*
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'
}

*/
39 changes: 37 additions & 2 deletions Sprint-2/implement/lookup.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,41 @@
const createLookup = require("./lookup.js");

test.todo("creates a country currency code lookup for multiple codes");
describe("when given invalid inputs", () => {
test("should return invalid input error, if the input is an empty array", () => {
expect(() => createLookup([])).toThrow(
"Input should not be an empty array"
);
});
test("should return invalid input error, if the input isn't an array of arrays", () => {
expect(() => createLookup(["hi", "hello"])).toThrow(
"Invalid input. All elements should be arrays"
);
});
test("should return invalid input error, if the input isn't an array of arrays", () => {
expect(() => createLookup("hi")).toThrow(
"Invalid input. It should be an array"
);
});
test("should return invalid input error, if the input isn't an array of arrays", () => {
expect(() => createLookup(2)).toThrow(
"Invalid input. It should be an array"
);
});
});

describe("when given valid inputs", () => {
test("should return an object where (Input ==> Output): keys:values ==> country code: corresponding currency", () => {
expect(
createLookup([
["US", "USD"],
["CA", "CAD"],
])
).toEqual({
US: "USD",
CA: "CAD",
});
});
});
Comment on lines +26 to +38

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you have included a simpler test to start with for valid inputs?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i added a simpler input with only one array in the array (one country's data)


/*

Expand All @@ -9,7 +44,7 @@ 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
- An array of arrays representing when given invalid inputs code pairs
e.g. [['US', 'USD'], ['CA', 'CAD']]

When
Expand Down
33 changes: 29 additions & 4 deletions Sprint-2/implement/querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,37 @@ function parseQueryString(queryString) {
if (queryString.length === 0) {
return queryParams;
}
const keyValuePairs = queryString.split("&");

for (const pair of keyValuePairs) {
const [key, value] = pair.split("=");
queryParams[key] = value;
//replace initial "?" if present
if (queryString.startsWith("?")) {
queryString = queryString.replace("?", "");
}
//replace encoded characters
queryString = decodeURIComponent(queryString);

//replace "+" with " "
queryString = queryString.replaceAll("+", " ");

const keyValuePairs = queryString.split("&");

//filter out empty strings from the keyValuePairs array of strings
let filteredKeyValuePairs = keyValuePairs.filter(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could this be a const?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, and i changed it now. (as above) I need to rememer to use const instead of let

(keyValuePair) => keyValuePair.length > 0
);

//assign key value pairs created by separating on the first "=" sign
filteredKeyValuePairs.forEach((str) => {
//if no "=", then the string should be the key
if (!str.includes("=")) {
const key = str;
queryParams[key] = "";
} else {
const indexOfFirstEqual = str.indexOf("=");
const key = str.slice(0, indexOfFirstEqual);
const value = str.slice(indexOfFirstEqual + 1);
queryParams[key] = value;
}
});

return queryParams;
}
Expand Down
19 changes: 11 additions & 8 deletions Sprint-2/implement/querystring.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -37,12 +37,15 @@ test("should replace '+' by ' '", () => {
});
});

test("should delete accidental '?' if first char by accident", () => {
expect(parseQueryString("?colour=teal")).toEqual({ colour: "teal" });
});
// 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",
});
});
// // 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",
// });
// });
17 changes: 16 additions & 1 deletion Sprint-2/implement/tally.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
function tally() {}
function tally(array) {
if (typeof array === "string") {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the input is a number or a boolean? How can you change this condition so it will hold up against any wrong input type?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, i took the instructions too literally :)
corrected and test written for this version

throw new Error("Input should be an array");
}

let tallySet = {};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this code still work if you made the variable a constant? Explain your answer :)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, and updated it.
It would work still, as the variable ramains the same, we are not trying to update it, merely working with the items inside


for (let item of array) {
if (!tallySet[item]) {
tallySet[item] = 1;
} else {
tallySet[item] += 1;
}
}
return tallySet;
}

module.exports = tally;
40 changes: 28 additions & 12 deletions Sprint-2/implement/tally.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,32 @@ 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
describe("tally()", () => {
// Given an array with duplicate items
// When passed to tally
// Then it should return counts for each unique item
describe("when given an array with duplicate items", () => {
test("should return an object with counts for each unique item", () => {
expect(tally(["a"])).toEqual({ a: 1 });
expect(tally(["a", "a", "a"])).toEqual({ a: 3 });
expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 });
Comment on lines +28 to +30

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think these are three different behaviours and so deserve their own test blocks to anyone reading them test suite can see the different behaviours clearly.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

corrected.

});
});
// Given an empty array
// When passed to tally
// Then it should return an empty object
describe("when given an empty array", () => {
test("should return an empty object", () => {
expect(tally([])).toEqual({});
});
});

// 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
// Given an invalid input like a string
// When passed to tally
// Then it should throw an error
describe("when given invalid input such as a string", () => {
test("should throw an error", () => {
expect(() => tally("apple")).toThrow("Input should be an array");
});
});
});
Loading
Loading