145 lines
3.1 KiB
JavaScript
145 lines
3.1 KiB
JavaScript
'use strict';
|
|
|
|
var test = require('tape');
|
|
var forEach = require('for-each');
|
|
var hasSymbols = require('has-symbols')();
|
|
var hasBigInts = require('has-bigints')();
|
|
var debug = require('object-inspect');
|
|
var iterate = require('..');
|
|
|
|
function testIteration(t, iterable, expected, message) {
|
|
t.deepEqual(iterate(iterable), expected, 'no callback: ' + message);
|
|
var values = [];
|
|
iterate(iterable, function (x) { values.push(x); });
|
|
t.deepEqual(values, expected, 'callback: ' + message);
|
|
return values;
|
|
}
|
|
|
|
function testNonIterable(t, nonIterable, isNumber) {
|
|
t['throws'](function () { iterate(nonIterable); }, TypeError, debug(nonIterable) + ' is not iterable');
|
|
if (nonIterable != null && hasSymbols && (!isNumber || !nonIterable[Symbol.iterator])) {
|
|
var o = Object(nonIterable);
|
|
o[Symbol.iterator] = function () {
|
|
return [1, 2, 3][Symbol.iterator]();
|
|
};
|
|
testIteration(t, o, [1, 2, 3], 'fake iterator works on non-iterable ' + debug(o));
|
|
}
|
|
}
|
|
|
|
function getArguments() {
|
|
return arguments;
|
|
}
|
|
|
|
test('non-iterables', function (t) {
|
|
var numbers = [0, -0, NaN, Infinity, 42];
|
|
var nonIterables = [
|
|
undefined,
|
|
null,
|
|
true,
|
|
false,
|
|
{},
|
|
/a/g,
|
|
function () {}
|
|
];
|
|
if (hasSymbols) {
|
|
nonIterables.push(Symbol.iterator);
|
|
}
|
|
if (hasBigInts) {
|
|
nonIterables.push(BigInt(42), BigInt(0));
|
|
}
|
|
forEach(nonIterables, function (nonIterable) {
|
|
testNonIterable(t, nonIterable);
|
|
});
|
|
if (hasSymbols && NaN[Symbol.iterator]) {
|
|
t.comment('# SKIP core-js v2 makes numbers iterable, in violation of the spec');
|
|
}
|
|
forEach(numbers, function (number) {
|
|
testNonIterable(t, number, true);
|
|
});
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('strings', function (t) {
|
|
testIteration(t, '', [], 'empty string');
|
|
testIteration(t, 'abc', ['a', 'b', 'c'], debug('abc'));
|
|
testIteration(t, 'a💩c', ['a', '💩', 'c'], debug('a💩c'));
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('arrays', function (t) {
|
|
forEach([
|
|
[],
|
|
[1, 2, 3]
|
|
], function (arr) {
|
|
testIteration(t, arr, arr, debug(arr));
|
|
});
|
|
var sparse = [1, , 3]; // eslint-disable-line no-sparse-arrays
|
|
var actual = testIteration(t, sparse, [1, undefined, 3], debug(sparse));
|
|
t.ok(1 in actual, 'actual is not sparse');
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('arguments', function (t) {
|
|
var empty = getArguments();
|
|
testIteration(t, empty, [], debug(empty));
|
|
|
|
var args = getArguments(1, 2, 3);
|
|
testIteration(t, args, [1, 2, 3], debug(args));
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('Maps', { skip: typeof Map !== 'function' }, function (t) {
|
|
var empty = new Map();
|
|
testIteration(t, empty, [], debug(empty));
|
|
|
|
var m = new Map();
|
|
m.set(1, 2);
|
|
m.set(3, 4);
|
|
testIteration(t, m, [[1, 2], [3, 4]], debug(m));
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('Sets', { skip: typeof Set !== 'function' }, function (t) {
|
|
var empty = new Set();
|
|
testIteration(t, empty, [], debug(empty));
|
|
|
|
var s = new Set();
|
|
s.add(1);
|
|
s.add(2);
|
|
testIteration(t, s, [1, 2], debug(s));
|
|
|
|
t.end();
|
|
});
|
|
|
|
test('non-function callbacks', function (t) {
|
|
forEach([
|
|
null,
|
|
undefined,
|
|
false,
|
|
true,
|
|
0,
|
|
-0,
|
|
NaN,
|
|
42,
|
|
Infinity,
|
|
'',
|
|
'abc',
|
|
/a/g,
|
|
[],
|
|
{}
|
|
], function (nonFunction) {
|
|
t['throws'](
|
|
function () { iterate([], nonFunction); },
|
|
TypeError,
|
|
debug(nonFunction) + ' is not a Function'
|
|
);
|
|
});
|
|
|
|
t.end();
|
|
});
|