Skip to content
Closed
5 changes: 4 additions & 1 deletion Sprint-2/debug/address.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Predict and explain first...
// This will fail because to parse from an object requires a key, not an index value

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

console.log(`My house number is ${address[0]}`);
console.log(
`My house number is ${address.houseNumber}, ${address.street}, ${address.city}, ${address.country}, ${address.postcode}`
);
3 changes: 2 additions & 1 deletion Sprint-2/debug/author.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Predict and explain first...
// the for loop it the syntax for an array, I'm not sure it will work with an object

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

for (const value of author) {
for (const value of Object.values(author)) {
console.log(value);
}
6 changes: 4 additions & 2 deletions Sprint-2/debug/recipe.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// Predict and explain first...
// the title and serves looks like it would work, the ingredients list is just calling the recipe object
// that won't list any values and may return an error or undefined.

// 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 @@ -11,5 +13,5 @@ const recipe = {
};

console.log(`${recipe.title} serves ${recipe.serves}
ingredients:
${recipe}`);
ingredients:
${recipe.ingredients.join("\n")}`);
11 changes: 10 additions & 1 deletion Sprint-2/implement/contains.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
function contains() {}
function contains(object, property) {
if (typeof object !== "object" || !object || Array.isArray(object)) {
return false;
}
if (typeof property !== "string" || !object) {
return false;
}

return Object.hasOwn(object, property);
}

module.exports = contains;
61 changes: 44 additions & 17 deletions Sprint-2/implement/contains.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,51 @@ as the object doesn't contains a key of 'c'
*/

// 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");

// 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
describe("contains", () => {
// Given an empty object
// When passed to contains
// Then it should return false
it("contains on empty object returns false", () => {
const object = {};
const property = "a";
expect(contains(object, property)).toEqual(false);
});

// Given an object with properties
// When passed to contains with an existing property name
// Then it should return true
it("object contains property returns true", () => {
const object = { a: 1, b: 2 };
const property = "a";
expect(contains(object, property)).toEqual(true);
});

// Given an object with properties
// When passed to contains with a non-existent property name
// Then it should return false
it("object does not contain property returns false", () => {
const object = { a: 1, b: 2 };
const property = "c";
expect(contains(object, property)).toEqual(false);
});

// Given invalid parameters like an array
// When passed to contains
// Then it should return false or throw an error
it("given invalid parameter (an array) returns false or throws an error", () => {
expect(contains([], [])).toEqual(false);
expect(contains(["a", 1], "a")).toEqual(false);
expect(contains({ a: 1, b: 2 }, ["a"])).toEqual(false);
expect(contains(["a", 1], ["a"])).toEqual(false);
});

it("given null returns false", () => {
expect(contains(null, "a")).toEqual(false);
expect(contains({ a: 1, b: 2 }, null)).toEqual(false);
expect(contains(null, null)).toEqual(false);
});
});
8 changes: 6 additions & 2 deletions Sprint-2/implement/lookup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
function createLookup() {
// implementation here
function createLookup(arrayOfArrays) {
const lookup = {};
for (const array of arrayOfArrays) {
lookup[array[0]] = array[1];
}
return lookup;
}

module.exports = createLookup;
15 changes: 14 additions & 1 deletion Sprint-2/implement/lookup.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
const createLookup = require("./lookup.js");

test.todo("creates a country currency code lookup for multiple codes");
describe("createLookup", () => {
it("creates a country currency code lookup for multiple codes", () => {
const arrayOfArrays = [
["US", "USD"],
["CA", "CAD"],
["UK", "GBP"],
];
expect(createLookup(arrayOfArrays)).toEqual({
US: "USD",
CA: "CAD",
UK: "GBP",
});
});
});

/*

Expand Down
17 changes: 15 additions & 2 deletions Sprint-2/implement/querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,24 @@ function parseQueryString(queryString) {
if (queryString.length === 0) {
return queryParams;
}

// Adds percentage-encoded characters
queryString = decodeURIComponent(queryString);

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

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

for (const pair of keyValuePairs) {
const [key, value] = pair.split("=");
queryParams[key] = value;
if (pair !== "") {
let index = pair.indexOf("=");
if (!pair.includes("=")) {
index = pair.length;
}
const [key, value] = [pair.slice(0, index), pair.slice(index + 1)];
queryParams[key] = value;
}
}

return queryParams;
Expand Down
4 changes: 3 additions & 1 deletion 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 @@ -40,9 +40,11 @@ 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"],
foo: "bar",
});
});
*/
13 changes: 12 additions & 1 deletion Sprint-2/implement/tally.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
function tally() {}
function tally(array) {
if (!Array.isArray(array)) {
throw new Error("Invalid array");
}
const count = Object.create(null);
array.forEach((item) => {
if (item in count) {
count[item] += 1;
} else count[item] = 1;
});
return count;
}

module.exports = tally;
35 changes: 25 additions & 10 deletions Sprint-2/implement/tally.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,30 @@ const tally = require("./tally.js");
// When passed an array of items
// Then it should return an object containing the count for each unique item

// 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("tally", () => {
// Given an empty array
// When passed to tally
// Then it should return an empty object
it("tally on an empty array returns an empty object", () => {
const array = [];
expect(tally(array)).toEqual({});
});

// Given an array with duplicate items
// When passed to tally
// Then it should return counts for each unique item
// Given an array with duplicate items
// When passed to tally
// Then it should return counts for each unique item
it("tally returns counts for each unique item", () => {
expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 });
expect(tally(["toString", "toString"])).toEqual({ toString: 2 });
});

// 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
it("tally on an empty array returns an empty object", () => {
const array = "string";
expect(() => {
tally(array);
}).toThrow("Invalid array");
});
});
15 changes: 13 additions & 2 deletions Sprint-2/interpret/invert.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,35 @@

// E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"}

invert({ a: 1, b: 2 });

function invert(obj) {
const invertedObj = {};

for (const [key, value] of Object.entries(obj)) {
invertedObj.key = value;
invertedObj[value] = key;
}

console.log(invertedObj);
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}
// {1: a, 2: b}

// c) What does Object.entries return? Why is it needed in this program?
// It turns the object into an array of arrays
// It's needed so the for..of loop can access the key:value pairs

// d) Explain why the current return value is different from the target output
// invertedObj.key = value;
// this line of code sets the key to "key"
// even if that worked as intended, the key and value haven't been swapped

// e) Fix the implementation of invert (and write tests to prove it's fixed!)
module.exports = invert;
13 changes: 13 additions & 0 deletions Sprint-2/interpret/invert.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const invert = require("./invert.js");

describe("invert", () => {
it("object returns inverted object", () => {
// a) What is the current return value when invert is called with { a : 1 }
let object = { a: 1 };
expect(invert(object)).toEqual({ 1: "a" });

// b) What is the current return value when invert is called with { a: 1, b: 2 }
object = { a: 1, b: 2 };
expect(invert(object)).toEqual({ 1: "a", 2: "b" });
});
});
4 changes: 2 additions & 2 deletions Sprint-3/quote-generator/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title here</title>
<title>Quote Generator App</title>
<script defer src="quotes.js"></script>
</head>
<body>
<h1>hello there</h1>
<h1>Random Quote:</h1>
<p id="quote"></p>
<p id="author"></p>
<button type="button" id="new-quote">New quote</button>
Expand Down
31 changes: 31 additions & 0 deletions Sprint-3/quote-generator/quotes.js
Original file line number Diff line number Diff line change
Expand Up @@ -491,3 +491,34 @@ const quotes = [
];

// call pickFromArray with the quotes array to check you get a random quote

function setup() {
updateQuote();
appendQuote();
}

const state = {
quote: "",
author: "",
};

function updateQuote() {
const chosenQuote = pickFromArray(quotes);
state.quote = chosenQuote.quote;
state.author = chosenQuote.author;
}

function appendQuote() {
const quoteElem = document.getElementById("quote");
const authorElem = document.getElementById("author");
quoteElem.textContent = "";
authorElem.textContent = "";
quoteElem.append(state.quote);
authorElem.append(state.author);
}

document.getElementById("new-quote").addEventListener("click", function () {
setup();
});

window.onload = setup;
Loading