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