From 44749424641a0e926db0a2c19ed1fa666d509cbe Mon Sep 17 00:00:00 2001 From: Wojciech Maj Date: Tue, 12 May 2020 19:57:51 +0200 Subject: [PATCH] Split utils into multiple files --- src/forEach.js | 5 + src/forEach.spec.js | 55 +++++++ src/forEach_strict.js | 5 + src/forEach_strict.spec.js | 75 ++++++++++ src/index.js | 50 ++----- src/index.spec.js | 283 ++----------------------------------- src/map.js | 3 + src/map.spec.js | 52 +++++++ src/map_strict.js | 12 ++ src/map_strict.spec.js | 74 ++++++++++ src/reduce.js | 12 ++ src/reduce.spec.js | 21 +++ test-utils.js | 34 +++++ 13 files changed, 374 insertions(+), 307 deletions(-) create mode 100644 src/forEach.js create mode 100644 src/forEach.spec.js create mode 100644 src/forEach_strict.js create mode 100644 src/forEach_strict.spec.js create mode 100644 src/map.js create mode 100644 src/map.spec.js create mode 100644 src/map_strict.js create mode 100644 src/map_strict.spec.js create mode 100644 src/reduce.js create mode 100644 src/reduce.spec.js create mode 100644 test-utils.js diff --git a/src/forEach.js b/src/forEach.js new file mode 100644 index 0000000..7ec39b8 --- /dev/null +++ b/src/forEach.js @@ -0,0 +1,5 @@ +import asyncMap from './map'; + +export default async function asyncForEach(arr, fn) { + await asyncMap(arr, fn); +} diff --git a/src/forEach.spec.js b/src/forEach.spec.js new file mode 100644 index 0000000..342c844 --- /dev/null +++ b/src/forEach.spec.js @@ -0,0 +1,55 @@ +import asyncForEach from './forEach'; + +import { + inputArr, + makePushDuplicate, + makePushDuplicateInRandomTime, +} from '../test-utils'; + +describe('asyncForEach()', () => { + it.skip('assertions below are valid for synchronous .forEach()', () => { + const [arr, pushDuplicate] = makePushDuplicate(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + inputArr.forEach(mapper); + + expect.assertions(1 + inputArr.length); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + inputArr.forEach((el) => { + expect(arr).toContain(el * 2); + }); + }); + + it('iterates through an array properly', async () => { + const [arr, pushDuplicate] = makePushDuplicateInRandomTime(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + await asyncForEach(inputArr, mapper); + + expect.assertions(1 + inputArr.length); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + inputArr.forEach((el) => { + expect(arr).toContain(el * 2); + }); + }); + + it.skip('assertions below are valid for synchronous .forEach()', () => { + const [, pushDuplicate] = makePushDuplicate(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + const result = inputArr.forEach(mapper); + + expect(result).toBe(undefined); + }); + + it('returns undefined', async () => { + const [, pushDuplicate] = makePushDuplicate(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + const result = await asyncForEach(inputArr, mapper); + + expect(result).toBe(undefined); + }); +}); diff --git a/src/forEach_strict.js b/src/forEach_strict.js new file mode 100644 index 0000000..cd71dd1 --- /dev/null +++ b/src/forEach_strict.js @@ -0,0 +1,5 @@ +import asyncMapStrict from './map_strict'; + +export default async function asyncForEachStrict(arr, fn) { + await asyncMapStrict(arr, fn); +} diff --git a/src/forEach_strict.spec.js b/src/forEach_strict.spec.js new file mode 100644 index 0000000..179b37c --- /dev/null +++ b/src/forEach_strict.spec.js @@ -0,0 +1,75 @@ +import asyncForEachStrict from './forEach_strict'; +import { + doubleInputArr, + inputArr, + makePushDuplicate, + makePushDuplicateInRandomTime, +} from '../test-utils'; + +describe('asyncForEachStrict()', () => { + it.skip('assertions below are valid for synchronous .forEach()', () => { + const [arr, pushDuplicate] = makePushDuplicate(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + inputArr.forEach(mapper); + + expect.assertions(1 + inputArr.length); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + inputArr.forEach((el) => { + expect(arr).toContain(el * 2); + }); + }); + + it('iterates through an array properly', async () => { + const [arr, pushDuplicate] = makePushDuplicateInRandomTime(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + await asyncForEachStrict(inputArr, mapper); + + expect.assertions(1 + inputArr.length); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + inputArr.forEach((el) => { + expect(arr).toContain(el * 2); + }); + }); + + it.skip('assertions below are valid for synchronous .forEach()', () => { + const [arr, pushDuplicate] = makePushDuplicate(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + inputArr.forEach(mapper); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + expect(arr).toEqual(doubleInputArr); + }); + + it('iterates through an array properly with side effects', async () => { + const [arr, pushDuplicate] = makePushDuplicateInRandomTime(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + await asyncForEachStrict(inputArr, mapper); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + expect(arr).toEqual(doubleInputArr); + }); + + it.skip('assertions below are valid for synchronous .forEach()', () => { + const [, pushDuplicate] = makePushDuplicate(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + const result = inputArr.forEach(mapper); + + expect(result).toBe(undefined); + }); + + it('returns undefined', async () => { + const [, pushDuplicate] = makePushDuplicate(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + const result = await asyncForEachStrict(inputArr, mapper); + + expect(result).toBe(undefined); + }); +}); diff --git a/src/index.js b/src/index.js index aec1663..7126b3c 100644 --- a/src/index.js +++ b/src/index.js @@ -1,37 +1,13 @@ -export async function asyncMap(arr, fn) { - return Promise.all(arr.map(fn)); -} - -export async function asyncMapStrict(arr, fn) { - const result = []; - - for (let idx = 0; idx < arr.length; idx += 1) { - const cur = arr[idx]; - - // eslint-disable-next-line no-await-in-loop - result.push(await fn(cur, idx, arr)); - } - - return result; -} - -export async function asyncForEach(arr, fn) { - await asyncMap(arr, fn); -} - -export async function asyncForEachStrict(arr, fn) { - await asyncMapStrict(arr, fn); -} - -export async function asyncReduce(arr, fn, initialValue) { - let temp = initialValue; - - for (let idx = 0; idx < arr.length; idx += 1) { - const cur = arr[idx]; - - // eslint-disable-next-line no-await-in-loop - temp = await fn(temp, cur, idx); - } - - return temp; -} +import asyncForEach from './forEach'; +import asyncForEachStrict from './forEach_strict'; +import asyncMap from './map'; +import asyncMapStrict from './map_strict'; +import asyncReduce from './reduce'; + +export { + asyncForEach, + asyncForEachStrict, + asyncMap, + asyncMapStrict, + asyncReduce, +}; diff --git a/src/index.spec.js b/src/index.spec.js index e5e28c6..579bccc 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -1,286 +1,29 @@ import { - asyncMap, - asyncMapStrict, asyncForEach, asyncForEachStrict, + asyncMap, + asyncMapStrict, asyncReduce, } from './index'; -function duplicate(x) { - return x * 2; -} - -function duplicateInRandomTime(x) { - return new Promise( - (resolve) => setTimeout(() => { - resolve(x * 2); - }, Math.random() * 100), - ); -} - -function makePushDuplicate() { - const arr = []; - - function pushDuplicate(x) { - arr.push(x * 2); - } - - return [arr, pushDuplicate]; -} - -function makePushDuplicateInRandomTime() { - const arr = []; - - async function pushDuplicate(x) { - arr.push(await duplicateInRandomTime(x)); - } - - return [arr, pushDuplicate]; -} - -const inputArr = [1, 2, 3, 4, 5]; -const doubleInputArr = [2, 4, 6, 8, 10]; - -describe('asyncMap()', () => { - it.skip('assertions below are valid for synchronous .map()', () => { - const mapper = jest.fn().mockImplementation(duplicate); - - inputArr.map(mapper); - - expect.assertions(1 + inputArr.length); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - inputArr.forEach((el, idx) => { - expect(mapper).toHaveBeenCalledWith(el, idx, inputArr); - }); - }); - - it('maps values properly', async () => { - const mapper = jest.fn().mockImplementation(duplicateInRandomTime); - - await asyncMap(inputArr, mapper); - - expect.assertions(1 + inputArr.length); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - inputArr.forEach((el, idx) => { - expect(mapper).toHaveBeenCalledWith(el, idx, inputArr); - }); - }); - - it.skip('assertions below are valid for synchronous .map()', () => { - const mapper = jest.fn().mockImplementation(duplicate); - - const result = inputArr.map(mapper); - - expect(result).toEqual(doubleInputArr); - }); - - it('returns result properly', async () => { - const mapper = jest.fn().mockImplementation(duplicateInRandomTime); - - const result = await asyncMap(inputArr, mapper); - - expect(result).toEqual(doubleInputArr); - }); -}); - -describe('asyncMapStrict()', () => { - it.skip('assertions below are valid for synchronous .map()', () => { - const mapper = jest.fn().mockImplementation(duplicate); - - inputArr.map(mapper); - - expect.assertions(1 + inputArr.length); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - inputArr.forEach((el, idx) => { - expect(mapper).toHaveBeenCalledWith(el, idx, inputArr); - }); - }); - - it('maps values properly', async () => { - const mapper = jest.fn().mockImplementation(duplicateInRandomTime); - - await asyncMapStrict(inputArr, mapper); - - expect.assertions(1 + inputArr.length); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - inputArr.forEach((el, idx) => { - expect(mapper).toHaveBeenCalledWith(el, idx, inputArr); - }); +describe('index', () => { + it('has asyncForEach exported properly', () => { + expect(asyncForEach).toBeInstanceOf(Function); }); - it.skip('assertions below are valid for synchronous .map()', () => { - const [arr, pushDuplicate] = makePushDuplicate(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - inputArr.forEach(mapper); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - expect(arr).toEqual(doubleInputArr); + it('has asyncForEachStrict exported properly', () => { + expect(asyncForEachStrict).toBeInstanceOf(Function); }); - it('maps values properly with side effects', async () => { - const [arr, pushDuplicate] = makePushDuplicateInRandomTime(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - await asyncMapStrict(inputArr, mapper); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - expect(arr).toEqual(doubleInputArr); + it('has asyncMap exported properly', () => { + expect(asyncMap).toBeInstanceOf(Function); }); - it.skip('assertions below are valid for synchronous .map()', () => { - const mapper = jest.fn().mockImplementation(duplicate); - - const result = inputArr.map(mapper); - - expect(result).toEqual(doubleInputArr); + it('has asyncMapStrict exported properly', () => { + expect(asyncMapStrict).toBeInstanceOf(Function); }); - it('returns result properly', async () => { - const mapper = jest.fn().mockImplementation(duplicateInRandomTime); - - const result = await asyncMapStrict(inputArr, mapper); - - expect(result).toEqual(doubleInputArr); - }); -}); - -describe('asyncForEach()', () => { - it.skip('assertions below are valid for synchronous .forEach()', () => { - const [arr, pushDuplicate] = makePushDuplicate(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - inputArr.forEach(mapper); - - expect.assertions(1 + inputArr.length); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - inputArr.forEach((el) => { - expect(arr).toContain(el * 2); - }); - }); - - it('iterates through an array properly', async () => { - const [arr, pushDuplicate] = makePushDuplicateInRandomTime(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - await asyncForEach(inputArr, mapper); - - expect.assertions(1 + inputArr.length); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - inputArr.forEach((el) => { - expect(arr).toContain(el * 2); - }); - }); - - it.skip('assertions below are valid for synchronous .forEach()', () => { - const [, pushDuplicate] = makePushDuplicate(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - const result = inputArr.forEach(mapper); - - expect(result).toBe(undefined); - }); - - it('returns undefined', async () => { - const [, pushDuplicate] = makePushDuplicate(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - const result = await asyncForEach(inputArr, mapper); - - expect(result).toBe(undefined); - }); -}); - -describe('asyncForEachStrict()', () => { - it.skip('assertions below are valid for synchronous .forEach()', () => { - const [arr, pushDuplicate] = makePushDuplicate(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - inputArr.forEach(mapper); - - expect.assertions(1 + inputArr.length); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - inputArr.forEach((el) => { - expect(arr).toContain(el * 2); - }); - }); - - it('iterates through an array properly', async () => { - const [arr, pushDuplicate] = makePushDuplicateInRandomTime(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - await asyncForEachStrict(inputArr, mapper); - - expect.assertions(1 + inputArr.length); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - inputArr.forEach((el) => { - expect(arr).toContain(el * 2); - }); - }); - - it.skip('assertions below are valid for synchronous .forEach()', () => { - const [arr, pushDuplicate] = makePushDuplicate(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - inputArr.forEach(mapper); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - expect(arr).toEqual(doubleInputArr); - }); - - it('iterates through an array properly with side effects', async () => { - const [arr, pushDuplicate] = makePushDuplicateInRandomTime(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - await asyncForEachStrict(inputArr, mapper); - - expect(mapper).toHaveBeenCalledTimes(inputArr.length); - expect(arr).toEqual(doubleInputArr); - }); - - it.skip('assertions below are valid for synchronous .forEach()', () => { - const [, pushDuplicate] = makePushDuplicate(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - const result = inputArr.forEach(mapper); - - expect(result).toBe(undefined); - }); - - it('returns undefined', async () => { - const [, pushDuplicate] = makePushDuplicate(); - const mapper = jest.fn().mockImplementation(pushDuplicate); - - const result = await asyncForEachStrict(inputArr, mapper); - - expect(result).toBe(undefined); - }); -}); - -describe('asyncReduce()', () => { - it.skip('assertions below are valid for synchronous .reduce()', () => { - const mapper = jest.fn().mockImplementation((temp, cur, idx) => [...temp, `${idx}:${cur}`]); - - const result = ['a', 'b', 'c'].reduce(mapper, ['start']); - - expect(mapper).toHaveBeenCalledTimes(3); - expect(result).toEqual(['start', '0:a', '1:b', '2:c']); - }); - - it('reduces an array properly', async () => { - const mapper = jest.fn().mockImplementation(async (temp, cur, idx) => [...temp, `${idx}:${cur}`]); - - const result = await asyncReduce(['a', 'b', 'c'], mapper, ['start']); - - expect(mapper).toHaveBeenCalledTimes(3); - expect(result).toEqual(['start', '0:a', '1:b', '2:c']); + it('has asyncReduce exported properly', () => { + expect(asyncReduce).toBeInstanceOf(Function); }); }); diff --git a/src/map.js b/src/map.js new file mode 100644 index 0000000..5185bd2 --- /dev/null +++ b/src/map.js @@ -0,0 +1,3 @@ +export default async function asyncMap(arr, fn) { + return Promise.all(arr.map(fn)); +} diff --git a/src/map.spec.js b/src/map.spec.js new file mode 100644 index 0000000..f28ed09 --- /dev/null +++ b/src/map.spec.js @@ -0,0 +1,52 @@ +import asyncMap from './map'; + +import { + doubleInputArr, + duplicate, + duplicateInRandomTime, + inputArr, +} from '../test-utils'; + +describe('asyncMap()', () => { + it.skip('assertions below are valid for synchronous .map()', () => { + const mapper = jest.fn().mockImplementation(duplicate); + + inputArr.map(mapper); + + expect.assertions(1 + inputArr.length); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + inputArr.forEach((el, idx) => { + expect(mapper).toHaveBeenCalledWith(el, idx, inputArr); + }); + }); + + it('maps values properly', async () => { + const mapper = jest.fn().mockImplementation(duplicateInRandomTime); + + await asyncMap(inputArr, mapper); + + expect.assertions(1 + inputArr.length); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + inputArr.forEach((el, idx) => { + expect(mapper).toHaveBeenCalledWith(el, idx, inputArr); + }); + }); + + it.skip('assertions below are valid for synchronous .map()', () => { + const mapper = jest.fn().mockImplementation(duplicate); + + const result = inputArr.map(mapper); + + expect(result).toEqual(doubleInputArr); + }); + + it('returns result properly', async () => { + const mapper = jest.fn().mockImplementation(duplicateInRandomTime); + + const result = await asyncMap(inputArr, mapper); + + expect(result).toEqual(doubleInputArr); + }); +}); diff --git a/src/map_strict.js b/src/map_strict.js new file mode 100644 index 0000000..87ffb7a --- /dev/null +++ b/src/map_strict.js @@ -0,0 +1,12 @@ +export default async function asyncMapStrict(arr, fn) { + const result = []; + + for (let idx = 0; idx < arr.length; idx += 1) { + const cur = arr[idx]; + + // eslint-disable-next-line no-await-in-loop + result.push(await fn(cur, idx, arr)); + } + + return result; +} diff --git a/src/map_strict.spec.js b/src/map_strict.spec.js new file mode 100644 index 0000000..5ca3b1e --- /dev/null +++ b/src/map_strict.spec.js @@ -0,0 +1,74 @@ +import asyncMapStrict from './map_strict'; + +import { + doubleInputArr, + duplicate, + duplicateInRandomTime, + inputArr, + makePushDuplicate, + makePushDuplicateInRandomTime, +} from '../test-utils'; + +describe('asyncMapStrict()', () => { + it.skip('assertions below are valid for synchronous .map()', () => { + const mapper = jest.fn().mockImplementation(duplicate); + + inputArr.map(mapper); + + expect.assertions(1 + inputArr.length); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + inputArr.forEach((el, idx) => { + expect(mapper).toHaveBeenCalledWith(el, idx, inputArr); + }); + }); + + it('maps values properly', async () => { + const mapper = jest.fn().mockImplementation(duplicateInRandomTime); + + await asyncMapStrict(inputArr, mapper); + + expect.assertions(1 + inputArr.length); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + inputArr.forEach((el, idx) => { + expect(mapper).toHaveBeenCalledWith(el, idx, inputArr); + }); + }); + + it.skip('assertions below are valid for synchronous .map()', () => { + const [arr, pushDuplicate] = makePushDuplicate(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + inputArr.forEach(mapper); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + expect(arr).toEqual(doubleInputArr); + }); + + it('maps values properly with side effects', async () => { + const [arr, pushDuplicate] = makePushDuplicateInRandomTime(); + const mapper = jest.fn().mockImplementation(pushDuplicate); + + await asyncMapStrict(inputArr, mapper); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + expect(arr).toEqual(doubleInputArr); + }); + + it.skip('assertions below are valid for synchronous .map()', () => { + const mapper = jest.fn().mockImplementation(duplicate); + + const result = inputArr.map(mapper); + + expect(result).toEqual(doubleInputArr); + }); + + it('returns result properly', async () => { + const mapper = jest.fn().mockImplementation(duplicateInRandomTime); + + const result = await asyncMapStrict(inputArr, mapper); + + expect(result).toEqual(doubleInputArr); + }); +}); diff --git a/src/reduce.js b/src/reduce.js new file mode 100644 index 0000000..9c95ef4 --- /dev/null +++ b/src/reduce.js @@ -0,0 +1,12 @@ +export default async function asyncReduce(arr, fn, initialValue) { + let temp = initialValue; + + for (let idx = 0; idx < arr.length; idx += 1) { + const cur = arr[idx]; + + // eslint-disable-next-line no-await-in-loop + temp = await fn(temp, cur, idx); + } + + return temp; +} diff --git a/src/reduce.spec.js b/src/reduce.spec.js new file mode 100644 index 0000000..1724227 --- /dev/null +++ b/src/reduce.spec.js @@ -0,0 +1,21 @@ +import asyncReduce from './reduce'; + +describe('asyncReduce()', () => { + it.skip('assertions below are valid for synchronous .reduce()', () => { + const mapper = jest.fn().mockImplementation((temp, cur, idx) => [...temp, `${idx}:${cur}`]); + + const result = ['a', 'b', 'c'].reduce(mapper, ['start']); + + expect(mapper).toHaveBeenCalledTimes(3); + expect(result).toEqual(['start', '0:a', '1:b', '2:c']); + }); + + it('reduces an array properly', async () => { + const mapper = jest.fn().mockImplementation(async (temp, cur, idx) => [...temp, `${idx}:${cur}`]); + + const result = await asyncReduce(['a', 'b', 'c'], mapper, ['start']); + + expect(mapper).toHaveBeenCalledTimes(3); + expect(result).toEqual(['start', '0:a', '1:b', '2:c']); + }); +}); diff --git a/test-utils.js b/test-utils.js new file mode 100644 index 0000000..ea530ca --- /dev/null +++ b/test-utils.js @@ -0,0 +1,34 @@ +export function duplicate(x) { + return x * 2; +} + +export function duplicateInRandomTime(x) { + return new Promise( + (resolve) => setTimeout(() => { + resolve(x * 2); + }, Math.random() * 100), + ); +} + +export function makePushDuplicate() { + const arr = []; + + function pushDuplicate(x) { + arr.push(x * 2); + } + + return [arr, pushDuplicate]; +} + +export function makePushDuplicateInRandomTime() { + const arr = []; + + async function pushDuplicate(x) { + arr.push(await duplicateInRandomTime(x)); + } + + return [arr, pushDuplicate]; +} + +export const inputArr = [1, 2, 3, 4, 5]; +export const doubleInputArr = [2, 4, 6, 8, 10]; -- 2.51.2