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
4 changes: 3 additions & 1 deletion Sprint-2/debug/address.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Predict and explain first...

//The code will not log the house number as it is using the wrong syntax to access the property.

// 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 +14,4 @@ const address = {
postcode: "XYZ 123",
};

console.log(`My house number is ${address[0]}`);
console.log(`My house number is ${address.houseNumber}`);
6 changes: 4 additions & 2 deletions Sprint-2/debug/author.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Predict and explain first...

// The code will not log the values of the object because a for of loop cannot be used on 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 +13,6 @@ const author = {
alive: true,
};

for (const value of author) {
console.log(value);
for (const value in author) {
console.log(author[value]);
}
4 changes: 3 additions & 1 deletion Sprint-2/debug/recipe.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Predict and explain first...

//The code is log the title and serves correctly, but will not log the ingredients properly because it is trying to log the entire recipe object and not the ingredients array

// This program should log out the title, how many it serves and the ingredients.
// Each ingredient should be logged on a new line
// How can you fix it?
Expand All @@ -12,4 +14,4 @@ const recipe = {

console.log(`${recipe.title} serves ${recipe.serves}
ingredients:
${recipe}`);
${recipe.ingredients}`);
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(obj, prop) {
if(arguments.length !== 2){
throw new Error('Invalid input: function requires two arguments');
}
if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) {
throw new Error('Invalid input: first argument must be an object');
}
return obj.hasOwnProperty(prop);

}

module.exports = contains;
53 changes: 51 additions & 2 deletions Sprint-2/implement/contains.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,65 @@ as the object doesn't contains a key of 'c'
// Given an empty object
// When passed to contains
// Then it should return false
test.todo("contains on empty object returns false");
test("should return false when passed an empty object", () => {
expect(contains({}, "a")).toBe(false);
});

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

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

// Given invalid parameters like an array
// When passed to contains
// Then it should return false or throw an error

describe('error on invalid input', () => {
test.each([
[null, 'a'],
[undefined, 'a'],
[42, 'a'],
['string', 'a'],
[true, 'a'],
[[], 'a'],
])('contains(%p, %p) should throw an error', (obj, prop) => {
expect(() => contains(obj, prop)).toThrow('Invalid input: first argument must be an object');
});
});

// Given an object with a property set to undefined
test("should return true when the property exists but is undefined", () => {
expect(contains({ a: undefined, b: 2 }, "a")).toBe(true);
});

// Given an object with a property set to null
test("should return true when the property exists but is null", () => {
expect(contains({ a: null, b: 2 }, "a")).toBe(true);
});

// Given an object with a property whose value is falsy
test("should return true when the property exists but is falsy", () => {
expect(contains({ a: 0, b: false, c: '', d: NaN }, "a")).toBe(true);
expect(contains({ a: 0, b: false, c: '', d: NaN }, "b")).toBe(true);
expect(contains({ a: 0, b: false, c: '', d: NaN }, "c")).toBe(true);
expect(contains({ a: 0, b: false, c: '', d: NaN }, "d")).toBe(true);
});

//incorrect arguments
test("should throw an error when called with incorrect number of arguments", () => {
expect(() => contains({ a: 1 })).toThrow('Invalid input: function requires two arguments');
expect(() => contains()).toThrow('Invalid input: function requires two arguments');
expect(() => contains({ a: 1 }, 'a', 'extra')).toThrow('Invalid input: function requires two arguments');
});



30 changes: 27 additions & 3 deletions Sprint-2/implement/lookup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
function createLookup() {
// implementation here
function createLookup(arr) {
if(!arguments.length) {
throw new Error('No arguments provided');
}
const result = {};
if (!Array.isArray(arr)) {
return result;
}
for (const item of arr) {
if (Array.isArray(item) && item.length >= 2) {
const country = item[0];
const currency = item[1];
if (Array.isArray(currency)) {
result[country] = currency;
}
if (currency === null || currency === undefined) {
continue;
}

if (country.length && currency.length && typeof country === 'string' && typeof currency === 'string') {
result[country] ? result[country] = [result[country], currency]
: result[country] = currency;
}
}
}
return result;
}

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

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

const createLookup = require("./lookup.js")
/*

Create a lookup object of key value pairs from an array of code pairs
Expand Down Expand Up @@ -33,3 +30,127 @@ It should return:
'CA': 'CAD'
}
*/
//return an object
test('should return an object', () => {
expect(typeof createLookup([['US', 'USD'], ['CA', 'CAD']])).toBe('object');
})
//empty array
test('should handle empty array', () => {
const result = createLookup([]);
expect(result).toEqual({});
})
//single entry
test("should handle single entry", () => {
const result = createLookup([["FR", "EUR"]]);
expect(result).toEqual({
FR: "EUR",
});
});
//multiple entries
test('should handle multiple entries', () => {
const result = createLookup([['US', 'USD'], ['CA', 'CAD'], ['GB', 'GBP']]);
expect(result).toEqual({
'US': 'USD',
'CA': 'CAD',
'GB': 'GBP'
});
})
//duplicate country codes
test('should handle duplicate country codes by creating an array for the values', () => {
const result = createLookup([['US', 'USD'], ['CA', 'CAD'], ['US', 'USN']]);
expect(result).toEqual({
'US': ['USD', 'USN'],
'CA': 'CAD'
});
})
//special characters
test('should handle country codes with special characters', () => {
const result = createLookup([['UK-1', 'GBP'], ['EU@27', 'EUR']]);
expect(result).toEqual({
'UK-1': 'GBP',
'EU@27': 'EUR'
});
})
//non-string country and currency codes
test('should omit non-string country and currency codes', () => {
const result = createLookup([[1, 100], [2, 200]]);
expect(result).toEqual({});
const result2 = createLookup([['US', 100], [2, 'CAD']]);
expect(result2).toEqual({})
})
//nested arrays
test('should handle nested arrays as values', () => {
const result = createLookup([['US', ['USD', 'USN']], ['CA', ['CAD', 'CADN']]]);
expect(result).toEqual({
'US': ['USD', 'USN'],
'CA': ['CAD', 'CADN']
});
})
//null and undefined values
test('should omit null and undefined values', () => {
const result = createLookup([['US', null], ['CA', undefined]]);
expect(result).toEqual({});
})
//insufficient elements
test('should omit array with insufficient elements', () => {
const result = createLookup([['US', 'USD'], ['CA'], ['GB', 'GBP']]);
expect(result).toEqual({
'US': 'USD',
'GB': 'GBP'
});
})
//extra elements
test('should handle array with extra elements', () => {
const result = createLookup([['US', 'USD', 'extra'], ['CA', 'CAD'], ['GB', 'GBP', 'extra2']]);
expect(result).toEqual({
'US': 'USD',
'CA': 'CAD',
'GB': 'GBP'
});
})
//whitespace in country and currency codes
test('should handle whitespace in country and currency codes', () => {
const result = createLookup([[' US ', ' USD '], [' CA ', ' CAD ']]);
expect(result).toEqual({
' US ': ' USD ',
' CA ': ' CAD '
});
})
//empty strings
test('should omit empty strings as country and currency codes', () => {
const result = createLookup([['', ''], ['CA', 'CAD']]);
expect(result).toEqual({
'CA': 'CAD'
});
})
//invalid array elements
test('should handle array with non-array and insufficient/extra elements', () => {
const result = createLookup([['US', 'USD'], 'invalid', ['CA'], ['GB', 'GBP']]);
expect(result).toEqual({
'US': 'USD',
'GB': 'GBP'
});
const result2 = createLookup([
["US", "USD", "extra"],
"invalid",
["CA", "CAD"],
["GB", "GBP", "extra2"],
]);
expect(result2).toEqual({
US: "USD",
CA: "CAD",
GB: "GBP",
});
})
//incorrect argument types
test('should return empty object for non-array arguments', () => {
expect(createLookup(null)).toEqual({});
expect(createLookup(undefined)).toEqual({});
expect(createLookup(123)).toEqual({});
expect(createLookup('string')).toEqual({});
expect(createLookup({})).toEqual({});
})
//no arguments
test('should throw error when no arguments are provided', () => {
expect(() => createLookup()).toThrow('No arguments provided');
})
12 changes: 10 additions & 2 deletions Sprint-2/implement/querystring.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,16 @@ function parseQueryString(queryString) {
const keyValuePairs = queryString.split("&");

for (const pair of keyValuePairs) {
const [key, value] = pair.split("=");
queryParams[key] = value;
if(pair.indexOf('=') !== pair.lastIndexOf('=')){
const firstEqualIndex = pair.indexOf('=');
const key = pair.substring(0, firstEqualIndex);
const value = pair.substring(firstEqualIndex + 1);
queryParams[key] = value;
continue;
} else {
const [key, value] = pair.split("=");
queryParams[key] = value;
}
}

return queryParams;
Expand Down
69 changes: 69 additions & 0 deletions Sprint-2/implement/querystring.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,72 @@ test("parses querystring values containing =", () => {
"equation": "x=y+1",
});
});
//other edge cases to consider:
test("parses empty querystring", () => {
expect(parseQueryString("")).toEqual({});
});

test("parses querystring with multiple key-value pairs", () => {
expect(parseQueryString("name=John&age=30&city=NewYork")).toEqual({
"name": "John",
"age": "30",
"city": "NewYork",
});
});

test("parses querystring with missing value", () => {
expect(parseQueryString("name=John&age=&city=NewYork")).toEqual({
"name": "John",
"age": "",
"city": "NewYork",
});
});

test("parses querystring with missing key", () => {
expect(parseQueryString("=John&age=30&city=NewYork")).toEqual({
"": "John",
"age": "30",
"city": "NewYork",
});
});

test("parses querystring with no equals sign", () => {
expect(parseQueryString("nameJohn&age30&cityNewYork")).toEqual({
"nameJohn": undefined,
"age30": undefined,
"cityNewYork": undefined,
});
});

test("parses querystring with encoded characters", () => {
expect(parseQueryString("name=John%20Doe&city=New%20York")).toEqual({
"name": "John%20Doe",
"city": "New%20York",
});
});

test("parses querystring with repeated keys", () => {
expect(parseQueryString("name=John&name=Jane&age=30")).toEqual({
"name": "Jane",
"age": "30",
});
});

test("parses querystring with special characters in keys and values", () => {
expect(parseQueryString("na!me=Jo@hn&ag#e=3$0")).toEqual({
"na!me": "Jo@hn",
"ag#e": "3$0",
});
});
test("parses querystring with leading and trailing ampersands", () => {
expect(parseQueryString("&name=John&age=30&")).toEqual({
"name": "John",
"age": "30",
});
});

test("parses querystring with multiple equals signs in value", () => {
expect(parseQueryString("data=a=b=c=d")).toEqual({
"data": "a=b=c=d",
});
});
Loading