+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(splitOnCommas.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(splitOnCommas.name, "splitOnCommas");
+ });
+ });
+});
+
+describe("stringCatenate", () => {
+ it("[[Call]] catenates the values", () => {
+ assertStrictEquals(stringCatenate("the", " values"), "the values");
+ });
+
+ it("[[Call]] returns an empty string when called with no values", () => {
+ assertStrictEquals(stringCatenate(), "");
+ });
+
+ it('[[Call]] uses "undefined" when explicitly provided undefined', () => {
+ assertStrictEquals(
+ stringCatenate(undefined, undefined),
+ "undefinedundefined",
+ );
+ });
+
+ it('[[Call]] uses "null" when provided null', () => {
+ assertStrictEquals(stringCatenate(null, null), "nullnull");
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringCatenate());
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringCatenate.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringCatenate.name, "stringCatenate");
+ });
+ });
+});
+
+describe("stringEndsWith", () => {
+ it("[[Call]] returns whether the string ends with the thing", () => {
+ assertStrictEquals(
+ stringEndsWith("very success", " success"),
+ true,
+ );
+ assertStrictEquals(stringEndsWith("very fail", " success"), false);
+ });
+
+ it("[[Call]] accepts an offset", () => {
+ assertStrictEquals(
+ stringEndsWith("very successful", " success", 12),
+ true,
+ );
+ });
+
+ it("[[Call]] returns true for an empty string test", () => {
+ assertStrictEquals(stringEndsWith("", ""), true);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringEndsWith("", ""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringEndsWith.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringEndsWith.name, "stringEndsWith");
+ });
+ });
+});
+
+describe("stringFromCodeUnits", () => {
+ it("[[Call]] makes the string", () => {
+ assertStrictEquals(
+ stringFromCodeUnits(0xD83C, 0xDD97),
+ "🆗",
+ );
+ });
+
+ it("[[Call]] throws with non‐integral arguments", () => {
+ assertThrows(() => stringFromCodeUnits(NaN));
+ assertThrows(() => stringFromCodeUnits(Infinity));
+ assertThrows(() => stringFromCodeUnits(0.1));
+ });
+
+ it("[[Call]] throws with arguments out of range", () => {
+ assertThrows(() => stringFromCodeUnits(-1));
+ assertThrows(() => stringFromCodeUnits(0x10000));
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringFromCodeUnits([]));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringFromCodeUnits.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ stringFromCodeUnits.name,
+ "stringFromCodeUnits",
+ );
+ });
+ });
+});
+
+describe("stringFromCodepoints", () => {
+ it("[[Call]] makes the string", () => {
+ assertStrictEquals(stringFromCodepoints(0x1F197), "🆗");
+ });
+
+ it("[[Call]] throws with non‐integral arguments", () => {
+ assertThrows(() => stringFromCodepoints(NaN));
+ assertThrows(() => stringFromCodepoints(Infinity));
+ assertThrows(() => stringFromCodepoints(0.1));
+ });
+
+ it("[[Call]] throws with arguments out of range", () => {
+ assertThrows(() => stringFromCodepoints(-1));
+ assertThrows(() => stringFromCodepoints(0x110000));
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringFromCodepoints([]));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringFromCodepoints.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ stringFromCodepoints.name,
+ "stringFromCodepoints",
+ );
+ });
+ });
+});
+
+describe("stringIncludes", () => {
+ it("[[Call]] returns whether the string includes the thing", () => {
+ assertStrictEquals(
+ stringIncludes("very success full", " success "),
+ true,
+ );
+ assertStrictEquals(
+ stringIncludes("very fail full", " success "),
+ false,
+ );
+ });
+
+ it("[[Call]] accepts an offset", () => {
+ assertStrictEquals(
+ stringIncludes("maybe success full", " success ", 4),
+ true,
+ );
+ assertStrictEquals(
+ stringIncludes("maybe success full", " success ", 5),
+ true,
+ );
+ assertStrictEquals(
+ stringIncludes("maybe success full", " success ", 6),
+ false,
+ );
+ });
+
+ it("[[Call]] returns true for an empty string test", () => {
+ assertStrictEquals(stringIncludes("", ""), true);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringIncludes("", ""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringIncludes.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringIncludes.name, "stringIncludes");
+ });
+ });
+});
+
+describe("stringMatch", () => {
+ it("[[Call]] does the match akin to String::match", () => {
+ assertEquals(
+ [...stringMatch("very success full", /([sc]+[ue]?)+/)],
+ ["success", "ss"],
+ );
+ assertEquals(
+ [...stringMatch("very success full", /([sc]+)[ue]?/g)],
+ ["su", "cce", "ss"],
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringMatch("", /(?:)/));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringMatch.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringMatch.name, "stringMatch");
+ });
+ });
+});
+
+describe("stringMatchAll", () => {
+ it("[[Call]] does the match akin to String::matchAll", () => {
+ assertEquals(
+ [...stringMatchAll("very success full", /([sc]+)[ue]?/g)].map((
+ match,
+ ) => [...match]),
+ [["su", "s"], ["cce", "cc"], ["ss", "ss"]],
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringMatchAll("", /(?:)/g));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringMatchAll.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringMatchAll.name, "stringMatchAll");
+ });
+ });
+});
+
+describe("stringNormalize", () => {
+ it("[[Call]] normalizes the string properly", () => {
+ assertStrictEquals(stringNormalize("ẛ", "NFC"), "\u1E9B");
+ assertStrictEquals(stringNormalize("ẛ", "NFD"), "\u017F\u0307");
+ assertStrictEquals(stringNormalize("ẛ", "NFKC"), "\u1E61");
+ assertStrictEquals(stringNormalize("ẛ", "NFKD"), "\u0073\u0307");
+ });
+
+ it("[[Call]] assumes NFC", () => {
+ assertStrictEquals(stringNormalize("\u017F\u0307"), "\u1E9B");
+ });
+
+ it("[[Call]] throws with an invalid form", () => {
+ assertThrows(() => stringNormalize("", "NFB"));
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringNormalize("", "NFC"));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringNormalize.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringNormalize.name, "stringNormalize");
+ });
+ });
+});
+
+describe("stringPadEnd", () => {
+ it("[[Call]] pads the end of the string", () => {
+ assertStrictEquals(stringPadEnd("xx", 3), "xx ");
+ assertStrictEquals(stringPadEnd("xx", 3, "o"), "xxo");
+ assertStrictEquals(stringPadEnd("", 3, "xo"), "xox");
+ assertStrictEquals(stringPadEnd("xx", 3, ""), "xx");
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringPadEnd("", 1));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringPadEnd.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringPadEnd.name, "stringPadEnd");
+ });
+ });
+});
+
+describe("stringPadStart", () => {
+ it("[[Call]] pads the start of the string", () => {
+ assertStrictEquals(stringPadStart("xx", 3), " xx");
+ assertStrictEquals(stringPadStart("xx", 3, "o"), "oxx");
+ assertStrictEquals(stringPadStart("", 3, "xo"), "xox");
+ assertStrictEquals(stringPadStart("xx", 3, ""), "xx");
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringPadStart("", 1));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringPadStart.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringPadStart.name, "stringPadStart");
+ });
+ });
+});
+
+describe("stringRepeat", () => {
+ it("[[Call]] repeats the string", () => {
+ assertStrictEquals(stringRepeat("xx", 3), "xxxxxx");
+ assertStrictEquals(stringRepeat("", 3), "");
+ assertStrictEquals(stringRepeat("xx", 0), "");
+ });
+
+ it("[[Call]] throws for negative repititions", () => {
+ assertThrows(() => stringRepeat("", -1));
+ });
+
+ it("[[Call]] throws for infinite repititions", () => {
+ assertThrows(() => stringRepeat("", Infinity));
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringRepeat("", 1));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringRepeat.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringRepeat.name, "stringRepeat");
+ });
+ });
+});
+
+describe("stringReplace", () => {
+ it("[[Call]] does the replacement akin to String::replace", () => {
+ assertStrictEquals(
+ stringReplace("it’s a failure", "failure", "success"),
+ "it’s a success",
+ );
+ assertStrictEquals(
+ stringReplace(
+ "very success full",
+ /([sc]+)[ue]?/,
+ ($) => $.length,
+ ),
+ "very 2ccess full",
+ );
+ assertStrictEquals(
+ stringReplace(
+ "very success full",
+ /([sc]+)[ue]?/g,
+ (...$s) =>
+ `${$s[0].length}`.repeat($s[1].length) +
+ $s[0].substring($s[1].length),
+ ),
+ "very 2u33e22 full",
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringReplace("", /(?:)/, ""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringReplace.length, 3);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringReplace.name, "stringReplace");
+ });
+ });
+});
+
+describe("stringReplaceAll", () => {
+ it("[[Call]] does the match akin to String::replaceAll", () => {
+ assertStrictEquals(
+ stringReplaceAll("it’s a failure failure", "failure", "success"),
+ "it’s a success success",
+ );
+ assertStrictEquals(
+ stringReplaceAll(
+ "very success full",
+ /([sc]+)[ue]?/g,
+ (...$s) =>
+ `${$s[0].length}`.repeat($s[1].length) +
+ $s[0].substring($s[1].length),
+ ),
+ "very 2u33e22 full",
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringReplaceAll("", /(?:)/g));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringReplaceAll.length, 3);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringReplaceAll.name, "stringReplaceAll");
+ });
+ });
+});
+
+describe("stringSearch", () => {
+ it("[[Call]] does the search akin to String::search", () => {
+ assertStrictEquals(
+ stringSearch("very success full", /([sc]+)[ue]?/),
+ 5,
+ );
+ assertStrictEquals(
+ stringSearch("very fail full", /([sc]+)[ue]?/),
+ -1,
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringSearch("", /(?:)/));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringSearch.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringSearch.name, "stringSearch");
+ });
+ });
+});
+
+describe("stringSlice", () => {
+ it("[[Call]] slices the string akin to String::search", () => {
+ assertStrictEquals(
+ stringSlice("very success full", 5, 12),
+ "success",
+ );
+ assertStrictEquals(
+ stringSlice("very success full", -12, -5),
+ "success",
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringSlice("", 0, 0));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringSlice.length, 3);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringSlice.name, "stringSlice");
+ });
+ });
+});
+
+describe("stringSplit", () => {
+ it("[[Call]] splits the string akin to String::split", () => {
+ assertEquals(stringSplit("success", ""), [
+ "s",
+ "u",
+ "c",
+ "c",
+ "e",
+ "s",
+ "s",
+ ]);
+ assertEquals(stringSplit("success", /(?<=[aeiou])(?=[^aeiou])/), [
+ "su",
+ "cce",
+ "ss",
+ ]);
+ assertEquals(stringSplit("success", "failure"), ["success"]);
+ });
+
+ it("[[Call]] recognizes a limit", () => {
+ assertEquals(stringSplit("success", "", 4), ["s", "u", "c", "c"]);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringSplit("", ""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringSplit.length, 3);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringSplit.name, "stringSplit");
+ });
+ });
+});
+
+describe("stringStartsWith", () => {
+ it("[[Call]] returns whether the string starts with the thing", () => {
+ assertStrictEquals(
+ stringStartsWith("success is had", "success "),
+ true,
+ );
+ assertStrictEquals(
+ stringStartsWith("no success is had", "success "),
+ false,
+ );
+ });
+
+ it("[[Call]] accepts an offset", () => {
+ assertStrictEquals(
+ stringStartsWith("much success is had", "success ", 5),
+ true,
+ );
+ });
+
+ it("[[Call]] returns true for an empty string test", () => {
+ assertStrictEquals(stringEndsWith("", ""), true);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringStartsWith("", ""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringStartsWith.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringStartsWith.name, "stringStartsWith");
+ });
+ });
+});
+
+describe("stringStartsWith", () => {
+ it("[[Call]] returns the string value of a string literal", () => {
+ assertStrictEquals(stringValue("success"), "success");
+ });
+
+ it("[[Call]] returns the string value of a string object", () => {
+ const string = new String("success");
+ Object.defineProperties(string, {
+ toString: { value: () => "failure" },
+ valueOf: { value: () => "failure" },
+ });
+ assertStrictEquals(stringValue(string), "success");
+ });
+
+ it("[[Call]] throws for non‐strings", () => {
+ assertThrows(() => stringValue(Object.create(String.prototype)));
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringValue(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringValue.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringValue.name, "stringValue");
+ });
+ });
+});
+
+describe("stripAndCollapseASCIIWhitespace", () => {
+ it("[[Call]] collapses mixed inner whitespace", () => {
+ assertEquals(
+ stripAndCollapseASCIIWhitespace("🅰️\f \t\n🅱️\r\n\r🆎\n\f🅾️"),
+ "🅰️ 🅱️ 🆎 🅾️",
+ );
+ });
+
+ it("[[Call]] trims leading and trailing whitespace", () => {
+ assertStrictEquals(
+ stripAndCollapseASCIIWhitespace(
+ "\f\r\n\r\n \n\t\f 🅰️\f \t\n🅱️\r\n\r🆎\n\f🅾️\n\f",