]> Lady’s Gitweb - Pisces/blobdiff - string.test.js
Add string functions and unit tests
[Pisces] / string.test.js
diff --git a/string.test.js b/string.test.js
new file mode 100644 (file)
index 0000000..5d713f0
--- /dev/null
@@ -0,0 +1,371 @@
+// ♓🌟 Piscēs ∷ string.test.js
+// ====================================================================
+//
+// Copyright © 2022 Lady [@ Lady’s Computer].
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+
+import {
+  assertEquals,
+  assertStrictEquals,
+  describe,
+  it,
+} from "./dev-deps.js";
+import {
+  asciiLowercase,
+  asciiUppercase,
+  codepoints,
+  codeUnits,
+  getCharacter,
+  join,
+  scalarValues,
+  scalarValueString,
+  splitOnASCIIWhitespace,
+  splitOnCommas,
+  stripAndCollapseASCIIWhitespace,
+  stripLeadingAndTrailingASCIIWhitespace,
+} from "./string.js";
+
+describe("asciiLowercase", () => {
+  it("[[Call]] lowercases (just) A·S·C·I·I letters", () => {
+    assertStrictEquals(asciiLowercase("aBſÆss FtɁɂß"), "abſÆss ftɁɂß");
+  });
+});
+
+describe("asciiUppercase", () => {
+  it("[[Call]] uppercases (just) A·S·C·I·I letters", () => {
+    assertStrictEquals(asciiUppercase("aBſÆss FtɁɂß"), "ABſÆSS FTɁɂß");
+  });
+});
+
+describe("codeUnits", () => {
+  it("[[Call]] returns an iterable", () => {
+    assertStrictEquals(
+      typeof codeUnits("")[Symbol.iterator],
+      "function",
+    );
+  });
+
+  it("[[Call]] returns an iterator", () => {
+    assertStrictEquals(typeof codeUnits("").next, "function");
+  });
+
+  it("[[Call]] returns a string code value iterator", () => {
+    assertStrictEquals(
+      codeUnits("")[Symbol.toStringTag],
+      "String Code Value Iterator",
+    );
+  });
+
+  it("[[Call]] iterates over the code units", () => {
+    assertEquals([
+      ...codeUnits("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
+    ], [
+      0x49,
+      0x69,
+      0xD83C,
+      0xDF99,
+      0xDFFF,
+      0xDD96,
+      0xD83C,
+      0xD800,
+      0xD83C,
+      0xDD97,
+      0x263A,
+    ]);
+  });
+});
+
+describe("codepoints", () => {
+  it("[[Call]] returns an iterable", () => {
+    assertStrictEquals(
+      typeof codepoints("")[Symbol.iterator],
+      "function",
+    );
+  });
+
+  it("[[Call]] returns an iterator", () => {
+    assertStrictEquals(typeof codepoints("").next, "function");
+  });
+
+  it("[[Call]] returns a string code value iterator", () => {
+    assertStrictEquals(
+      codepoints("")[Symbol.toStringTag],
+      "String Code Value Iterator",
+    );
+  });
+
+  it("[[Call]] iterates over the codepoints", () => {
+    assertEquals([
+      ...codepoints("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
+    ], [
+      0x49,
+      0x69,
+      0x1F399,
+      0xDFFF,
+      0xDD96,
+      0xD83C,
+      0xD800,
+      0x1F197,
+      0x263A,
+    ]);
+  });
+});
+
+describe("getCharacter", () => {
+  it("[[Call]] returns the character at the provided position", () => {
+    assertStrictEquals(getCharacter("Ii🎙🆗☺", 4), "🆗");
+  });
+
+  it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
+    assertStrictEquals(getCharacter("Ii🎙🆗☺", 5), "\uDD97");
+  });
+
+  it("[[Call]] returns undefined for an out‐of‐bounds index", () => {
+    assertStrictEquals(getCharacter("Ii🎙🆗☺", -1), void {});
+    assertStrictEquals(getCharacter("Ii🎙🆗☺", 7), void {});
+  });
+});
+
+describe("join", () => {
+  it("[[Call]] joins the provided iterator with the provided separartor", () => {
+    assertStrictEquals(join([1, 2, 3, 4].values(), "☂"), "1☂2☂3☂4");
+  });
+
+  it('[[Call]] uses "," if no separator is provided', () => {
+    assertStrictEquals(join([1, 2, 3, 4].values()), "1,2,3,4");
+  });
+
+  it("[[Call]] uses the empty sting for nullish values", () => {
+    assertStrictEquals(
+      join([null, , null, undefined].values(), "☂"),
+      "☂☂☂",
+    );
+  });
+});
+
+describe("scalarValueString", () => {
+  it("[[Call]] replaces invalid values", () => {
+    assertStrictEquals(
+      scalarValueString("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
+      "Ii🎙\uFFFD\uFFFD\uFFFD\uFFFD🆗☺",
+    );
+  });
+});
+
+describe("scalarValues", () => {
+  it("[[Call]] returns an iterable", () => {
+    assertStrictEquals(
+      typeof scalarValues("")[Symbol.iterator],
+      "function",
+    );
+  });
+
+  it("[[Call]] returns an iterator", () => {
+    assertStrictEquals(typeof scalarValues("").next, "function");
+  });
+
+  it("[[Call]] returns a string code value iterator", () => {
+    assertStrictEquals(
+      scalarValues("")[Symbol.toStringTag],
+      "String Code Value Iterator",
+    );
+  });
+
+  it("[[Call]] iterates over the scalar values", () => {
+    assertEquals([
+      ...scalarValues("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
+    ], [
+      0x49,
+      0x69,
+      0x1F399,
+      0xFFFD,
+      0xFFFD,
+      0xFFFD,
+      0xFFFD,
+      0x1F197,
+      0x263A,
+    ]);
+  });
+});
+
+describe("splitOnASCIIWhitespace", () => {
+  it("[[Call]] splits on sequences of spaces", () => {
+    assertEquals(
+      splitOnASCIIWhitespace("🅰️   🅱️ 🆎  🅾️"),
+      ["🅰️", "🅱️", "🆎", "🅾️"],
+    );
+  });
+
+  it("[[Call]] splits on sequences of tabs", () => {
+    assertEquals(
+      splitOnASCIIWhitespace("🅰️\t\t\t🅱️\t🆎\t\t🅾️"),
+      ["🅰️", "🅱️", "🆎", "🅾️"],
+    );
+  });
+
+  it("[[Call]] splits on sequences of carriage returns", () => {
+    assertEquals(
+      splitOnASCIIWhitespace("🅰️\r\r\r🅱️\r🆎\r\r🅾️"),
+      ["🅰️", "🅱️", "🆎", "🅾️"],
+    );
+  });
+
+  it("[[Call]] splits on sequences of newlines", () => {
+    assertEquals(
+      splitOnASCIIWhitespace("🅰️\r\r\r🅱️\r🆎\r\r🅾️"),
+      ["🅰️", "🅱️", "🆎", "🅾️"],
+    );
+  });
+
+  it("[[Call]] splits on sequences of form feeds", () => {
+    assertEquals(
+      splitOnASCIIWhitespace("🅰️\f\f\f🅱️\f🆎\f\f🅾️"),
+      ["🅰️", "🅱️", "🆎", "🅾️"],
+    );
+  });
+
+  it("[[Call]] splits on mixed whitespace", () => {
+    assertEquals(
+      splitOnASCIIWhitespace("🅰️\f \t\n🅱️\r\n\r🆎\n\f🅾️"),
+      ["🅰️", "🅱️", "🆎", "🅾️"],
+    );
+  });
+
+  it("[[Call]] returns an array of just the empty string for the empty string", () => {
+    assertEquals(splitOnASCIIWhitespace(""), [""]);
+  });
+
+  it("[[Call]] returns a single token if there are no spaces", () => {
+    assertEquals(splitOnASCIIWhitespace("abcd"), ["abcd"]);
+  });
+
+  it("[[Call]] does not split on other kinds of whitespace", () => {
+    assertEquals(
+      splitOnASCIIWhitespace("a\u202F\u205F\xa0\v\0\bb"),
+      ["a\u202F\u205F\xa0\v\0\bb"],
+    );
+  });
+
+  it("[[Call]] trims leading and trailing whitespace", () => {
+    assertEquals(
+      splitOnASCIIWhitespace(
+        "\f\r\n\r\n \n\t🅰️\f \t\n🅱️\r🆎\n\f🅾️\n\f",
+      ),
+      ["🅰️", "🅱️", "🆎", "🅾️"],
+    );
+  });
+});
+
+describe("splitOnCommas", () => {
+  it("[[Call]] splits on commas", () => {
+    assertEquals(
+      splitOnCommas("🅰️,🅱️,🆎,🅾️"),
+      ["🅰️", "🅱️", "🆎", "🅾️"],
+    );
+  });
+
+  it("[[Call]] returns an array of just the empty string for the empty string", () => {
+    assertEquals(splitOnCommas(""), [""]);
+  });
+
+  it("[[Call]] returns a single token if there are no commas", () => {
+    assertEquals(splitOnCommas("abcd"), ["abcd"]);
+  });
+
+  it("[[Call]] splits into empty strings if there are only commas", () => {
+    assertEquals(splitOnCommas(",,,"), ["", "", "", ""]);
+  });
+
+  it("[[Call]] trims leading and trailing whitespace", () => {
+    assertEquals(
+      splitOnCommas("\f\r\n\r\n \n\t🅰️,🅱️,🆎,🅾️\n\f"),
+      ["🅰️", "🅱️", "🆎", "🅾️"],
+    );
+    assertEquals(
+      splitOnCommas("\f\r\n\r\n \n\t,,,\n\f"),
+      ["", "", "", ""],
+    );
+  });
+
+  it("[[Call]] removes whitespace from the split tokens", () => {
+    assertEquals(
+      splitOnCommas(
+        "\f\r\n\r\n \n\t🅰️\f , \t\n🅱️,\r\n\r🆎\n\f,🅾️\n\f",
+      ),
+      ["🅰️", "🅱️", "🆎", "🅾️"],
+    );
+    assertEquals(
+      splitOnCommas("\f\r\n\r\n \n\t\f , \t\n,\r\n\r\n\f,\n\f"),
+      ["", "", "", ""],
+    );
+  });
+});
+
+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",
+      ),
+      "🅰️ 🅱️ 🆎 🅾️",
+    );
+  });
+
+  it("[[Call]] returns the empty string for strings of whitespace", () => {
+    assertStrictEquals(
+      stripAndCollapseASCIIWhitespace("\f\r\n\r\n \n\t\f \n\f"),
+      "",
+    );
+  });
+
+  it("[[Call]] does not collapse other kinds of whitespace", () => {
+    assertEquals(
+      stripAndCollapseASCIIWhitespace("a\u202F\u205F\xa0\v\0\bb"),
+      "a\u202F\u205F\xa0\v\0\bb",
+    );
+  });
+});
+
+describe("stripLeadingAndTrailingASCIIWhitespace", () => {
+  it("[[Call]] trims leading and trailing whitespace", () => {
+    assertStrictEquals(
+      stripLeadingAndTrailingASCIIWhitespace(
+        "\f\r\n\r\n \n\t\f 🅰️🅱️🆎🅾️\n\f",
+      ),
+      "🅰️🅱️🆎🅾️",
+    );
+  });
+
+  it("[[Call]] returns the empty string for strings of whitespace", () => {
+    assertStrictEquals(
+      stripLeadingAndTrailingASCIIWhitespace("\f\r\n\r\n \n\t\f \n\f"),
+      "",
+    );
+  });
+
+  it("[[Call]] does not trim other kinds of whitespace", () => {
+    assertEquals(
+      stripLeadingAndTrailingASCIIWhitespace(
+        "\v\u202F\u205Fx\0\b\xa0",
+      ),
+      "\v\u202F\u205Fx\0\b\xa0",
+    );
+  });
+
+  it("[[Call]] does not adjust inner whitespace", () => {
+    assertEquals(
+      stripLeadingAndTrailingASCIIWhitespace("a   b"),
+      "a   b",
+    );
+  });
+});
This page took 0.026615 seconds and 4 git commands to generate.