diff --git a/src/reduce.js b/src/reduce.js index 38be21c..4187e36 100644 --- a/src/reduce.js +++ b/src/reduce.js @@ -1,21 +1,33 @@ -'use strict'; +'use strict'; /** + * Custom implementation of Array.prototype.reduce + * * @param {function} callback * @param {*} startValue * * @returns {*} */ function reduce(callback, startValue) { - let prev = startValue; + if (typeof callback !== 'function') { + throw new TypeError(callback + ' is not a function'); + } + + let prev; let startIndex = 0; if (arguments.length < 2) { - startIndex = 1; + if (this.length === 0) { + throw new TypeError('Reduce of empty array with no initial value'); + } prev = this[0]; + startIndex = 1; + } else { + prev = startValue; } for (let i = startIndex; i < this.length; i++) { + if (!(i in this)) continue; // skip sparse array holes prev = callback(prev, this[i], i, this); } diff --git a/src/reduce.test.js b/src/reduce.test.js index 47a892f..da571cf 100644 --- a/src/reduce.test.js +++ b/src/reduce.test.js @@ -11,9 +11,52 @@ describe('reduce', () => { delete Array.prototype.reduce2; }); - it('should ', () => { + it('should sum numbers in an array', () => { + const arr = [1, 2, 3, 4]; + const result = arr.reduce2((acc, val) => acc + val, 0); + expect(result).toBe(10); + }); + + it('should multiply numbers in an array', () => { + const arr = [1, 2, 3, 4]; + const result = arr.reduce2((acc, val) => acc * val, 1); + expect(result).toBe(24); + }); + it('should work without initial value', () => { + const arr = [1, 2, 3]; + const result = arr.reduce2((acc, val) => acc + val); + expect(result).toBe(6); }); - // Add tests here + it('should handle empty array with initial value', () => { + const arr = []; + const mockCb = jest.fn(); + const result = arr.reduce2(mockCb, 5); + + expect(result).toBe(5); + expect(mockCb).toHaveBeenCalledTimes(0); + }); + + it('should throw error when empty array and no initial value', () => { + const arr = []; + expect(() => + arr.reduce2((acc, val) => acc + val) + ).toThrow(TypeError); + }); + + it('should pass correct arguments to callback', () => { + const arr = [10, 20]; + const mockCb = jest.fn((acc, val, idx, array) => acc + val); + arr.reduce2(mockCb, 0); + + const argsCall1 = [0, 10, 0, arr]; + const argsCall2 = [10, 20, 1, arr]; + + expect(mockCb).toHaveBeenCalledTimes(2); + expect(mockCb).toHaveBeenNthCalledWith(1, ...argsCall1); + expect(mockCb).toHaveBeenNthCalledWith(2, ...argsCall2); + }); }); + +