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