From 26b3cbe8f4e3685afa0ce69da80ed403ae298cbf Mon Sep 17 00:00:00 2001 From: Wojciech Maj Date: Thu, 19 Nov 2020 09:54:11 +0100 Subject: [PATCH] Add everyStrict util --- README.md | 23 +++++++++ src/every_strict.js | 16 ++++++ src/every_strict.spec.js | 108 +++++++++++++++++++++++++++++++++++++++ src/index.js | 2 + src/index.spec.js | 5 ++ 5 files changed, 154 insertions(+) create mode 100644 src/every_strict.js create mode 100644 src/every_strict.spec.js diff --git a/README.md b/README.md index 1e934f3..63e92b8 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ A collection of array-related async utilities. ### Table of contents * [`asyncEvery()`](#asyncEvery) +* [`asyncEveryStrict()`](#asyncEveryStrict) * [`asyncFilter()`](#asyncFilter) * [`asyncFilterStrict()`](#asyncFilterStrict) * [`asyncForEach()`](#asyncForEach) @@ -30,6 +31,8 @@ A collection of array-related async utilities. Tests whether all elements in the array pass the test implemented by the provided asynchronous function. It returns a Boolean value. +Note: For optimization purposes, all iterations are ran concurrently. If you rely on any side effects, consider `asyncEveryStrict()` instead. + #### Sample usage ```js @@ -38,6 +41,26 @@ import { asyncEvery } from '@wojtekmaj/async-array-utils'; const largerThanZero = await asyncEvery([1, 2, 3], async (el) => el > 0); // true ``` +### `asyncEveryStrict()` + +Like `asyncEvery()`, but runs iterations non-concurrently. + +#### Sample usage + +```js +import { asyncEveryStrict } from '@wojtekmaj/async-array-utils'; + +const indexes = []; +const largerThanZero = await asyncEveryStrict( + [1, 2, 3], + async (el, index) => { + indexes.push(index); + return el > 0; + }, +); // true +console.log(indexes); // [0, 1, 2] +``` + ### `asyncFilter()` Creates a new array with all elements that pass the test implemented by the provided asynchronous function. diff --git a/src/every_strict.js b/src/every_strict.js new file mode 100644 index 0000000..2ac0193 --- /dev/null +++ b/src/every_strict.js @@ -0,0 +1,16 @@ +import asyncForEachStrict from './forEach_strict'; + +export default function asyncEveryStrict(arr, fn) { + return new Promise((resolve) => { + // eslint-disable-next-line no-shadow + asyncForEachStrict(arr, async (cur, idx, arr) => { + const result = await fn(cur, idx, arr); + + if (!result) { + resolve(false); + } + }).then(() => { + resolve(true); + }); + }); +} diff --git a/src/every_strict.spec.js b/src/every_strict.spec.js new file mode 100644 index 0000000..ff1173f --- /dev/null +++ b/src/every_strict.spec.js @@ -0,0 +1,108 @@ +import asyncEveryStrict from './every_strict'; + +import { + doubleInputArr, + inputArr, + largerThanOneHundred, + largerThanOneHundredInRandomTime, + makePushDuplicate, + makePushDuplicateInRandomTime, +} from '../test-utils'; + +function largerOrEqualThanZero(x) { + return x >= 0; +} + +function largerOrEqualThanZeroInRandomTime(x) { + return new Promise( + (resolve) => setTimeout(() => { + resolve(x >= 0); + }, Math.random() * 100), + ); +} + +describe('asyncEvery()', () => { + it.skip('assertions below are valid for synchronous .every()', () => { + const mapper = jest.fn().mockImplementation(largerOrEqualThanZero); + + inputArr.every(mapper); + + expect.assertions(1 + inputArr.length); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + inputArr.forEach((el, idx) => { + expect(mapper).toHaveBeenCalledWith(el, idx, inputArr); + }); + }); + + it('iterates over values properly', async () => { + const mapper = jest.fn().mockImplementation(largerOrEqualThanZeroInRandomTime); + + await asyncEveryStrict(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 .every()', () => { + const [arr, pushDuplicate] = makePushDuplicate(); + const mapper = jest.fn().mockImplementation((el) => { + pushDuplicate(el); + return largerOrEqualThanZero(el); + }); + + inputArr.every(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(async (el) => { + await pushDuplicate(el); + return largerOrEqualThanZero(el); + }); + + await asyncEveryStrict(inputArr, mapper); + + expect(mapper).toHaveBeenCalledTimes(inputArr.length); + expect(arr).toEqual(doubleInputArr); + }); + + it.skip('assertions below are valid for synchronous .every()', () => { + const mapper = jest.fn().mockImplementation(largerOrEqualThanZero); + + const result = inputArr.every(mapper); + + expect(result).toEqual(true); + }); + + it('returns truthy result properly', async () => { + const mapper = jest.fn().mockImplementation(largerOrEqualThanZeroInRandomTime); + + const result = await asyncEveryStrict(inputArr, mapper); + + expect(result).toEqual(true); + }); + + it.skip('assertions below are valid for synchronous .every()', () => { + const mapper = jest.fn().mockImplementation(largerThanOneHundred); + + const result = inputArr.every(mapper); + + expect(result).toEqual(false); + }); + + it('returns falsy result properly', async () => { + const mapper = jest.fn().mockImplementation(largerThanOneHundredInRandomTime); + + const result = await asyncEveryStrict(inputArr, mapper); + + expect(result).toEqual(false); + }); +}); diff --git a/src/index.js b/src/index.js index f564fbe..ab4e155 100644 --- a/src/index.js +++ b/src/index.js @@ -3,6 +3,7 @@ import asyncFilterStrict from './filter_strict'; import asyncForEach from './forEach'; import asyncForEachStrict from './forEach_strict'; import asyncEvery from './every'; +import asyncEveryStrict from './every_strict'; import asyncMap from './map'; import asyncMapStrict from './map_strict'; import asyncReduce from './reduce'; @@ -15,6 +16,7 @@ export { asyncForEach, asyncForEachStrict, asyncEvery, + asyncEveryStrict, asyncMap, asyncMapStrict, asyncReduce, diff --git a/src/index.spec.js b/src/index.spec.js index 6adb70a..9205e45 100644 --- a/src/index.spec.js +++ b/src/index.spec.js @@ -4,6 +4,7 @@ import { asyncForEach, asyncForEachStrict, asyncEvery, + asyncEveryStrict, asyncMap, asyncMapStrict, asyncReduce, @@ -32,6 +33,10 @@ describe('index', () => { expect(asyncEvery).toBeInstanceOf(Function); }); + it('has asyncEveryStrict exported properly', () => { + expect(asyncEveryStrict).toBeInstanceOf(Function); + }); + it('has asyncMap exported properly', () => { expect(asyncMap).toBeInstanceOf(Function); }); -- 2.51.2