1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/test/test-sequence.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1163 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +"use strict"; 1.8 + 1.9 +let { seq, iterate, filter, map, reductions, reduce, count, 1.10 + isEmpty, every, isEvery, some, take, takeWhile, drop, 1.11 + dropWhile, concat, first, rest, nth, last, dropLast, 1.12 + distinct, remove, mapcat, fromEnumerator, string, 1.13 + object, pairs, keys, values, each 1.14 + } = require("sdk/util/sequence"); 1.15 + 1.16 +const boom = () => { throw new Error("Boom!"); }; 1.17 +const broken = seq(function*() { 1.18 + yield 1; 1.19 + throw new Error("Boom!"); 1.20 +}); 1.21 + 1.22 +exports["test seq"] = assert => { 1.23 + let xs = seq(function*() { 1.24 + yield 1; 1.25 + yield 2; 1.26 + yield 3; 1.27 + }); 1.28 + 1.29 + assert.deepEqual([...seq(null)], [], "seq of null is empty"); 1.30 + assert.deepEqual([...seq(void(0))], [], "seq of void is empty"); 1.31 + assert.deepEqual([...xs], [1, 2, 3], "seq of 1 2 3"); 1.32 + assert.deepEqual([...seq(xs)], [1, 2, 3], "seq of seq is seq"); 1.33 + 1.34 + assert.deepEqual([...seq([])], [], "seq of emtpy array is empty"); 1.35 + assert.deepEqual([...seq([1])], [1], "seq of lonly array is single element"); 1.36 + assert.deepEqual([...seq([1, 2, 3])], [1, 2, 3], "seq of array is it's elements"); 1.37 + 1.38 + assert.deepEqual([...seq("")], [], "seq of emtpy string is empty"); 1.39 + assert.deepEqual([...seq("o")], ["o"], "seq of char is single char seq"); 1.40 + assert.deepEqual([...seq("hello")], ["h", "e", "l", "l", "o"], 1.41 + "seq of string are chars"); 1.42 + 1.43 + assert.deepEqual([...seq(new Set())], [], "seq of emtpy set is empty"); 1.44 + assert.deepEqual([...seq(new Set([1]))], [1], "seq of lonely set is single"); 1.45 + assert.deepEqual([...seq(new Set([1, 2, 3]))], [1, 2, 3], "seq of lonely set is single"); 1.46 + 1.47 + assert.deepEqual([...seq(new Map())], [], "seq of emtpy map is empty"); 1.48 + assert.deepEqual([...seq(new Map([[1, 2]]))], [[1, 2]], "seq single mapping is that mapping"); 1.49 + assert.deepEqual([...seq(new Map([[1, 2], [3, 4], [5, 6]]))], 1.50 + [[1, 2], [3, 4], [5, 6]], 1.51 + "seq of map is key value mappings"); 1.52 + 1.53 + [function(){}, 1, /foo/, true].forEach(x => { 1.54 + assert.throws(() => seq(x), "Type is not seq-able"); 1.55 + }); 1.56 + 1.57 + assert.throws(() => [...broken], 1.58 + /Boom/, 1.59 + "broken sequence errors propagate"); 1.60 +}; 1.61 + 1.62 +exports["test seq casting"] = assert => { 1.63 + const xs = seq(function*() { yield 1; yield 2; yield 3; }); 1.64 + const ys = seq(function*() { yield 1; }); 1.65 + const zs = seq(function*() {}); 1.66 + const kvs = seq(function*() { yield ["a", 1]; yield ["b", 2]; }); 1.67 + const kv = seq(function*() { yield ["a", 1]; }); 1.68 + 1.69 + assert.deepEqual([...xs], [1, 2, 3], "cast to array"); 1.70 + assert.deepEqual([...ys], [1], "cast to of one element"); 1.71 + assert.deepEqual([...zs], [], "cast empty array"); 1.72 + 1.73 + assert.deepEqual(string(...xs), "123", "cast to string"); 1.74 + assert.deepEqual(string(...ys), "1", "cast to char"); 1.75 + assert.deepEqual(string(...zs), "", "cast to empty string"); 1.76 + 1.77 + assert.deepEqual(new Set(xs), new Set([1, 2, 3]), 1.78 + "cast to set of items"); 1.79 + assert.deepEqual(new Set(ys), new Set([1]), 1.80 + "cast to set of one item"); 1.81 + assert.deepEqual(new Set(zs), new Set(), 1.82 + "cast to set of one item"); 1.83 + 1.84 + assert.deepEqual(new Map(kvs), new Map([["a", 1], ["b", 2]]), 1.85 + "cast to map"); 1.86 + assert.deepEqual(new Map(kv), new Map([["a", 1]]), 1.87 + "cast to single mapping"); 1.88 + assert.deepEqual(new Map(zs), new Map(), 1.89 + "cast to empty map"); 1.90 + 1.91 + assert.deepEqual(object(...kvs), {a: 1, b: 2}, 1.92 + "cast to object"); 1.93 + assert.deepEqual(object(...kv), {a: 1}, 1.94 + "cast to single pair"); 1.95 + assert.deepEqual(object(...zs), {}, 1.96 + "cast to empty object"); 1.97 +}; 1.98 + 1.99 +exports["test pairs"] = assert => { 1.100 + assert.deepEqual([...pairs(null)], [], "pairs on null is empty"); 1.101 + assert.deepEqual([...pairs(void(0))], [], "pairs on void is empty"); 1.102 + assert.deepEqual([...pairs({})], [], "empty sequence"); 1.103 + assert.deepEqual([...pairs({a: 1})], [["a", 1]], "single pair"); 1.104 + assert.deepEqual([...pairs({a: 1, b: 2, c: 3})].sort(), 1.105 + [["a", 1], ["b", 2], ["c", 3]], 1.106 + "creates pairs"); 1.107 + let items = []; 1.108 + for (let [key, value] of pairs({a: 1, b: 2, c: 3})) 1.109 + items.push([key, value]); 1.110 + 1.111 + assert.deepEqual(items.sort(), 1.112 + [["a", 1], ["b", 2], ["c", 3]], 1.113 + "for of works on pairs"); 1.114 + 1.115 + 1.116 + assert.deepEqual([...pairs([])], [], "pairs on empty array is empty"); 1.117 + assert.deepEqual([...pairs([1])], [[0, 1]], "pairs on array is [index, element]"); 1.118 + assert.deepEqual([...pairs([1, 2, 3])], 1.119 + [[0, 1], [1, 2], [2, 3]], 1.120 + "for arrays it pair of [index, element]"); 1.121 + 1.122 + assert.deepEqual([...pairs("")], [], "pairs on empty string is empty"); 1.123 + assert.deepEqual([...pairs("a")], [[0, "a"]], "pairs on char is [0, char]"); 1.124 + assert.deepEqual([...pairs("hello")], 1.125 + [[0, "h"], [1, "e"], [2, "l"], [3, "l"], [4, "o"]], 1.126 + "for strings it's pair of [index, char]"); 1.127 + 1.128 + assert.deepEqual([...pairs(new Map())], 1.129 + [], 1.130 + "pairs on empty map is empty"); 1.131 + assert.deepEqual([...pairs(new Map([[1, 3]]))], 1.132 + [[1, 3]], 1.133 + "pairs on single mapping single mapping"); 1.134 + assert.deepEqual([...pairs(new Map([[1, 2], [3, 4]]))], 1.135 + [[1, 2], [3, 4]], 1.136 + "pairs on map returs key vaule pairs"); 1.137 + 1.138 + assert.throws(() => pairs(new Set()), 1.139 + "can't pair set"); 1.140 + 1.141 + assert.throws(() => pairs(4), 1.142 + "can't pair number"); 1.143 + 1.144 + assert.throws(() => pairs(true), 1.145 + "can't pair boolean"); 1.146 +}; 1.147 + 1.148 +exports["test keys"] = assert => { 1.149 + assert.deepEqual([...keys(null)], [], "keys on null is empty"); 1.150 + assert.deepEqual([...keys(void(0))], [], "keys on void is empty"); 1.151 + assert.deepEqual([...keys({})], [], "empty sequence"); 1.152 + assert.deepEqual([...keys({a: 1})], ["a"], "single key"); 1.153 + assert.deepEqual([...keys({a: 1, b: 2, c: 3})].sort(), 1.154 + ["a", "b", "c"], 1.155 + "all keys"); 1.156 + 1.157 + let items = []; 1.158 + for (let key of keys({a: 1, b: 2, c: 3})) 1.159 + items.push(key); 1.160 + 1.161 + assert.deepEqual(items.sort(), 1.162 + ["a", "b", "c"], 1.163 + "for of works on keys"); 1.164 + 1.165 + 1.166 + assert.deepEqual([...keys([])], [], "keys on empty array is empty"); 1.167 + assert.deepEqual([...keys([1])], [0], "keys on array is indexes"); 1.168 + assert.deepEqual([...keys([1, 2, 3])], 1.169 + [0, 1, 2], 1.170 + "keys on arrays returns indexes"); 1.171 + 1.172 + assert.deepEqual([...keys("")], [], "keys on empty string is empty"); 1.173 + assert.deepEqual([...keys("a")], [0], "keys on char is 0"); 1.174 + assert.deepEqual([...keys("hello")], 1.175 + [0, 1, 2, 3, 4], 1.176 + "keys on strings is char indexes"); 1.177 + 1.178 + assert.deepEqual([...keys(new Map())], 1.179 + [], 1.180 + "keys on empty map is empty"); 1.181 + assert.deepEqual([...keys(new Map([[1, 3]]))], 1.182 + [1], 1.183 + "keys on single mapping single mapping is single key"); 1.184 + assert.deepEqual([...keys(new Map([[1, 2], [3, 4]]))], 1.185 + [1, 3], 1.186 + "keys on map is keys from map"); 1.187 + 1.188 + assert.throws(() => keys(new Set()), 1.189 + "can't keys set"); 1.190 + 1.191 + assert.throws(() => keys(4), 1.192 + "can't keys number"); 1.193 + 1.194 + assert.throws(() => keys(true), 1.195 + "can't keys boolean"); 1.196 +}; 1.197 + 1.198 +exports["test values"] = assert => { 1.199 + assert.deepEqual([...values({})], [], "empty sequence"); 1.200 + assert.deepEqual([...values({a: 1})], [1], "single value"); 1.201 + assert.deepEqual([...values({a: 1, b: 2, c: 3})].sort(), 1.202 + [1, 2, 3], 1.203 + "all values"); 1.204 + 1.205 + let items = []; 1.206 + for (let value of values({a: 1, b: 2, c: 3})) 1.207 + items.push(value); 1.208 + 1.209 + assert.deepEqual(items.sort(), 1.210 + [1, 2, 3], 1.211 + "for of works on values"); 1.212 + 1.213 + assert.deepEqual([...values([])], [], "values on empty array is empty"); 1.214 + assert.deepEqual([...values([1])], [1], "values on array elements"); 1.215 + assert.deepEqual([...values([1, 2, 3])], 1.216 + [1, 2, 3], 1.217 + "values on arrays returns elements"); 1.218 + 1.219 + assert.deepEqual([...values("")], [], "values on empty string is empty"); 1.220 + assert.deepEqual([...values("a")], ["a"], "values on char is char"); 1.221 + assert.deepEqual([...values("hello")], 1.222 + ["h", "e", "l", "l", "o"], 1.223 + "values on strings is chars"); 1.224 + 1.225 + assert.deepEqual([...values(new Map())], 1.226 + [], 1.227 + "values on empty map is empty"); 1.228 + assert.deepEqual([...values(new Map([[1, 3]]))], 1.229 + [3], 1.230 + "keys on single mapping single mapping is single key"); 1.231 + assert.deepEqual([...values(new Map([[1, 2], [3, 4]]))], 1.232 + [2, 4], 1.233 + "values on map is values from map"); 1.234 + 1.235 + assert.deepEqual([...values(new Set())], [], "values on empty set is empty"); 1.236 + assert.deepEqual([...values(new Set([1]))], [1], "values on set is it's items"); 1.237 + assert.deepEqual([...values(new Set([1, 2, 3]))], 1.238 + [1, 2, 3], 1.239 + "values on set is it's items"); 1.240 + 1.241 + 1.242 + assert.throws(() => values(4), 1.243 + "can't values number"); 1.244 + 1.245 + assert.throws(() => values(true), 1.246 + "can't values boolean"); 1.247 +}; 1.248 + 1.249 +exports["test fromEnumerator"] = assert => { 1.250 + const { Cc, Ci } = require("chrome"); 1.251 + const { enumerateObservers, 1.252 + addObserver, 1.253 + removeObserver } = Cc["@mozilla.org/observer-service;1"]. 1.254 + getService(Ci.nsIObserverService); 1.255 + 1.256 + 1.257 + const topic = "sec:" + Math.random().toString(32).substr(2); 1.258 + const [a, b, c] = [{wrappedJSObject: {}}, 1.259 + {wrappedJSObject: {}}, 1.260 + {wrappedJSObject: {}}]; 1.261 + const unwrap = x => x.wrappedJSObject; 1.262 + 1.263 + [a, b, c].forEach(x => addObserver(x, topic, false)); 1.264 + 1.265 + const xs = fromEnumerator(() => enumerateObservers(topic)); 1.266 + const ys = map(unwrap, xs); 1.267 + 1.268 + assert.deepEqual([...ys], [a, b, c].map(unwrap), 1.269 + "all observers are there"); 1.270 + 1.271 + removeObserver(b, topic); 1.272 + 1.273 + assert.deepEqual([...ys], [a, c].map(unwrap), 1.274 + "b was removed"); 1.275 + 1.276 + removeObserver(a, topic); 1.277 + 1.278 + assert.deepEqual([...ys], [c].map(unwrap), 1.279 + "a was removed"); 1.280 + 1.281 + removeObserver(c, topic); 1.282 + 1.283 + assert.deepEqual([...ys], [], 1.284 + "c was removed, now empty"); 1.285 + 1.286 + addObserver(a, topic, false); 1.287 + 1.288 + assert.deepEqual([...ys], [a].map(unwrap), 1.289 + "a was added"); 1.290 + 1.291 + removeObserver(a, topic); 1.292 + 1.293 + assert.deepEqual([...ys], [].map(unwrap), 1.294 + "a was removed, now empty"); 1.295 + 1.296 +}; 1.297 + 1.298 +exports["test filter"] = assert => { 1.299 + const isOdd = x => x % 2; 1.300 + const odds = seq(function*() { yield 1; yield 3; yield 5; }); 1.301 + const evens = seq(function*() { yield 2; yield 4; yield 6; }); 1.302 + const mixed = seq(function*() { 1.303 + yield 1; 1.304 + yield 2; 1.305 + yield 3; 1.306 + yield 4; 1.307 + }); 1.308 + 1.309 + assert.deepEqual([...filter(isOdd, mixed)], [1, 3], 1.310 + "filtered odds"); 1.311 + assert.deepEqual([...filter(isOdd, odds)], [1, 3, 5], 1.312 + "kept all"); 1.313 + assert.deepEqual([...filter(isOdd, evens)], [], 1.314 + "kept none"); 1.315 + 1.316 + 1.317 + let xs = filter(boom, mixed); 1.318 + assert.throws(() => [...xs], /Boom/, "errors propagate"); 1.319 + 1.320 + assert.throws(() => [...filter(isOdd, broken)], /Boom/, 1.321 + "sequence errors propagate"); 1.322 +}; 1.323 + 1.324 +exports["test filter array"] = assert => { 1.325 + let isOdd = x => x % 2; 1.326 + let xs = filter(isOdd, [1, 2, 3, 4]); 1.327 + let ys = filter(isOdd, [1, 3, 5]); 1.328 + let zs = filter(isOdd, [2, 4, 6]); 1.329 + 1.330 + assert.deepEqual([...xs], [1, 3], "filteres odds"); 1.331 + assert.deepEqual([...ys], [1, 3, 5], "kept all"); 1.332 + assert.deepEqual([...zs], [], "kept none"); 1.333 + assert.ok(!Array.isArray(xs)); 1.334 +}; 1.335 + 1.336 +exports["test filter set"] = assert => { 1.337 + let isOdd = x => x % 2; 1.338 + let xs = filter(isOdd, new Set([1, 2, 3, 4])); 1.339 + let ys = filter(isOdd, new Set([1, 3, 5])); 1.340 + let zs = filter(isOdd, new Set([2, 4, 6])); 1.341 + 1.342 + assert.deepEqual([...xs], [1, 3], "filteres odds"); 1.343 + assert.deepEqual([...ys], [1, 3, 5], "kept all"); 1.344 + assert.deepEqual([...zs], [], "kept none"); 1.345 +}; 1.346 + 1.347 +exports["test filter string"] = assert => { 1.348 + let isUpperCase = x => x.toUpperCase() === x; 1.349 + let xs = filter(isUpperCase, "aBcDe"); 1.350 + let ys = filter(isUpperCase, "ABC"); 1.351 + let zs = filter(isUpperCase, "abcd"); 1.352 + 1.353 + assert.deepEqual([...xs], ["B", "D"], "filteres odds"); 1.354 + assert.deepEqual([...ys], ["A", "B", "C"], "kept all"); 1.355 + assert.deepEqual([...zs], [], "kept none"); 1.356 +}; 1.357 + 1.358 +exports["test filter lazy"] = assert => { 1.359 + const x = 1; 1.360 + let y = 2; 1.361 + 1.362 + const xy = seq(function*() { yield x; yield y; }); 1.363 + const isOdd = x => x % 2; 1.364 + const actual = filter(isOdd, xy); 1.365 + 1.366 + assert.deepEqual([...actual], [1], "only one odd number"); 1.367 + y = 3; 1.368 + assert.deepEqual([...actual], [1, 3], "filter is lazy"); 1.369 +}; 1.370 + 1.371 +exports["test filter non sequences"] = assert => { 1.372 + const False = _ => false; 1.373 + assert.throws(() => [...filter(False, 1)], 1.374 + "can't iterate number"); 1.375 + assert.throws(() => [...filter(False, {a: 1, b:2})], 1.376 + "can't iterate object"); 1.377 +}; 1.378 + 1.379 +exports["test map"] = assert => { 1.380 + let inc = x => x + 1; 1.381 + let xs = seq(function*() { yield 1; yield 2; yield 3; }); 1.382 + let ys = map(inc, xs); 1.383 + 1.384 + assert.deepEqual([...ys], [2, 3, 4], "incremented each item"); 1.385 + 1.386 + assert.deepEqual([...map(inc, null)], [], "mapping null is empty"); 1.387 + assert.deepEqual([...map(inc, void(0))], [], "mapping void is empty"); 1.388 + assert.deepEqual([...map(inc, new Set([1, 2, 3]))], [2, 3, 4], "maps set items"); 1.389 +}; 1.390 + 1.391 +exports["test map two inputs"] = assert => { 1.392 + let sum = (x, y) => x + y; 1.393 + let xs = seq(function*() { yield 1; yield 2; yield 3; }); 1.394 + let ys = seq(function*() { yield 4; yield 5; yield 6; }); 1.395 + 1.396 + let zs = map(sum, xs, ys); 1.397 + 1.398 + assert.deepEqual([...zs], [5, 7, 9], "summed numbers"); 1.399 +}; 1.400 + 1.401 +exports["test map diff sized inputs"] = assert => { 1.402 + let sum = (x, y) => x + y; 1.403 + let xs = seq(function*() { yield 1; yield 2; yield 3; }); 1.404 + let ys = seq(function*() { yield 4; yield 5; yield 6; yield 7; yield 8; }); 1.405 + 1.406 + let zs = map(sum, xs, ys); 1.407 + 1.408 + assert.deepEqual([...zs], [5, 7, 9], "summed numbers"); 1.409 + assert.deepEqual([...map(sum, ys, xs)], [5, 7, 9], 1.410 + "index of exhasting input is irrelevant"); 1.411 +}; 1.412 + 1.413 +exports["test map multi"] = assert => { 1.414 + let sum = (x, y, z, w) => x + y + z + w; 1.415 + let xs = seq(function*() { yield 1; yield 2; yield 3; yield 4; }); 1.416 + let ys = seq(function*() { yield 4; yield 5; yield 6; yield 7; yield 8; }); 1.417 + let zs = seq(function*() { yield 10; yield 11; yield 12; }); 1.418 + let ws = seq(function*() { yield 0; yield 20; yield 40; yield 60; }); 1.419 + 1.420 + let actual = map(sum, xs, ys, zs, ws); 1.421 + 1.422 + assert.deepEqual([...actual], [15, 38, 61], "summed numbers"); 1.423 +}; 1.424 + 1.425 +exports["test map errors"] = assert => { 1.426 + assert.deepEqual([...map(boom, [])], [], 1.427 + "won't throw if empty"); 1.428 + 1.429 + const xs = map(boom, [1, 2, 4]); 1.430 + 1.431 + assert.throws(() => [...xs], /Boom/, "propagates errors"); 1.432 + 1.433 + assert.throws(() => [...map(x => x, broken)], /Boom/, 1.434 + "sequence errors propagate"); 1.435 +}; 1.436 + 1.437 +exports["test reductions"] = assert => { 1.438 + let sum = (...xs) => xs.reduce((x, y) => x + y, 0); 1.439 + 1.440 + assert.deepEqual([...reductions(sum, [1, 1, 1, 1])], 1.441 + [1, 2, 3, 4], 1.442 + "works with arrays"); 1.443 + assert.deepEqual([...reductions(sum, 5, [1, 1, 1, 1])], 1.444 + [5, 6, 7, 8, 9], 1.445 + "array with initial"); 1.446 + 1.447 + assert.deepEqual([...reductions(sum, seq(function*() { 1.448 + yield 1; 1.449 + yield 2; 1.450 + yield 3; 1.451 + }))], 1.452 + [1, 3, 6], 1.453 + "works with sequences"); 1.454 + 1.455 + assert.deepEqual([...reductions(sum, 10, seq(function*() { 1.456 + yield 1; 1.457 + yield 2; 1.458 + yield 3; 1.459 + }))], 1.460 + [10, 11, 13, 16], 1.461 + "works with sequences"); 1.462 + 1.463 + assert.deepEqual([...reductions(sum, [])], [0], 1.464 + "invokes accumulator with no args"); 1.465 + 1.466 + assert.throws(() => [...reductions(boom, 1, [1])], 1.467 + /Boom/, 1.468 + "arg errors errors propagate"); 1.469 + assert.throws(() => [...reductions(sum, 1, broken)], 1.470 + /Boom/, 1.471 + "sequence errors propagate"); 1.472 +}; 1.473 + 1.474 +exports["test reduce"] = assert => { 1.475 + let sum = (...xs) => xs.reduce((x, y) => x + y, 0); 1.476 + 1.477 + assert.deepEqual(reduce(sum, [1, 2, 3, 4, 5]), 1.478 + 15, 1.479 + "works with arrays"); 1.480 + 1.481 + assert.deepEqual(reduce(sum, seq(function*() { 1.482 + yield 1; 1.483 + yield 2; 1.484 + yield 3; 1.485 + })), 1.486 + 6, 1.487 + "works with sequences"); 1.488 + 1.489 + assert.deepEqual(reduce(sum, 10, [1, 2, 3, 4, 5]), 1.490 + 25, 1.491 + "works with array & initial"); 1.492 + 1.493 + assert.deepEqual(reduce(sum, 5, seq(function*() { 1.494 + yield 1; 1.495 + yield 2; 1.496 + yield 3; 1.497 + })), 1.498 + 11, 1.499 + "works with sequences & initial"); 1.500 + 1.501 + assert.deepEqual(reduce(sum, []), 0, "reduce with no args"); 1.502 + assert.deepEqual(reduce(sum, "a", []), "a", "reduce with initial"); 1.503 + assert.deepEqual(reduce(sum, 1, [1]), 2, "reduce with single & initial"); 1.504 + 1.505 + assert.throws(() => [...reduce(boom, 1, [1])], 1.506 + /Boom/, 1.507 + "arg errors errors propagate"); 1.508 + assert.throws(() => [...reduce(sum, 1, broken)], 1.509 + /Boom/, 1.510 + "sequence errors propagate"); 1.511 +}; 1.512 + 1.513 +exports["test each"] = assert => { 1.514 + const collect = xs => { 1.515 + let result = []; 1.516 + each((...etc) => result.push(...etc), xs); 1.517 + return result; 1.518 + }; 1.519 + 1.520 + assert.deepEqual(collect(null), [], "each ignores null"); 1.521 + assert.deepEqual(collect(void(0)), [], "each ignores void"); 1.522 + 1.523 + assert.deepEqual(collect([]), [], "each ignores empty"); 1.524 + assert.deepEqual(collect([1]), [1], "each works on single item arrays"); 1.525 + assert.deepEqual(collect([1, 2, 3, 4, 5]), 1.526 + [1, 2, 3, 4, 5], 1.527 + "works with arrays"); 1.528 + 1.529 + assert.deepEqual(collect(seq(function*() { 1.530 + yield 1; 1.531 + yield 2; 1.532 + yield 3; 1.533 + })), 1.534 + [1, 2, 3], 1.535 + "works with sequences"); 1.536 + 1.537 + assert.deepEqual(collect(""), [], "ignores empty strings"); 1.538 + assert.deepEqual(collect("a"), ["a"], "works on chars"); 1.539 + assert.deepEqual(collect("hello"), ["h", "e", "l", "l", "o"], 1.540 + "works on strings"); 1.541 + 1.542 + assert.deepEqual(collect(new Set()), [], "ignores empty sets"); 1.543 + assert.deepEqual(collect(new Set(["a"])), ["a"], 1.544 + "works on single item sets"); 1.545 + assert.deepEqual(collect(new Set([1, 2, 3])), [1, 2, 3], 1.546 + "works on muti item tests"); 1.547 + 1.548 + assert.deepEqual(collect(new Map()), [], "ignores empty maps"); 1.549 + assert.deepEqual(collect(new Map([["a", 1]])), [["a", 1]], 1.550 + "works on single mapping maps"); 1.551 + assert.deepEqual(collect(new Map([[1, 2], [3, 4], [5, 6]])), 1.552 + [[1, 2], [3, 4], [5, 6]], 1.553 + "works on muti mapping maps"); 1.554 + 1.555 + assert.throws(() => collect({}), "objects arn't supported"); 1.556 + assert.throws(() => collect(1), "numbers arn't supported"); 1.557 + assert.throws(() => collect(true), "booleas arn't supported"); 1.558 +}; 1.559 + 1.560 +exports["test count"] = assert => { 1.561 + assert.equal(count(null), 0, "null counts to 0"); 1.562 + assert.equal(count(), 0, "undefined counts to 0"); 1.563 + assert.equal(count([]), 0, "empty array"); 1.564 + assert.equal(count([1, 2, 3]), 3, "non-empty array"); 1.565 + assert.equal(count(""), 0, "empty string"); 1.566 + assert.equal(count("hello"), 5, "non-empty string"); 1.567 + assert.equal(count(new Map()), 0, "empty map"); 1.568 + assert.equal(count(new Map([[1, 2], [2, 3]])), 2, "non-empty map"); 1.569 + assert.equal(count(new Set()), 0, "empty set"); 1.570 + assert.equal(count(new Set([1, 2, 3, 4])), 4, "non-empty set"); 1.571 + assert.equal(count(seq(function*() {})), 0, "empty sequence"); 1.572 + assert.equal(count(seq(function*() { yield 1; yield 2; })), 2, 1.573 + "non-empty sequence"); 1.574 + 1.575 + assert.throws(() => count(broken), 1.576 + /Boom/, 1.577 + "sequence errors propagate"); 1.578 +}; 1.579 + 1.580 +exports["test isEmpty"] = assert => { 1.581 + assert.equal(isEmpty(null), true, "null is empty"); 1.582 + assert.equal(isEmpty(), true, "undefined is empty"); 1.583 + assert.equal(isEmpty([]), true, "array is array"); 1.584 + assert.equal(isEmpty([1, 2, 3]), false, "array isn't empty"); 1.585 + assert.equal(isEmpty(""), true, "string is empty"); 1.586 + assert.equal(isEmpty("hello"), false, "non-empty string"); 1.587 + assert.equal(isEmpty(new Map()), true, "empty map"); 1.588 + assert.equal(isEmpty(new Map([[1, 2], [2, 3]])), false, "non-empty map"); 1.589 + assert.equal(isEmpty(new Set()), true, "empty set"); 1.590 + assert.equal(isEmpty(new Set([1, 2, 3, 4])), false , "non-empty set"); 1.591 + assert.equal(isEmpty(seq(function*() {})), true, "empty sequence"); 1.592 + assert.equal(isEmpty(seq(function*() { yield 1; yield 2; })), false, 1.593 + "non-empty sequence"); 1.594 + 1.595 + assert.equal(isEmpty(broken), false, "hasn't reached error"); 1.596 +}; 1.597 + 1.598 +exports["test isEvery"] = assert => { 1.599 + let isOdd = x => x % 2; 1.600 + let isTrue = x => x === true; 1.601 + let isFalse = x => x === false; 1.602 + 1.603 + assert.equal(isEvery(isOdd, seq(function*() { 1.604 + yield 1; 1.605 + yield 3; 1.606 + yield 5; 1.607 + })), true, "all are odds"); 1.608 + 1.609 + assert.equal(isEvery(isOdd, seq(function*() { 1.610 + yield 1; 1.611 + yield 2; 1.612 + yield 3; 1.613 + })), false, "contains even"); 1.614 + 1.615 + assert.equal(isEvery(isTrue, seq(function*() {})), true, "true if empty"); 1.616 + assert.equal(isEvery(isFalse, seq(function*() {})), true, "true if empty"); 1.617 + 1.618 + assert.equal(isEvery(isTrue, null), true, "true for null"); 1.619 + assert.equal(isEvery(isTrue, undefined), true, "true for undefined"); 1.620 + 1.621 + assert.throws(() => isEvery(boom, [1, 2]), 1.622 + /Boom/, 1.623 + "arg errors errors propagate"); 1.624 + assert.throws(() => isEvery(x => true, broken), 1.625 + /Boom/, 1.626 + "sequence errors propagate"); 1.627 + 1.628 + assert.equal(isEvery(x => false, broken), false, 1.629 + "hasn't reached error"); 1.630 +}; 1.631 + 1.632 +exports["test some"] = assert => { 1.633 + let isOdd = x => x % 2; 1.634 + let isTrue = x => x === true; 1.635 + let isFalse = x => x === false; 1.636 + 1.637 + assert.equal(some(isOdd, seq(function*() { 1.638 + yield 2; 1.639 + yield 4; 1.640 + yield 6; 1.641 + })), null, "all are even"); 1.642 + 1.643 + assert.equal(some(isOdd, seq(function*() { 1.644 + yield 2; 1.645 + yield 3; 1.646 + yield 4; 1.647 + })), true, "contains odd"); 1.648 + 1.649 + assert.equal(some(isTrue, seq(function*() {})), null, 1.650 + "null if empty") 1.651 + assert.equal(some(isFalse, seq(function*() {})), null, 1.652 + "null if empty") 1.653 + 1.654 + assert.equal(some(isTrue, null), null, "null for null"); 1.655 + assert.equal(some(isTrue, undefined), null, "null for undefined"); 1.656 + 1.657 + assert.throws(() => some(boom, [1, 2]), 1.658 + /Boom/, 1.659 + "arg errors errors propagate"); 1.660 + assert.throws(() => some(x => false, broken), 1.661 + /Boom/, 1.662 + "sequence errors propagate"); 1.663 + 1.664 + assert.equal(some(x => true, broken), true, 1.665 + "hasn't reached error"); 1.666 +}; 1.667 + 1.668 +exports["test take"] = assert => { 1.669 + let xs = seq(function*() { 1.670 + yield 1; 1.671 + yield 2; 1.672 + yield 3; 1.673 + yield 4; 1.674 + yield 5; 1.675 + yield 6; 1.676 + }); 1.677 + 1.678 + assert.deepEqual([...take(3, xs)], [1, 2, 3], "took 3 items"); 1.679 + assert.deepEqual([...take(3, [1, 2, 3, 4, 5])], [1, 2, 3], 1.680 + "took 3 from array"); 1.681 + 1.682 + let ys = seq(function*() { yield 1; yield 2; }); 1.683 + assert.deepEqual([...take(3, ys)], [1, 2], "takes at max n"); 1.684 + assert.deepEqual([...take(3, [1, 2])], [1, 2], 1.685 + "takes at max n from arary"); 1.686 + 1.687 + let empty = seq(function*() {}); 1.688 + assert.deepEqual([...take(5, empty)], [], "nothing to take"); 1.689 + 1.690 + assert.throws(() => [...take(3, broken)], 1.691 + /Boom/, 1.692 + "sequence errors propagate"); 1.693 + 1.694 + assert.deepEqual([...take(1, broken)], [1], 1.695 + "hasn't reached error"); 1.696 +}; 1.697 + 1.698 +exports["test iterate"] = assert => { 1.699 + let inc = x => x + 1; 1.700 + let nums = iterate(inc, 0); 1.701 + 1.702 + assert.deepEqual([...take(5, nums)], [0, 1, 2, 3, 4], "took 5"); 1.703 + assert.deepEqual([...take(10, nums)], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], "took 10"); 1.704 + 1.705 + let xs = iterate(x => x * 3, 2); 1.706 + assert.deepEqual([...take(4, xs)], [2, 6, 18, 54], "took 4"); 1.707 + 1.708 + assert.throws(() => [...iterate(boom, 0)], 1.709 + /Boom/, 1.710 + "function exceptions propagate"); 1.711 +}; 1.712 + 1.713 +exports["test takeWhile"] = assert => { 1.714 + let isNegative = x => x < 0; 1.715 + let xs = seq(function*() { 1.716 + yield -2; 1.717 + yield -1; 1.718 + yield 0; 1.719 + yield 1; 1.720 + yield 2; 1.721 + yield 3; 1.722 + }); 1.723 + 1.724 + assert.deepEqual([...takeWhile(isNegative, xs)], [-2, -1], 1.725 + "took until 0"); 1.726 + 1.727 + let ys = seq(function*() {}); 1.728 + assert.deepEqual([...takeWhile(isNegative, ys)], [], 1.729 + "took none"); 1.730 + 1.731 + let zs = seq(function*() { 1.732 + yield 0; 1.733 + yield 1; 1.734 + yield 2; 1.735 + yield 3; 1.736 + }); 1.737 + 1.738 + assert.deepEqual([...takeWhile(isNegative, zs)], [], 1.739 + "took none"); 1.740 + 1.741 + assert.throws(() => [...takeWhile(boom, zs)], 1.742 + /Boom/, 1.743 + "function errors errors propagate"); 1.744 + assert.throws(() => [...takeWhile(x => true, broken)], 1.745 + /Boom/, 1.746 + "sequence errors propagate"); 1.747 + 1.748 + assert.deepEqual([...takeWhile(x => false, broken)], 1.749 + [], 1.750 + "hasn't reached error"); 1.751 +}; 1.752 + 1.753 +exports["test drop"] = assert => { 1.754 + let testDrop = xs => { 1.755 + assert.deepEqual([...drop(2, xs)], 1.756 + [3, 4], 1.757 + "dropped two elements"); 1.758 + 1.759 + assert.deepEqual([...drop(1, xs)], 1.760 + [2, 3, 4], 1.761 + "dropped one"); 1.762 + 1.763 + assert.deepEqual([...drop(0, xs)], 1.764 + [1, 2, 3, 4], 1.765 + "dropped 0"); 1.766 + 1.767 + assert.deepEqual([...drop(-2, xs)], 1.768 + [1, 2, 3, 4], 1.769 + "dropped 0 on negative `n`"); 1.770 + 1.771 + assert.deepEqual([...drop(5, xs)], 1.772 + [], 1.773 + "dropped all items"); 1.774 + }; 1.775 + 1.776 + testDrop([1, 2, 3, 4]); 1.777 + testDrop(seq(function*() { 1.778 + yield 1; 1.779 + yield 2; 1.780 + yield 3; 1.781 + yield 4; 1.782 + })); 1.783 + 1.784 + assert.throws(() => [...drop(1, broken)], 1.785 + /Boom/, 1.786 + "sequence errors propagate"); 1.787 +}; 1.788 + 1.789 + 1.790 +exports["test dropWhile"] = assert => { 1.791 + let isNegative = x => x < 0; 1.792 + let True = _ => true; 1.793 + let False = _ => false; 1.794 + 1.795 + let test = xs => { 1.796 + assert.deepEqual([...dropWhile(isNegative, xs)], 1.797 + [0, 1, 2], 1.798 + "dropped negative"); 1.799 + 1.800 + assert.deepEqual([...dropWhile(True, xs)], 1.801 + [], 1.802 + "drop all"); 1.803 + 1.804 + assert.deepEqual([...dropWhile(False, xs)], 1.805 + [-2, -1, 0, 1, 2], 1.806 + "keep all"); 1.807 + }; 1.808 + 1.809 + test([-2, -1, 0, 1, 2]); 1.810 + test(seq(function*() { 1.811 + yield -2; 1.812 + yield -1; 1.813 + yield 0; 1.814 + yield 1; 1.815 + yield 2; 1.816 + })); 1.817 + 1.818 + assert.throws(() => [...dropWhile(boom, [1, 2, 3])], 1.819 + /Boom/, 1.820 + "function errors errors propagate"); 1.821 + assert.throws(() => [...dropWhile(x => true, broken)], 1.822 + /Boom/, 1.823 + "sequence errors propagate"); 1.824 +}; 1.825 + 1.826 + 1.827 +exports["test concat"] = assert => { 1.828 + let test = (a, b, c, d) => { 1.829 + assert.deepEqual([...concat()], 1.830 + [], 1.831 + "nothing to concat"); 1.832 + assert.deepEqual([...concat(a)], 1.833 + [1, 2, 3], 1.834 + "concat with nothing returns same as first"); 1.835 + assert.deepEqual([...concat(a, b)], 1.836 + [1, 2, 3, 4, 5], 1.837 + "concat items from both"); 1.838 + assert.deepEqual([...concat(a, b, a)], 1.839 + [1, 2, 3, 4, 5, 1, 2, 3], 1.840 + "concat itself"); 1.841 + assert.deepEqual([...concat(c)], 1.842 + [], 1.843 + "concat of empty is empty"); 1.844 + assert.deepEqual([...concat(a, c)], 1.845 + [1, 2, 3], 1.846 + "concat with empty"); 1.847 + assert.deepEqual([...concat(c, c, c)], 1.848 + [], 1.849 + "concat of empties is empty"); 1.850 + assert.deepEqual([...concat(c, b)], 1.851 + [4, 5], 1.852 + "empty can be in front"); 1.853 + assert.deepEqual([...concat(d)], 1.854 + [7], 1.855 + "concat singular"); 1.856 + assert.deepEqual([...concat(d, d)], 1.857 + [7, 7], 1.858 + "concat singulars"); 1.859 + 1.860 + assert.deepEqual([...concat(a, a, b, c, d, c, d, d)], 1.861 + [1, 2, 3, 1, 2, 3, 4, 5, 7, 7, 7], 1.862 + "many concats"); 1.863 + 1.864 + let ab = concat(a, b); 1.865 + let abcd = concat(ab, concat(c, d)); 1.866 + let cdabcd = concat(c, d, abcd); 1.867 + 1.868 + assert.deepEqual([...cdabcd], 1.869 + [7, 1, 2, 3, 4, 5, 7], 1.870 + "nested concats"); 1.871 + }; 1.872 + 1.873 + test([1, 2, 3], 1.874 + [4, 5], 1.875 + [], 1.876 + [7]); 1.877 + 1.878 + test(seq(function*() { yield 1; yield 2; yield 3; }), 1.879 + seq(function*() { yield 4; yield 5; }), 1.880 + seq(function*() { }), 1.881 + seq(function*() { yield 7; })); 1.882 + 1.883 + assert.throws(() => [...concat(broken, [1, 2, 3])], 1.884 + /Boom/, 1.885 + "function errors errors propagate"); 1.886 +}; 1.887 + 1.888 + 1.889 +exports["test first"] = assert => { 1.890 + let test = (xs, empty) => { 1.891 + assert.equal(first(xs), 1, "returns first"); 1.892 + assert.equal(first(empty), null, "returns null empty"); 1.893 + }; 1.894 + 1.895 + test("1234", ""); 1.896 + test([1, 2, 3], []); 1.897 + test([1, 2, 3], null); 1.898 + test([1, 2, 3], undefined); 1.899 + test(seq(function*() { yield 1; yield 2; yield 3; }), 1.900 + seq(function*() { })); 1.901 + assert.equal(first(broken), 1, "did not reached error"); 1.902 +}; 1.903 + 1.904 +exports["test rest"] = assert => { 1.905 + let test = (xs, x, nil) => { 1.906 + assert.deepEqual([...rest(xs)], ["b", "c"], 1.907 + "rest items"); 1.908 + assert.deepEqual([...rest(x)], [], 1.909 + "empty when singular"); 1.910 + assert.deepEqual([...rest(nil)], [], 1.911 + "empty when empty"); 1.912 + }; 1.913 + 1.914 + test("abc", "a", ""); 1.915 + test(["a", "b", "c"], ["d"], []); 1.916 + test(seq(function*() { yield "a"; yield "b"; yield "c"; }), 1.917 + seq(function*() { yield "d"; }), 1.918 + seq(function*() {})); 1.919 + test(["a", "b", "c"], ["d"], null); 1.920 + test(["a", "b", "c"], ["d"], undefined); 1.921 + 1.922 + assert.throws(() => [...rest(broken)], 1.923 + /Boom/, 1.924 + "sequence errors propagate"); 1.925 +}; 1.926 + 1.927 + 1.928 +exports["test nth"] = assert => { 1.929 + let notFound = {}; 1.930 + let test = xs => { 1.931 + assert.equal(nth(xs, 0), "h", "first"); 1.932 + assert.equal(nth(xs, 1), "e", "second"); 1.933 + assert.equal(nth(xs, 5), void(0), "out of bound"); 1.934 + assert.equal(nth(xs, 5, notFound), notFound, "out of bound"); 1.935 + assert.equal(nth(xs, -1), void(0), "out of bound"); 1.936 + assert.equal(nth(xs, -1, notFound), notFound, "out of bound"); 1.937 + assert.equal(nth(xs, 4), "o", "5th"); 1.938 + }; 1.939 + 1.940 + let testEmpty = xs => { 1.941 + assert.equal(nth(xs, 0), void(0), "no first in empty"); 1.942 + assert.equal(nth(xs, 5), void(0), "no 5th in empty"); 1.943 + assert.equal(nth(xs, 0, notFound), notFound, "notFound on out of bound"); 1.944 + }; 1.945 + 1.946 + test("hello"); 1.947 + test(["h", "e", "l", "l", "o"]); 1.948 + test(seq(function*() { 1.949 + yield "h"; 1.950 + yield "e"; 1.951 + yield "l"; 1.952 + yield "l"; 1.953 + yield "o"; 1.954 + })); 1.955 + testEmpty(null); 1.956 + testEmpty(undefined); 1.957 + testEmpty([]); 1.958 + testEmpty(""); 1.959 + testEmpty(seq(function*() {})); 1.960 + 1.961 + 1.962 + assert.throws(() => nth(broken, 1), 1.963 + /Boom/, 1.964 + "sequence errors propagate"); 1.965 + assert.equal(nth(broken, 0), 1, "have not reached error"); 1.966 +}; 1.967 + 1.968 + 1.969 +exports["test last"] = assert => { 1.970 + assert.equal(last(null), null, "no last in null"); 1.971 + assert.equal(last(void(0)), null, "no last in undefined"); 1.972 + assert.equal(last([]), null, "no last in []"); 1.973 + assert.equal(last(""), null, "no last in ''"); 1.974 + assert.equal(last(seq(function*() { })), null, "no last in empty"); 1.975 + 1.976 + assert.equal(last("hello"), "o", "last from string"); 1.977 + assert.equal(last([1, 2, 3]), 3, "last from array"); 1.978 + assert.equal(last([1]), 1, "last from singular"); 1.979 + assert.equal(last(seq(function*() { 1.980 + yield 1; 1.981 + yield 2; 1.982 + yield 3; 1.983 + })), 3, "last from sequence"); 1.984 + 1.985 + assert.throws(() => last(broken), 1.986 + /Boom/, 1.987 + "sequence errors propagate"); 1.988 +}; 1.989 + 1.990 + 1.991 +exports["test dropLast"] = assert => { 1.992 + let test = xs => { 1.993 + assert.deepEqual([...dropLast(xs)], 1.994 + [1, 2, 3, 4], 1.995 + "dropped last"); 1.996 + assert.deepEqual([...dropLast(0, xs)], 1.997 + [1, 2, 3, 4, 5], 1.998 + "dropped none on 0"); 1.999 + assert.deepEqual([...dropLast(-3, xs)], 1.1000 + [1, 2, 3, 4, 5], 1.1001 + "drop none on negative"); 1.1002 + assert.deepEqual([...dropLast(3, xs)], 1.1003 + [1, 2], 1.1004 + "dropped given number"); 1.1005 + assert.deepEqual([...dropLast(5, xs)], 1.1006 + [], 1.1007 + "dropped all"); 1.1008 + }; 1.1009 + 1.1010 + let testEmpty = xs => { 1.1011 + assert.deepEqual([...dropLast(xs)], 1.1012 + [], 1.1013 + "nothing to drop"); 1.1014 + assert.deepEqual([...dropLast(0, xs)], 1.1015 + [], 1.1016 + "dropped none on 0"); 1.1017 + assert.deepEqual([...dropLast(-3, xs)], 1.1018 + [], 1.1019 + "drop none on negative"); 1.1020 + assert.deepEqual([...dropLast(3, xs)], 1.1021 + [], 1.1022 + "nothing to drop"); 1.1023 + }; 1.1024 + 1.1025 + test([1, 2, 3, 4, 5]); 1.1026 + test(seq(function*() { 1.1027 + yield 1; 1.1028 + yield 2; 1.1029 + yield 3; 1.1030 + yield 4; 1.1031 + yield 5; 1.1032 + })); 1.1033 + testEmpty([]); 1.1034 + testEmpty(""); 1.1035 + testEmpty(seq(function*() {})); 1.1036 + 1.1037 + assert.throws(() => [...dropLast(broken)], 1.1038 + /Boom/, 1.1039 + "sequence errors propagate"); 1.1040 +}; 1.1041 + 1.1042 + 1.1043 +exports["test distinct"] = assert => { 1.1044 + let test = (xs, message) => { 1.1045 + assert.deepEqual([...distinct(xs)], 1.1046 + [1, 2, 3, 4, 5], 1.1047 + message); 1.1048 + }; 1.1049 + 1.1050 + test([1, 2, 1, 3, 1, 4, 1, 5], "works with arrays"); 1.1051 + test(seq(function*() { 1.1052 + yield 1; 1.1053 + yield 2; 1.1054 + yield 1; 1.1055 + yield 3; 1.1056 + yield 1; 1.1057 + yield 4; 1.1058 + yield 1; 1.1059 + yield 5; 1.1060 + }), "works with sequences"); 1.1061 + test(new Set([1, 2, 1, 3, 1, 4, 1, 5]), 1.1062 + "works with sets"); 1.1063 + test(seq(function*() { 1.1064 + yield 1; 1.1065 + yield 2; 1.1066 + yield 2; 1.1067 + yield 2; 1.1068 + yield 1; 1.1069 + yield 3; 1.1070 + yield 1; 1.1071 + yield 4; 1.1072 + yield 4; 1.1073 + yield 4; 1.1074 + yield 1; 1.1075 + yield 5; 1.1076 + }), "works with multiple repeatitions"); 1.1077 + test([1, 2, 3, 4, 5], "work with distinct arrays"); 1.1078 + test(seq(function*() { 1.1079 + yield 1; 1.1080 + yield 2; 1.1081 + yield 3; 1.1082 + yield 4; 1.1083 + yield 5; 1.1084 + }), "works with distinct seqs"); 1.1085 +}; 1.1086 + 1.1087 + 1.1088 +exports["test remove"] = assert => { 1.1089 + let isPositive = x => x > 0; 1.1090 + let test = xs => { 1.1091 + assert.deepEqual([...remove(isPositive, xs)], 1.1092 + [-2, -1, 0], 1.1093 + "removed positives"); 1.1094 + }; 1.1095 + 1.1096 + test([1, -2, 2, -1, 3, 7, 0]); 1.1097 + test(seq(function*() { 1.1098 + yield 1; 1.1099 + yield -2; 1.1100 + yield 2; 1.1101 + yield -1; 1.1102 + yield 3; 1.1103 + yield 7; 1.1104 + yield 0; 1.1105 + })); 1.1106 + 1.1107 + assert.throws(() => [...distinct(broken)], 1.1108 + /Boom/, 1.1109 + "sequence errors propagate"); 1.1110 +}; 1.1111 + 1.1112 + 1.1113 +exports["test mapcat"] = assert => { 1.1114 + let upto = n => seq(function* () { 1.1115 + let index = 0; 1.1116 + while (index < n) { 1.1117 + yield index; 1.1118 + index = index + 1; 1.1119 + } 1.1120 + }); 1.1121 + 1.1122 + assert.deepEqual([...mapcat(upto, [1, 2, 3, 4])], 1.1123 + [0, 0, 1, 0, 1, 2, 0, 1, 2, 3], 1.1124 + "expands given sequence"); 1.1125 + 1.1126 + assert.deepEqual([...mapcat(upto, [0, 1, 2, 0])], 1.1127 + [0, 0, 1], 1.1128 + "expands given sequence"); 1.1129 + 1.1130 + assert.deepEqual([...mapcat(upto, [0, 0, 0])], 1.1131 + [], 1.1132 + "expands given sequence"); 1.1133 + 1.1134 + assert.deepEqual([...mapcat(upto, [])], 1.1135 + [], 1.1136 + "nothing to expand"); 1.1137 + 1.1138 + assert.deepEqual([...mapcat(upto, null)], 1.1139 + [], 1.1140 + "nothing to expand"); 1.1141 + 1.1142 + assert.deepEqual([...mapcat(upto, void(0))], 1.1143 + [], 1.1144 + "nothing to expand"); 1.1145 + 1.1146 + let xs = seq(function*() { 1.1147 + yield 0; 1.1148 + yield 1; 1.1149 + yield 0; 1.1150 + yield 2; 1.1151 + yield 0; 1.1152 + }); 1.1153 + 1.1154 + assert.deepEqual([...mapcat(upto, xs)], 1.1155 + [0, 0, 1], 1.1156 + "expands given sequence"); 1.1157 + 1.1158 + assert.throws(() => [...mapcat(boom, xs)], 1.1159 + /Boom/, 1.1160 + "function errors errors propagate"); 1.1161 + assert.throws(() => [...mapcat(upto, broken)], 1.1162 + /Boom/, 1.1163 + "sequence errors propagate"); 1.1164 +}; 1.1165 + 1.1166 +require("sdk/test").run(exports);