1 // ♓🌟 Piscēs ∷ iterable.test.js 
   2 // ==================================================================== 
   4 // Copyright © 2023 Lady [@ Lady’s Computer]. 
   6 // This Source Code Form is subject to the terms of the Mozilla Public 
   7 // License, v. 2.0. If a copy of the MPL was not distributed with this 
   8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>. 
  16 } from "./dev-deps.js"; 
  18   arrayIteratorFunction
, 
  19   generatorIteratorFunction
, 
  22   stringIteratorFunction
, 
  23 } from "./iterable.js"; 
  25 describe("arrayIteratorFunction", () => { 
  26   it("[[Call]] returns a function", () => { 
  27     assertStrictEquals(typeof arrayIteratorFunction(), "function"); 
  30   it("[[Call]] returns a value which has a prototype of %FunctionPrototype%", () => { 
  32       Object
.getPrototypeOf(arrayIteratorFunction()), 
  37   describe("()", () => { 
  38     it("[[Call]] returns a value which inherits from %IteratorPrototype%", () => { 
  39       const iteratorProto 
= Object
.getPrototypeOf( 
  40         Object
.getPrototypeOf([][Symbol
.iterator
]), 
  42       const iterator 
= arrayIteratorFunction(); 
  44         iterator([]) instanceof Object
.assign( 
  46           { prototype: iteratorProto 
}, 
  52     it("[[Call]] returns a value with the provided string tag", () => { 
  53       const iterator 
= arrayIteratorFunction(null, "My Iterator"); 
  55         iterator([])[Symbol
.toStringTag
], 
  60     it("[[Call]] yields the values", () => { 
  61       const iterator 
= arrayIteratorFunction(); 
  63         [...iterator(["etaoin", "shrdlu"])], 
  68     it("[[Call]] maps the values", () => { 
  69       const iterator 
= arrayIteratorFunction(function* ($) { 
  70         yield $.toUpperCase(); 
  73         [...iterator(["etaoin", "shrdlu"])], 
  78     it("[[Call]] can map to nothing", () => { 
  79       const iterator 
= arrayIteratorFunction(function* () {}); 
  81         [...iterator(["etaoin", "shrdlu"])], 
  86     it("[[Call]] can map to multiple values", () => { 
  87       const iterator 
= arrayIteratorFunction(function* ($) { 
  91         [...iterator(["etaoin", "shrdlu"])], 
  96     it("[[Call]] throws if not provided with any arguments", () => { 
  97       const iterator 
= arrayIteratorFunction(); 
 103     it("[[Call]] throws if not provided an arraylike", () => { 
 104       const iterator 
= arrayIteratorFunction(); 
 110     describe("::next", () => { 
 111       it("[[Call]] throws if there are values and the mapper is not a generator function", () => { 
 112         const iterator 
= arrayIteratorFunction(function () {}); 
 114           iterator(["etaoin"]).next(); 
 121 describe("generatorIteratorFunction", () => { 
 122   it("[[Call]] returns a function", () => { 
 123     assertStrictEquals(typeof generatorIteratorFunction(), "function"); 
 126   it("[[Call]] returns a value which has a prototype of %FunctionPrototype%", () => { 
 128       Object
.getPrototypeOf(generatorIteratorFunction()), 
 133   describe("()", () => { 
 134     it("[[Call]] returns a value which inherits from %IteratorPrototype%", () => { 
 135       const iteratorProto 
= Object
.getPrototypeOf( 
 136         Object
.getPrototypeOf([][Symbol
.iterator
]), 
 138       const iterator 
= generatorIteratorFunction(); 
 140         iterator(function* () {}) instanceof Object
.assign( 
 142           { prototype: iteratorProto 
}, 
 148     it("[[Call]] returns a value with the provided string tag", () => { 
 149       const iterator 
= generatorIteratorFunction(null, "My Iterator"); 
 151         iterator(function* () {})[Symbol
.toStringTag
], 
 156     it("[[Call]] yields the values", () => { 
 157       const generator 
= function* () { 
 158         yield* ["etaoin", "shrdlu"]; 
 160       const iterator 
= generatorIteratorFunction(); 
 162         [...iterator(generator
)], 
 163         ["etaoin", "shrdlu"], 
 167     it("[[Call]] maps the values", () => { 
 168       const generator 
= function* () { 
 169         yield* ["etaoin", "shrdlu"]; 
 171       const iterator 
= generatorIteratorFunction(function* ($) { 
 172         yield $.toUpperCase(); 
 175         [...iterator(generator
)], 
 176         ["ETAOIN", "SHRDLU"], 
 180     it("[[Call]] can map to nothing", () => { 
 181       const generator 
= function* () { 
 182         yield* ["etaoin", "shrdlu"]; 
 184       const iterator 
= generatorIteratorFunction(function* () {}); 
 186         [...iterator(generator
)], 
 191     it("[[Call]] can map to multiple values", () => { 
 192       const generator 
= function* () { 
 193         yield* ["etaoin", "shrdlu"]; 
 195       const iterator 
= generatorIteratorFunction(function* ($) { 
 199         [...iterator(generator
)], 
 204     it("[[Call]] throws if not provided with any arguments", () => { 
 205       const iterator 
= generatorIteratorFunction(); 
 211     it("[[Call]] throws if not provided a function", () => { 
 212       const iterator 
= generatorIteratorFunction(); 
 218     describe("::next", () => { 
 219       it("[[Call]] throws if there are values and the mapper is not a generator function", () => { 
 220         const generator 
= function* () { 
 223         const iterator 
= generatorIteratorFunction(function () {}); 
 225           iterator(generator
).next(); 
 229       it("[[Call]] throws if not constructed with a generator function", () => { 
 230         const iterator 
= generatorIteratorFunction(); 
 232           iterator(Array
.prototype[Symbol
.iterator
].bind([])).next(); 
 239 describe("mapIteratorFunction", () => { 
 240   it("[[Call]] returns a function", () => { 
 241     assertStrictEquals(typeof mapIteratorFunction(), "function"); 
 244   it("[[Call]] returns a value which has a prototype of %FunctionPrototype%", () => { 
 246       Object
.getPrototypeOf(mapIteratorFunction()), 
 251   describe("()", () => { 
 252     it("[[Call]] returns a value which inherits from %IteratorPrototype%", () => { 
 253       const iteratorProto 
= Object
.getPrototypeOf( 
 254         Object
.getPrototypeOf([][Symbol
.iterator
]), 
 256       const iterator 
= mapIteratorFunction(); 
 258         iterator(new Map()) instanceof Object
.assign( 
 260           { prototype: iteratorProto 
}, 
 266     it("[[Call]] returns a value with the provided string tag", () => { 
 267       const iterator 
= mapIteratorFunction(null, "My Iterator"); 
 269         iterator(new Map())[Symbol
.toStringTag
], 
 274     it("[[Call]] yields the values", () => { 
 275       const iterator 
= mapIteratorFunction(); 
 277         [...iterator(new Map([["etaoin", "shrdlu"]]))], 
 278         [["etaoin", "shrdlu"]], 
 282     it("[[Call]] maps the values", () => { 
 283       const iterator 
= mapIteratorFunction(function* ([k
, v
]) { 
 284         yield [k
.toUpperCase(), v
.toUpperCase()]; 
 287         [...iterator(new Map([["etaoin", "shrdlu"]]))], 
 288         [["ETAOIN", "SHRDLU"]], 
 292     it("[[Call]] can map to nothing", () => { 
 293       const iterator 
= mapIteratorFunction(function* () {}); 
 295         [...iterator(new Map([["etaoin", "shrdlu"]]))], 
 300     it("[[Call]] can map to multiple values", () => { 
 301       const iterator 
= mapIteratorFunction(function* ($) { 
 305         [...iterator(new Map([["etaoin", "shrdlu"]]))], 
 306         ["etaoin", "shrdlu"], 
 310     it("[[Call]] throws if not provided with any arguments", () => { 
 311       const iterator 
= mapIteratorFunction(); 
 317     it("[[Call]] throws if not provided a map", () => { 
 318       const iterator 
= mapIteratorFunction(); 
 324     describe("::next", () => { 
 325       it("[[Call]] throws if there are values and the mapper is not a generator function", () => { 
 326         const iterator 
= mapIteratorFunction(function () {}); 
 328           iterator(new Map([["etaoin", "shrdlu"]])).next(); 
 335 describe("setIteratorFunction", () => { 
 336   it("[[Call]] returns a function", () => { 
 337     assertStrictEquals(typeof setIteratorFunction(), "function"); 
 340   it("[[Call]] returns a value which has a prototype of %FunctionPrototype%", () => { 
 342       Object
.getPrototypeOf(setIteratorFunction()), 
 347   describe("()", () => { 
 348     it("[[Call]] returns a value which inherits from %IteratorPrototype%", () => { 
 349       const iteratorProto 
= Object
.getPrototypeOf( 
 350         Object
.getPrototypeOf([][Symbol
.iterator
]), 
 352       const iterator 
= setIteratorFunction(); 
 354         iterator(new Set()) instanceof Object
.assign( 
 356           { prototype: iteratorProto 
}, 
 362     it("[[Call]] returns a value with the provided string tag", () => { 
 363       const iterator 
= setIteratorFunction(null, "My Iterator"); 
 365         iterator(new Set())[Symbol
.toStringTag
], 
 370     it("[[Call]] yields the values", () => { 
 371       const iterator 
= setIteratorFunction(); 
 373         [...iterator(new Set(["etaoin", "shrdlu"]))], 
 374         ["etaoin", "shrdlu"], 
 378     it("[[Call]] maps the values", () => { 
 379       const iterator 
= setIteratorFunction(function* ($) { 
 380         yield $.toUpperCase(); 
 383         [...iterator(new Set(["etaoin", "shrdlu"]))], 
 384         ["ETAOIN", "SHRDLU"], 
 388     it("[[Call]] can map to nothing", () => { 
 389       const iterator 
= setIteratorFunction(function* () {}); 
 391         [...iterator(new Set(["etaoin", "shrdlu"]))], 
 396     it("[[Call]] can map to multiple values", () => { 
 397       const iterator 
= setIteratorFunction(function* ($) { 
 401         [...iterator(new Set(["etaoin", "shrdlu"]))], 
 406     it("[[Call]] throws if not provided with any arguments", () => { 
 407       const iterator 
= setIteratorFunction(); 
 413     it("[[Call]] throws if not provided a set", () => { 
 414       const iterator 
= setIteratorFunction(); 
 420     describe("::next", () => { 
 421       it("[[Call]] throws if there are values and the mapper is not a generator function", () => { 
 422         const iterator 
= setIteratorFunction(function () {}); 
 424           iterator(new Set(["etaoin"])).next(); 
 431 describe("stringIteratorFunction", () => { 
 432   it("[[Call]] returns a function", () => { 
 433     assertStrictEquals(typeof stringIteratorFunction(), "function"); 
 436   it("[[Call]] returns a value which has a prototype of %FunctionPrototype%", () => { 
 438       Object
.getPrototypeOf(stringIteratorFunction()), 
 443   describe("()", () => { 
 444     it("[[Call]] returns a value which inherits from %IteratorPrototype%", () => { 
 445       const iteratorProto 
= Object
.getPrototypeOf( 
 446         Object
.getPrototypeOf([][Symbol
.iterator
]), 
 448       const iterator 
= stringIteratorFunction(); 
 450         iterator("") instanceof Object
.assign( 
 452           { prototype: iteratorProto 
}, 
 458     it("[[Call]] returns a value with the provided string tag", () => { 
 459       const iterator 
= stringIteratorFunction(null, "My Iterator"); 
 461         iterator("")[Symbol
.toStringTag
], 
 466     it("[[Call]] yields the values", () => { 
 467       const iterator 
= stringIteratorFunction(); 
 469         [...iterator("etaoin👀")], 
 474     it("[[Call]] maps the values", () => { 
 475       const iterator 
= stringIteratorFunction(function* ($) { 
 476         yield $.toUpperCase(); 
 479         [...iterator("etaoin👀")], 
 484     it("[[Call]] can map to nothing", () => { 
 485       const iterator 
= stringIteratorFunction(function* () {}); 
 487         [...iterator("etaoin👀")], 
 492     it("[[Call]] can map to multiple values", () => { 
 493       const iterator 
= stringIteratorFunction(function* ($) { 
 498         [...iterator("etaoin👀")], 
 499         [..."eettaaooiinn👀👀"], 
 503     it("[[Call]] throws if not provided with any arguments", () => { 
 504       const iterator 
= stringIteratorFunction(); 
 510     it("[[Call]] throws if not provided something convertible to a string", () => { 
 511       const iterator 
= stringIteratorFunction(); 
 521     describe("::next", () => { 
 522       it("[[Call]] throws if there are values and the mapper is not a generator function", () => { 
 523         const iterator 
= stringIteratorFunction(function () {}); 
 525           iterator("etaoin").next();