|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 "use strict"; |
|
5 |
|
6 let { seq, iterate, filter, map, reductions, reduce, count, |
|
7 isEmpty, every, isEvery, some, take, takeWhile, drop, |
|
8 dropWhile, concat, first, rest, nth, last, dropLast, |
|
9 distinct, remove, mapcat, fromEnumerator, string, |
|
10 object, pairs, keys, values, each |
|
11 } = require("sdk/util/sequence"); |
|
12 |
|
13 const boom = () => { throw new Error("Boom!"); }; |
|
14 const broken = seq(function*() { |
|
15 yield 1; |
|
16 throw new Error("Boom!"); |
|
17 }); |
|
18 |
|
19 exports["test seq"] = assert => { |
|
20 let xs = seq(function*() { |
|
21 yield 1; |
|
22 yield 2; |
|
23 yield 3; |
|
24 }); |
|
25 |
|
26 assert.deepEqual([...seq(null)], [], "seq of null is empty"); |
|
27 assert.deepEqual([...seq(void(0))], [], "seq of void is empty"); |
|
28 assert.deepEqual([...xs], [1, 2, 3], "seq of 1 2 3"); |
|
29 assert.deepEqual([...seq(xs)], [1, 2, 3], "seq of seq is seq"); |
|
30 |
|
31 assert.deepEqual([...seq([])], [], "seq of emtpy array is empty"); |
|
32 assert.deepEqual([...seq([1])], [1], "seq of lonly array is single element"); |
|
33 assert.deepEqual([...seq([1, 2, 3])], [1, 2, 3], "seq of array is it's elements"); |
|
34 |
|
35 assert.deepEqual([...seq("")], [], "seq of emtpy string is empty"); |
|
36 assert.deepEqual([...seq("o")], ["o"], "seq of char is single char seq"); |
|
37 assert.deepEqual([...seq("hello")], ["h", "e", "l", "l", "o"], |
|
38 "seq of string are chars"); |
|
39 |
|
40 assert.deepEqual([...seq(new Set())], [], "seq of emtpy set is empty"); |
|
41 assert.deepEqual([...seq(new Set([1]))], [1], "seq of lonely set is single"); |
|
42 assert.deepEqual([...seq(new Set([1, 2, 3]))], [1, 2, 3], "seq of lonely set is single"); |
|
43 |
|
44 assert.deepEqual([...seq(new Map())], [], "seq of emtpy map is empty"); |
|
45 assert.deepEqual([...seq(new Map([[1, 2]]))], [[1, 2]], "seq single mapping is that mapping"); |
|
46 assert.deepEqual([...seq(new Map([[1, 2], [3, 4], [5, 6]]))], |
|
47 [[1, 2], [3, 4], [5, 6]], |
|
48 "seq of map is key value mappings"); |
|
49 |
|
50 [function(){}, 1, /foo/, true].forEach(x => { |
|
51 assert.throws(() => seq(x), "Type is not seq-able"); |
|
52 }); |
|
53 |
|
54 assert.throws(() => [...broken], |
|
55 /Boom/, |
|
56 "broken sequence errors propagate"); |
|
57 }; |
|
58 |
|
59 exports["test seq casting"] = assert => { |
|
60 const xs = seq(function*() { yield 1; yield 2; yield 3; }); |
|
61 const ys = seq(function*() { yield 1; }); |
|
62 const zs = seq(function*() {}); |
|
63 const kvs = seq(function*() { yield ["a", 1]; yield ["b", 2]; }); |
|
64 const kv = seq(function*() { yield ["a", 1]; }); |
|
65 |
|
66 assert.deepEqual([...xs], [1, 2, 3], "cast to array"); |
|
67 assert.deepEqual([...ys], [1], "cast to of one element"); |
|
68 assert.deepEqual([...zs], [], "cast empty array"); |
|
69 |
|
70 assert.deepEqual(string(...xs), "123", "cast to string"); |
|
71 assert.deepEqual(string(...ys), "1", "cast to char"); |
|
72 assert.deepEqual(string(...zs), "", "cast to empty string"); |
|
73 |
|
74 assert.deepEqual(new Set(xs), new Set([1, 2, 3]), |
|
75 "cast to set of items"); |
|
76 assert.deepEqual(new Set(ys), new Set([1]), |
|
77 "cast to set of one item"); |
|
78 assert.deepEqual(new Set(zs), new Set(), |
|
79 "cast to set of one item"); |
|
80 |
|
81 assert.deepEqual(new Map(kvs), new Map([["a", 1], ["b", 2]]), |
|
82 "cast to map"); |
|
83 assert.deepEqual(new Map(kv), new Map([["a", 1]]), |
|
84 "cast to single mapping"); |
|
85 assert.deepEqual(new Map(zs), new Map(), |
|
86 "cast to empty map"); |
|
87 |
|
88 assert.deepEqual(object(...kvs), {a: 1, b: 2}, |
|
89 "cast to object"); |
|
90 assert.deepEqual(object(...kv), {a: 1}, |
|
91 "cast to single pair"); |
|
92 assert.deepEqual(object(...zs), {}, |
|
93 "cast to empty object"); |
|
94 }; |
|
95 |
|
96 exports["test pairs"] = assert => { |
|
97 assert.deepEqual([...pairs(null)], [], "pairs on null is empty"); |
|
98 assert.deepEqual([...pairs(void(0))], [], "pairs on void is empty"); |
|
99 assert.deepEqual([...pairs({})], [], "empty sequence"); |
|
100 assert.deepEqual([...pairs({a: 1})], [["a", 1]], "single pair"); |
|
101 assert.deepEqual([...pairs({a: 1, b: 2, c: 3})].sort(), |
|
102 [["a", 1], ["b", 2], ["c", 3]], |
|
103 "creates pairs"); |
|
104 let items = []; |
|
105 for (let [key, value] of pairs({a: 1, b: 2, c: 3})) |
|
106 items.push([key, value]); |
|
107 |
|
108 assert.deepEqual(items.sort(), |
|
109 [["a", 1], ["b", 2], ["c", 3]], |
|
110 "for of works on pairs"); |
|
111 |
|
112 |
|
113 assert.deepEqual([...pairs([])], [], "pairs on empty array is empty"); |
|
114 assert.deepEqual([...pairs([1])], [[0, 1]], "pairs on array is [index, element]"); |
|
115 assert.deepEqual([...pairs([1, 2, 3])], |
|
116 [[0, 1], [1, 2], [2, 3]], |
|
117 "for arrays it pair of [index, element]"); |
|
118 |
|
119 assert.deepEqual([...pairs("")], [], "pairs on empty string is empty"); |
|
120 assert.deepEqual([...pairs("a")], [[0, "a"]], "pairs on char is [0, char]"); |
|
121 assert.deepEqual([...pairs("hello")], |
|
122 [[0, "h"], [1, "e"], [2, "l"], [3, "l"], [4, "o"]], |
|
123 "for strings it's pair of [index, char]"); |
|
124 |
|
125 assert.deepEqual([...pairs(new Map())], |
|
126 [], |
|
127 "pairs on empty map is empty"); |
|
128 assert.deepEqual([...pairs(new Map([[1, 3]]))], |
|
129 [[1, 3]], |
|
130 "pairs on single mapping single mapping"); |
|
131 assert.deepEqual([...pairs(new Map([[1, 2], [3, 4]]))], |
|
132 [[1, 2], [3, 4]], |
|
133 "pairs on map returs key vaule pairs"); |
|
134 |
|
135 assert.throws(() => pairs(new Set()), |
|
136 "can't pair set"); |
|
137 |
|
138 assert.throws(() => pairs(4), |
|
139 "can't pair number"); |
|
140 |
|
141 assert.throws(() => pairs(true), |
|
142 "can't pair boolean"); |
|
143 }; |
|
144 |
|
145 exports["test keys"] = assert => { |
|
146 assert.deepEqual([...keys(null)], [], "keys on null is empty"); |
|
147 assert.deepEqual([...keys(void(0))], [], "keys on void is empty"); |
|
148 assert.deepEqual([...keys({})], [], "empty sequence"); |
|
149 assert.deepEqual([...keys({a: 1})], ["a"], "single key"); |
|
150 assert.deepEqual([...keys({a: 1, b: 2, c: 3})].sort(), |
|
151 ["a", "b", "c"], |
|
152 "all keys"); |
|
153 |
|
154 let items = []; |
|
155 for (let key of keys({a: 1, b: 2, c: 3})) |
|
156 items.push(key); |
|
157 |
|
158 assert.deepEqual(items.sort(), |
|
159 ["a", "b", "c"], |
|
160 "for of works on keys"); |
|
161 |
|
162 |
|
163 assert.deepEqual([...keys([])], [], "keys on empty array is empty"); |
|
164 assert.deepEqual([...keys([1])], [0], "keys on array is indexes"); |
|
165 assert.deepEqual([...keys([1, 2, 3])], |
|
166 [0, 1, 2], |
|
167 "keys on arrays returns indexes"); |
|
168 |
|
169 assert.deepEqual([...keys("")], [], "keys on empty string is empty"); |
|
170 assert.deepEqual([...keys("a")], [0], "keys on char is 0"); |
|
171 assert.deepEqual([...keys("hello")], |
|
172 [0, 1, 2, 3, 4], |
|
173 "keys on strings is char indexes"); |
|
174 |
|
175 assert.deepEqual([...keys(new Map())], |
|
176 [], |
|
177 "keys on empty map is empty"); |
|
178 assert.deepEqual([...keys(new Map([[1, 3]]))], |
|
179 [1], |
|
180 "keys on single mapping single mapping is single key"); |
|
181 assert.deepEqual([...keys(new Map([[1, 2], [3, 4]]))], |
|
182 [1, 3], |
|
183 "keys on map is keys from map"); |
|
184 |
|
185 assert.throws(() => keys(new Set()), |
|
186 "can't keys set"); |
|
187 |
|
188 assert.throws(() => keys(4), |
|
189 "can't keys number"); |
|
190 |
|
191 assert.throws(() => keys(true), |
|
192 "can't keys boolean"); |
|
193 }; |
|
194 |
|
195 exports["test values"] = assert => { |
|
196 assert.deepEqual([...values({})], [], "empty sequence"); |
|
197 assert.deepEqual([...values({a: 1})], [1], "single value"); |
|
198 assert.deepEqual([...values({a: 1, b: 2, c: 3})].sort(), |
|
199 [1, 2, 3], |
|
200 "all values"); |
|
201 |
|
202 let items = []; |
|
203 for (let value of values({a: 1, b: 2, c: 3})) |
|
204 items.push(value); |
|
205 |
|
206 assert.deepEqual(items.sort(), |
|
207 [1, 2, 3], |
|
208 "for of works on values"); |
|
209 |
|
210 assert.deepEqual([...values([])], [], "values on empty array is empty"); |
|
211 assert.deepEqual([...values([1])], [1], "values on array elements"); |
|
212 assert.deepEqual([...values([1, 2, 3])], |
|
213 [1, 2, 3], |
|
214 "values on arrays returns elements"); |
|
215 |
|
216 assert.deepEqual([...values("")], [], "values on empty string is empty"); |
|
217 assert.deepEqual([...values("a")], ["a"], "values on char is char"); |
|
218 assert.deepEqual([...values("hello")], |
|
219 ["h", "e", "l", "l", "o"], |
|
220 "values on strings is chars"); |
|
221 |
|
222 assert.deepEqual([...values(new Map())], |
|
223 [], |
|
224 "values on empty map is empty"); |
|
225 assert.deepEqual([...values(new Map([[1, 3]]))], |
|
226 [3], |
|
227 "keys on single mapping single mapping is single key"); |
|
228 assert.deepEqual([...values(new Map([[1, 2], [3, 4]]))], |
|
229 [2, 4], |
|
230 "values on map is values from map"); |
|
231 |
|
232 assert.deepEqual([...values(new Set())], [], "values on empty set is empty"); |
|
233 assert.deepEqual([...values(new Set([1]))], [1], "values on set is it's items"); |
|
234 assert.deepEqual([...values(new Set([1, 2, 3]))], |
|
235 [1, 2, 3], |
|
236 "values on set is it's items"); |
|
237 |
|
238 |
|
239 assert.throws(() => values(4), |
|
240 "can't values number"); |
|
241 |
|
242 assert.throws(() => values(true), |
|
243 "can't values boolean"); |
|
244 }; |
|
245 |
|
246 exports["test fromEnumerator"] = assert => { |
|
247 const { Cc, Ci } = require("chrome"); |
|
248 const { enumerateObservers, |
|
249 addObserver, |
|
250 removeObserver } = Cc["@mozilla.org/observer-service;1"]. |
|
251 getService(Ci.nsIObserverService); |
|
252 |
|
253 |
|
254 const topic = "sec:" + Math.random().toString(32).substr(2); |
|
255 const [a, b, c] = [{wrappedJSObject: {}}, |
|
256 {wrappedJSObject: {}}, |
|
257 {wrappedJSObject: {}}]; |
|
258 const unwrap = x => x.wrappedJSObject; |
|
259 |
|
260 [a, b, c].forEach(x => addObserver(x, topic, false)); |
|
261 |
|
262 const xs = fromEnumerator(() => enumerateObservers(topic)); |
|
263 const ys = map(unwrap, xs); |
|
264 |
|
265 assert.deepEqual([...ys], [a, b, c].map(unwrap), |
|
266 "all observers are there"); |
|
267 |
|
268 removeObserver(b, topic); |
|
269 |
|
270 assert.deepEqual([...ys], [a, c].map(unwrap), |
|
271 "b was removed"); |
|
272 |
|
273 removeObserver(a, topic); |
|
274 |
|
275 assert.deepEqual([...ys], [c].map(unwrap), |
|
276 "a was removed"); |
|
277 |
|
278 removeObserver(c, topic); |
|
279 |
|
280 assert.deepEqual([...ys], [], |
|
281 "c was removed, now empty"); |
|
282 |
|
283 addObserver(a, topic, false); |
|
284 |
|
285 assert.deepEqual([...ys], [a].map(unwrap), |
|
286 "a was added"); |
|
287 |
|
288 removeObserver(a, topic); |
|
289 |
|
290 assert.deepEqual([...ys], [].map(unwrap), |
|
291 "a was removed, now empty"); |
|
292 |
|
293 }; |
|
294 |
|
295 exports["test filter"] = assert => { |
|
296 const isOdd = x => x % 2; |
|
297 const odds = seq(function*() { yield 1; yield 3; yield 5; }); |
|
298 const evens = seq(function*() { yield 2; yield 4; yield 6; }); |
|
299 const mixed = seq(function*() { |
|
300 yield 1; |
|
301 yield 2; |
|
302 yield 3; |
|
303 yield 4; |
|
304 }); |
|
305 |
|
306 assert.deepEqual([...filter(isOdd, mixed)], [1, 3], |
|
307 "filtered odds"); |
|
308 assert.deepEqual([...filter(isOdd, odds)], [1, 3, 5], |
|
309 "kept all"); |
|
310 assert.deepEqual([...filter(isOdd, evens)], [], |
|
311 "kept none"); |
|
312 |
|
313 |
|
314 let xs = filter(boom, mixed); |
|
315 assert.throws(() => [...xs], /Boom/, "errors propagate"); |
|
316 |
|
317 assert.throws(() => [...filter(isOdd, broken)], /Boom/, |
|
318 "sequence errors propagate"); |
|
319 }; |
|
320 |
|
321 exports["test filter array"] = assert => { |
|
322 let isOdd = x => x % 2; |
|
323 let xs = filter(isOdd, [1, 2, 3, 4]); |
|
324 let ys = filter(isOdd, [1, 3, 5]); |
|
325 let zs = filter(isOdd, [2, 4, 6]); |
|
326 |
|
327 assert.deepEqual([...xs], [1, 3], "filteres odds"); |
|
328 assert.deepEqual([...ys], [1, 3, 5], "kept all"); |
|
329 assert.deepEqual([...zs], [], "kept none"); |
|
330 assert.ok(!Array.isArray(xs)); |
|
331 }; |
|
332 |
|
333 exports["test filter set"] = assert => { |
|
334 let isOdd = x => x % 2; |
|
335 let xs = filter(isOdd, new Set([1, 2, 3, 4])); |
|
336 let ys = filter(isOdd, new Set([1, 3, 5])); |
|
337 let zs = filter(isOdd, new Set([2, 4, 6])); |
|
338 |
|
339 assert.deepEqual([...xs], [1, 3], "filteres odds"); |
|
340 assert.deepEqual([...ys], [1, 3, 5], "kept all"); |
|
341 assert.deepEqual([...zs], [], "kept none"); |
|
342 }; |
|
343 |
|
344 exports["test filter string"] = assert => { |
|
345 let isUpperCase = x => x.toUpperCase() === x; |
|
346 let xs = filter(isUpperCase, "aBcDe"); |
|
347 let ys = filter(isUpperCase, "ABC"); |
|
348 let zs = filter(isUpperCase, "abcd"); |
|
349 |
|
350 assert.deepEqual([...xs], ["B", "D"], "filteres odds"); |
|
351 assert.deepEqual([...ys], ["A", "B", "C"], "kept all"); |
|
352 assert.deepEqual([...zs], [], "kept none"); |
|
353 }; |
|
354 |
|
355 exports["test filter lazy"] = assert => { |
|
356 const x = 1; |
|
357 let y = 2; |
|
358 |
|
359 const xy = seq(function*() { yield x; yield y; }); |
|
360 const isOdd = x => x % 2; |
|
361 const actual = filter(isOdd, xy); |
|
362 |
|
363 assert.deepEqual([...actual], [1], "only one odd number"); |
|
364 y = 3; |
|
365 assert.deepEqual([...actual], [1, 3], "filter is lazy"); |
|
366 }; |
|
367 |
|
368 exports["test filter non sequences"] = assert => { |
|
369 const False = _ => false; |
|
370 assert.throws(() => [...filter(False, 1)], |
|
371 "can't iterate number"); |
|
372 assert.throws(() => [...filter(False, {a: 1, b:2})], |
|
373 "can't iterate object"); |
|
374 }; |
|
375 |
|
376 exports["test map"] = assert => { |
|
377 let inc = x => x + 1; |
|
378 let xs = seq(function*() { yield 1; yield 2; yield 3; }); |
|
379 let ys = map(inc, xs); |
|
380 |
|
381 assert.deepEqual([...ys], [2, 3, 4], "incremented each item"); |
|
382 |
|
383 assert.deepEqual([...map(inc, null)], [], "mapping null is empty"); |
|
384 assert.deepEqual([...map(inc, void(0))], [], "mapping void is empty"); |
|
385 assert.deepEqual([...map(inc, new Set([1, 2, 3]))], [2, 3, 4], "maps set items"); |
|
386 }; |
|
387 |
|
388 exports["test map two inputs"] = assert => { |
|
389 let sum = (x, y) => x + y; |
|
390 let xs = seq(function*() { yield 1; yield 2; yield 3; }); |
|
391 let ys = seq(function*() { yield 4; yield 5; yield 6; }); |
|
392 |
|
393 let zs = map(sum, xs, ys); |
|
394 |
|
395 assert.deepEqual([...zs], [5, 7, 9], "summed numbers"); |
|
396 }; |
|
397 |
|
398 exports["test map diff sized inputs"] = assert => { |
|
399 let sum = (x, y) => x + y; |
|
400 let xs = seq(function*() { yield 1; yield 2; yield 3; }); |
|
401 let ys = seq(function*() { yield 4; yield 5; yield 6; yield 7; yield 8; }); |
|
402 |
|
403 let zs = map(sum, xs, ys); |
|
404 |
|
405 assert.deepEqual([...zs], [5, 7, 9], "summed numbers"); |
|
406 assert.deepEqual([...map(sum, ys, xs)], [5, 7, 9], |
|
407 "index of exhasting input is irrelevant"); |
|
408 }; |
|
409 |
|
410 exports["test map multi"] = assert => { |
|
411 let sum = (x, y, z, w) => x + y + z + w; |
|
412 let xs = seq(function*() { yield 1; yield 2; yield 3; yield 4; }); |
|
413 let ys = seq(function*() { yield 4; yield 5; yield 6; yield 7; yield 8; }); |
|
414 let zs = seq(function*() { yield 10; yield 11; yield 12; }); |
|
415 let ws = seq(function*() { yield 0; yield 20; yield 40; yield 60; }); |
|
416 |
|
417 let actual = map(sum, xs, ys, zs, ws); |
|
418 |
|
419 assert.deepEqual([...actual], [15, 38, 61], "summed numbers"); |
|
420 }; |
|
421 |
|
422 exports["test map errors"] = assert => { |
|
423 assert.deepEqual([...map(boom, [])], [], |
|
424 "won't throw if empty"); |
|
425 |
|
426 const xs = map(boom, [1, 2, 4]); |
|
427 |
|
428 assert.throws(() => [...xs], /Boom/, "propagates errors"); |
|
429 |
|
430 assert.throws(() => [...map(x => x, broken)], /Boom/, |
|
431 "sequence errors propagate"); |
|
432 }; |
|
433 |
|
434 exports["test reductions"] = assert => { |
|
435 let sum = (...xs) => xs.reduce((x, y) => x + y, 0); |
|
436 |
|
437 assert.deepEqual([...reductions(sum, [1, 1, 1, 1])], |
|
438 [1, 2, 3, 4], |
|
439 "works with arrays"); |
|
440 assert.deepEqual([...reductions(sum, 5, [1, 1, 1, 1])], |
|
441 [5, 6, 7, 8, 9], |
|
442 "array with initial"); |
|
443 |
|
444 assert.deepEqual([...reductions(sum, seq(function*() { |
|
445 yield 1; |
|
446 yield 2; |
|
447 yield 3; |
|
448 }))], |
|
449 [1, 3, 6], |
|
450 "works with sequences"); |
|
451 |
|
452 assert.deepEqual([...reductions(sum, 10, seq(function*() { |
|
453 yield 1; |
|
454 yield 2; |
|
455 yield 3; |
|
456 }))], |
|
457 [10, 11, 13, 16], |
|
458 "works with sequences"); |
|
459 |
|
460 assert.deepEqual([...reductions(sum, [])], [0], |
|
461 "invokes accumulator with no args"); |
|
462 |
|
463 assert.throws(() => [...reductions(boom, 1, [1])], |
|
464 /Boom/, |
|
465 "arg errors errors propagate"); |
|
466 assert.throws(() => [...reductions(sum, 1, broken)], |
|
467 /Boom/, |
|
468 "sequence errors propagate"); |
|
469 }; |
|
470 |
|
471 exports["test reduce"] = assert => { |
|
472 let sum = (...xs) => xs.reduce((x, y) => x + y, 0); |
|
473 |
|
474 assert.deepEqual(reduce(sum, [1, 2, 3, 4, 5]), |
|
475 15, |
|
476 "works with arrays"); |
|
477 |
|
478 assert.deepEqual(reduce(sum, seq(function*() { |
|
479 yield 1; |
|
480 yield 2; |
|
481 yield 3; |
|
482 })), |
|
483 6, |
|
484 "works with sequences"); |
|
485 |
|
486 assert.deepEqual(reduce(sum, 10, [1, 2, 3, 4, 5]), |
|
487 25, |
|
488 "works with array & initial"); |
|
489 |
|
490 assert.deepEqual(reduce(sum, 5, seq(function*() { |
|
491 yield 1; |
|
492 yield 2; |
|
493 yield 3; |
|
494 })), |
|
495 11, |
|
496 "works with sequences & initial"); |
|
497 |
|
498 assert.deepEqual(reduce(sum, []), 0, "reduce with no args"); |
|
499 assert.deepEqual(reduce(sum, "a", []), "a", "reduce with initial"); |
|
500 assert.deepEqual(reduce(sum, 1, [1]), 2, "reduce with single & initial"); |
|
501 |
|
502 assert.throws(() => [...reduce(boom, 1, [1])], |
|
503 /Boom/, |
|
504 "arg errors errors propagate"); |
|
505 assert.throws(() => [...reduce(sum, 1, broken)], |
|
506 /Boom/, |
|
507 "sequence errors propagate"); |
|
508 }; |
|
509 |
|
510 exports["test each"] = assert => { |
|
511 const collect = xs => { |
|
512 let result = []; |
|
513 each((...etc) => result.push(...etc), xs); |
|
514 return result; |
|
515 }; |
|
516 |
|
517 assert.deepEqual(collect(null), [], "each ignores null"); |
|
518 assert.deepEqual(collect(void(0)), [], "each ignores void"); |
|
519 |
|
520 assert.deepEqual(collect([]), [], "each ignores empty"); |
|
521 assert.deepEqual(collect([1]), [1], "each works on single item arrays"); |
|
522 assert.deepEqual(collect([1, 2, 3, 4, 5]), |
|
523 [1, 2, 3, 4, 5], |
|
524 "works with arrays"); |
|
525 |
|
526 assert.deepEqual(collect(seq(function*() { |
|
527 yield 1; |
|
528 yield 2; |
|
529 yield 3; |
|
530 })), |
|
531 [1, 2, 3], |
|
532 "works with sequences"); |
|
533 |
|
534 assert.deepEqual(collect(""), [], "ignores empty strings"); |
|
535 assert.deepEqual(collect("a"), ["a"], "works on chars"); |
|
536 assert.deepEqual(collect("hello"), ["h", "e", "l", "l", "o"], |
|
537 "works on strings"); |
|
538 |
|
539 assert.deepEqual(collect(new Set()), [], "ignores empty sets"); |
|
540 assert.deepEqual(collect(new Set(["a"])), ["a"], |
|
541 "works on single item sets"); |
|
542 assert.deepEqual(collect(new Set([1, 2, 3])), [1, 2, 3], |
|
543 "works on muti item tests"); |
|
544 |
|
545 assert.deepEqual(collect(new Map()), [], "ignores empty maps"); |
|
546 assert.deepEqual(collect(new Map([["a", 1]])), [["a", 1]], |
|
547 "works on single mapping maps"); |
|
548 assert.deepEqual(collect(new Map([[1, 2], [3, 4], [5, 6]])), |
|
549 [[1, 2], [3, 4], [5, 6]], |
|
550 "works on muti mapping maps"); |
|
551 |
|
552 assert.throws(() => collect({}), "objects arn't supported"); |
|
553 assert.throws(() => collect(1), "numbers arn't supported"); |
|
554 assert.throws(() => collect(true), "booleas arn't supported"); |
|
555 }; |
|
556 |
|
557 exports["test count"] = assert => { |
|
558 assert.equal(count(null), 0, "null counts to 0"); |
|
559 assert.equal(count(), 0, "undefined counts to 0"); |
|
560 assert.equal(count([]), 0, "empty array"); |
|
561 assert.equal(count([1, 2, 3]), 3, "non-empty array"); |
|
562 assert.equal(count(""), 0, "empty string"); |
|
563 assert.equal(count("hello"), 5, "non-empty string"); |
|
564 assert.equal(count(new Map()), 0, "empty map"); |
|
565 assert.equal(count(new Map([[1, 2], [2, 3]])), 2, "non-empty map"); |
|
566 assert.equal(count(new Set()), 0, "empty set"); |
|
567 assert.equal(count(new Set([1, 2, 3, 4])), 4, "non-empty set"); |
|
568 assert.equal(count(seq(function*() {})), 0, "empty sequence"); |
|
569 assert.equal(count(seq(function*() { yield 1; yield 2; })), 2, |
|
570 "non-empty sequence"); |
|
571 |
|
572 assert.throws(() => count(broken), |
|
573 /Boom/, |
|
574 "sequence errors propagate"); |
|
575 }; |
|
576 |
|
577 exports["test isEmpty"] = assert => { |
|
578 assert.equal(isEmpty(null), true, "null is empty"); |
|
579 assert.equal(isEmpty(), true, "undefined is empty"); |
|
580 assert.equal(isEmpty([]), true, "array is array"); |
|
581 assert.equal(isEmpty([1, 2, 3]), false, "array isn't empty"); |
|
582 assert.equal(isEmpty(""), true, "string is empty"); |
|
583 assert.equal(isEmpty("hello"), false, "non-empty string"); |
|
584 assert.equal(isEmpty(new Map()), true, "empty map"); |
|
585 assert.equal(isEmpty(new Map([[1, 2], [2, 3]])), false, "non-empty map"); |
|
586 assert.equal(isEmpty(new Set()), true, "empty set"); |
|
587 assert.equal(isEmpty(new Set([1, 2, 3, 4])), false , "non-empty set"); |
|
588 assert.equal(isEmpty(seq(function*() {})), true, "empty sequence"); |
|
589 assert.equal(isEmpty(seq(function*() { yield 1; yield 2; })), false, |
|
590 "non-empty sequence"); |
|
591 |
|
592 assert.equal(isEmpty(broken), false, "hasn't reached error"); |
|
593 }; |
|
594 |
|
595 exports["test isEvery"] = assert => { |
|
596 let isOdd = x => x % 2; |
|
597 let isTrue = x => x === true; |
|
598 let isFalse = x => x === false; |
|
599 |
|
600 assert.equal(isEvery(isOdd, seq(function*() { |
|
601 yield 1; |
|
602 yield 3; |
|
603 yield 5; |
|
604 })), true, "all are odds"); |
|
605 |
|
606 assert.equal(isEvery(isOdd, seq(function*() { |
|
607 yield 1; |
|
608 yield 2; |
|
609 yield 3; |
|
610 })), false, "contains even"); |
|
611 |
|
612 assert.equal(isEvery(isTrue, seq(function*() {})), true, "true if empty"); |
|
613 assert.equal(isEvery(isFalse, seq(function*() {})), true, "true if empty"); |
|
614 |
|
615 assert.equal(isEvery(isTrue, null), true, "true for null"); |
|
616 assert.equal(isEvery(isTrue, undefined), true, "true for undefined"); |
|
617 |
|
618 assert.throws(() => isEvery(boom, [1, 2]), |
|
619 /Boom/, |
|
620 "arg errors errors propagate"); |
|
621 assert.throws(() => isEvery(x => true, broken), |
|
622 /Boom/, |
|
623 "sequence errors propagate"); |
|
624 |
|
625 assert.equal(isEvery(x => false, broken), false, |
|
626 "hasn't reached error"); |
|
627 }; |
|
628 |
|
629 exports["test some"] = assert => { |
|
630 let isOdd = x => x % 2; |
|
631 let isTrue = x => x === true; |
|
632 let isFalse = x => x === false; |
|
633 |
|
634 assert.equal(some(isOdd, seq(function*() { |
|
635 yield 2; |
|
636 yield 4; |
|
637 yield 6; |
|
638 })), null, "all are even"); |
|
639 |
|
640 assert.equal(some(isOdd, seq(function*() { |
|
641 yield 2; |
|
642 yield 3; |
|
643 yield 4; |
|
644 })), true, "contains odd"); |
|
645 |
|
646 assert.equal(some(isTrue, seq(function*() {})), null, |
|
647 "null if empty") |
|
648 assert.equal(some(isFalse, seq(function*() {})), null, |
|
649 "null if empty") |
|
650 |
|
651 assert.equal(some(isTrue, null), null, "null for null"); |
|
652 assert.equal(some(isTrue, undefined), null, "null for undefined"); |
|
653 |
|
654 assert.throws(() => some(boom, [1, 2]), |
|
655 /Boom/, |
|
656 "arg errors errors propagate"); |
|
657 assert.throws(() => some(x => false, broken), |
|
658 /Boom/, |
|
659 "sequence errors propagate"); |
|
660 |
|
661 assert.equal(some(x => true, broken), true, |
|
662 "hasn't reached error"); |
|
663 }; |
|
664 |
|
665 exports["test take"] = assert => { |
|
666 let xs = seq(function*() { |
|
667 yield 1; |
|
668 yield 2; |
|
669 yield 3; |
|
670 yield 4; |
|
671 yield 5; |
|
672 yield 6; |
|
673 }); |
|
674 |
|
675 assert.deepEqual([...take(3, xs)], [1, 2, 3], "took 3 items"); |
|
676 assert.deepEqual([...take(3, [1, 2, 3, 4, 5])], [1, 2, 3], |
|
677 "took 3 from array"); |
|
678 |
|
679 let ys = seq(function*() { yield 1; yield 2; }); |
|
680 assert.deepEqual([...take(3, ys)], [1, 2], "takes at max n"); |
|
681 assert.deepEqual([...take(3, [1, 2])], [1, 2], |
|
682 "takes at max n from arary"); |
|
683 |
|
684 let empty = seq(function*() {}); |
|
685 assert.deepEqual([...take(5, empty)], [], "nothing to take"); |
|
686 |
|
687 assert.throws(() => [...take(3, broken)], |
|
688 /Boom/, |
|
689 "sequence errors propagate"); |
|
690 |
|
691 assert.deepEqual([...take(1, broken)], [1], |
|
692 "hasn't reached error"); |
|
693 }; |
|
694 |
|
695 exports["test iterate"] = assert => { |
|
696 let inc = x => x + 1; |
|
697 let nums = iterate(inc, 0); |
|
698 |
|
699 assert.deepEqual([...take(5, nums)], [0, 1, 2, 3, 4], "took 5"); |
|
700 assert.deepEqual([...take(10, nums)], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], "took 10"); |
|
701 |
|
702 let xs = iterate(x => x * 3, 2); |
|
703 assert.deepEqual([...take(4, xs)], [2, 6, 18, 54], "took 4"); |
|
704 |
|
705 assert.throws(() => [...iterate(boom, 0)], |
|
706 /Boom/, |
|
707 "function exceptions propagate"); |
|
708 }; |
|
709 |
|
710 exports["test takeWhile"] = assert => { |
|
711 let isNegative = x => x < 0; |
|
712 let xs = seq(function*() { |
|
713 yield -2; |
|
714 yield -1; |
|
715 yield 0; |
|
716 yield 1; |
|
717 yield 2; |
|
718 yield 3; |
|
719 }); |
|
720 |
|
721 assert.deepEqual([...takeWhile(isNegative, xs)], [-2, -1], |
|
722 "took until 0"); |
|
723 |
|
724 let ys = seq(function*() {}); |
|
725 assert.deepEqual([...takeWhile(isNegative, ys)], [], |
|
726 "took none"); |
|
727 |
|
728 let zs = seq(function*() { |
|
729 yield 0; |
|
730 yield 1; |
|
731 yield 2; |
|
732 yield 3; |
|
733 }); |
|
734 |
|
735 assert.deepEqual([...takeWhile(isNegative, zs)], [], |
|
736 "took none"); |
|
737 |
|
738 assert.throws(() => [...takeWhile(boom, zs)], |
|
739 /Boom/, |
|
740 "function errors errors propagate"); |
|
741 assert.throws(() => [...takeWhile(x => true, broken)], |
|
742 /Boom/, |
|
743 "sequence errors propagate"); |
|
744 |
|
745 assert.deepEqual([...takeWhile(x => false, broken)], |
|
746 [], |
|
747 "hasn't reached error"); |
|
748 }; |
|
749 |
|
750 exports["test drop"] = assert => { |
|
751 let testDrop = xs => { |
|
752 assert.deepEqual([...drop(2, xs)], |
|
753 [3, 4], |
|
754 "dropped two elements"); |
|
755 |
|
756 assert.deepEqual([...drop(1, xs)], |
|
757 [2, 3, 4], |
|
758 "dropped one"); |
|
759 |
|
760 assert.deepEqual([...drop(0, xs)], |
|
761 [1, 2, 3, 4], |
|
762 "dropped 0"); |
|
763 |
|
764 assert.deepEqual([...drop(-2, xs)], |
|
765 [1, 2, 3, 4], |
|
766 "dropped 0 on negative `n`"); |
|
767 |
|
768 assert.deepEqual([...drop(5, xs)], |
|
769 [], |
|
770 "dropped all items"); |
|
771 }; |
|
772 |
|
773 testDrop([1, 2, 3, 4]); |
|
774 testDrop(seq(function*() { |
|
775 yield 1; |
|
776 yield 2; |
|
777 yield 3; |
|
778 yield 4; |
|
779 })); |
|
780 |
|
781 assert.throws(() => [...drop(1, broken)], |
|
782 /Boom/, |
|
783 "sequence errors propagate"); |
|
784 }; |
|
785 |
|
786 |
|
787 exports["test dropWhile"] = assert => { |
|
788 let isNegative = x => x < 0; |
|
789 let True = _ => true; |
|
790 let False = _ => false; |
|
791 |
|
792 let test = xs => { |
|
793 assert.deepEqual([...dropWhile(isNegative, xs)], |
|
794 [0, 1, 2], |
|
795 "dropped negative"); |
|
796 |
|
797 assert.deepEqual([...dropWhile(True, xs)], |
|
798 [], |
|
799 "drop all"); |
|
800 |
|
801 assert.deepEqual([...dropWhile(False, xs)], |
|
802 [-2, -1, 0, 1, 2], |
|
803 "keep all"); |
|
804 }; |
|
805 |
|
806 test([-2, -1, 0, 1, 2]); |
|
807 test(seq(function*() { |
|
808 yield -2; |
|
809 yield -1; |
|
810 yield 0; |
|
811 yield 1; |
|
812 yield 2; |
|
813 })); |
|
814 |
|
815 assert.throws(() => [...dropWhile(boom, [1, 2, 3])], |
|
816 /Boom/, |
|
817 "function errors errors propagate"); |
|
818 assert.throws(() => [...dropWhile(x => true, broken)], |
|
819 /Boom/, |
|
820 "sequence errors propagate"); |
|
821 }; |
|
822 |
|
823 |
|
824 exports["test concat"] = assert => { |
|
825 let test = (a, b, c, d) => { |
|
826 assert.deepEqual([...concat()], |
|
827 [], |
|
828 "nothing to concat"); |
|
829 assert.deepEqual([...concat(a)], |
|
830 [1, 2, 3], |
|
831 "concat with nothing returns same as first"); |
|
832 assert.deepEqual([...concat(a, b)], |
|
833 [1, 2, 3, 4, 5], |
|
834 "concat items from both"); |
|
835 assert.deepEqual([...concat(a, b, a)], |
|
836 [1, 2, 3, 4, 5, 1, 2, 3], |
|
837 "concat itself"); |
|
838 assert.deepEqual([...concat(c)], |
|
839 [], |
|
840 "concat of empty is empty"); |
|
841 assert.deepEqual([...concat(a, c)], |
|
842 [1, 2, 3], |
|
843 "concat with empty"); |
|
844 assert.deepEqual([...concat(c, c, c)], |
|
845 [], |
|
846 "concat of empties is empty"); |
|
847 assert.deepEqual([...concat(c, b)], |
|
848 [4, 5], |
|
849 "empty can be in front"); |
|
850 assert.deepEqual([...concat(d)], |
|
851 [7], |
|
852 "concat singular"); |
|
853 assert.deepEqual([...concat(d, d)], |
|
854 [7, 7], |
|
855 "concat singulars"); |
|
856 |
|
857 assert.deepEqual([...concat(a, a, b, c, d, c, d, d)], |
|
858 [1, 2, 3, 1, 2, 3, 4, 5, 7, 7, 7], |
|
859 "many concats"); |
|
860 |
|
861 let ab = concat(a, b); |
|
862 let abcd = concat(ab, concat(c, d)); |
|
863 let cdabcd = concat(c, d, abcd); |
|
864 |
|
865 assert.deepEqual([...cdabcd], |
|
866 [7, 1, 2, 3, 4, 5, 7], |
|
867 "nested concats"); |
|
868 }; |
|
869 |
|
870 test([1, 2, 3], |
|
871 [4, 5], |
|
872 [], |
|
873 [7]); |
|
874 |
|
875 test(seq(function*() { yield 1; yield 2; yield 3; }), |
|
876 seq(function*() { yield 4; yield 5; }), |
|
877 seq(function*() { }), |
|
878 seq(function*() { yield 7; })); |
|
879 |
|
880 assert.throws(() => [...concat(broken, [1, 2, 3])], |
|
881 /Boom/, |
|
882 "function errors errors propagate"); |
|
883 }; |
|
884 |
|
885 |
|
886 exports["test first"] = assert => { |
|
887 let test = (xs, empty) => { |
|
888 assert.equal(first(xs), 1, "returns first"); |
|
889 assert.equal(first(empty), null, "returns null empty"); |
|
890 }; |
|
891 |
|
892 test("1234", ""); |
|
893 test([1, 2, 3], []); |
|
894 test([1, 2, 3], null); |
|
895 test([1, 2, 3], undefined); |
|
896 test(seq(function*() { yield 1; yield 2; yield 3; }), |
|
897 seq(function*() { })); |
|
898 assert.equal(first(broken), 1, "did not reached error"); |
|
899 }; |
|
900 |
|
901 exports["test rest"] = assert => { |
|
902 let test = (xs, x, nil) => { |
|
903 assert.deepEqual([...rest(xs)], ["b", "c"], |
|
904 "rest items"); |
|
905 assert.deepEqual([...rest(x)], [], |
|
906 "empty when singular"); |
|
907 assert.deepEqual([...rest(nil)], [], |
|
908 "empty when empty"); |
|
909 }; |
|
910 |
|
911 test("abc", "a", ""); |
|
912 test(["a", "b", "c"], ["d"], []); |
|
913 test(seq(function*() { yield "a"; yield "b"; yield "c"; }), |
|
914 seq(function*() { yield "d"; }), |
|
915 seq(function*() {})); |
|
916 test(["a", "b", "c"], ["d"], null); |
|
917 test(["a", "b", "c"], ["d"], undefined); |
|
918 |
|
919 assert.throws(() => [...rest(broken)], |
|
920 /Boom/, |
|
921 "sequence errors propagate"); |
|
922 }; |
|
923 |
|
924 |
|
925 exports["test nth"] = assert => { |
|
926 let notFound = {}; |
|
927 let test = xs => { |
|
928 assert.equal(nth(xs, 0), "h", "first"); |
|
929 assert.equal(nth(xs, 1), "e", "second"); |
|
930 assert.equal(nth(xs, 5), void(0), "out of bound"); |
|
931 assert.equal(nth(xs, 5, notFound), notFound, "out of bound"); |
|
932 assert.equal(nth(xs, -1), void(0), "out of bound"); |
|
933 assert.equal(nth(xs, -1, notFound), notFound, "out of bound"); |
|
934 assert.equal(nth(xs, 4), "o", "5th"); |
|
935 }; |
|
936 |
|
937 let testEmpty = xs => { |
|
938 assert.equal(nth(xs, 0), void(0), "no first in empty"); |
|
939 assert.equal(nth(xs, 5), void(0), "no 5th in empty"); |
|
940 assert.equal(nth(xs, 0, notFound), notFound, "notFound on out of bound"); |
|
941 }; |
|
942 |
|
943 test("hello"); |
|
944 test(["h", "e", "l", "l", "o"]); |
|
945 test(seq(function*() { |
|
946 yield "h"; |
|
947 yield "e"; |
|
948 yield "l"; |
|
949 yield "l"; |
|
950 yield "o"; |
|
951 })); |
|
952 testEmpty(null); |
|
953 testEmpty(undefined); |
|
954 testEmpty([]); |
|
955 testEmpty(""); |
|
956 testEmpty(seq(function*() {})); |
|
957 |
|
958 |
|
959 assert.throws(() => nth(broken, 1), |
|
960 /Boom/, |
|
961 "sequence errors propagate"); |
|
962 assert.equal(nth(broken, 0), 1, "have not reached error"); |
|
963 }; |
|
964 |
|
965 |
|
966 exports["test last"] = assert => { |
|
967 assert.equal(last(null), null, "no last in null"); |
|
968 assert.equal(last(void(0)), null, "no last in undefined"); |
|
969 assert.equal(last([]), null, "no last in []"); |
|
970 assert.equal(last(""), null, "no last in ''"); |
|
971 assert.equal(last(seq(function*() { })), null, "no last in empty"); |
|
972 |
|
973 assert.equal(last("hello"), "o", "last from string"); |
|
974 assert.equal(last([1, 2, 3]), 3, "last from array"); |
|
975 assert.equal(last([1]), 1, "last from singular"); |
|
976 assert.equal(last(seq(function*() { |
|
977 yield 1; |
|
978 yield 2; |
|
979 yield 3; |
|
980 })), 3, "last from sequence"); |
|
981 |
|
982 assert.throws(() => last(broken), |
|
983 /Boom/, |
|
984 "sequence errors propagate"); |
|
985 }; |
|
986 |
|
987 |
|
988 exports["test dropLast"] = assert => { |
|
989 let test = xs => { |
|
990 assert.deepEqual([...dropLast(xs)], |
|
991 [1, 2, 3, 4], |
|
992 "dropped last"); |
|
993 assert.deepEqual([...dropLast(0, xs)], |
|
994 [1, 2, 3, 4, 5], |
|
995 "dropped none on 0"); |
|
996 assert.deepEqual([...dropLast(-3, xs)], |
|
997 [1, 2, 3, 4, 5], |
|
998 "drop none on negative"); |
|
999 assert.deepEqual([...dropLast(3, xs)], |
|
1000 [1, 2], |
|
1001 "dropped given number"); |
|
1002 assert.deepEqual([...dropLast(5, xs)], |
|
1003 [], |
|
1004 "dropped all"); |
|
1005 }; |
|
1006 |
|
1007 let testEmpty = xs => { |
|
1008 assert.deepEqual([...dropLast(xs)], |
|
1009 [], |
|
1010 "nothing to drop"); |
|
1011 assert.deepEqual([...dropLast(0, xs)], |
|
1012 [], |
|
1013 "dropped none on 0"); |
|
1014 assert.deepEqual([...dropLast(-3, xs)], |
|
1015 [], |
|
1016 "drop none on negative"); |
|
1017 assert.deepEqual([...dropLast(3, xs)], |
|
1018 [], |
|
1019 "nothing to drop"); |
|
1020 }; |
|
1021 |
|
1022 test([1, 2, 3, 4, 5]); |
|
1023 test(seq(function*() { |
|
1024 yield 1; |
|
1025 yield 2; |
|
1026 yield 3; |
|
1027 yield 4; |
|
1028 yield 5; |
|
1029 })); |
|
1030 testEmpty([]); |
|
1031 testEmpty(""); |
|
1032 testEmpty(seq(function*() {})); |
|
1033 |
|
1034 assert.throws(() => [...dropLast(broken)], |
|
1035 /Boom/, |
|
1036 "sequence errors propagate"); |
|
1037 }; |
|
1038 |
|
1039 |
|
1040 exports["test distinct"] = assert => { |
|
1041 let test = (xs, message) => { |
|
1042 assert.deepEqual([...distinct(xs)], |
|
1043 [1, 2, 3, 4, 5], |
|
1044 message); |
|
1045 }; |
|
1046 |
|
1047 test([1, 2, 1, 3, 1, 4, 1, 5], "works with arrays"); |
|
1048 test(seq(function*() { |
|
1049 yield 1; |
|
1050 yield 2; |
|
1051 yield 1; |
|
1052 yield 3; |
|
1053 yield 1; |
|
1054 yield 4; |
|
1055 yield 1; |
|
1056 yield 5; |
|
1057 }), "works with sequences"); |
|
1058 test(new Set([1, 2, 1, 3, 1, 4, 1, 5]), |
|
1059 "works with sets"); |
|
1060 test(seq(function*() { |
|
1061 yield 1; |
|
1062 yield 2; |
|
1063 yield 2; |
|
1064 yield 2; |
|
1065 yield 1; |
|
1066 yield 3; |
|
1067 yield 1; |
|
1068 yield 4; |
|
1069 yield 4; |
|
1070 yield 4; |
|
1071 yield 1; |
|
1072 yield 5; |
|
1073 }), "works with multiple repeatitions"); |
|
1074 test([1, 2, 3, 4, 5], "work with distinct arrays"); |
|
1075 test(seq(function*() { |
|
1076 yield 1; |
|
1077 yield 2; |
|
1078 yield 3; |
|
1079 yield 4; |
|
1080 yield 5; |
|
1081 }), "works with distinct seqs"); |
|
1082 }; |
|
1083 |
|
1084 |
|
1085 exports["test remove"] = assert => { |
|
1086 let isPositive = x => x > 0; |
|
1087 let test = xs => { |
|
1088 assert.deepEqual([...remove(isPositive, xs)], |
|
1089 [-2, -1, 0], |
|
1090 "removed positives"); |
|
1091 }; |
|
1092 |
|
1093 test([1, -2, 2, -1, 3, 7, 0]); |
|
1094 test(seq(function*() { |
|
1095 yield 1; |
|
1096 yield -2; |
|
1097 yield 2; |
|
1098 yield -1; |
|
1099 yield 3; |
|
1100 yield 7; |
|
1101 yield 0; |
|
1102 })); |
|
1103 |
|
1104 assert.throws(() => [...distinct(broken)], |
|
1105 /Boom/, |
|
1106 "sequence errors propagate"); |
|
1107 }; |
|
1108 |
|
1109 |
|
1110 exports["test mapcat"] = assert => { |
|
1111 let upto = n => seq(function* () { |
|
1112 let index = 0; |
|
1113 while (index < n) { |
|
1114 yield index; |
|
1115 index = index + 1; |
|
1116 } |
|
1117 }); |
|
1118 |
|
1119 assert.deepEqual([...mapcat(upto, [1, 2, 3, 4])], |
|
1120 [0, 0, 1, 0, 1, 2, 0, 1, 2, 3], |
|
1121 "expands given sequence"); |
|
1122 |
|
1123 assert.deepEqual([...mapcat(upto, [0, 1, 2, 0])], |
|
1124 [0, 0, 1], |
|
1125 "expands given sequence"); |
|
1126 |
|
1127 assert.deepEqual([...mapcat(upto, [0, 0, 0])], |
|
1128 [], |
|
1129 "expands given sequence"); |
|
1130 |
|
1131 assert.deepEqual([...mapcat(upto, [])], |
|
1132 [], |
|
1133 "nothing to expand"); |
|
1134 |
|
1135 assert.deepEqual([...mapcat(upto, null)], |
|
1136 [], |
|
1137 "nothing to expand"); |
|
1138 |
|
1139 assert.deepEqual([...mapcat(upto, void(0))], |
|
1140 [], |
|
1141 "nothing to expand"); |
|
1142 |
|
1143 let xs = seq(function*() { |
|
1144 yield 0; |
|
1145 yield 1; |
|
1146 yield 0; |
|
1147 yield 2; |
|
1148 yield 0; |
|
1149 }); |
|
1150 |
|
1151 assert.deepEqual([...mapcat(upto, xs)], |
|
1152 [0, 0, 1], |
|
1153 "expands given sequence"); |
|
1154 |
|
1155 assert.throws(() => [...mapcat(boom, xs)], |
|
1156 /Boom/, |
|
1157 "function errors errors propagate"); |
|
1158 assert.throws(() => [...mapcat(upto, broken)], |
|
1159 /Boom/, |
|
1160 "sequence errors propagate"); |
|
1161 }; |
|
1162 |
|
1163 require("sdk/test").run(exports); |