diff --git a/src/reduce.js b/src/reduce.js index 38be21c..fdd0761 100644 --- a/src/reduce.js +++ b/src/reduce.js @@ -7,6 +7,14 @@ * @returns {*} */ function reduce(callback, startValue) { + if (typeof callback !== 'function') { + throw new TypeError(callback + ' is not a function'); + } + + if (this.length === 0 && arguments.length < 2) { + throw new TypeError('Reduce of empty array with no initial value'); + } + let prev = startValue; let startIndex = 0; diff --git a/src/reduce.test.js b/src/reduce.test.js index 47a892f..16012bc 100644 --- a/src/reduce.test.js +++ b/src/reduce.test.js @@ -1,8 +1,11 @@ 'use strict'; -const { reduce } = require('./reduce'); +describe('Reduce function', () => { + const { reduce } = require('./reduce'); + let mockReducer; + const testArr = [10, 20, 30]; + const initialValue = 5; -describe('reduce', () => { beforeAll(() => { Array.prototype.reduce2 = reduce; // eslint-disable-line }); @@ -11,9 +14,123 @@ describe('reduce', () => { delete Array.prototype.reduce2; }); - it('should ', () => { + beforeEach(() => { + mockReducer = jest.fn((acc, value) => acc + value); + }); + + it('should be declared', () => { + expect(reduce).toBeInstanceOf(Function); + }); + + describe('if initialValue is provided', () => { + it('should execute correct sum', () => { + const actual = testArr.reduce2(mockReducer, initialValue); + const expected = 5 + 10 + 20 + 30; + + expect(mockReducer).toHaveBeenCalledTimes(3); + expect(mockReducer).toHaveBeenCalledWith(5, 10, 0, [10, 20, 30]); + expect(mockReducer).toHaveBeenCalledWith(15, 20, 1, [10, 20, 30]); + expect(mockReducer).toHaveBeenCalledWith(35, 30, 2, [10, 20, 30]); + expect(actual).toBe(expected); + }); + + it('should handle single-element array', () => { + const actual = [10].reduce2(mockReducer, initialValue); + const expected = 5 + 10; + + expect(mockReducer).toHaveBeenCalledTimes(1); + expect(mockReducer).toHaveBeenCalledWith(5, 10, 0, [10]); + expect(actual).toBe(expected); + }); + + it('should execute correct multiply', () => { + mockReducer = jest.fn((acc, value) => acc * value); + + const actual = testArr.reduce2(mockReducer, initialValue); + const expected = 5 * 10 * 20 * 30; + + expect(mockReducer).toHaveBeenCalledTimes(3); + expect(mockReducer).toHaveBeenCalledWith(5, 10, 0, [10, 20, 30]); + expect(mockReducer).toHaveBeenCalledWith(50, 20, 1, [10, 20, 30]); + expect(mockReducer).toHaveBeenCalledWith(1000, 30, 2, [10, 20, 30]); + expect(actual).toBe(expected); + }); + + it('should execute correct concatenate', () => { + const actual = ['Mate ', 'Academy ', '!'].reduce2(mockReducer, ''); + const expected = 'Mate Academy !'; + + expect(mockReducer).toHaveBeenCalledTimes(3); + + expect(mockReducer).toHaveBeenCalledWith('', + 'Mate ', 0, ['Mate ', 'Academy ', '!']); + + expect(mockReducer).toHaveBeenCalledWith('Mate ', + 'Academy ', 1, ['Mate ', 'Academy ', '!']); + + expect(mockReducer).toHaveBeenCalledWith('Mate Academy ', + '!', 2, ['Mate ', 'Academy ', '!']); + expect(actual).toBe(expected); + }); + + it('should handle empty array', () => { + const actual = [].reduce2(mockReducer, initialValue); + const expected = initialValue; + + expect(mockReducer).toHaveBeenCalledTimes(0); + expect(actual).toBe(expected); + }); }); - // Add tests here + describe('if initialValue is not provided', () => { + it('should execute correct sum', () => { + const actual = testArr.reduce2(mockReducer); + const expected = 10 + 20 + 30; + + expect(mockReducer).toHaveBeenCalledTimes(2); + expect(mockReducer).toHaveBeenCalledWith(10, 20, 1, [10, 20, 30]); + expect(mockReducer).toHaveBeenCalledWith(30, 30, 2, [10, 20, 30]); + expect(actual).toBe(expected); + }); + + it('should handle single-element array', () => { + const actual = [10].reduce2(mockReducer); + const expected = 10; + + expect(mockReducer).toHaveBeenCalledTimes(0); + expect(actual).toBe(expected); + }); + + it('should execute correct multiply', () => { + mockReducer = jest.fn((acc, value) => acc * value); + + const actual = testArr.reduce2(mockReducer); + const expected = 10 * 20 * 30; + + expect(mockReducer).toHaveBeenCalledTimes(2); + expect(mockReducer).toHaveBeenCalledWith(10, 20, 1, [10, 20, 30]); + expect(mockReducer).toHaveBeenCalledWith(200, 30, 2, [10, 20, 30]); + expect(actual).toBe(expected); + }); + + it('should execute correct concatenate', () => { + const actual = ['Mate ', 'Academy ', '!'].reduce2(mockReducer); + const expected = 'Mate Academy !'; + + expect(mockReducer).toHaveBeenCalledTimes(2); + + expect(mockReducer).toHaveBeenCalledWith('Mate ', + 'Academy ', 1, ['Mate ', 'Academy ', '!']); + + expect(mockReducer).toHaveBeenCalledWith('Mate Academy ', + '!', 2, ['Mate ', 'Academy ', '!']); + + expect(actual).toBe(expected); + }); + + it('should handle empty array and throw TypeError', () => { + expect(() => [].reduce2(mockReducer)).toThrow(TypeError); + }); + }); });