1 // SPDX-FileCopyrightText: 2023, 2025 Lady <https://www.ladys.computer/about/#lady>
2 // SPDX-License-Identifier: MPL-2.0
4 * ⁌ ♓🧩 Piscēs ∷ iterable.test.js
6 * Copyright © 2023, 2025 Lady [@ Ladys Computer].
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
19 } from "./dev-deps.js";
21 arrayIteratorFunction
,
22 generatorIteratorFunction
,
25 stringIteratorFunction
,
26 } from "./iterable.js";
28 describe("arrayIteratorFunction", () => {
29 it("[[Call]] returns a function", () => {
30 assertStrictEquals(typeof arrayIteratorFunction(), "function");
33 it("[[Call]] returns a value which has a prototype of %FunctionPrototype%", () => {
35 Object
.getPrototypeOf(arrayIteratorFunction()),
40 it("[[Construct]] throws an error", () => {
41 assertThrows(() => new arrayIteratorFunction());
44 describe(".length", () => {
45 it("[[Get]] returns the correct length", () => {
46 assertStrictEquals(arrayIteratorFunction
.length
, 1);
50 describe(".name", () => {
51 it("[[Get]] returns the correct name", () => {
53 arrayIteratorFunction
.name
,
54 "arrayIteratorFunction",
59 describe("()", () => {
60 it("[[Call]] returns a value which inherits from %IteratorPrototype%", () => {
61 const iteratorProto
= Object
.getPrototypeOf(
62 Object
.getPrototypeOf([][Symbol
.iterator
]),
64 const iterator
= arrayIteratorFunction();
66 iterator([]) instanceof Object
.assign(
68 { prototype: iteratorProto
},
74 it("[[Call]] returns a value with the provided string tag", () => {
75 const iterator
= arrayIteratorFunction(null, "My Iterator");
77 iterator([])[Symbol
.toStringTag
],
82 it("[[Call]] yields the values", () => {
83 const iterator
= arrayIteratorFunction();
85 [...iterator(["etaoin", "shrdlu"])],
90 it("[[Call]] maps the values", () => {
91 const iterator
= arrayIteratorFunction(function* ($) {
92 yield $.toUpperCase();
95 [...iterator(["etaoin", "shrdlu"])],
100 it("[[Call]] can map to nothing", () => {
101 const iterator
= arrayIteratorFunction(function* () {});
103 [...iterator(["etaoin", "shrdlu"])],
108 it("[[Call]] can map to multiple values", () => {
109 const iterator
= arrayIteratorFunction(function* ($) {
113 [...iterator(["etaoin", "shrdlu"])],
118 it("[[Call]] throws if not provided with any arguments", () => {
119 const iterator
= arrayIteratorFunction();
125 it("[[Call]] throws if not provided an arraylike", () => {
126 const iterator
= arrayIteratorFunction();
132 it("[[Construct]] throws an error", () => {
133 const iterator
= arrayIteratorFunction();
134 assertThrows(() => new iterator([]));
137 describe(".length", () => {
138 it("[[Get]] returns the correct length", () => {
139 assertStrictEquals(arrayIteratorFunction().length
, 1);
143 describe(".name", () => {
144 it("[[Get]] returns the correct name", () => {
146 arrayIteratorFunction().name
,
152 describe("::next", () => {
153 it("[[Call]] throws if there are values and the mapper is not a generator function", () => {
154 const iterator
= arrayIteratorFunction(function () {});
156 iterator(["etaoin"]).next();
163 describe("generatorIteratorFunction", () => {
164 it("[[Call]] returns a function", () => {
165 assertStrictEquals(typeof generatorIteratorFunction(), "function");
168 it("[[Call]] returns a value which has a prototype of %FunctionPrototype%", () => {
170 Object
.getPrototypeOf(generatorIteratorFunction()),
175 it("[[Construct]] throws an error", () => {
176 assertThrows(() => new generatorIteratorFunction());
179 describe(".length", () => {
180 it("[[Get]] returns the correct length", () => {
181 assertStrictEquals(generatorIteratorFunction
.length
, 1);
185 describe(".name", () => {
186 it("[[Get]] returns the correct name", () => {
188 generatorIteratorFunction
.name
,
189 "generatorIteratorFunction",
194 describe("()", () => {
195 it("[[Call]] returns a value which inherits from %IteratorPrototype%", () => {
196 const iteratorProto
= Object
.getPrototypeOf(
197 Object
.getPrototypeOf([][Symbol
.iterator
]),
199 const iterator
= generatorIteratorFunction();
201 iterator(function* () {}) instanceof Object
.assign(
203 { prototype: iteratorProto
},
209 it("[[Call]] returns a value with the provided string tag", () => {
210 const iterator
= generatorIteratorFunction(null, "My Iterator");
212 iterator(function* () {})[Symbol
.toStringTag
],
217 it("[[Call]] yields the values", () => {
218 const generator
= function* () {
219 yield* ["etaoin", "shrdlu"];
221 const iterator
= generatorIteratorFunction();
223 [...iterator(generator
)],
224 ["etaoin", "shrdlu"],
228 it("[[Call]] maps the values", () => {
229 const generator
= function* () {
230 yield* ["etaoin", "shrdlu"];
232 const iterator
= generatorIteratorFunction(function* ($) {
233 yield $.toUpperCase();
236 [...iterator(generator
)],
237 ["ETAOIN", "SHRDLU"],
241 it("[[Call]] can map to nothing", () => {
242 const generator
= function* () {
243 yield* ["etaoin", "shrdlu"];
245 const iterator
= generatorIteratorFunction(function* () {});
247 [...iterator(generator
)],
252 it("[[Call]] can map to multiple values", () => {
253 const generator
= function* () {
254 yield* ["etaoin", "shrdlu"];
256 const iterator
= generatorIteratorFunction(function* ($) {
260 [...iterator(generator
)],
265 it("[[Call]] throws if not provided with any arguments", () => {
266 const iterator
= generatorIteratorFunction();
272 it("[[Call]] throws if not provided a function", () => {
273 const iterator
= generatorIteratorFunction();
279 it("[[Construct]] throws an error", () => {
280 const iterator
= generatorIteratorFunction();
281 assertThrows(() => new iterator(function* () {}));
284 describe(".length", () => {
285 it("[[Get]] returns the correct length", () => {
286 assertStrictEquals(generatorIteratorFunction().length
, 1);
290 describe(".name", () => {
291 it("[[Get]] returns the correct name", () => {
293 generatorIteratorFunction().name
,
299 describe("::next", () => {
300 it("[[Call]] throws if there are values and the mapper is not a generator function", () => {
301 const generator
= function* () {
304 const iterator
= generatorIteratorFunction(function () {});
306 iterator(generator
).next();
310 it("[[Call]] throws if not constructed with a generator function", () => {
311 const iterator
= generatorIteratorFunction();
313 iterator(Array
.prototype[Symbol
.iterator
].bind([])).next();
320 describe("mapIteratorFunction", () => {
321 it("[[Call]] returns a function", () => {
322 assertStrictEquals(typeof mapIteratorFunction(), "function");
325 it("[[Call]] returns a value which has a prototype of %FunctionPrototype%", () => {
327 Object
.getPrototypeOf(mapIteratorFunction()),
332 it("[[Construct]] throws an error", () => {
333 assertThrows(() => new mapIteratorFunction());
336 describe(".length", () => {
337 it("[[Get]] returns the correct length", () => {
338 assertStrictEquals(mapIteratorFunction
.length
, 1);
342 describe(".name", () => {
343 it("[[Get]] returns the correct name", () => {
345 mapIteratorFunction
.name
,
346 "mapIteratorFunction",
351 describe("()", () => {
352 it("[[Call]] returns a value which inherits from %IteratorPrototype%", () => {
353 const iteratorProto
= Object
.getPrototypeOf(
354 Object
.getPrototypeOf([][Symbol
.iterator
]),
356 const iterator
= mapIteratorFunction();
358 iterator(new Map()) instanceof Object
.assign(
360 { prototype: iteratorProto
},
366 it("[[Call]] returns a value with the provided string tag", () => {
367 const iterator
= mapIteratorFunction(null, "My Iterator");
369 iterator(new Map())[Symbol
.toStringTag
],
374 it("[[Call]] yields the values", () => {
375 const iterator
= mapIteratorFunction();
377 [...iterator(new Map([["etaoin", "shrdlu"]]))],
378 [["etaoin", "shrdlu"]],
382 it("[[Call]] maps the values", () => {
383 const iterator
= mapIteratorFunction(function* ([k
, v
]) {
384 yield [k
.toUpperCase(), v
.toUpperCase()];
387 [...iterator(new Map([["etaoin", "shrdlu"]]))],
388 [["ETAOIN", "SHRDLU"]],
392 it("[[Call]] can map to nothing", () => {
393 const iterator
= mapIteratorFunction(function* () {});
395 [...iterator(new Map([["etaoin", "shrdlu"]]))],
400 it("[[Call]] can map to multiple values", () => {
401 const iterator
= mapIteratorFunction(function* ($) {
405 [...iterator(new Map([["etaoin", "shrdlu"]]))],
406 ["etaoin", "shrdlu"],
410 it("[[Call]] throws if not provided with any arguments", () => {
411 const iterator
= mapIteratorFunction();
417 it("[[Call]] throws if not provided a map", () => {
418 const iterator
= mapIteratorFunction();
424 it("[[Construct]] throws an error", () => {
425 const iterator
= mapIteratorFunction();
426 assertThrows(() => new iterator(new Map()));
429 describe(".length", () => {
430 it("[[Get]] returns the correct length", () => {
431 assertStrictEquals(mapIteratorFunction().length
, 1);
435 describe(".name", () => {
436 it("[[Get]] returns the correct name", () => {
438 mapIteratorFunction().name
,
444 describe("::next", () => {
445 it("[[Call]] throws if there are values and the mapper is not a generator function", () => {
446 const iterator
= mapIteratorFunction(function () {});
448 iterator(new Map([["etaoin", "shrdlu"]])).next();
455 describe("setIteratorFunction", () => {
456 it("[[Call]] returns a function", () => {
457 assertStrictEquals(typeof setIteratorFunction(), "function");
460 it("[[Call]] returns a value which has a prototype of %FunctionPrototype%", () => {
462 Object
.getPrototypeOf(setIteratorFunction()),
467 it("[[Construct]] throws an error", () => {
468 assertThrows(() => new setIteratorFunction());
471 describe(".length", () => {
472 it("[[Get]] returns the correct length", () => {
473 assertStrictEquals(setIteratorFunction
.length
, 1);
477 describe(".name", () => {
478 it("[[Get]] returns the correct name", () => {
480 setIteratorFunction
.name
,
481 "setIteratorFunction",
486 describe("()", () => {
487 it("[[Call]] returns a value which inherits from %IteratorPrototype%", () => {
488 const iteratorProto
= Object
.getPrototypeOf(
489 Object
.getPrototypeOf([][Symbol
.iterator
]),
491 const iterator
= setIteratorFunction();
493 iterator(new Set()) instanceof Object
.assign(
495 { prototype: iteratorProto
},
501 it("[[Call]] returns a value with the provided string tag", () => {
502 const iterator
= setIteratorFunction(null, "My Iterator");
504 iterator(new Set())[Symbol
.toStringTag
],
509 it("[[Call]] yields the values", () => {
510 const iterator
= setIteratorFunction();
512 [...iterator(new Set(["etaoin", "shrdlu"]))],
513 ["etaoin", "shrdlu"],
517 it("[[Call]] maps the values", () => {
518 const iterator
= setIteratorFunction(function* ($) {
519 yield $.toUpperCase();
522 [...iterator(new Set(["etaoin", "shrdlu"]))],
523 ["ETAOIN", "SHRDLU"],
527 it("[[Call]] can map to nothing", () => {
528 const iterator
= setIteratorFunction(function* () {});
530 [...iterator(new Set(["etaoin", "shrdlu"]))],
535 it("[[Call]] can map to multiple values", () => {
536 const iterator
= setIteratorFunction(function* ($) {
540 [...iterator(new Set(["etaoin", "shrdlu"]))],
545 it("[[Call]] throws if not provided with any arguments", () => {
546 const iterator
= setIteratorFunction();
552 it("[[Call]] throws if not provided a set", () => {
553 const iterator
= setIteratorFunction();
559 it("[[Construct]] throws an error", () => {
560 const iterator
= setIteratorFunction();
561 assertThrows(() => new iterator(new Set()));
564 describe(".length", () => {
565 it("[[Get]] returns the correct length", () => {
566 assertStrictEquals(setIteratorFunction().length
, 1);
570 describe(".name", () => {
571 it("[[Get]] returns the correct name", () => {
573 setIteratorFunction().name
,
579 describe("::next", () => {
580 it("[[Call]] throws if there are values and the mapper is not a generator function", () => {
581 const iterator
= setIteratorFunction(function () {});
583 iterator(new Set(["etaoin"])).next();
590 describe("stringIteratorFunction", () => {
591 it("[[Call]] returns a function", () => {
592 assertStrictEquals(typeof stringIteratorFunction(), "function");
595 it("[[Call]] returns a value which has a prototype of %FunctionPrototype%", () => {
597 Object
.getPrototypeOf(stringIteratorFunction()),
602 it("[[Construct]] throws an error", () => {
603 assertThrows(() => new stringIteratorFunction());
606 describe(".length", () => {
607 it("[[Get]] returns the correct length", () => {
608 assertStrictEquals(stringIteratorFunction
.length
, 1);
612 describe(".name", () => {
613 it("[[Get]] returns the correct name", () => {
615 stringIteratorFunction
.name
,
616 "stringIteratorFunction",
621 describe("()", () => {
622 it("[[Call]] returns a value which inherits from %IteratorPrototype%", () => {
623 const iteratorProto
= Object
.getPrototypeOf(
624 Object
.getPrototypeOf([][Symbol
.iterator
]),
626 const iterator
= stringIteratorFunction();
628 iterator("") instanceof Object
.assign(
630 { prototype: iteratorProto
},
636 it("[[Call]] returns a value with the provided string tag", () => {
637 const iterator
= stringIteratorFunction(null, "My Iterator");
639 iterator("")[Symbol
.toStringTag
],
644 it("[[Call]] yields the values", () => {
645 const iterator
= stringIteratorFunction();
647 [...iterator("etaoin👀")],
652 it("[[Call]] maps the values", () => {
653 const iterator
= stringIteratorFunction(function* ($) {
654 yield $.toUpperCase();
657 [...iterator("etaoin👀")],
662 it("[[Call]] can map to nothing", () => {
663 const iterator
= stringIteratorFunction(function* () {});
665 [...iterator("etaoin👀")],
670 it("[[Call]] can map to multiple values", () => {
671 const iterator
= stringIteratorFunction(function* ($) {
676 [...iterator("etaoin👀")],
677 [..."eettaaooiinn👀👀"],
681 it("[[Call]] throws if not provided with any arguments", () => {
682 const iterator
= stringIteratorFunction();
688 it("[[Call]] throws if not provided something convertible to a string", () => {
689 const iterator
= stringIteratorFunction();
699 it("[[Construct]] throws an error", () => {
700 const iterator
= stringIteratorFunction();
701 assertThrows(() => new iterator(""));
704 describe(".length", () => {
705 it("[[Get]] returns the correct length", () => {
706 assertStrictEquals(stringIteratorFunction().length
, 1);
710 describe(".name", () => {
711 it("[[Get]] returns the correct name", () => {
713 stringIteratorFunction().name
,
719 describe("::next", () => {
720 it("[[Call]] throws if there are values and the mapper is not a generator function", () => {
721 const iterator
= stringIteratorFunction(function () {});
723 iterator("etaoin").next();