Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 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
4 changes: 2 additions & 2 deletions Sprint-2/debug/address.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
// Fix anything that isn't working

const address = {
houseNumber: 42,
houseNumber: "42",
street: "Imaginary Road",
city: "Manchester",
country: "England",
postcode: "XYZ 123",
};

console.log(`My house number is ${address[0]}`);
console.log(`My house number is ${address.houseNumber}`);
4 changes: 2 additions & 2 deletions Sprint-2/debug/author.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ const author = {
firstName: "Zadie",
lastName: "Smith",
occupation: "writer",
age: 40,
age: "40",
alive: true,
};

for (const value of author) {
for (const value of Object.values(author)) {
console.log(value);
}
10 changes: 5 additions & 5 deletions Sprint-2/debug/recipe.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
// How can you fix it?

const recipe = {
title: "bruschetta",
title: "bruschetta",
serves: 2,
ingredients: ["olive oil", "tomatoes", "salt", "pepper"],
};

console.log(`${recipe.title} serves ${recipe.serves}
ingredients:
${recipe}`);
console.log(`${recipe.title} \nserves ${recipe.serves} \nIngredients:`);
for (const ingredient of recipe.ingredients) {
console.log(ingredient);
}
7 changes: 6 additions & 1 deletion Sprint-2/implement/contains.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
function contains() {}
function contains(obj, prop) {
if (obj !== null && typeof obj === 'object' && !Array.isArray(obj)) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
return false;
}

module.exports = contains;
22 changes: 21 additions & 1 deletion Sprint-2/implement/contains.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,40 @@ as the object doesn't contains a key of 'c'
// 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
test("returns true for existing property and false for non-existing property", () => {
const obj = { a: 1, b: 2};
expect(contains(obj, "a")).toBe(true);
expect(contains(obj, "c")).toBe(false);
});

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

// Given an object with properties
// When passed to contains with an existing property name
// Then it should return true
test("returns true for existing property", () => {
const obj = { firstName: "Gina", lastName: "Rogers" };
expect(contains(obj, "firstName")).toBe(true);
});

// Given an object with properties
// When passed to contains with a non-existent property name
// Then it should return false
test("returns false for non-existing property", () => {
const obj = { firstName: "Gina", lastName: "Rogers" };
expect(contains(obj, "age")).toBe(false);
});

// Given invalid parameters like an array
// When passed to contains
// Then it should return false or throw an error
test("handles invalid parameters", () => {
const arr = [1, 2, 3];
expect(contains(arr, "0")).toBe(false);
});
18 changes: 16 additions & 2 deletions Sprint-2/implement/lookup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
function createLookup() {
// implementation here
function createLookup(pairs) {
// function accepts one parameter: pairs of country-currency code arrays
if (!Array.isArray(pairs)) {
return {}; // Return empty object if input is not an array
}

const lookup = {}; // Initialize empty lookup object, key-value pairs stored in this object
for (const pair of pairs) {
// Iterate over each pair in the input array
if (Array.isArray(pair) && pair.length >= 2) {
const [countryCode, currencyCode] = pair; // Destructuring first two elements of pair array and assigning them to country and currency
lookup[countryCode] = currencyCode; // Add country-currency pair to the lookup object - later entries overwrite earlier ones if duplicate country codes exist.
}
}
return lookup;
}


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

test.todo("creates a country currency code lookup for multiple codes");

test("creates a country currency code lookup for multiple codes", () => {
const countryCurrencyPairs = [
["US", "USD"],
["CA", "CAD"],
["GB", "GBP"],
];

const expectedLookup = {
US: "USD",
CA: "CAD",
GB: "GBP",
};

expect(createLookup(countryCurrencyPairs)).toEqual(expectedLookup);
});
/*

Create a lookup object of key value pairs from an array of code pairs
Expand Down
18 changes: 13 additions & 5 deletions Sprint-2/implement/querystring.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
function parseQueryString(queryString) {
const queryParams = {};
if (queryString.length === 0) {
return queryParams;
if (!queryString || queryString.length === 0) {
return queryParams; // Return empty object for empty query string
}
const keyValuePairs = queryString.split("&");
const keyValuePairs = queryString.split("&"); // Split by '&' to get individual key-value pairs

for (const pair of keyValuePairs) {
const [key, value] = pair.split("=");
queryParams[key] = value;
// Iterate over each key-value pair
if (!pair.includes("=")) {
// Handle missing equals sign
queryParams[pair] = undefined; // Assign undefined for keys without equals sign
continue; // Move to the next pair
}
const [key, ...rest] = pair.split("="); // array destructured into key and rest of array.
// Split by '=' to separate key and value.
const value = rest.join("="); // Join back any '=' in the value using rest operator
queryParams[key] = value; // Assign key-value pair to the result object
}

return queryParams;
Expand Down
39 changes: 36 additions & 3 deletions Sprint-2/implement/querystring.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,43 @@
// Below is one test case for an edge case the implementation doesn't handle well.
// Fix the implementation for this test, 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("parses querystring values containing =", () => {
expect(parseQueryString("equation=x=y+1")).toEqual({
"equation": "x=y+1",
expect(parseQueryString("equation=x=y+1")).toEqual({ equation: "x=y+1" });
});

test("parses empty string to empty object", () => {
expect(parseQueryString("")).toEqual({});
});

test("parses single key-value pair", () => {
expect(parseQueryString("name=Gina")).toEqual({ name: "Gina" });
});

test("parses multiple key-value pairs", () => {
expect(parseQueryString("name=Gina&age=23&city=Nottingham")).toEqual({
name: "Gina",
age: "23",
city: "Nottingham",
});
});

test("handles keys without values", () => {
expect(parseQueryString("name=&age=23")).toEqual({ name: "", age: "23" });
});

test("handles values without keys", () => {
expect(parseQueryString("=Gina&age=23")).toEqual({ "": "Gina", age: "23" });
});

test("handles missing equals sign", () => {
expect(parseQueryString("nameGina&age23")).toEqual({
nameGina: undefined,
age23: undefined,
});
});

test("handles repeated keys", () => {
expect(parseQueryString("name=Gina&name=Jane")).toEqual({ name: "Jane" });
});
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(items) {
if (!Array.isArray(items)) {
throw new Error("Input must be an array");
}
const counts = {}; // empty object to store tally of key-value pairs
for (const item of items) {
// iterates through each element in the items array
if (counts[item]) {
// checks if the item already exists as a key in counts object
counts[item] += 1; // increments the count for that item by 1
} else {
counts[item] = 1; // initializes the count for that item to 1
}
}
return counts; // returns the final counts object
}

module.exports = tally;
20 changes: 19 additions & 1 deletion Sprint-2/implement/tally.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,34 @@ 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("tally counts frequency of each item in an array", () => {
const input = ["a", "a", "b", "c", "b", "a"];
const expectedOutput = { a: 3, b: 2, c: 1 };
expect(tally(input)).toEqual(expectedOutput);
});

// 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 expectedOutput = {};
expect(tally(input)).toEqual(expectedOutput);
});

// Given an array with duplicate items
// When passed to tally
// Then it should return counts for each unique item
test("tally counts each unique item in an array with duplicates", () => {
const input = ["x", "y", "x", "z", "y", "x"];
const expectedOutput = { x: 3, y: 2, z: 1 };
expect(tally(input)).toEqual(expectedOutput);
});

// Given an invalid input like a string
// When passed to tally
// Then it should throw an error
test("tally throws an error for invalid input", () => {
const input = "invalid input";
expect(() => tally(input)).toThrow("Input must be an array");
});
17 changes: 16 additions & 1 deletion Sprint-2/interpret/invert.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,38 @@
// E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"}

function invert(obj) {
// Guard: only accept plain objects (not null, not arrays, not primitives)
if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) {
return {};
}

const invertedObj = {};

for (const [key, value] of Object.entries(obj)) {
invertedObj.key = value;
// Ensure the value is used as a string key (object keys are strings)
invertedObj[String(value)] = key;
}

return invertedObj;
}

module.exports = invert;

// a) What is the current return value when invert is called with { a : 1 }
// { '1': 'a' }

// b) What is the current return value when invert is called with { a: 1, b: 2 }
// { '1': 'a', '2': 'b' }

// 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 returns an array of key-value pairs from the object.
// It is needed to iterate over each key-value pair in the input object.

// d) Explain why the current return value is different from the target output
// Numeric key values are converted to strings in the output object keys.

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

describe('invert', () => {
test('inverts a single key', () => {
expect(invert({ a: 1 })).toEqual({ '1': 'a' });
});

test('inverts multiple keys', () => {
expect(invert({ a: 1, b: 2 })).toEqual({ '1': 'a', '2': 'b' });
});

test('duplicate values: last key wins', () => {
expect(invert({ a: 1, b: 1 })).toEqual({ '1': 'b' });
});

test('non-object inputs return empty object', () => {
expect(invert(null)).toEqual({});
expect(invert(undefined)).toEqual({});
expect(invert(123)).toEqual({});
expect(invert([1, 2, 3])).toEqual({});
});
});