123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- var test = require('tape-catch');
- var plus = require('1-liners/plus');
- var isNative = require('lodash.isnative');
- // Shim Symbol.iterator if it's not available
- require('core-js/es6/symbol');
- var arrayFrom = require('./polyfill');
- test('Works as expected', function(is) {
- var mock = {
- 0: 'a',
- 1: 'b',
- 2: 'c',
- length: 3,
- };
- is.deepEqual(
- arrayFrom(mock),
- ['a', 'b', 'c'],
- 'with a mock object'
- );
- is.ok(
- arrayFrom(mock) instanceof Array,
- '– returning an array'
- );
- is.deepEqual(
- arrayFrom({
- 0: 'a',
- 1: 'b',
- 2: 'c',
- 'a': 'left out',
- '-1': 'left out',
- length: 3,
- }),
- ['a', 'b', 'c'],
- '– ignoring illegal indices'
- );
- is.deepEqual(
- arrayFrom({}),
- [],
- 'with an empty object'
- );
- is.deepEqual(
- arrayFrom([]),
- [],
- 'with an empty array'
- );
- is.deepEqual(
- (function() {return arrayFrom(arguments);})('a', 'b', 'c'),
- ['a', 'b', 'c'],
- 'with the `arguments` object'
- );
- is.deepEqual(
- arrayFrom(['a', 'b', 'c']),
- ['a', 'b', 'c'],
- 'with an array'
- );
- is.deepEqual(
- arrayFrom(mock, plus),
- ['a0', 'b1', 'c2'],
- 'when dealing with `mapFn`'
- );
- var context = {suffix: '+'};
- is.deepEqual(
- arrayFrom(mock,
- function(item) {return (item + this.suffix);},
- context
- ),
- ['a+', 'b+', 'c+'],
- 'when dealing with `mapFn` and `thisArg`'
- );
- var Transferable = function(){};
- Transferable.from = arrayFrom;
- is.ok(
- Transferable.from([1]) instanceof Transferable,
- 'can be transferred to other constructor functions'
- );
- is.end();
- });
- test('Works for iterable objects', function(is) {
- var SetPolyfill = require('core-js/library/fn/set');
- is.deepEqual(
- arrayFrom(new SetPolyfill(['a', 'b', 'c'])),
- ['a', 'b', 'c'],
- 'with Set (polyfill)'
- );
- is.deepEqual(
- arrayFrom(new SetPolyfill(['a', 'b', 'c']).values(), plus),
- ['a0', 'b1', 'c2'],
- 'when dealing with `mapFn`'
- );
- var context = {suffix: '+'};
- is.deepEqual(
- arrayFrom(new SetPolyfill(['a', 'b', 'c']).keys(),
- function(item) {return (item + this.suffix);},
- context
- ),
- ['a+', 'b+', 'c+'],
- 'when dealing with `mapFn` and `thisArg`'
- );
- if(typeof Set !== 'undefined' && isNative(Set)) {
- is.deepEqual(
- arrayFrom(new Set(['a', 'b', 'c'])),
- ['a', 'b', 'c'],
- 'with native Set'
- );
- }
- if(typeof Map !== 'undefined' && isNative(Map)) {
- is.deepEqual(
- arrayFrom(new Map()
- .set('key1', 'value1')
- .set('key2', 'value2')
- .set('key3', 'value3')
- .keys()
- ),
- ['key1', 'key2', 'key3'],
- 'with native Map'
- );
- }
- var geckoIterator = {
- value : 1,
- '@@iterator' : function(){
- var hasValue = true;
- var value = this.value;
- return {
- next: function(){
- if(hasValue) {
- hasValue = false;
- return { value: value, done: false };
- } else {
- return { done: true };
- }
- }
- };
- }
- };
- is.deepEqual(
- arrayFrom(geckoIterator),
- [1],
- 'when using Gecko-based "@@iterator" property.'
- );
- geckoIterator['@@iterator'] = null;
- is.deepEqual(
- arrayFrom(geckoIterator),
- [],
- 'null iterator is like no iterator');
- var Transferable = function(){};
- Transferable.from = arrayFrom;
- is.ok(Transferable.from(new SetPolyfill(['a'])) instanceof Transferable,
- 'can be transferred to other constructor functions (iterable)'
- );
- is.end();
- });
- test('Throws when things go very wrong.', function(is) {
- is.throws(
- function() {
- arrayFrom();
- },
- TypeError,
- 'when the given object is invalid'
- );
- is.throws(
- function() {
- arrayFrom({length: 0}, /invalid/);
- },
- TypeError,
- 'when `mapFn` is invalid'
- );
- var invalidIterator = {};
- invalidIterator[Symbol.iterator] = {};
- is.throws(
- function() {
- arrayFrom(invalidIterator);
- },
- TypeError,
- 'when an iterable has an invalid iterator property'
- );
- var noIterator = {};
- noIterator[Symbol.iterator] = function(){};
- is.throws(
- function() {
- arrayFrom(noIterator);
- },
- TypeError,
- '– no iterator returned');
- var noNext = {};
- noNext[Symbol.iterator] = function(){ return {}; };
- is.throws(
- function() {
- arrayFrom(noNext);
- },
- TypeError,
- '– no `next` function'
- );
- is.end();
- });
- test('Works for non-objects', function(is) {
- is.deepEqual(
- arrayFrom('a'),
- ['a'],
- 'string'
- );
- is.deepEqual(
- arrayFrom('👺'),
- ['👺'],
- 'string(emoji)'
- );
- is.deepEqual(
- arrayFrom('abc'),
- ['a', 'b', 'c'],
- 'string'
- );
- is.deepEqual(
- arrayFrom('👺🍣🍻'),
- ['👺', '🍣', '🍻'],
- 'string(emoji)'
- );
- is.deepEqual(
- arrayFrom(true),
- [],
- 'boolean'
- );
- is.deepEqual(
- arrayFrom(1),
- [],
- 'number'
- );
- is.deepEqual(
- arrayFrom(Symbol()),
- [],
- 'symbol'
- );
- is.end();
- });
|