Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Add isAsyncIterable function #2309

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/index.js
Expand Up @@ -10,6 +10,7 @@ export { default as isNotNull } from './isNotNull';
export { default as isNotNil } from './isNotNil';
export { default as isArray } from './isArray';
export { default as isIterable } from './isIterable';
export { default as isAsyncIterable } from './isAsyncIterable';
export { default as isEmptyArray } from './isEmptyArray';
export { default as isNotArray } from './isNotArray';
export { default as isNonEmptyArray } from './isNonEmptyArray';
Expand Down
41 changes: 41 additions & 0 deletions src/isAsyncIterable.js
@@ -0,0 +1,41 @@
import { hasIn, curryN } from 'ramda';

import isFunction from './isFunction';

/**
* Checks whether the passed value is async iterable.
*
* @func isAsyncIterable
* @memberOf RA
* @since {@link https://char0n.github.io/ramda-adjunct/3.2.0|v3.2.0}
* @category Type
* @sig * -> Boolean
* @param {*} val The value to test
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator}
* @return {boolean}
* @example
*
* RA.isAsyncIterable({
* async* [Symbol.asyncIterator]() {
* yield "Blade";
* yield "Runner"
* }
* }); //=> true
*
* RA.isAsyncIterable({}); //=> false
* RA.isAsyncIterable(-0); //=> false
* RA.isAsyncIterable(null); //=> false
* RA.isAsyncIterable(undefined); //=> false
*/
const isAsyncIterable = curryN(1, (val) => {
if (typeof Symbol === 'undefined') {
return false;
}

return (
hasIn(Symbol.asyncIterator, Object(val)) &&
isFunction(val[Symbol.asyncIterator])
);
});

export default isAsyncIterable;
89 changes: 89 additions & 0 deletions test/isAsyncIterable.js
@@ -0,0 +1,89 @@
import { assert } from 'chai';
import * as R from 'ramda';

import * as RA from '../src';

describe('isAsyncIterable', function () {
context('given the item is an array with items', function () {
specify('should return false', function () {
assert.isFalse(RA.isAsyncIterable(['arrays', 'are', 'iterable']));
});
});

context(
'given the item is an Object implementing an asyncIterator',
function () {
specify('should return true', function () {
const asyncIterable = {
async *[Symbol.asyncIterator]() {
yield 'Blade';
yield 'Runner';
},
};
assert.isTrue(RA.isAsyncIterable(asyncIterable));
});
}
);

context('given the value undefined', function () {
specify('should return false', function () {
assert.isFalse(RA.isAsyncIterable(undefined));
});
});

context('given a number', function () {
specify('should return false', function () {
assert.isFalse(RA.isAsyncIterable(42));
});
});

context('given the value null', function () {
specify('should return false', function () {
assert.isFalse(RA.isAsyncIterable(null));
});
});

context('given the value NaN', function () {
specify('should return false', function () {
assert.isFalse(RA.isAsyncIterable(NaN));
});
});

context('given the value Infinity', function () {
specify('should return false', function () {
assert.isFalse(RA.isAsyncIterable(Infinity));
});
});

context('given a boolean value', function () {
specify('should return false', function () {
assert.isFalse(RA.isAsyncIterable(true));
});
});

context('given the value -0', function () {
specify('should return false', function () {
assert.isFalse(RA.isAsyncIterable(-0));
});
});

context('given an empty object', function () {
specify('should return false', function () {
assert.isFalse(RA.isAsyncIterable({}));
});
});

context('should support placeholder to specify "gaps"', function () {
specify('should return false', function () {
const isAsyncIterable = RA.isAsyncIterable(R.__);
const asyncIterable = {
async *[Symbol.asyncIterator]() {
yield 'Blade';
yield 'Runner';
},
};

assert.isTrue(isAsyncIterable(asyncIterable));
});
});
});