]> Ladyโ€™s Gitweb - Pisces/blob - string.test.js
Add string functions and unit tests
[Pisces] / string.test.js
1 // โ™“๐ŸŒŸ Piscฤ“s โˆท string.test.js
2 // ====================================================================
3 //
4 // Copyright ยฉ 2022 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 assertEquals,
12 assertStrictEquals,
13 describe,
14 it,
15 } from "./dev-deps.js";
16 import {
17 asciiLowercase,
18 asciiUppercase,
19 codepoints,
20 codeUnits,
21 getCharacter,
22 join,
23 scalarValues,
24 scalarValueString,
25 splitOnASCIIWhitespace,
26 splitOnCommas,
27 stripAndCollapseASCIIWhitespace,
28 stripLeadingAndTrailingASCIIWhitespace,
29 } from "./string.js";
30
31 describe("asciiLowercase", () => {
32 it("[[Call]] lowercases (just) AยทSยทCยทIยทI letters", () => {
33 assertStrictEquals(asciiLowercase("aBลฟร†ss Ftษษ‚รŸ"), "abลฟร†ss ftษษ‚รŸ");
34 });
35 });
36
37 describe("asciiUppercase", () => {
38 it("[[Call]] uppercases (just) AยทSยทCยทIยทI letters", () => {
39 assertStrictEquals(asciiUppercase("aBลฟร†ss Ftษษ‚รŸ"), "ABลฟร†SS FTษษ‚รŸ");
40 });
41 });
42
43 describe("codeUnits", () => {
44 it("[[Call]] returns an iterable", () => {
45 assertStrictEquals(
46 typeof codeUnits("")[Symbol.iterator],
47 "function",
48 );
49 });
50
51 it("[[Call]] returns an iterator", () => {
52 assertStrictEquals(typeof codeUnits("").next, "function");
53 });
54
55 it("[[Call]] returns a string code value iterator", () => {
56 assertStrictEquals(
57 codeUnits("")[Symbol.toStringTag],
58 "String Code Value Iterator",
59 );
60 });
61
62 it("[[Call]] iterates over the code units", () => {
63 assertEquals([
64 ...codeUnits("Ii๐ŸŽ™\uDFFF\uDD96\uD83C\uD800๐Ÿ†—โ˜บ"),
65 ], [
66 0x49,
67 0x69,
68 0xD83C,
69 0xDF99,
70 0xDFFF,
71 0xDD96,
72 0xD83C,
73 0xD800,
74 0xD83C,
75 0xDD97,
76 0x263A,
77 ]);
78 });
79 });
80
81 describe("codepoints", () => {
82 it("[[Call]] returns an iterable", () => {
83 assertStrictEquals(
84 typeof codepoints("")[Symbol.iterator],
85 "function",
86 );
87 });
88
89 it("[[Call]] returns an iterator", () => {
90 assertStrictEquals(typeof codepoints("").next, "function");
91 });
92
93 it("[[Call]] returns a string code value iterator", () => {
94 assertStrictEquals(
95 codepoints("")[Symbol.toStringTag],
96 "String Code Value Iterator",
97 );
98 });
99
100 it("[[Call]] iterates over the codepoints", () => {
101 assertEquals([
102 ...codepoints("Ii๐ŸŽ™\uDFFF\uDD96\uD83C\uD800๐Ÿ†—โ˜บ"),
103 ], [
104 0x49,
105 0x69,
106 0x1F399,
107 0xDFFF,
108 0xDD96,
109 0xD83C,
110 0xD800,
111 0x1F197,
112 0x263A,
113 ]);
114 });
115 });
116
117 describe("getCharacter", () => {
118 it("[[Call]] returns the character at the provided position", () => {
119 assertStrictEquals(getCharacter("Ii๐ŸŽ™๐Ÿ†—โ˜บ", 4), "๐Ÿ†—");
120 });
121
122 it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
123 assertStrictEquals(getCharacter("Ii๐ŸŽ™๐Ÿ†—โ˜บ", 5), "\uDD97");
124 });
125
126 it("[[Call]] returns undefined for an outโ€ofโ€bounds index", () => {
127 assertStrictEquals(getCharacter("Ii๐ŸŽ™๐Ÿ†—โ˜บ", -1), void {});
128 assertStrictEquals(getCharacter("Ii๐ŸŽ™๐Ÿ†—โ˜บ", 7), void {});
129 });
130 });
131
132 describe("join", () => {
133 it("[[Call]] joins the provided iterator with the provided separartor", () => {
134 assertStrictEquals(join([1, 2, 3, 4].values(), "โ˜‚"), "1โ˜‚2โ˜‚3โ˜‚4");
135 });
136
137 it('[[Call]] uses "," if no separator is provided', () => {
138 assertStrictEquals(join([1, 2, 3, 4].values()), "1,2,3,4");
139 });
140
141 it("[[Call]] uses the empty sting for nullish values", () => {
142 assertStrictEquals(
143 join([null, , null, undefined].values(), "โ˜‚"),
144 "โ˜‚โ˜‚โ˜‚",
145 );
146 });
147 });
148
149 describe("scalarValueString", () => {
150 it("[[Call]] replaces invalid values", () => {
151 assertStrictEquals(
152 scalarValueString("Ii๐ŸŽ™\uDFFF\uDD96\uD83C\uD800๐Ÿ†—โ˜บ"),
153 "Ii๐ŸŽ™\uFFFD\uFFFD\uFFFD\uFFFD๐Ÿ†—โ˜บ",
154 );
155 });
156 });
157
158 describe("scalarValues", () => {
159 it("[[Call]] returns an iterable", () => {
160 assertStrictEquals(
161 typeof scalarValues("")[Symbol.iterator],
162 "function",
163 );
164 });
165
166 it("[[Call]] returns an iterator", () => {
167 assertStrictEquals(typeof scalarValues("").next, "function");
168 });
169
170 it("[[Call]] returns a string code value iterator", () => {
171 assertStrictEquals(
172 scalarValues("")[Symbol.toStringTag],
173 "String Code Value Iterator",
174 );
175 });
176
177 it("[[Call]] iterates over the scalar values", () => {
178 assertEquals([
179 ...scalarValues("Ii๐ŸŽ™\uDFFF\uDD96\uD83C\uD800๐Ÿ†—โ˜บ"),
180 ], [
181 0x49,
182 0x69,
183 0x1F399,
184 0xFFFD,
185 0xFFFD,
186 0xFFFD,
187 0xFFFD,
188 0x1F197,
189 0x263A,
190 ]);
191 });
192 });
193
194 describe("splitOnASCIIWhitespace", () => {
195 it("[[Call]] splits on sequences of spaces", () => {
196 assertEquals(
197 splitOnASCIIWhitespace("๐Ÿ…ฐ๏ธ ๐Ÿ…ฑ๏ธ ๐Ÿ†Ž ๐Ÿ…พ๏ธ"),
198 ["๐Ÿ…ฐ๏ธ", "๐Ÿ…ฑ๏ธ", "๐Ÿ†Ž", "๐Ÿ…พ๏ธ"],
199 );
200 });
201
202 it("[[Call]] splits on sequences of tabs", () => {
203 assertEquals(
204 splitOnASCIIWhitespace("๐Ÿ…ฐ๏ธ\t\t\t๐Ÿ…ฑ๏ธ\t๐Ÿ†Ž\t\t๐Ÿ…พ๏ธ"),
205 ["๐Ÿ…ฐ๏ธ", "๐Ÿ…ฑ๏ธ", "๐Ÿ†Ž", "๐Ÿ…พ๏ธ"],
206 );
207 });
208
209 it("[[Call]] splits on sequences of carriage returns", () => {
210 assertEquals(
211 splitOnASCIIWhitespace("๐Ÿ…ฐ๏ธ\r\r\r๐Ÿ…ฑ๏ธ\r๐Ÿ†Ž\r\r๐Ÿ…พ๏ธ"),
212 ["๐Ÿ…ฐ๏ธ", "๐Ÿ…ฑ๏ธ", "๐Ÿ†Ž", "๐Ÿ…พ๏ธ"],
213 );
214 });
215
216 it("[[Call]] splits on sequences of newlines", () => {
217 assertEquals(
218 splitOnASCIIWhitespace("๐Ÿ…ฐ๏ธ\r\r\r๐Ÿ…ฑ๏ธ\r๐Ÿ†Ž\r\r๐Ÿ…พ๏ธ"),
219 ["๐Ÿ…ฐ๏ธ", "๐Ÿ…ฑ๏ธ", "๐Ÿ†Ž", "๐Ÿ…พ๏ธ"],
220 );
221 });
222
223 it("[[Call]] splits on sequences of form feeds", () => {
224 assertEquals(
225 splitOnASCIIWhitespace("๐Ÿ…ฐ๏ธ\f\f\f๐Ÿ…ฑ๏ธ\f๐Ÿ†Ž\f\f๐Ÿ…พ๏ธ"),
226 ["๐Ÿ…ฐ๏ธ", "๐Ÿ…ฑ๏ธ", "๐Ÿ†Ž", "๐Ÿ…พ๏ธ"],
227 );
228 });
229
230 it("[[Call]] splits on mixed whitespace", () => {
231 assertEquals(
232 splitOnASCIIWhitespace("๐Ÿ…ฐ๏ธ\f \t\n๐Ÿ…ฑ๏ธ\r\n\r๐Ÿ†Ž\n\f๐Ÿ…พ๏ธ"),
233 ["๐Ÿ…ฐ๏ธ", "๐Ÿ…ฑ๏ธ", "๐Ÿ†Ž", "๐Ÿ…พ๏ธ"],
234 );
235 });
236
237 it("[[Call]] returns an array of just the empty string for the empty string", () => {
238 assertEquals(splitOnASCIIWhitespace(""), [""]);
239 });
240
241 it("[[Call]] returns a single token if there are no spaces", () => {
242 assertEquals(splitOnASCIIWhitespace("abcd"), ["abcd"]);
243 });
244
245 it("[[Call]] does not split on other kinds of whitespace", () => {
246 assertEquals(
247 splitOnASCIIWhitespace("a\u202F\u205F\xa0\v\0\bb"),
248 ["a\u202F\u205F\xa0\v\0\bb"],
249 );
250 });
251
252 it("[[Call]] trims leading and trailing whitespace", () => {
253 assertEquals(
254 splitOnASCIIWhitespace(
255 "\f\r\n\r\n \n\t๐Ÿ…ฐ๏ธ\f \t\n๐Ÿ…ฑ๏ธ\r๐Ÿ†Ž\n\f๐Ÿ…พ๏ธ\n\f",
256 ),
257 ["๐Ÿ…ฐ๏ธ", "๐Ÿ…ฑ๏ธ", "๐Ÿ†Ž", "๐Ÿ…พ๏ธ"],
258 );
259 });
260 });
261
262 describe("splitOnCommas", () => {
263 it("[[Call]] splits on commas", () => {
264 assertEquals(
265 splitOnCommas("๐Ÿ…ฐ๏ธ,๐Ÿ…ฑ๏ธ,๐Ÿ†Ž,๐Ÿ…พ๏ธ"),
266 ["๐Ÿ…ฐ๏ธ", "๐Ÿ…ฑ๏ธ", "๐Ÿ†Ž", "๐Ÿ…พ๏ธ"],
267 );
268 });
269
270 it("[[Call]] returns an array of just the empty string for the empty string", () => {
271 assertEquals(splitOnCommas(""), [""]);
272 });
273
274 it("[[Call]] returns a single token if there are no commas", () => {
275 assertEquals(splitOnCommas("abcd"), ["abcd"]);
276 });
277
278 it("[[Call]] splits into empty strings if there are only commas", () => {
279 assertEquals(splitOnCommas(",,,"), ["", "", "", ""]);
280 });
281
282 it("[[Call]] trims leading and trailing whitespace", () => {
283 assertEquals(
284 splitOnCommas("\f\r\n\r\n \n\t๐Ÿ…ฐ๏ธ,๐Ÿ…ฑ๏ธ,๐Ÿ†Ž,๐Ÿ…พ๏ธ\n\f"),
285 ["๐Ÿ…ฐ๏ธ", "๐Ÿ…ฑ๏ธ", "๐Ÿ†Ž", "๐Ÿ…พ๏ธ"],
286 );
287 assertEquals(
288 splitOnCommas("\f\r\n\r\n \n\t,,,\n\f"),
289 ["", "", "", ""],
290 );
291 });
292
293 it("[[Call]] removes whitespace from the split tokens", () => {
294 assertEquals(
295 splitOnCommas(
296 "\f\r\n\r\n \n\t๐Ÿ…ฐ๏ธ\f , \t\n๐Ÿ…ฑ๏ธ,\r\n\r๐Ÿ†Ž\n\f,๐Ÿ…พ๏ธ\n\f",
297 ),
298 ["๐Ÿ…ฐ๏ธ", "๐Ÿ…ฑ๏ธ", "๐Ÿ†Ž", "๐Ÿ…พ๏ธ"],
299 );
300 assertEquals(
301 splitOnCommas("\f\r\n\r\n \n\t\f , \t\n,\r\n\r\n\f,\n\f"),
302 ["", "", "", ""],
303 );
304 });
305 });
306
307 describe("stripAndCollapseASCIIWhitespace", () => {
308 it("[[Call]] collapses mixed inner whitespace", () => {
309 assertEquals(
310 stripAndCollapseASCIIWhitespace("๐Ÿ…ฐ๏ธ\f \t\n๐Ÿ…ฑ๏ธ\r\n\r๐Ÿ†Ž\n\f๐Ÿ…พ๏ธ"),
311 "๐Ÿ…ฐ๏ธ ๐Ÿ…ฑ๏ธ ๐Ÿ†Ž ๐Ÿ…พ๏ธ",
312 );
313 });
314
315 it("[[Call]] trims leading and trailing whitespace", () => {
316 assertStrictEquals(
317 stripAndCollapseASCIIWhitespace(
318 "\f\r\n\r\n \n\t\f ๐Ÿ…ฐ๏ธ\f \t\n๐Ÿ…ฑ๏ธ\r\n\r๐Ÿ†Ž\n\f๐Ÿ…พ๏ธ\n\f",
319 ),
320 "๐Ÿ…ฐ๏ธ ๐Ÿ…ฑ๏ธ ๐Ÿ†Ž ๐Ÿ…พ๏ธ",
321 );
322 });
323
324 it("[[Call]] returns the empty string for strings of whitespace", () => {
325 assertStrictEquals(
326 stripAndCollapseASCIIWhitespace("\f\r\n\r\n \n\t\f \n\f"),
327 "",
328 );
329 });
330
331 it("[[Call]] does not collapse other kinds of whitespace", () => {
332 assertEquals(
333 stripAndCollapseASCIIWhitespace("a\u202F\u205F\xa0\v\0\bb"),
334 "a\u202F\u205F\xa0\v\0\bb",
335 );
336 });
337 });
338
339 describe("stripLeadingAndTrailingASCIIWhitespace", () => {
340 it("[[Call]] trims leading and trailing whitespace", () => {
341 assertStrictEquals(
342 stripLeadingAndTrailingASCIIWhitespace(
343 "\f\r\n\r\n \n\t\f ๐Ÿ…ฐ๏ธ๐Ÿ…ฑ๏ธ๐Ÿ†Ž๐Ÿ…พ๏ธ\n\f",
344 ),
345 "๐Ÿ…ฐ๏ธ๐Ÿ…ฑ๏ธ๐Ÿ†Ž๐Ÿ…พ๏ธ",
346 );
347 });
348
349 it("[[Call]] returns the empty string for strings of whitespace", () => {
350 assertStrictEquals(
351 stripLeadingAndTrailingASCIIWhitespace("\f\r\n\r\n \n\t\f \n\f"),
352 "",
353 );
354 });
355
356 it("[[Call]] does not trim other kinds of whitespace", () => {
357 assertEquals(
358 stripLeadingAndTrailingASCIIWhitespace(
359 "\v\u202F\u205Fx\0\b\xa0",
360 ),
361 "\v\u202F\u205Fx\0\b\xa0",
362 );
363 });
364
365 it("[[Call]] does not adjust inner whitespace", () => {
366 assertEquals(
367 stripLeadingAndTrailingASCIIWhitespace("a b"),
368 "a b",
369 );
370 });
371 });
This page took 0.088926 seconds and 5 git commands to generate.