diff --git a/src/reduce.js b/src/reduce.js index 38be21c..69d12a0 100644 --- a/src/reduce.js +++ b/src/reduce.js @@ -7,12 +7,17 @@ * @returns {*} */ function reduce(callback, startValue) { - let prev = startValue; + let prev; let startIndex = 0; if (arguments.length < 2) { + if (this.length === 0) { + throw new TypeError('Reduce of empty array with no initial value'); + } startIndex = 1; prev = this[0]; + } else { + prev = startValue; } for (let i = startIndex; i < this.length; i++) { diff --git a/src/reduce.test.js b/src/reduce.test.js index 47a892f..b2d8a2c 100644 --- a/src/reduce.test.js +++ b/src/reduce.test.js @@ -1,6 +1,8 @@ 'use strict'; const { reduce } = require('./reduce'); +const arr = [0, 1, 2, 3, 4]; +const sumCb = (acc, current, i, array) => acc + current; describe('reduce', () => { beforeAll(() => { @@ -11,9 +13,53 @@ describe('reduce', () => { delete Array.prototype.reduce2; }); - it('should ', () => { + it('should return a number', () => { + expect(typeof arr.reduce2(sumCb, 0)).toBe('number'); + }); + + it('should return an accumulated value', () => { + expect(arr.reduce2(sumCb, 0)).toBe(10); + }); + + it('should return an initial value if array is empty', () => { + expect([].reduce2(sumCb, 0)).toBe(0); + }); + + it('should call cb for every item', () => { + const cb = jest.fn(); + + arr.reduce2(cb, 0); + expect(cb).toHaveBeenCalledTimes(5); + }); + + it('should call cb with all params', () => { + const cb = jest.fn(sumCb); + arr.reduce2(cb, 0); + + expect(cb).nthCalledWith(1, 0, 0, 0, arr); + expect(cb).nthCalledWith(2, 0, 1, 1, arr); + expect(cb).nthCalledWith(3, 1, 2, 2, arr); + expect(cb).nthCalledWith(4, 3, 3, 3, arr); + expect(cb).nthCalledWith(5, 6, 4, 4, arr); }); - // Add tests here + it('should use first element as accumulator if it is not provided', () => { + const cb = jest.fn(); + + arr.reduce2(cb); + expect(cb).nthCalledWith(1, arr[0], arr[1], 1, arr); + }); + + it('throws TypeError if array and initial value are empty', () => { + expect(() => [].reduce2(sumCb)).toThrow(TypeError); + }); + + it("doesn't call cb for [1] without init", () => { + const cb = jest.fn(); + + [1].reduce2(cb); + + expect(cb).not.toHaveBeenCalled(); + }); });