Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
6e09b64
Add initial mean.js and mean.test.js files
Iswanna Oct 23, 2025
49b82d5
Write a test for the function in the median.js file.
Iswanna Oct 23, 2025
94d5edf
Implement calculateMedian function
Iswanna Oct 23, 2025
b6b2060
Add functions, extra code, and explanatory comments to mean-median.js…
Iswanna Oct 24, 2025
935e47e
Add a return statement to the function calculateMean
Iswanna Oct 24, 2025
dfe0f44
Export function to test file using module.exports
Iswanna Oct 24, 2025
22abc47
Import calculateMean function from mean.js
Iswanna Oct 24, 2025
e0bed31
Import calculateMedian function from median.js
Iswanna Oct 24, 2025
e092070
Add package.json file
Iswanna Oct 24, 2025
4fe7d13
Comment out function that mutates array with splice
Iswanna Oct 26, 2025
f729643
Add function to calculate median without mutating the array
Iswanna Oct 27, 2025
3449f32
Add Jest test case to verify that the function implementation does no…
Iswanna Oct 27, 2025
696f20b
Add a Jest test case to check that calculateMedian returns the correc…
Iswanna Oct 30, 2025
2bf9d3c
Update function implementation to handle even-length arrays when calc…
Iswanna Oct 30, 2025
f658cab
Remove function call and console.log debugging statements
Iswanna Oct 30, 2025
7ecf949
Fix inconsistent indentation in jest test
Iswanna Oct 30, 2025
c217567
Add input validation to return null when a non-array is passed
Iswanna Nov 3, 2025
d75a3ce
Reformat median test suite for readability
Iswanna Nov 3, 2025
4040d9b
Add validation to ensure input is an array
Iswanna Nov 3, 2025
57c20f4
Filter out non-numeric values from the array and assign its reference…
Iswanna Nov 3, 2025
8a41346
Add statements to duplicate the input array and sort it in ascending …
Iswanna Nov 3, 2025
17d40f7
Add logic to calculate the median for arrays with odd or even lengths
Iswanna Nov 3, 2025
a22309d
Add test case to ensure `dedupe` returns an empty array for empty input
Iswanna Nov 3, 2025
8d14298
Make function accessible in other files by adding module.exports
Iswanna Nov 3, 2025
50670f0
Add test case for `dedupe` to ensure it returns a copy of the array w…
Iswanna Nov 3, 2025
63e538f
Refactor test cases to data-driven format using an array and loop
Iswanna Nov 4, 2025
950a4a3
Add test case to ensure dedupe removes duplicates and keeps the first…
Iswanna Nov 4, 2025
37d1133
Comment out unused test.todo
Iswanna Nov 4, 2025
1f17291
Add additional test cases for no duplicates, duplicate and mixed str…
Iswanna Nov 4, 2025
a73b980
Add case to verify dedupe removes invalid elements and duplicates, re…
Iswanna Nov 4, 2025
4ea5009
Remove the semi-colon after the expect expression
Iswanna Nov 4, 2025
e8bda7b
Add test case in invalid elements category to ensure NaN is ignored
Iswanna Nov 4, 2025
c5249d9
Rename describe block to 'dedupe - valid inputs'
Iswanna Nov 4, 2025
e95f6a4
Add describe block for invalid inputs and a test case to ensure dedup…
Iswanna Nov 4, 2025
4e105a6
Remove the if statement that checks if length of the array is equlas …
Iswanna Nov 5, 2025
ae9fb0e
Add input validation for non-array values
Iswanna Nov 5, 2025
54e1a28
Add implementation for when empty array is passed as input
Iswanna Nov 5, 2025
52e97c6
Update dedupe test cases for correct expected output
Iswanna Nov 6, 2025
ba0eff3
Implement dedupe function to remove duplicate numbers and strings,
Iswanna Nov 6, 2025
0da3ea8
Refactor condition in dedupe for easier reading and parsing
Iswanna Nov 6, 2025
a7e57bf
Remove console.log statement used for debugging
Iswanna Nov 6, 2025
06f06ed
Add comments to clarify dedupe implementation
Iswanna Nov 6, 2025
b38a131
Replace test.todo with actual test cases for findMax
Iswanna Nov 6, 2025
110ef31
Add tests for non-array inputs in findMax
Iswanna Nov 6, 2025
6e91a42
Change deduplicate back to dedupe
Iswanna Nov 6, 2025
bd49eed
Add findMax implementation for numeric arrays and handle empty array …
Iswanna Nov 9, 2025
7957277
Add logic to findMax to handle non-array inputs by throwing a TypeError
Iswanna Nov 9, 2025
b3a96a6
Add full findMax implementation:
Iswanna Nov 9, 2025
68b5557
Add multiple test cases for each findMax scenario
Iswanna Nov 9, 2025
d5d84f7
Add comments to each acceptance criteria scenario
Iswanna Nov 9, 2025
4882181
Remove .todo and add test cases for each scenario of the sum function
Iswanna Nov 9, 2025
1cad41b
Implement sum function to pass all acceptance criteria test cases
Iswanna Nov 9, 2025
ba35631
Update input and expected value for test when array contains non-numb…
Iswanna Nov 9, 2025
9f244db
Add additional test cases for each acceptance criteria scenario
Iswanna Nov 10, 2025
973758b
Refactor the implementation of includes to use a for...of loop
Iswanna Nov 10, 2025
0fb3f24
Remove redundant variable element and use item in the if statement
Iswanna Nov 10, 2025
e5e09ee
Refactor calculateMedian to remove unnecessary intermediate array clone
Iswanna Nov 20, 2025
9ed4c2c
test: ensure dedupe returns a new array copy
Iswanna Nov 20, 2025
f6c5f8a
Update sum.test.js to use toBeCloseTo for decimal/float sums
Iswanna Nov 20, 2025
68a0f81
Refactor calculateMedian by removing unnecessary array copy
Iswanna Nov 20, 2025
3b01cee
Fix errors and omissions in findMax tests: add missing assertions and…
Iswanna Nov 20, 2025
0a5cd81
Remove .toFixed(2) when returning the numeric value of sumElements
Iswanna Nov 20, 2025
d112b5b
Remove explicit precision from `toBeCloseTo` test cases
Iswanna Nov 20, 2025
b32105e
Remove redundant Number() conversion around sumElement
Iswanna Nov 20, 2025
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
32 changes: 29 additions & 3 deletions Sprint-1/fix/median.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,35 @@
// or 'list' has mixed values (the function is expected to sort only numbers).

function calculateMedian(list) {
const middleIndex = Math.floor(list.length / 2);
const median = list.splice(middleIndex, 1)[0];
return median;
// Check that the input passed to the function is an array
if (!Array.isArray(list)) {
return null;
}

// Filter valid numbers and store them in `validNumbers`
const validNumbers = list.filter(
(item) => typeof item === "number" && !isNaN(item)
);

// Return `null` if there are no valid numbers
if (validNumbers.length === 0) {
return null;
}

// Sort `validNumbers` in ascending order
// Sort validNumbers (safe to mutate because it's a new array created by filter)
validNumbers.sort((a, b) => a - b);

// Calculate the middle index of the sorted array
const middleIndex = Math.floor(validNumbers.length / 2);

// If the array has an odd number of elements, return the middle element
if (validNumbers.length % 2 !== 0) {
return validNumbers[middleIndex];
} else {
// If the array has an even number of elements, return the average of the two middle elements
return (validNumbers[middleIndex - 1] + validNumbers[middleIndex]) / 2;
}
}

module.exports = calculateMedian;
22 changes: 17 additions & 5 deletions Sprint-1/fix/median.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ describe("calculateMedian", () => {
{ input: [1, 2, 3, 4], expected: 2.5 },
{ input: [1, 2, 3, 4, 5, 6], expected: 3.5 },
].forEach(({ input, expected }) =>
it(`returns the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected))
it(`returns the median for [${input}]`, () =>
expect(calculateMedian(input)).toEqual(expected))
);

[
Expand All @@ -24,7 +25,8 @@ describe("calculateMedian", () => {
{ input: [110, 20, 0], expected: 20 },
{ input: [6, -2, 2, 12, 14], expected: 6 },
].forEach(({ input, expected }) =>
it(`returns the correct median for unsorted array [${input}]`, () => expect(calculateMedian(input)).toEqual(expected))
it(`returns the correct median for unsorted array [${input}]`, () =>
expect(calculateMedian(input)).toEqual(expected))
);

it("doesn't modify the input array [3, 1, 2]", () => {
Expand All @@ -33,8 +35,17 @@ describe("calculateMedian", () => {
expect(list).toEqual([3, 1, 2]);
});

[ 'not an array', 123, null, undefined, {}, [], ["apple", null, undefined] ].forEach(val =>
it(`returns null for non-numeric array (${val})`, () => expect(calculateMedian(val)).toBe(null))
[
"not an array",
123,
null,
undefined,
{},
[],
["apple", null, undefined],
].forEach((val) =>
it(`returns null for non-numeric array (${val})`, () =>
expect(calculateMedian(val)).toBe(null))
);

[
Expand All @@ -45,6 +56,7 @@ describe("calculateMedian", () => {
{ input: [3, "apple", 1, null, 2, undefined, 4], expected: 2.5 },
{ input: ["banana", 5, 3, "apple", 1, 4, 2], expected: 3 },
].forEach(({ input, expected }) =>
it(`filters out non-numeric values and calculates the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected))
it(`filters out non-numeric values and calculates the median for [${input}]`, () =>
expect(calculateMedian(input)).toEqual(expected))
);
});
44 changes: 43 additions & 1 deletion Sprint-1/implement/dedupe.js
Original file line number Diff line number Diff line change
@@ -1 +1,43 @@
function dedupe() {}
// This defines a function named dedupe with a parameter arrayInput. arrayInput should be an array.
function dedupe(arrayInput) {
// This checks whether the input is not an array.
if (!Array.isArray(arrayInput)) {
// If the input is not an array, the function stops, throws a TypeError and shows an error message saying:“Input must be an array.”
throw new TypeError("Input must be an array");
}
// This checks if the array is empty (has no elements).
if (arrayInput.length === 0) {
// If the array is empty, it returns an empty array.
return [];
}

// This declares a new variable `newArray` which will hold a reference to an empty array in memory
const newArray = [];
// This decares a new varibale `seen` which will hold a reference to the actual set object in memory
const seen = new Set(); // variable seen keeps track of all items that have already been added to the result array
// seen is a Set object that remembers items,

// newArray is an array that holds the actual result.

// This starts a loop that goes through each element in the input array one by one.
for (const item of arrayInput) {
// This big condition checks two things before adding an item:

// !seen.has(item) — The item has not been added before.

// The item is either a number (but not NaN) or a string.
// So only real numbers and strings that haven’t appeared yet will be kept.
if (
!seen.has(item) &&
((typeof item === "number" && !Number.isNaN(item)) ||
typeof item === "string")
) {
newArray.push(item); // If the item passes the condition, it gets added to the new array.
seen.add(item); // The item is then recorded in the Set, so it won’t be added again later.
}
}
// After the loop finishes, return the final deduplicated array
return newArray; // After checking all items, the function returns the new array with duplicates removed and invalid items filtered out.
}

module.exports = dedupe; // This line allows the dedupe function to be used in other files (like the test file).
90 changes: 78 additions & 12 deletions Sprint-1/implement/dedupe.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
const dedupe = require("./dedupe.js");

/*
Dedupe Array

📖 Dedupe means **deduplicate**
📖 Dedupe means **dedupe**

In this kata, you will need to deduplicate the elements of an array
In this kata, you will need to dedupe the elements of an array

E.g. dedupe(['a','a','a','b','b','c']) target output: ['a','b','c']
E.g. dedupe([5, 1, 1, 2, 3, 2, 5, 8]) target output: [5, 1, 2, 3, 8]
Expand All @@ -13,15 +14,80 @@ E.g. dedupe([1, 2, 1]) target output: [1, 2]

// Acceptance Criteria:

// Given an empty array
// When passed to the dedupe function
// Then it should return an empty array
test.todo("given an empty array, it returns an empty array");
describe("dedupe - valid inputs", () => {
// Given an empty array
// When passed to the dedupe function
// Then it should return an empty array
[{ input: [], expected: [] }].forEach(({ input, expected }) =>
test(`returns an empty array for input [${input}]`, () => {
const result = dedupe(input);
expect(result).toEqual(expected);
expect(result).not.toBe(input); // ensures it's a new array
Comment on lines +23 to +25
Copy link
Contributor

Choose a reason for hiding this comment

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

Nicely done.

Copy link
Author

Choose a reason for hiding this comment

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

Nicely done.

Thank you.

})
);

// Given an array with no duplicates
// When passed to the dedupe function
// Then it should return a copy of the original array
[
{ input: [1, 2, 3], expected: [1, 2, 3] },
{ input: ["a", "b", "car"], expected: ["a", "b", "car"] },
{ input: [0, 1, 5, 6], expected: [0, 1, 5, 6] },
].forEach(({ input, expected }) =>
test(`returns a copy of the array when no duplicates exist for input [${input}]`, () => {
const result = dedupe(input);
expect(result).toEqual(expected);
expect(result).not.toBe(input); // ensures it's a new array
})
);

// Given arrays with duplicates
[
{ input: [5, 1, 1, 2, 3, 2, 5, 8], expected: [5, 1, 2, 3, 8] },
{ input: [1, 1, 1, 1], expected: [1] },
{ input: ["a", "a", "a", "b", "b", "c"], expected: ["a", "b", "c"] },
].forEach(({ input, expected }) =>
test(`removes duplicate elements and keeps the first occurrence for [${input}]`, () => {
const result = dedupe(input);
expect(result).toEqual(expected);
expect(result).not.toBe(input); // ensures it's a new array
})
);

// Given arrays with numbers and strings mixed
[
{ input: ["1", 1, "1", 1], expected: ["1", 1] },
{ input: [2, "3", "hello", 5, 5], expected: [2, "3", "hello", 5] },
].forEach(({ input, expected }) =>
test(`removes duplicates from an array of numbers and strings, keeping the first occurrence for input [${input}]`, () => {
const result = dedupe(input);
expect(result).toEqual(expected);
expect(result).not.toBe(input); // ensures it's a new array
})
);

// Given arrays with invalid elements
[
{ input: [1, 2, true, 3, null, "a", {}], expected: [1, 2, 3, "a"] },
{ input: ["x", undefined, "x", "y", []], expected: ["x", "y"] },
{ input: [false, 5, 5, "hello", () => {}, 5], expected: [5, "hello"] },
{ input: [1, NaN, 2, NaN, "hello"], expected: [1, 2, "hello"] },
].forEach(({ input, expected }) =>
test(`filters invalid elements, removes duplicates, and returns a copy for input [${input}]`, () => {
const result = dedupe(input);
expect(result).toEqual(expected);
expect(result).not.toBe(input); // ensures it's a new array
})
);
});

// Given an array with no duplicates
// When passed to the dedupe function
// Then it should return a copy of the original array
describe("dedupe - invalid inputs", () => {
const invalidInputs = [null, undefined, 123, "string", {}, () => {}];

// Given an array with strings or numbers
// When passed to the dedupe function
// Then it should remove the duplicate values, preserving the first occurence of each element
invalidInputs.forEach((input) =>
test(`throws typeError when input is ${String(input)}`, () => {
expect(() => dedupe(input)).toThrow(TypeError);
expect(() => dedupe(input)).toThrow("Input must be an array");
})
);
});
8 changes: 8 additions & 0 deletions Sprint-1/implement/max.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
function findMax(elements) {
if (!Array.isArray(elements)) {
throw new TypeError("Input must be an array");
} else {
const filteredArray = elements.filter(
(ele) => typeof ele === "number" && !isNaN(ele)
)
return Math.max(...filteredArray);
}
}

module.exports = findMax;
50 changes: 49 additions & 1 deletion Sprint-1/implement/max.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,76 @@ const findMax = require("./max.js");
// When passed to the max function
// Then it should return -Infinity
// Delete this test.todo and replace it with a test.
test.todo("given an empty array, returns -Infinity");
test("given an empty array, returns -Infinity", () => {
expect(findMax([])).toBe(-Infinity);
});

// Given an array with one number
// When passed to the max function
// Then it should return that number
test("given an array with one number, returns that number", () => {
expect(findMax([8])).toBe(8);
expect(findMax([-42])).toBe(-42);
expect(findMax([0])).toBe(0);
});

// Given an array with both positive and negative numbers
// When passed to the max function
// Then it should return the largest number overall
test("given an array with both positive and negative numbers, returns the largest number overall", () => {
expect(findMax([10, -5, 20, 0])).toBe(20);
expect(findMax([-1, -100, -50, 30])).toBe(30);
expect(findMax([0, -10, 5])).toBe(5);
});

// Given an array with just negative numbers
// When passed to the max function
// Then it should return the closest one to zero
test("given an array with just negative numbers, returns the closest one to zero", () => {
expect(findMax([-10, -5, -20])).toBe(-5);
expect(findMax([-100, -50, -60])).toBe(-50);
expect(findMax([-1000, -60, -1])).toBe(-1);
});

// Given an array with decimal numbers
// When passed to the max function
// Then it should return the largest decimal number
test("given an array with decimal numbers, returns the largest decimal number", () => {
expect(findMax([1.1, 2.5, 0.3])).toBe(2.5);
expect(findMax([-1.2, -0.5, -0.1])).toBe(-0.1);
expect(findMax([-1000.23, -80.54, -63.110])).toBe(-63.110);
});

// Given an array with non-number values
// When passed to the max function
// Then it should return the max and ignore non-numeric values
test("given an array with non-number values, returns the max and ignore the non-numeric values", () => {
expect(findMax([10, "hi", 20, null])).toBe(20);
expect(findMax([0, false, 5, "a"])).toBe(5);
expect(findMax([undefined, 5, null, NaN, -9])).toBe(5);
});

// Given an array with only non-number values
// When passed to the max function
// Then it should return the least surprising value given how it behaves for all other inputs
test("given an array with only non-number values", () => {
expect(findMax(["a", null, undefined])).toBe(-Infinity);
expect(findMax([{}, [], "hi"])).toBe(-Infinity);
expect(findMax([true, false, true])).toBe(-Infinity);
expect(findMax([Symbol("x"), () => {}, function () {}])).toBe(-Infinity);
});

// Edge cases
// Given an array with non-array values
// when passed to the max function
// Then it should throw and error
test("given a non-array input, throws a TypeError with message 'Input must be an array'", () => {
expect(() => findMax(42)).toThrow(new TypeError("Input must be an array"));
expect(() => findMax("hello")).toThrow(
new TypeError("Input must be an array")
);
expect(() => findMax(null)).toThrow(new TypeError("Input must be an array"));
expect(() => findMax(undefined)).toThrow(
new TypeError("Input must be an array")
);
});
12 changes: 12 additions & 0 deletions Sprint-1/implement/sum.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
function sum(elements) {
if (!Array.isArray(elements)) {
throw new TypeError("Input must be an array");
}
const filteredElements = elements.filter(
(ele) => typeof ele === "number" && !isNaN(ele)
);
let sumElements = 0;

for (const item of filteredElements) {
sumElements += item;
}
return sumElements;
}

module.exports = sum;
Loading