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