test.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. var test = require('tape-catch');
  2. var plus = require('1-liners/plus');
  3. var isNative = require('lodash.isnative');
  4. // Shim Symbol.iterator if it's not available
  5. require('core-js/es6/symbol');
  6. var arrayFrom = require('./polyfill');
  7. test('Works as expected', function(is) {
  8. var mock = {
  9. 0: 'a',
  10. 1: 'b',
  11. 2: 'c',
  12. length: 3,
  13. };
  14. is.deepEqual(
  15. arrayFrom(mock),
  16. ['a', 'b', 'c'],
  17. 'with a mock object'
  18. );
  19. is.ok(
  20. arrayFrom(mock) instanceof Array,
  21. '– returning an array'
  22. );
  23. is.deepEqual(
  24. arrayFrom({
  25. 0: 'a',
  26. 1: 'b',
  27. 2: 'c',
  28. 'a': 'left out',
  29. '-1': 'left out',
  30. length: 3,
  31. }),
  32. ['a', 'b', 'c'],
  33. '– ignoring illegal indices'
  34. );
  35. is.deepEqual(
  36. arrayFrom({}),
  37. [],
  38. 'with an empty object'
  39. );
  40. is.deepEqual(
  41. arrayFrom([]),
  42. [],
  43. 'with an empty array'
  44. );
  45. is.deepEqual(
  46. (function() {return arrayFrom(arguments);})('a', 'b', 'c'),
  47. ['a', 'b', 'c'],
  48. 'with the `arguments` object'
  49. );
  50. is.deepEqual(
  51. arrayFrom(['a', 'b', 'c']),
  52. ['a', 'b', 'c'],
  53. 'with an array'
  54. );
  55. is.deepEqual(
  56. arrayFrom(mock, plus),
  57. ['a0', 'b1', 'c2'],
  58. 'when dealing with `mapFn`'
  59. );
  60. var context = {suffix: '+'};
  61. is.deepEqual(
  62. arrayFrom(mock,
  63. function(item) {return (item + this.suffix);},
  64. context
  65. ),
  66. ['a+', 'b+', 'c+'],
  67. 'when dealing with `mapFn` and `thisArg`'
  68. );
  69. var Transferable = function(){};
  70. Transferable.from = arrayFrom;
  71. is.ok(
  72. Transferable.from([1]) instanceof Transferable,
  73. 'can be transferred to other constructor functions'
  74. );
  75. is.end();
  76. });
  77. test('Works for iterable objects', function(is) {
  78. var SetPolyfill = require('core-js/library/fn/set');
  79. is.deepEqual(
  80. arrayFrom(new SetPolyfill(['a', 'b', 'c'])),
  81. ['a', 'b', 'c'],
  82. 'with Set (polyfill)'
  83. );
  84. is.deepEqual(
  85. arrayFrom(new SetPolyfill(['a', 'b', 'c']).values(), plus),
  86. ['a0', 'b1', 'c2'],
  87. 'when dealing with `mapFn`'
  88. );
  89. var context = {suffix: '+'};
  90. is.deepEqual(
  91. arrayFrom(new SetPolyfill(['a', 'b', 'c']).keys(),
  92. function(item) {return (item + this.suffix);},
  93. context
  94. ),
  95. ['a+', 'b+', 'c+'],
  96. 'when dealing with `mapFn` and `thisArg`'
  97. );
  98. if(typeof Set !== 'undefined' && isNative(Set)) {
  99. is.deepEqual(
  100. arrayFrom(new Set(['a', 'b', 'c'])),
  101. ['a', 'b', 'c'],
  102. 'with native Set'
  103. );
  104. }
  105. if(typeof Map !== 'undefined' && isNative(Map)) {
  106. is.deepEqual(
  107. arrayFrom(new Map()
  108. .set('key1', 'value1')
  109. .set('key2', 'value2')
  110. .set('key3', 'value3')
  111. .keys()
  112. ),
  113. ['key1', 'key2', 'key3'],
  114. 'with native Map'
  115. );
  116. }
  117. var geckoIterator = {
  118. value : 1,
  119. '@@iterator' : function(){
  120. var hasValue = true;
  121. var value = this.value;
  122. return {
  123. next: function(){
  124. if(hasValue) {
  125. hasValue = false;
  126. return { value: value, done: false };
  127. } else {
  128. return { done: true };
  129. }
  130. }
  131. };
  132. }
  133. };
  134. is.deepEqual(
  135. arrayFrom(geckoIterator),
  136. [1],
  137. 'when using Gecko-based "@@iterator" property.'
  138. );
  139. geckoIterator['@@iterator'] = null;
  140. is.deepEqual(
  141. arrayFrom(geckoIterator),
  142. [],
  143. 'null iterator is like no iterator');
  144. var Transferable = function(){};
  145. Transferable.from = arrayFrom;
  146. is.ok(Transferable.from(new SetPolyfill(['a'])) instanceof Transferable,
  147. 'can be transferred to other constructor functions (iterable)'
  148. );
  149. is.end();
  150. });
  151. test('Throws when things go very wrong.', function(is) {
  152. is.throws(
  153. function() {
  154. arrayFrom();
  155. },
  156. TypeError,
  157. 'when the given object is invalid'
  158. );
  159. is.throws(
  160. function() {
  161. arrayFrom({length: 0}, /invalid/);
  162. },
  163. TypeError,
  164. 'when `mapFn` is invalid'
  165. );
  166. var invalidIterator = {};
  167. invalidIterator[Symbol.iterator] = {};
  168. is.throws(
  169. function() {
  170. arrayFrom(invalidIterator);
  171. },
  172. TypeError,
  173. 'when an iterable has an invalid iterator property'
  174. );
  175. var noIterator = {};
  176. noIterator[Symbol.iterator] = function(){};
  177. is.throws(
  178. function() {
  179. arrayFrom(noIterator);
  180. },
  181. TypeError,
  182. '– no iterator returned');
  183. var noNext = {};
  184. noNext[Symbol.iterator] = function(){ return {}; };
  185. is.throws(
  186. function() {
  187. arrayFrom(noNext);
  188. },
  189. TypeError,
  190. '– no `next` function'
  191. );
  192. is.end();
  193. });
  194. test('Works for non-objects', function(is) {
  195. is.deepEqual(
  196. arrayFrom('a'),
  197. ['a'],
  198. 'string'
  199. );
  200. is.deepEqual(
  201. arrayFrom('👺'),
  202. ['👺'],
  203. 'string(emoji)'
  204. );
  205. is.deepEqual(
  206. arrayFrom('abc'),
  207. ['a', 'b', 'c'],
  208. 'string'
  209. );
  210. is.deepEqual(
  211. arrayFrom('👺🍣🍻'),
  212. ['👺', '🍣', '🍻'],
  213. 'string(emoji)'
  214. );
  215. is.deepEqual(
  216. arrayFrom(true),
  217. [],
  218. 'boolean'
  219. );
  220. is.deepEqual(
  221. arrayFrom(1),
  222. [],
  223. 'number'
  224. );
  225. is.deepEqual(
  226. arrayFrom(Symbol()),
  227. [],
  228. 'symbol'
  229. );
  230. is.end();
  231. });