addon-sdk/source/test/test-sequence.js

changeset 0
6474c204b198
     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);

mercurial