]> Lady’s Gitweb - Pisces/blob - string.test.js
Add denseProxy, various collection.js improvements
[Pisces] / string.test.js
1 // SPDX-FileCopyrightText: 2022, 2023, 2025 Lady <https://www.ladys.computer/about/#lady>
2 // SPDX-License-Identifier: MPL-2.0
3 /**
4 * ⁌ ♓🧩 Piscēs ∷ string.test.js
5 *
6 * Copyright © 2022–2023, 2025 Lady [@ Ladys Computer].
7 *
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/>.
11 */
12
13 import {
14 assert,
15 assertEquals,
16 assertSpyCalls,
17 assertStrictEquals,
18 assertThrows,
19 describe,
20 it,
21 spy,
22 } from "./dev-deps.js";
23 import {
24 asciiLowercase,
25 asciiUppercase,
26 characters,
27 codepoints,
28 codeUnits,
29 getCharacter,
30 getCodepoint,
31 getCodeUnit,
32 getFirstSubstringIndex,
33 getLastSubstringIndex,
34 join,
35 Matcher,
36 rawString,
37 scalarValues,
38 splitOnAsciiWhitespace,
39 splitOnCommas,
40 stringCatenate,
41 stringEndsWith,
42 stringFromCodepoints,
43 stringFromCodeUnits,
44 stringIncludes,
45 stringMatch,
46 stringMatchAll,
47 stringNormalize,
48 stringPadEnd,
49 stringPadStart,
50 stringRepeat,
51 stringReplace,
52 stringReplaceAll,
53 stringSearch,
54 stringSlice,
55 stringSplit,
56 stringStartsWith,
57 stringValue,
58 stripAndCollapseAsciiWhitespace,
59 stripLeadingAndTrailingAsciiWhitespace,
60 substring,
61 toScalarValueString,
62 toString,
63 } from "./string.js";
64
65 describe("Matcher", () => {
66 it("[[Call]] throws an error", () => {
67 assertThrows(() => Matcher(""));
68 });
69
70 it("[[Construct]] accepts a string first argument", () => {
71 assert(new Matcher(""));
72 });
73
74 it("[[Construct]] accepts a unicode regular expression first argument", () => {
75 assert(new Matcher(/(?:)/u));
76 });
77
78 it("[[Construct]] accepts a unicode sets regular expression first argument", () => {
79 assert(new Matcher(/(?:)/v));
80 });
81
82 it("[[Construct]] throws with a non·unicode·aware regular expression first argument", () => {
83 assertThrows(() => new Matcher(/(?:)/));
84 });
85
86 it("[[Construct]] creates a callable object", () => {
87 assertStrictEquals(typeof new Matcher(""), "function");
88 });
89
90 it("[[Construct]] creates a new Matcher", () => {
91 assertStrictEquals(
92 Object.getPrototypeOf(new Matcher("")),
93 Matcher.prototype,
94 );
95 });
96
97 it("[[Construct]] creates an object which inherits from RegExp", () => {
98 assert(new Matcher("") instanceof RegExp);
99 });
100
101 it("[[Construct]] throws when provided with a noncallable, non·null third argument", () => {
102 assertThrows(() => new Matcher("", undefined, "failure"));
103 });
104
105 describe(".length", () => {
106 it("[[Get]] returns the correct length", () => {
107 assertStrictEquals(Matcher.length, 1);
108 });
109 });
110
111 describe(".name", () => {
112 it("[[Get]] returns the correct name", () => {
113 assertStrictEquals(Matcher.name, "Matcher");
114 });
115 });
116
117 describe("::constructor", () => {
118 it("[[Get]] returns the same constructor", () => {
119 assertStrictEquals(new Matcher(/(?:)/su).constructor, Matcher);
120 });
121 });
122
123 describe("::dotAll", () => {
124 it("[[Get]] returns true when the dotAll flag is present", () => {
125 assertStrictEquals(new Matcher(/(?:)/su).dotAll, true);
126 });
127
128 it("[[Get]] returns false when the dotAll flag is not present", () => {
129 assertStrictEquals(new Matcher(/(?:)/u).dotAll, false);
130 });
131
132 describe("[[GetOwnProperty]].get.length", () => {
133 it("[[Get]] returns the correct length", () => {
134 assertStrictEquals(
135 Object.getOwnPropertyDescriptor(
136 Matcher.prototype,
137 "dotAll",
138 ).get.length,
139 0,
140 );
141 });
142 });
143
144 describe("[[GetOwnProperty]].get.name", () => {
145 it("[[Get]] returns the correct name", () => {
146 assertStrictEquals(
147 Object.getOwnPropertyDescriptor(
148 Matcher.prototype,
149 "dotAll",
150 ).get.name,
151 "get dotAll",
152 );
153 });
154 });
155 });
156
157 describe("::exec", () => {
158 it("[[Call]] returns the match object given a complete match", () => {
159 assertEquals(
160 [...new Matcher(/.(?<wow>(?:.(?=.))*)(.)?/u).exec("success")],
161 ["success", "ucces", "s"],
162 );
163 assertEquals(
164 [...new Matcher(
165 /.(?<wow>(?:.(?=.))*)(.)?/u,
166 undefined,
167 ($) => $ === "success",
168 ).exec("success")],
169 ["success", "ucces", "s"],
170 );
171 });
172
173 it("[[Call]] calls the constraint if the match succeeds", () => {
174 const constraint = spy((_) => true);
175 const matcher = new Matcher("(.).*", undefined, constraint);
176 const result = matcher.exec({
177 toString() {
178 return "etaoin";
179 },
180 });
181 assertEquals([...result], ["etaoin", "e"]);
182 assertSpyCalls(constraint, 1);
183 assertStrictEquals(constraint.calls[0].args[0], "etaoin");
184 assertEquals([...constraint.calls[0].args[1]], ["etaoin", "e"]);
185 assertStrictEquals(constraint.calls[0].args[2], matcher);
186 assertStrictEquals(constraint.calls[0].self, undefined);
187 });
188
189 it("[[Call]] does not call the constraint if the match fails", () => {
190 const constraint = spy((_) => true);
191 const matcher = new Matcher("", undefined, constraint);
192 matcher.exec("failure");
193 assertSpyCalls(constraint, 0);
194 });
195
196 it("[[Call]] returns null given a partial match", () => {
197 assertStrictEquals(new Matcher("").exec("failure"), null);
198 });
199
200 it("[[Call]] returns null if the constraint fails", () => {
201 assertStrictEquals(
202 new Matcher(".*", undefined, () => false).exec(""),
203 null,
204 );
205 });
206
207 it("[[Construct]] throws an error", () => {
208 const matcher = new Matcher("");
209 assertThrows(() => new matcher.exec());
210 });
211
212 describe(".length", () => {
213 it("[[Get]] returns the correct length", () => {
214 assertStrictEquals(Matcher.prototype.exec.length, 1);
215 });
216 });
217
218 describe(".name", () => {
219 it("[[Get]] returns the correct name", () => {
220 assertStrictEquals(Matcher.prototype.exec.name, "exec");
221 });
222 });
223 });
224
225 describe("::global", () => {
226 it("[[Get]] returns true when the global flag is present", () => {
227 assertStrictEquals(new Matcher(/(?:)/gu).global, true);
228 });
229
230 it("[[Get]] returns false when the global flag is not present", () => {
231 assertStrictEquals(new Matcher(/(?:)/u).global, false);
232 });
233
234 describe("[[GetOwnProperty]].get.length", () => {
235 it("[[Get]] returns the correct length", () => {
236 assertStrictEquals(
237 Object.getOwnPropertyDescriptor(
238 Matcher.prototype,
239 "global",
240 ).get.length,
241 0,
242 );
243 });
244 });
245
246 describe("[[GetOwnProperty]].get.name", () => {
247 it("[[Get]] returns the correct name", () => {
248 assertStrictEquals(
249 Object.getOwnPropertyDescriptor(
250 Matcher.prototype,
251 "global",
252 ).get.name,
253 "get global",
254 );
255 });
256 });
257 });
258
259 describe("::hasIndices", () => {
260 it("[[Get]] returns true when the hasIndices flag is present", () => {
261 assertStrictEquals(new Matcher(/(?:)/du).hasIndices, true);
262 });
263
264 it("[[Get]] returns false when the hasIndices flag is not present", () => {
265 assertStrictEquals(new Matcher(/(?:)/u).hasIndices, false);
266 });
267
268 describe("[[GetOwnProperty]].get.length", () => {
269 it("[[Get]] returns the correct length", () => {
270 assertStrictEquals(
271 Object.getOwnPropertyDescriptor(
272 Matcher.prototype,
273 "hasIndices",
274 ).get.length,
275 0,
276 );
277 });
278 });
279
280 describe("[[GetOwnProperty]].get.name", () => {
281 it("[[Get]] returns the correct name", () => {
282 assertStrictEquals(
283 Object.getOwnPropertyDescriptor(
284 Matcher.prototype,
285 "hasIndices",
286 ).get.name,
287 "get hasIndices",
288 );
289 });
290 });
291 });
292
293 describe("::ignoreCase", () => {
294 it("[[Get]] returns true when the ignoreCase flag is present", () => {
295 assertStrictEquals(new Matcher(/(?:)/iu).ignoreCase, true);
296 });
297
298 it("[[Get]] returns false when the ignoreCase flag is not present", () => {
299 assertStrictEquals(new Matcher(/(?:)/u).ignoreCase, false);
300 });
301
302 describe("[[GetOwnProperty]].get.length", () => {
303 it("[[Get]] returns the correct length", () => {
304 assertStrictEquals(
305 Object.getOwnPropertyDescriptor(
306 Matcher.prototype,
307 "ignoreCase",
308 ).get.length,
309 0,
310 );
311 });
312 });
313
314 describe("[[GetOwnProperty]].get.name", () => {
315 it("[[Get]] returns the correct name", () => {
316 assertStrictEquals(
317 Object.getOwnPropertyDescriptor(
318 Matcher.prototype,
319 "ignoreCase",
320 ).get.name,
321 "get ignoreCase",
322 );
323 });
324 });
325 });
326
327 describe("::multiline", () => {
328 it("[[Get]] returns true when the multiline flag is present", () => {
329 assertStrictEquals(new Matcher(/(?:)/mu).multiline, true);
330 });
331
332 it("[[Get]] returns false when the multiline flag is not present", () => {
333 assertStrictEquals(new Matcher(/(?:)/u).multiline, false);
334 });
335
336 describe("[[GetOwnProperty]].get.length", () => {
337 it("[[Get]] returns the correct length", () => {
338 assertStrictEquals(
339 Object.getOwnPropertyDescriptor(
340 Matcher.prototype,
341 "multiline",
342 ).get.length,
343 0,
344 );
345 });
346 });
347
348 describe("[[GetOwnProperty]].get.name", () => {
349 it("[[Get]] returns the correct name", () => {
350 assertStrictEquals(
351 Object.getOwnPropertyDescriptor(
352 Matcher.prototype,
353 "multiline",
354 ).get.name,
355 "get multiline",
356 );
357 });
358 });
359 });
360
361 describe("::source", () => {
362 it("[[Get]] returns the RegExp source", () => {
363 assertStrictEquals(new Matcher("").source, "(?:)");
364 assertStrictEquals(new Matcher(/.*/su).source, ".*");
365 });
366
367 describe("[[GetOwnProperty]].get.length", () => {
368 it("[[Get]] returns the correct length", () => {
369 assertStrictEquals(
370 Object.getOwnPropertyDescriptor(
371 Matcher.prototype,
372 "source",
373 ).get.length,
374 0,
375 );
376 });
377 });
378
379 describe("[[GetOwnProperty]].get.name", () => {
380 it("[[Get]] returns the correct name", () => {
381 assertStrictEquals(
382 Object.getOwnPropertyDescriptor(
383 Matcher.prototype,
384 "source",
385 ).get.name,
386 "get source",
387 );
388 });
389 });
390 });
391
392 describe("::sticky", () => {
393 it("[[Get]] returns true when the sticky flag is present", () => {
394 assertStrictEquals(new Matcher(/(?:)/uy).sticky, true);
395 });
396
397 it("[[Get]] returns false when the sticky flag is not present", () => {
398 assertStrictEquals(new Matcher(/(?:)/u).sticky, false);
399 });
400
401 describe("[[GetOwnProperty]].get.length", () => {
402 it("[[Get]] returns the correct length", () => {
403 assertStrictEquals(
404 Object.getOwnPropertyDescriptor(
405 Matcher.prototype,
406 "sticky",
407 ).get.length,
408 0,
409 );
410 });
411 });
412
413 describe("[[GetOwnProperty]].get.name", () => {
414 it("[[Get]] returns the correct name", () => {
415 assertStrictEquals(
416 Object.getOwnPropertyDescriptor(
417 Matcher.prototype,
418 "sticky",
419 ).get.name,
420 "get sticky",
421 );
422 });
423 });
424 });
425
426 describe("::toString", () => {
427 it("[[Call]] returns the string source", () => {
428 assertStrictEquals(new Matcher(/(?:)/u).toString(), "/(?:)/u");
429 });
430
431 it("[[Construct]] throws an error", () => {
432 const matcher = new Matcher("");
433 assertThrows(() => new matcher.toString());
434 });
435
436 describe(".length", () => {
437 it("[[Get]] returns the correct length", () => {
438 assertStrictEquals(Matcher.prototype.toString.length, 0);
439 });
440 });
441
442 describe(".name", () => {
443 it("[[Get]] returns the correct name", () => {
444 assertStrictEquals(
445 Matcher.prototype.toString.name,
446 "toString",
447 );
448 });
449 });
450 });
451
452 describe("::unicode", () => {
453 it("[[Get]] returns true when the unicode flag is present", () => {
454 assertStrictEquals(new Matcher(/(?:)/u).unicode, true);
455 });
456
457 describe("[[GetOwnProperty]].get.length", () => {
458 it("[[Get]] returns the correct length", () => {
459 assertStrictEquals(
460 Object.getOwnPropertyDescriptor(
461 Matcher.prototype,
462 "unicode",
463 ).get.length,
464 0,
465 );
466 });
467 });
468
469 describe("[[GetOwnProperty]].get.name", () => {
470 it("[[Get]] returns the correct name", () => {
471 assertStrictEquals(
472 Object.getOwnPropertyDescriptor(
473 Matcher.prototype,
474 "unicode",
475 ).get.name,
476 "get unicode",
477 );
478 });
479 });
480 });
481
482 describe("::unicodeSets", () => {
483 it("[[Get]] returns true when the unicode sets flag is present", () => {
484 assertStrictEquals(new Matcher(/(?:)/v).unicodeSets, true);
485 });
486
487 describe("[[GetOwnProperty]].get.length", () => {
488 it("[[Get]] returns the correct length", () => {
489 assertStrictEquals(
490 Object.getOwnPropertyDescriptor(
491 Matcher.prototype,
492 "unicodeSets",
493 ).get.length,
494 0,
495 );
496 });
497 });
498
499 describe("[[GetOwnProperty]].get.name", () => {
500 it("[[Get]] returns the correct name", () => {
501 assertStrictEquals(
502 Object.getOwnPropertyDescriptor(
503 Matcher.prototype,
504 "unicodeSets",
505 ).get.name,
506 "get unicodeSets",
507 );
508 });
509 });
510 });
511
512 describe("~", () => {
513 it("[[Call]] returns true for a complete match", () => {
514 assertStrictEquals(new Matcher("")(""), true);
515 assertStrictEquals(new Matcher(/.*/su)("success\nyay"), true);
516 assertStrictEquals(
517 new Matcher(/.*/su, undefined, ($) => $ === "success")(
518 "success",
519 ),
520 true,
521 );
522 });
523
524 it("[[Call]] calls the constraint if the match succeeds", () => {
525 const constraint = spy((_) => true);
526 const matcher = new Matcher("(.).*", undefined, constraint);
527 matcher("etaoin");
528 assertSpyCalls(constraint, 1);
529 assertStrictEquals(constraint.calls[0].args[0], "etaoin");
530 assertEquals([...constraint.calls[0].args[1]], ["etaoin", "e"]);
531 assertStrictEquals(constraint.calls[0].args[2], matcher);
532 assertStrictEquals(constraint.calls[0].self, undefined);
533 });
534
535 it("[[Call]] does not call the constraint if the match fails", () => {
536 const constraint = spy((_) => true);
537 const matcher = new Matcher("", undefined, constraint);
538 matcher("failure");
539 assertSpyCalls(constraint, 0);
540 });
541
542 it("[[Call]] returns false for a partial match", () => {
543 assertStrictEquals(new Matcher("")("failure"), false);
544 assertStrictEquals(new Matcher(/.*/u)("failure\nno"), false);
545 });
546
547 it("[[Call]] returns false if the constraint fails", () => {
548 assertStrictEquals(
549 new Matcher(".*", undefined, () => false)(""),
550 false,
551 );
552 });
553
554 it("[[Construct]] throws an error", () => {
555 const matcher = new Matcher("");
556 assertThrows(() => new matcher(""));
557 });
558 });
559
560 describe("~lastIndex", () => {
561 it("[[Get]] returns zero", () => {
562 assertStrictEquals(new Matcher("").lastIndex, 0);
563 });
564
565 it("[[Set]] fails", () => {
566 assertThrows(() => (new Matcher("").lastIndex = 1));
567 });
568 });
569
570 describe("~length", () => {
571 it("[[Get]] returns one", () => {
572 assertStrictEquals(new Matcher("").length, 1);
573 });
574 });
575
576 describe("~name", () => {
577 it("[[Get]] wraps the stringified regular expression if no name was provided", () => {
578 assertStrictEquals(new Matcher("").name, "Matcher(/(?:)/u)");
579 assertStrictEquals(
580 new Matcher(/.*/gsu).name,
581 "Matcher(/.*/gsu)",
582 );
583 });
584
585 it("[[Get]] uses the provided name if one was provided", () => {
586 assertStrictEquals(new Matcher("", "success").name, "success");
587 });
588 });
589 });
590
591 describe("asciiLowercase", () => {
592 it("[[Call]] lowercases (just) A·S·C·I·I letters", () => {
593 assertStrictEquals(asciiLowercase("aBſÆss FtɁɂß"), "abſÆss ftɁɂß");
594 });
595
596 it("[[Construct]] throws an error", () => {
597 assertThrows(() => new asciiLowercase(""));
598 });
599
600 describe(".length", () => {
601 it("[[Get]] returns the correct length", () => {
602 assertStrictEquals(asciiLowercase.length, 1);
603 });
604 });
605
606 describe(".name", () => {
607 it("[[Get]] returns the correct name", () => {
608 assertStrictEquals(asciiLowercase.name, "asciiLowercase");
609 });
610 });
611 });
612
613 describe("asciiUppercase", () => {
614 it("[[Call]] uppercases (just) A·S·C·I·I letters", () => {
615 assertStrictEquals(asciiUppercase("aBſÆss FtɁɂß"), "ABſÆSS FTɁɂß");
616 });
617
618 it("[[Construct]] throws an error", () => {
619 assertThrows(() => new asciiUppercase(""));
620 });
621
622 describe(".length", () => {
623 it("[[Get]] returns the correct length", () => {
624 assertStrictEquals(asciiUppercase.length, 1);
625 });
626 });
627
628 describe(".name", () => {
629 it("[[Get]] returns the correct name", () => {
630 assertStrictEquals(asciiUppercase.name, "asciiUppercase");
631 });
632 });
633 });
634
635 describe("characters", () => {
636 it("[[Call]] returns an iterable", () => {
637 assertStrictEquals(
638 typeof characters("")[Symbol.iterator],
639 "function",
640 );
641 });
642
643 it("[[Call]] returns an iterator", () => {
644 assertStrictEquals(typeof characters("").next, "function");
645 });
646
647 it("[[Call]] returns a string character iterator", () => {
648 assertStrictEquals(
649 characters("")[Symbol.toStringTag],
650 "String Character Iterator",
651 );
652 });
653
654 it("[[Call]] iterates over the characters", () => {
655 assertEquals([
656 ...characters("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
657 ], [
658 "I",
659 "i",
660 "🎙",
661 "\uDFFF",
662 "\uDD96",
663 "\uD83C",
664 "\uD800",
665 "🆗",
666 "☺",
667 ]);
668 });
669
670 it("[[Construct]] throws an error", () => {
671 assertThrows(() => new characters(""));
672 });
673
674 describe(".length", () => {
675 it("[[Get]] returns the correct length", () => {
676 assertStrictEquals(characters.length, 1);
677 });
678 });
679
680 describe(".name", () => {
681 it("[[Get]] returns the correct name", () => {
682 assertStrictEquals(characters.name, "characters");
683 });
684 });
685 });
686
687 describe("codeUnits", () => {
688 it("[[Call]] returns an iterable", () => {
689 assertStrictEquals(
690 typeof codeUnits("")[Symbol.iterator],
691 "function",
692 );
693 });
694
695 it("[[Call]] returns an iterator", () => {
696 assertStrictEquals(typeof codeUnits("").next, "function");
697 });
698
699 it("[[Call]] returns a string code unit iterator", () => {
700 assertStrictEquals(
701 codeUnits("")[Symbol.toStringTag],
702 "String Code Unit Iterator",
703 );
704 });
705
706 it("[[Call]] iterates over the code units", () => {
707 assertEquals([
708 ...codeUnits("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
709 ], [
710 0x49,
711 0x69,
712 0xD83C,
713 0xDF99,
714 0xDFFF,
715 0xDD96,
716 0xD83C,
717 0xD800,
718 0xD83C,
719 0xDD97,
720 0x263A,
721 ]);
722 });
723
724 it("[[Construct]] throws an error", () => {
725 assertThrows(() => new codeUnits(""));
726 });
727
728 describe(".length", () => {
729 it("[[Get]] returns the correct length", () => {
730 assertStrictEquals(codeUnits.length, 1);
731 });
732 });
733
734 describe(".name", () => {
735 it("[[Get]] returns the correct name", () => {
736 assertStrictEquals(codeUnits.name, "codeUnits");
737 });
738 });
739 });
740
741 describe("codepoints", () => {
742 it("[[Call]] returns an iterable", () => {
743 assertStrictEquals(
744 typeof codepoints("")[Symbol.iterator],
745 "function",
746 );
747 });
748
749 it("[[Call]] returns an iterator", () => {
750 assertStrictEquals(typeof codepoints("").next, "function");
751 });
752
753 it("[[Call]] returns a string codepoint iterator", () => {
754 assertStrictEquals(
755 codepoints("")[Symbol.toStringTag],
756 "String Codepoint Iterator",
757 );
758 });
759
760 it("[[Call]] iterates over the codepoints", () => {
761 assertEquals([
762 ...codepoints("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
763 ], [
764 0x49,
765 0x69,
766 0x1F399,
767 0xDFFF,
768 0xDD96,
769 0xD83C,
770 0xD800,
771 0x1F197,
772 0x263A,
773 ]);
774 });
775
776 it("[[Construct]] throws an error", () => {
777 assertThrows(() => new codepoints(""));
778 });
779
780 describe(".length", () => {
781 it("[[Get]] returns the correct length", () => {
782 assertStrictEquals(codepoints.length, 1);
783 });
784 });
785
786 describe(".name", () => {
787 it("[[Get]] returns the correct name", () => {
788 assertStrictEquals(codepoints.name, "codepoints");
789 });
790 });
791 });
792
793 describe("getCharacter", () => {
794 it("[[Call]] returns the character at the provided position", () => {
795 assertStrictEquals(getCharacter("Ii🎙🆗☺", 4), "🆗");
796 });
797
798 it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
799 assertStrictEquals(getCharacter("Ii🎙🆗☺", 5), "\uDD97");
800 });
801
802 it("[[Call]] returns undefined for an out‐of‐bounds index", () => {
803 assertStrictEquals(getCharacter("Ii🎙🆗☺", -1), undefined);
804 assertStrictEquals(getCharacter("Ii🎙🆗☺", 7), undefined);
805 });
806
807 it("[[Construct]] throws an error", () => {
808 assertThrows(() => new getCharacter("a", 0));
809 });
810
811 describe(".length", () => {
812 it("[[Get]] returns the correct length", () => {
813 assertStrictEquals(getCharacter.length, 2);
814 });
815 });
816
817 describe(".name", () => {
818 it("[[Get]] returns the correct name", () => {
819 assertStrictEquals(getCharacter.name, "getCharacter");
820 });
821 });
822 });
823
824 describe("getCodeUnit", () => {
825 it("[[Call]] returns the code unit at the provided position", () => {
826 assertStrictEquals(getCodeUnit("Ii🎙🆗☺", 4), 0xD83C);
827 });
828
829 it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
830 assertStrictEquals(getCodeUnit("Ii🎙🆗☺", 5), 0xDD97);
831 });
832
833 it("[[Call]] returns undefined for an out‐of‐bounds index", () => {
834 assertStrictEquals(getCodeUnit("Ii🎙🆗☺", -1), undefined);
835 assertStrictEquals(getCodeUnit("Ii🎙🆗☺", 7), undefined);
836 });
837
838 it("[[Construct]] throws an error", () => {
839 assertThrows(() => new getCodeUnit("a", 0));
840 });
841
842 describe(".length", () => {
843 it("[[Get]] returns the correct length", () => {
844 assertStrictEquals(getCodeUnit.length, 2);
845 });
846 });
847
848 describe(".name", () => {
849 it("[[Get]] returns the correct name", () => {
850 assertStrictEquals(getCodeUnit.name, "getCodeUnit");
851 });
852 });
853 });
854
855 describe("getCodepoint", () => {
856 it("[[Call]] returns the character at the provided position", () => {
857 assertStrictEquals(getCodepoint("Ii🎙🆗☺", 4), 0x1F197);
858 });
859
860 it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
861 assertStrictEquals(getCodepoint("Ii🎙🆗☺", 5), 0xDD97);
862 });
863
864 it("[[Call]] returns undefined for an out‐of‐bounds index", () => {
865 assertStrictEquals(getCodepoint("Ii🎙🆗☺", -1), undefined);
866 assertStrictEquals(getCodepoint("Ii🎙🆗☺", 7), undefined);
867 });
868
869 it("[[Construct]] throws an error", () => {
870 assertThrows(() => new getCodepoint("a", 0));
871 });
872
873 describe(".length", () => {
874 it("[[Get]] returns the correct length", () => {
875 assertStrictEquals(getCodepoint.length, 2);
876 });
877 });
878
879 describe(".name", () => {
880 it("[[Get]] returns the correct name", () => {
881 assertStrictEquals(getCodepoint.name, "getCodepoint");
882 });
883 });
884 });
885
886 describe("getFirstSubstringIndex", () => {
887 it("[[Call]] returns the index of the first match", () => {
888 assertStrictEquals(getFirstSubstringIndex("Ii🎙🆗☺🆗", "🆗"), 4);
889 });
890
891 it("[[Call]] returns −1 if no match is found", () => {
892 assertStrictEquals(getFirstSubstringIndex("Ii🎙🆗☺🆗", "🆗🆖"), -1);
893 });
894
895 it("[[Call]] returns 0 when provided with an empty string", () => {
896 assertStrictEquals(getFirstSubstringIndex("Ii🎙🆗☺🆗", ""), 0);
897 });
898
899 it("[[Construct]] throws an error", () => {
900 assertThrows(() => new getFirstSubstringIndex("", ""));
901 });
902
903 describe(".length", () => {
904 it("[[Get]] returns the correct length", () => {
905 assertStrictEquals(getFirstSubstringIndex.length, 2);
906 });
907 });
908
909 describe(".name", () => {
910 it("[[Get]] returns the correct name", () => {
911 assertStrictEquals(
912 getFirstSubstringIndex.name,
913 "getFirstSubstringIndex",
914 );
915 });
916 });
917 });
918
919 describe("getLastSubstringIndex", () => {
920 it("[[Call]] returns the index of the first match", () => {
921 assertStrictEquals(getLastSubstringIndex("Ii🎙🆗☺🆗", "🆗"), 7);
922 });
923
924 it("[[Call]] returns −1 if no match is found", () => {
925 assertStrictEquals(getLastSubstringIndex("Ii🎙🆗☺🆗", "🆖🆗"), -1);
926 });
927
928 it("[[Call]] returns the length when provided with an empty string", () => {
929 assertStrictEquals(
930 getLastSubstringIndex("Ii🎙🆗☺🆗", ""),
931 "Ii🎙🆗☺🆗".length,
932 );
933 });
934
935 it("[[Construct]] throws an error", () => {
936 assertThrows(() => new getLastSubstringIndex("", ""));
937 });
938
939 describe(".length", () => {
940 it("[[Get]] returns the correct length", () => {
941 assertStrictEquals(getLastSubstringIndex.length, 2);
942 });
943 });
944
945 describe(".name", () => {
946 it("[[Get]] returns the correct name", () => {
947 assertStrictEquals(
948 getLastSubstringIndex.name,
949 "getLastSubstringIndex",
950 );
951 });
952 });
953 });
954
955 describe("join", () => {
956 it("[[Call]] joins the provided iterator with the provided separartor", () => {
957 assertStrictEquals(join([1, 2, 3, 4].values(), "☂"), "1☂2☂3☂4");
958 });
959
960 it('[[Call]] uses "," if no separator is provided', () => {
961 assertStrictEquals(join([1, 2, 3, 4].values()), "1,2,3,4");
962 });
963
964 it("[[Call]] uses the empty sting for nullish values", () => {
965 assertStrictEquals(
966 join([null, , null, undefined].values(), "☂"),
967 "☂☂☂",
968 );
969 });
970
971 it("[[Construct]] throws an error", () => {
972 assertThrows(() => new join([]));
973 });
974
975 describe(".length", () => {
976 it("[[Get]] returns the correct length", () => {
977 assertStrictEquals(join.length, 2);
978 });
979 });
980
981 describe(".name", () => {
982 it("[[Get]] returns the correct name", () => {
983 assertStrictEquals(join.name, "join");
984 });
985 });
986 });
987
988 describe("rawString", () => {
989 it("[[Call]] acts like String.raw", () => {
990 assertStrictEquals(rawString`\nraw${" string"}`, "\\nraw string");
991 });
992
993 it("[[Construct]] throws an error", () => {
994 assertThrows(() => new rawString(["string"]));
995 });
996
997 describe(".length", () => {
998 it("[[Get]] returns the correct length", () => {
999 assertStrictEquals(rawString.length, 1);
1000 });
1001 });
1002
1003 describe(".name", () => {
1004 it("[[Get]] returns the correct name", () => {
1005 assertStrictEquals(rawString.name, "rawString");
1006 });
1007 });
1008 });
1009
1010 describe("scalarValues", () => {
1011 it("[[Call]] returns an iterable", () => {
1012 assertStrictEquals(
1013 typeof scalarValues("")[Symbol.iterator],
1014 "function",
1015 );
1016 });
1017
1018 it("[[Call]] returns an iterator", () => {
1019 assertStrictEquals(typeof scalarValues("").next, "function");
1020 });
1021
1022 it("[[Call]] returns a string scalar value iterator", () => {
1023 assertStrictEquals(
1024 scalarValues("")[Symbol.toStringTag],
1025 "String Scalar Value Iterator",
1026 );
1027 });
1028
1029 it("[[Call]] iterates over the scalar values", () => {
1030 assertEquals([
1031 ...scalarValues("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
1032 ], [
1033 0x49,
1034 0x69,
1035 0x1F399,
1036 0xFFFD,
1037 0xFFFD,
1038 0xFFFD,
1039 0xFFFD,
1040 0x1F197,
1041 0x263A,
1042 ]);
1043 });
1044
1045 it("[[Construct]] throws an error", () => {
1046 assertThrows(() => new scalarValues(""));
1047 });
1048
1049 describe(".length", () => {
1050 it("[[Get]] returns the correct length", () => {
1051 assertStrictEquals(scalarValues.length, 1);
1052 });
1053 });
1054
1055 describe(".name", () => {
1056 it("[[Get]] returns the correct name", () => {
1057 assertStrictEquals(scalarValues.name, "scalarValues");
1058 });
1059 });
1060 });
1061
1062 describe("splitOnAsciiWhitespace", () => {
1063 it("[[Call]] splits on sequences of spaces", () => {
1064 assertEquals(
1065 splitOnAsciiWhitespace("🅰️ 🅱️ 🆎 🅾️"),
1066 ["🅰️", "🅱️", "🆎", "🅾️"],
1067 );
1068 });
1069
1070 it("[[Call]] splits on sequences of tabs", () => {
1071 assertEquals(
1072 splitOnAsciiWhitespace("🅰️\t\t\t🅱️\t🆎\t\t🅾️"),
1073 ["🅰️", "🅱️", "🆎", "🅾️"],
1074 );
1075 });
1076
1077 it("[[Call]] splits on sequences of carriage returns", () => {
1078 assertEquals(
1079 splitOnAsciiWhitespace("🅰️\r\r\r🅱️\r🆎\r\r🅾️"),
1080 ["🅰️", "🅱️", "🆎", "🅾️"],
1081 );
1082 });
1083
1084 it("[[Call]] splits on sequences of newlines", () => {
1085 assertEquals(
1086 splitOnAsciiWhitespace("🅰️\r\r\r🅱️\r🆎\r\r🅾️"),
1087 ["🅰️", "🅱️", "🆎", "🅾️"],
1088 );
1089 });
1090
1091 it("[[Call]] splits on sequences of form feeds", () => {
1092 assertEquals(
1093 splitOnAsciiWhitespace("🅰️\f\f\f🅱️\f🆎\f\f🅾️"),
1094 ["🅰️", "🅱️", "🆎", "🅾️"],
1095 );
1096 });
1097
1098 it("[[Call]] splits on mixed whitespace", () => {
1099 assertEquals(
1100 splitOnAsciiWhitespace("🅰️\f \t\n🅱️\r\n\r🆎\n\f🅾️"),
1101 ["🅰️", "🅱️", "🆎", "🅾️"],
1102 );
1103 });
1104
1105 it("[[Call]] returns an array of just the empty string for the empty string", () => {
1106 assertEquals(splitOnAsciiWhitespace(""), [""]);
1107 });
1108
1109 it("[[Call]] returns a single token if there are no spaces", () => {
1110 assertEquals(splitOnAsciiWhitespace("abcd"), ["abcd"]);
1111 });
1112
1113 it("[[Call]] does not split on other kinds of whitespace", () => {
1114 assertEquals(
1115 splitOnAsciiWhitespace("a\u202F\u205F\xa0\v\0\bb"),
1116 ["a\u202F\u205F\xa0\v\0\bb"],
1117 );
1118 });
1119
1120 it("[[Call]] trims leading and trailing whitespace", () => {
1121 assertEquals(
1122 splitOnAsciiWhitespace(
1123 "\f\r\n\r\n \n\t🅰️\f \t\n🅱️\r🆎\n\f🅾️\n\f",
1124 ),
1125 ["🅰️", "🅱️", "🆎", "🅾️"],
1126 );
1127 });
1128
1129 it("[[Construct]] throws an error", () => {
1130 assertThrows(() => new splitOnAsciiWhitespace(""));
1131 });
1132
1133 describe(".length", () => {
1134 it("[[Get]] returns the correct length", () => {
1135 assertStrictEquals(splitOnAsciiWhitespace.length, 1);
1136 });
1137 });
1138
1139 describe(".name", () => {
1140 it("[[Get]] returns the correct name", () => {
1141 assertStrictEquals(
1142 splitOnAsciiWhitespace.name,
1143 "splitOnAsciiWhitespace",
1144 );
1145 });
1146 });
1147 });
1148
1149 describe("splitOnCommas", () => {
1150 it("[[Call]] splits on commas", () => {
1151 assertEquals(
1152 splitOnCommas("🅰️,🅱️,🆎,🅾️"),
1153 ["🅰️", "🅱️", "🆎", "🅾️"],
1154 );
1155 });
1156
1157 it("[[Call]] returns an array of just the empty string for the empty string", () => {
1158 assertEquals(splitOnCommas(""), [""]);
1159 });
1160
1161 it("[[Call]] returns a single token if there are no commas", () => {
1162 assertEquals(splitOnCommas("abcd"), ["abcd"]);
1163 });
1164
1165 it("[[Call]] splits into empty strings if there are only commas", () => {
1166 assertEquals(splitOnCommas(",,,"), ["", "", "", ""]);
1167 });
1168
1169 it("[[Call]] trims leading and trailing whitespace", () => {
1170 assertEquals(
1171 splitOnCommas("\f\r\n\r\n \n\t🅰️,🅱️,🆎,🅾️\n\f"),
1172 ["🅰️", "🅱️", "🆎", "🅾️"],
1173 );
1174 assertEquals(
1175 splitOnCommas("\f\r\n\r\n \n\t,,,\n\f"),
1176 ["", "", "", ""],
1177 );
1178 });
1179
1180 it("[[Call]] removes whitespace from the split tokens", () => {
1181 assertEquals(
1182 splitOnCommas(
1183 "\f\r\n\r\n \n\t🅰️\f , \t\n🅱️,\r\n\r🆎\n\f,🅾️\n\f",
1184 ),
1185 ["🅰️", "🅱️", "🆎", "🅾️"],
1186 );
1187 assertEquals(
1188 splitOnCommas("\f\r\n\r\n \n\t\f , \t\n,\r\n\r\n\f,\n\f"),
1189 ["", "", "", ""],
1190 );
1191 });
1192
1193 it("[[Construct]] throws an error", () => {
1194 assertThrows(() => new splitOnCommas(""));
1195 });
1196
1197 describe(".length", () => {
1198 it("[[Get]] returns the correct length", () => {
1199 assertStrictEquals(splitOnCommas.length, 1);
1200 });
1201 });
1202
1203 describe(".name", () => {
1204 it("[[Get]] returns the correct name", () => {
1205 assertStrictEquals(splitOnCommas.name, "splitOnCommas");
1206 });
1207 });
1208 });
1209
1210 describe("stringCatenate", () => {
1211 it("[[Call]] catenates the values", () => {
1212 assertStrictEquals(stringCatenate("the", " values"), "the values");
1213 });
1214
1215 it("[[Call]] returns an empty string when called with no values", () => {
1216 assertStrictEquals(stringCatenate(), "");
1217 });
1218
1219 it('[[Call]] uses "undefined" when explicitly provided undefined', () => {
1220 assertStrictEquals(
1221 stringCatenate(undefined, undefined),
1222 "undefinedundefined",
1223 );
1224 });
1225
1226 it('[[Call]] uses "null" when provided null', () => {
1227 assertStrictEquals(stringCatenate(null, null), "nullnull");
1228 });
1229
1230 it("[[Construct]] throws an error", () => {
1231 assertThrows(() => new stringCatenate());
1232 });
1233
1234 describe(".length", () => {
1235 it("[[Get]] returns the correct length", () => {
1236 assertStrictEquals(stringCatenate.length, 2);
1237 });
1238 });
1239
1240 describe(".name", () => {
1241 it("[[Get]] returns the correct name", () => {
1242 assertStrictEquals(stringCatenate.name, "stringCatenate");
1243 });
1244 });
1245 });
1246
1247 describe("stringEndsWith", () => {
1248 it("[[Call]] returns whether the string ends with the thing", () => {
1249 assertStrictEquals(
1250 stringEndsWith("very success", " success"),
1251 true,
1252 );
1253 assertStrictEquals(stringEndsWith("very fail", " success"), false);
1254 });
1255
1256 it("[[Call]] accepts an offset", () => {
1257 assertStrictEquals(
1258 stringEndsWith("very successful", " success", 12),
1259 true,
1260 );
1261 });
1262
1263 it("[[Call]] returns true for an empty string test", () => {
1264 assertStrictEquals(stringEndsWith("", ""), true);
1265 });
1266
1267 it("[[Construct]] throws an error", () => {
1268 assertThrows(() => new stringEndsWith("", ""));
1269 });
1270
1271 describe(".length", () => {
1272 it("[[Get]] returns the correct length", () => {
1273 assertStrictEquals(stringEndsWith.length, 2);
1274 });
1275 });
1276
1277 describe(".name", () => {
1278 it("[[Get]] returns the correct name", () => {
1279 assertStrictEquals(stringEndsWith.name, "stringEndsWith");
1280 });
1281 });
1282 });
1283
1284 describe("stringFromCodeUnits", () => {
1285 it("[[Call]] makes the string", () => {
1286 assertStrictEquals(
1287 stringFromCodeUnits(0xD83C, 0xDD97),
1288 "🆗",
1289 );
1290 });
1291
1292 it("[[Call]] throws with non‐integral arguments", () => {
1293 assertThrows(() => stringFromCodeUnits(NaN));
1294 assertThrows(() => stringFromCodeUnits(Infinity));
1295 assertThrows(() => stringFromCodeUnits(0.1));
1296 });
1297
1298 it("[[Call]] throws with arguments out of range", () => {
1299 assertThrows(() => stringFromCodeUnits(-1));
1300 assertThrows(() => stringFromCodeUnits(0x10000));
1301 });
1302
1303 it("[[Construct]] throws an error", () => {
1304 assertThrows(() => new stringFromCodeUnits([]));
1305 });
1306
1307 describe(".length", () => {
1308 it("[[Get]] returns the correct length", () => {
1309 assertStrictEquals(stringFromCodeUnits.length, 1);
1310 });
1311 });
1312
1313 describe(".name", () => {
1314 it("[[Get]] returns the correct name", () => {
1315 assertStrictEquals(
1316 stringFromCodeUnits.name,
1317 "stringFromCodeUnits",
1318 );
1319 });
1320 });
1321 });
1322
1323 describe("stringFromCodepoints", () => {
1324 it("[[Call]] makes the string", () => {
1325 assertStrictEquals(stringFromCodepoints(0x1F197), "🆗");
1326 });
1327
1328 it("[[Call]] throws with non‐integral arguments", () => {
1329 assertThrows(() => stringFromCodepoints(NaN));
1330 assertThrows(() => stringFromCodepoints(Infinity));
1331 assertThrows(() => stringFromCodepoints(0.1));
1332 });
1333
1334 it("[[Call]] throws with arguments out of range", () => {
1335 assertThrows(() => stringFromCodepoints(-1));
1336 assertThrows(() => stringFromCodepoints(0x110000));
1337 });
1338
1339 it("[[Construct]] throws an error", () => {
1340 assertThrows(() => new stringFromCodepoints([]));
1341 });
1342
1343 describe(".length", () => {
1344 it("[[Get]] returns the correct length", () => {
1345 assertStrictEquals(stringFromCodepoints.length, 1);
1346 });
1347 });
1348
1349 describe(".name", () => {
1350 it("[[Get]] returns the correct name", () => {
1351 assertStrictEquals(
1352 stringFromCodepoints.name,
1353 "stringFromCodepoints",
1354 );
1355 });
1356 });
1357 });
1358
1359 describe("stringIncludes", () => {
1360 it("[[Call]] returns whether the string includes the thing", () => {
1361 assertStrictEquals(
1362 stringIncludes("very success full", " success "),
1363 true,
1364 );
1365 assertStrictEquals(
1366 stringIncludes("very fail full", " success "),
1367 false,
1368 );
1369 });
1370
1371 it("[[Call]] accepts an offset", () => {
1372 assertStrictEquals(
1373 stringIncludes("maybe success full", " success ", 4),
1374 true,
1375 );
1376 assertStrictEquals(
1377 stringIncludes("maybe success full", " success ", 5),
1378 true,
1379 );
1380 assertStrictEquals(
1381 stringIncludes("maybe success full", " success ", 6),
1382 false,
1383 );
1384 });
1385
1386 it("[[Call]] returns true for an empty string test", () => {
1387 assertStrictEquals(stringIncludes("", ""), true);
1388 });
1389
1390 it("[[Construct]] throws an error", () => {
1391 assertThrows(() => new stringIncludes("", ""));
1392 });
1393
1394 describe(".length", () => {
1395 it("[[Get]] returns the correct length", () => {
1396 assertStrictEquals(stringIncludes.length, 2);
1397 });
1398 });
1399
1400 describe(".name", () => {
1401 it("[[Get]] returns the correct name", () => {
1402 assertStrictEquals(stringIncludes.name, "stringIncludes");
1403 });
1404 });
1405 });
1406
1407 describe("stringMatch", () => {
1408 it("[[Call]] does the match akin to String::match", () => {
1409 assertEquals(
1410 [...stringMatch("very success full", /([sc]+[ue]?)+/)],
1411 ["success", "ss"],
1412 );
1413 assertEquals(
1414 [...stringMatch("very success full", /([sc]+)[ue]?/g)],
1415 ["su", "cce", "ss"],
1416 );
1417 });
1418
1419 it("[[Construct]] throws an error", () => {
1420 assertThrows(() => new stringMatch("", /(?:)/));
1421 });
1422
1423 describe(".length", () => {
1424 it("[[Get]] returns the correct length", () => {
1425 assertStrictEquals(stringMatch.length, 2);
1426 });
1427 });
1428
1429 describe(".name", () => {
1430 it("[[Get]] returns the correct name", () => {
1431 assertStrictEquals(stringMatch.name, "stringMatch");
1432 });
1433 });
1434 });
1435
1436 describe("stringMatchAll", () => {
1437 it("[[Call]] does the match akin to String::matchAll", () => {
1438 assertEquals(
1439 [...stringMatchAll("very success full", /([sc]+)[ue]?/g)].map((
1440 match,
1441 ) => [...match]),
1442 [["su", "s"], ["cce", "cc"], ["ss", "ss"]],
1443 );
1444 });
1445
1446 it("[[Construct]] throws an error", () => {
1447 assertThrows(() => new stringMatchAll("", /(?:)/g));
1448 });
1449
1450 describe(".length", () => {
1451 it("[[Get]] returns the correct length", () => {
1452 assertStrictEquals(stringMatchAll.length, 2);
1453 });
1454 });
1455
1456 describe(".name", () => {
1457 it("[[Get]] returns the correct name", () => {
1458 assertStrictEquals(stringMatchAll.name, "stringMatchAll");
1459 });
1460 });
1461 });
1462
1463 describe("stringNormalize", () => {
1464 it("[[Call]] normalizes the string properly", () => {
1465 assertStrictEquals(stringNormalize("ẛ", "NFC"), "\u1E9B");
1466 assertStrictEquals(stringNormalize("ẛ", "NFD"), "\u017F\u0307");
1467 assertStrictEquals(stringNormalize("ẛ", "NFKC"), "\u1E61");
1468 assertStrictEquals(stringNormalize("ẛ", "NFKD"), "\u0073\u0307");
1469 });
1470
1471 it("[[Call]] assumes NFC", () => {
1472 assertStrictEquals(stringNormalize("\u017F\u0307"), "\u1E9B");
1473 });
1474
1475 it("[[Call]] throws with an invalid form", () => {
1476 assertThrows(() => stringNormalize("", "NFB"));
1477 });
1478
1479 it("[[Construct]] throws an error", () => {
1480 assertThrows(() => new stringNormalize("", "NFC"));
1481 });
1482
1483 describe(".length", () => {
1484 it("[[Get]] returns the correct length", () => {
1485 assertStrictEquals(stringNormalize.length, 1);
1486 });
1487 });
1488
1489 describe(".name", () => {
1490 it("[[Get]] returns the correct name", () => {
1491 assertStrictEquals(stringNormalize.name, "stringNormalize");
1492 });
1493 });
1494 });
1495
1496 describe("stringPadEnd", () => {
1497 it("[[Call]] pads the end of the string", () => {
1498 assertStrictEquals(stringPadEnd("xx", 3), "xx ");
1499 assertStrictEquals(stringPadEnd("xx", 3, "o"), "xxo");
1500 assertStrictEquals(stringPadEnd("", 3, "xo"), "xox");
1501 assertStrictEquals(stringPadEnd("xx", 3, ""), "xx");
1502 });
1503
1504 it("[[Construct]] throws an error", () => {
1505 assertThrows(() => new stringPadEnd("", 1));
1506 });
1507
1508 describe(".length", () => {
1509 it("[[Get]] returns the correct length", () => {
1510 assertStrictEquals(stringPadEnd.length, 2);
1511 });
1512 });
1513
1514 describe(".name", () => {
1515 it("[[Get]] returns the correct name", () => {
1516 assertStrictEquals(stringPadEnd.name, "stringPadEnd");
1517 });
1518 });
1519 });
1520
1521 describe("stringPadStart", () => {
1522 it("[[Call]] pads the start of the string", () => {
1523 assertStrictEquals(stringPadStart("xx", 3), " xx");
1524 assertStrictEquals(stringPadStart("xx", 3, "o"), "oxx");
1525 assertStrictEquals(stringPadStart("", 3, "xo"), "xox");
1526 assertStrictEquals(stringPadStart("xx", 3, ""), "xx");
1527 });
1528
1529 it("[[Construct]] throws an error", () => {
1530 assertThrows(() => new stringPadStart("", 1));
1531 });
1532
1533 describe(".length", () => {
1534 it("[[Get]] returns the correct length", () => {
1535 assertStrictEquals(stringPadStart.length, 2);
1536 });
1537 });
1538
1539 describe(".name", () => {
1540 it("[[Get]] returns the correct name", () => {
1541 assertStrictEquals(stringPadStart.name, "stringPadStart");
1542 });
1543 });
1544 });
1545
1546 describe("stringRepeat", () => {
1547 it("[[Call]] repeats the string", () => {
1548 assertStrictEquals(stringRepeat("xx", 3), "xxxxxx");
1549 assertStrictEquals(stringRepeat("", 3), "");
1550 assertStrictEquals(stringRepeat("xx", 0), "");
1551 });
1552
1553 it("[[Call]] throws for negative repititions", () => {
1554 assertThrows(() => stringRepeat("", -1));
1555 });
1556
1557 it("[[Call]] throws for infinite repititions", () => {
1558 assertThrows(() => stringRepeat("", Infinity));
1559 });
1560
1561 it("[[Construct]] throws an error", () => {
1562 assertThrows(() => new stringRepeat("", 1));
1563 });
1564
1565 describe(".length", () => {
1566 it("[[Get]] returns the correct length", () => {
1567 assertStrictEquals(stringRepeat.length, 2);
1568 });
1569 });
1570
1571 describe(".name", () => {
1572 it("[[Get]] returns the correct name", () => {
1573 assertStrictEquals(stringRepeat.name, "stringRepeat");
1574 });
1575 });
1576 });
1577
1578 describe("stringReplace", () => {
1579 it("[[Call]] does the replacement akin to String::replace", () => {
1580 assertStrictEquals(
1581 stringReplace("it’s a failure", "failure", "success"),
1582 "it’s a success",
1583 );
1584 assertStrictEquals(
1585 stringReplace(
1586 "very success full",
1587 /([sc]+)[ue]?/,
1588 ($) => $.length,
1589 ),
1590 "very 2ccess full",
1591 );
1592 assertStrictEquals(
1593 stringReplace(
1594 "very success full",
1595 /([sc]+)[ue]?/g,
1596 (...$s) =>
1597 `${$s[0].length}`.repeat($s[1].length)
1598 + $s[0].substring($s[1].length),
1599 ),
1600 "very 2u33e22 full",
1601 );
1602 });
1603
1604 it("[[Construct]] throws an error", () => {
1605 assertThrows(() => new stringReplace("", /(?:)/, ""));
1606 });
1607
1608 describe(".length", () => {
1609 it("[[Get]] returns the correct length", () => {
1610 assertStrictEquals(stringReplace.length, 3);
1611 });
1612 });
1613
1614 describe(".name", () => {
1615 it("[[Get]] returns the correct name", () => {
1616 assertStrictEquals(stringReplace.name, "stringReplace");
1617 });
1618 });
1619 });
1620
1621 describe("stringReplaceAll", () => {
1622 it("[[Call]] does the match akin to String::replaceAll", () => {
1623 assertStrictEquals(
1624 stringReplaceAll("it’s a failure failure", "failure", "success"),
1625 "it’s a success success",
1626 );
1627 assertStrictEquals(
1628 stringReplaceAll(
1629 "very success full",
1630 /([sc]+)[ue]?/g,
1631 (...$s) =>
1632 `${$s[0].length}`.repeat($s[1].length)
1633 + $s[0].substring($s[1].length),
1634 ),
1635 "very 2u33e22 full",
1636 );
1637 });
1638
1639 it("[[Construct]] throws an error", () => {
1640 assertThrows(() => new stringReplaceAll("", /(?:)/g));
1641 });
1642
1643 describe(".length", () => {
1644 it("[[Get]] returns the correct length", () => {
1645 assertStrictEquals(stringReplaceAll.length, 3);
1646 });
1647 });
1648
1649 describe(".name", () => {
1650 it("[[Get]] returns the correct name", () => {
1651 assertStrictEquals(stringReplaceAll.name, "stringReplaceAll");
1652 });
1653 });
1654 });
1655
1656 describe("stringSearch", () => {
1657 it("[[Call]] does the search akin to String::search", () => {
1658 assertStrictEquals(
1659 stringSearch("very success full", /([sc]+)[ue]?/),
1660 5,
1661 );
1662 assertStrictEquals(
1663 stringSearch("very fail full", /([sc]+)[ue]?/),
1664 -1,
1665 );
1666 });
1667
1668 it("[[Construct]] throws an error", () => {
1669 assertThrows(() => new stringSearch("", /(?:)/));
1670 });
1671
1672 describe(".length", () => {
1673 it("[[Get]] returns the correct length", () => {
1674 assertStrictEquals(stringSearch.length, 2);
1675 });
1676 });
1677
1678 describe(".name", () => {
1679 it("[[Get]] returns the correct name", () => {
1680 assertStrictEquals(stringSearch.name, "stringSearch");
1681 });
1682 });
1683 });
1684
1685 describe("stringSlice", () => {
1686 it("[[Call]] slices the string akin to String::search", () => {
1687 assertStrictEquals(
1688 stringSlice("very success full", 5, 12),
1689 "success",
1690 );
1691 assertStrictEquals(
1692 stringSlice("very success full", -12, -5),
1693 "success",
1694 );
1695 });
1696
1697 it("[[Construct]] throws an error", () => {
1698 assertThrows(() => new stringSlice("", 0, 0));
1699 });
1700
1701 describe(".length", () => {
1702 it("[[Get]] returns the correct length", () => {
1703 assertStrictEquals(stringSlice.length, 3);
1704 });
1705 });
1706
1707 describe(".name", () => {
1708 it("[[Get]] returns the correct name", () => {
1709 assertStrictEquals(stringSlice.name, "stringSlice");
1710 });
1711 });
1712 });
1713
1714 describe("stringSplit", () => {
1715 it("[[Call]] splits the string akin to String::split", () => {
1716 assertEquals(stringSplit("success", ""), [
1717 "s",
1718 "u",
1719 "c",
1720 "c",
1721 "e",
1722 "s",
1723 "s",
1724 ]);
1725 assertEquals(stringSplit("success", /(?<=[aeiou])(?=[^aeiou])/), [
1726 "su",
1727 "cce",
1728 "ss",
1729 ]);
1730 assertEquals(stringSplit("success", "failure"), ["success"]);
1731 });
1732
1733 it("[[Call]] recognizes a limit", () => {
1734 assertEquals(stringSplit("success", "", 4), ["s", "u", "c", "c"]);
1735 });
1736
1737 it("[[Construct]] throws an error", () => {
1738 assertThrows(() => new stringSplit("", ""));
1739 });
1740
1741 describe(".length", () => {
1742 it("[[Get]] returns the correct length", () => {
1743 assertStrictEquals(stringSplit.length, 3);
1744 });
1745 });
1746
1747 describe(".name", () => {
1748 it("[[Get]] returns the correct name", () => {
1749 assertStrictEquals(stringSplit.name, "stringSplit");
1750 });
1751 });
1752 });
1753
1754 describe("stringStartsWith", () => {
1755 it("[[Call]] returns whether the string starts with the thing", () => {
1756 assertStrictEquals(
1757 stringStartsWith("success is had", "success "),
1758 true,
1759 );
1760 assertStrictEquals(
1761 stringStartsWith("no success is had", "success "),
1762 false,
1763 );
1764 });
1765
1766 it("[[Call]] accepts an offset", () => {
1767 assertStrictEquals(
1768 stringStartsWith("much success is had", "success ", 5),
1769 true,
1770 );
1771 });
1772
1773 it("[[Call]] returns true for an empty string test", () => {
1774 assertStrictEquals(stringEndsWith("", ""), true);
1775 });
1776
1777 it("[[Construct]] throws an error", () => {
1778 assertThrows(() => new stringStartsWith("", ""));
1779 });
1780
1781 describe(".length", () => {
1782 it("[[Get]] returns the correct length", () => {
1783 assertStrictEquals(stringStartsWith.length, 2);
1784 });
1785 });
1786
1787 describe(".name", () => {
1788 it("[[Get]] returns the correct name", () => {
1789 assertStrictEquals(stringStartsWith.name, "stringStartsWith");
1790 });
1791 });
1792 });
1793
1794 describe("stringStartsWith", () => {
1795 it("[[Call]] returns the string value of a string literal", () => {
1796 assertStrictEquals(stringValue("success"), "success");
1797 });
1798
1799 it("[[Call]] returns the string value of a string object", () => {
1800 const string = new String("success");
1801 Object.defineProperties(string, {
1802 toString: { value: () => "failure" },
1803 valueOf: { value: () => "failure" },
1804 });
1805 assertStrictEquals(stringValue(string), "success");
1806 });
1807
1808 it("[[Call]] throws for non‐strings", () => {
1809 assertThrows(() => stringValue(Object.create(String.prototype)));
1810 });
1811
1812 it("[[Construct]] throws an error", () => {
1813 assertThrows(() => new stringValue(""));
1814 });
1815
1816 describe(".length", () => {
1817 it("[[Get]] returns the correct length", () => {
1818 assertStrictEquals(stringValue.length, 1);
1819 });
1820 });
1821
1822 describe(".name", () => {
1823 it("[[Get]] returns the correct name", () => {
1824 assertStrictEquals(stringValue.name, "stringValue");
1825 });
1826 });
1827 });
1828
1829 describe("stripAndCollapseAsciiWhitespace", () => {
1830 it("[[Call]] collapses mixed inner whitespace", () => {
1831 assertEquals(
1832 stripAndCollapseAsciiWhitespace("🅰️\f \t\n🅱️\r\n\r🆎\n\f🅾️"),
1833 "🅰️ 🅱️ 🆎 🅾️",
1834 );
1835 });
1836
1837 it("[[Call]] trims leading and trailing whitespace", () => {
1838 assertStrictEquals(
1839 stripAndCollapseAsciiWhitespace(
1840 "\f\r\n\r\n \n\t\f 🅰️\f \t\n🅱️\r\n\r🆎\n\f🅾️\n\f",
1841 ),
1842 "🅰️ 🅱️ 🆎 🅾️",
1843 );
1844 });
1845
1846 it("[[Call]] returns the empty string for strings of whitespace", () => {
1847 assertStrictEquals(
1848 stripAndCollapseAsciiWhitespace("\f\r\n\r\n \n\t\f \n\f"),
1849 "",
1850 );
1851 });
1852
1853 it("[[Call]] does not collapse other kinds of whitespace", () => {
1854 assertEquals(
1855 stripAndCollapseAsciiWhitespace("a\u202F\u205F\xa0\v\0\bb"),
1856 "a\u202F\u205F\xa0\v\0\bb",
1857 );
1858 });
1859
1860 it("[[Construct]] throws an error", () => {
1861 assertThrows(() => new stripAndCollapseAsciiWhitespace(""));
1862 });
1863
1864 describe(".length", () => {
1865 it("[[Get]] returns the correct length", () => {
1866 assertStrictEquals(stripAndCollapseAsciiWhitespace.length, 1);
1867 });
1868 });
1869
1870 describe(".name", () => {
1871 it("[[Get]] returns the correct name", () => {
1872 assertStrictEquals(
1873 stripAndCollapseAsciiWhitespace.name,
1874 "stripAndCollapseAsciiWhitespace",
1875 );
1876 });
1877 });
1878 });
1879
1880 describe("stripLeadingAndTrailingAsciiWhitespace", () => {
1881 it("[[Call]] trims leading and trailing whitespace", () => {
1882 assertStrictEquals(
1883 stripLeadingAndTrailingAsciiWhitespace(
1884 "\f\r\n\r\n \n\t\f 🅰️🅱️🆎🅾️\n\f",
1885 ),
1886 "🅰️🅱️🆎🅾️",
1887 );
1888 });
1889
1890 it("[[Call]] returns the empty string for strings of whitespace", () => {
1891 assertStrictEquals(
1892 stripLeadingAndTrailingAsciiWhitespace("\f\r\n\r\n \n\t\f \n\f"),
1893 "",
1894 );
1895 });
1896
1897 it("[[Call]] does not trim other kinds of whitespace", () => {
1898 assertEquals(
1899 stripLeadingAndTrailingAsciiWhitespace(
1900 "\v\u202F\u205Fx\0\b\xa0",
1901 ),
1902 "\v\u202F\u205Fx\0\b\xa0",
1903 );
1904 });
1905
1906 it("[[Call]] does not adjust inner whitespace", () => {
1907 assertEquals(
1908 stripLeadingAndTrailingAsciiWhitespace("a b"),
1909 "a b",
1910 );
1911 });
1912
1913 it("[[Construct]] throws an error", () => {
1914 assertThrows(() => new stripLeadingAndTrailingAsciiWhitespace(""));
1915 });
1916
1917 describe(".length", () => {
1918 it("[[Get]] returns the correct length", () => {
1919 assertStrictEquals(
1920 stripLeadingAndTrailingAsciiWhitespace.length,
1921 1,
1922 );
1923 });
1924 });
1925
1926 describe(".name", () => {
1927 it("[[Get]] returns the correct name", () => {
1928 assertStrictEquals(
1929 stripLeadingAndTrailingAsciiWhitespace.name,
1930 "stripLeadingAndTrailingAsciiWhitespace",
1931 );
1932 });
1933 });
1934 });
1935
1936 describe("substring", () => {
1937 it("[[Call]] returns the substring", () => {
1938 assertStrictEquals(
1939 substring("success", 0),
1940 "success",
1941 );
1942 assertStrictEquals(
1943 substring("very success full", 5, 12),
1944 "success",
1945 );
1946 });
1947
1948 it("[[Construct]] throws an error", () => {
1949 assertThrows(() => new substring("", 0));
1950 });
1951
1952 describe(".length", () => {
1953 it("[[Get]] returns the correct length", () => {
1954 assertStrictEquals(substring.length, 3);
1955 });
1956 });
1957
1958 describe(".name", () => {
1959 it("[[Get]] returns the correct name", () => {
1960 assertStrictEquals(substring.name, "substring");
1961 });
1962 });
1963 });
1964
1965 describe("toScalarValueString", () => {
1966 it("[[Call]] replaces invalid values", () => {
1967 assertStrictEquals(
1968 toScalarValueString("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
1969 "Ii🎙\uFFFD\uFFFD\uFFFD\uFFFD🆗☺",
1970 );
1971 });
1972
1973 it("[[Construct]] throws an error", () => {
1974 assertThrows(() => new toScalarValueString(""));
1975 });
1976
1977 describe(".length", () => {
1978 it("[[Get]] returns the correct length", () => {
1979 assertStrictEquals(toScalarValueString.length, 1);
1980 });
1981 });
1982
1983 describe(".name", () => {
1984 it("[[Get]] returns the correct name", () => {
1985 assertStrictEquals(
1986 toScalarValueString.name,
1987 "toScalarValueString",
1988 );
1989 });
1990 });
1991 });
1992
1993 describe("toString", () => {
1994 it("[[Call]] converts to a string", () => {
1995 assertStrictEquals(
1996 toString({
1997 toString() {
1998 return "success";
1999 },
2000 }),
2001 "success",
2002 );
2003 });
2004
2005 it("[[Call]] throws when provided a symbol", () => {
2006 assertThrows(() => toString(Symbol()));
2007 });
2008
2009 it("[[Construct]] throws an error", () => {
2010 assertThrows(() => new toString(""));
2011 });
2012
2013 describe(".length", () => {
2014 it("[[Get]] returns the correct length", () => {
2015 assertStrictEquals(toString.length, 1);
2016 });
2017 });
2018
2019 describe(".name", () => {
2020 it("[[Get]] returns the correct name", () => {
2021 assertStrictEquals(toString.name, "toString");
2022 });
2023 });
2024 });
This page took 0.705299 seconds and 5 git commands to generate.