1 // ♓🌟 Piscēs ∷ collection.test.js
2 // ====================================================================
4 // Copyright © 2022 Lady [@ Lady’s Computer].
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/>.
19 } from "./dev-deps.js";
21 canonicalNumericIndexString
,
31 } from "./collection.js";
33 describe("canonicalNumericIndexString", () => {
34 it("[[Call]] returns undefined for nonstrings", () => {
35 assertStrictEquals(canonicalNumericIndexString(1), void {});
38 it("[[Call]] returns undefined for noncanonical strings", () => {
39 assertStrictEquals(canonicalNumericIndexString(""), void {});
40 assertStrictEquals(canonicalNumericIndexString("01"), void {});
42 canonicalNumericIndexString("9007199254740993"),
47 it('[[Call]] returns -0 for "-0"', () => {
48 assertStrictEquals(canonicalNumericIndexString("-0"), -0);
51 it("[[Call]] returns the corresponding number for canonical strings", () => {
52 assertStrictEquals(canonicalNumericIndexString("0"), 0);
53 assertStrictEquals(canonicalNumericIndexString("-0.25"), -0.25);
55 canonicalNumericIndexString("9007199254740992"),
58 assertStrictEquals(canonicalNumericIndexString("NaN"), 0 / 0);
59 assertStrictEquals(canonicalNumericIndexString("Infinity"), 1 / 0);
61 canonicalNumericIndexString("-Infinity"),
67 describe("findIndexedEntry", () => {
68 it("[[Call]] returns undefined if no matching entry exists", () => {
69 assertStrictEquals(findIndexedEntry([], () => true), void {});
70 assertStrictEquals(findIndexedEntry([1], () => false), void {});
73 it("[[Call]] returns an entry for the first match", () => {
75 findIndexedEntry([, true, false], ($) => $ ?? true),
79 findIndexedEntry(["failure", "success"], ($) => $ == "success"),
84 it("[[Call]] works on arraylike objects", () => {
86 findIndexedEntry({ 1: "success", length
: 2 }, ($) => $),
90 findIndexedEntry({ 1: "failure", length
: 1 }, ($) => $),
95 it("[[Call]] only gets the value once", () => {
96 const get1
= spy(() => true);
103 assertSpyCalls(get1
, 1);
106 it("[[Call]] passes the value, index, and this value to the callback", () => {
107 const arr
= ["failure", "success", "success"];
108 const callback
= spy(($) => $ === "success");
110 findIndexedEntry(arr
, callback
, thisArg
);
111 assertSpyCalls(callback
, 2);
112 assertSpyCall(callback
, 0, {
113 args
: ["failure", 0, arr
],
116 assertSpyCall(callback
, 1, {
117 args
: ["success", 1, arr
],
123 describe("isArrayIndexString", () => {
124 it("[[Call]] returns false for nonstrings", () => {
125 assertStrictEquals(isArrayIndexString(1), false);
128 it("[[Call]] returns false for noncanonical strings", () => {
129 assertStrictEquals(isArrayIndexString(""), false);
130 assertStrictEquals(isArrayIndexString("01"), false);
131 assertStrictEquals(isArrayIndexString("9007199254740993"), false);
134 it("[[Call]] returns false for nonfinite numbers", () => {
135 assertStrictEquals(isArrayIndexString("NaN"), false);
136 assertStrictEquals(isArrayIndexString("Infinity"), false);
137 assertStrictEquals(isArrayIndexString("-Infinity"), false);
140 it("[[Call]] returns false for negative numbers", () => {
141 assertStrictEquals(isArrayIndexString("-0"), false);
142 assertStrictEquals(isArrayIndexString("-1"), false);
145 it("[[Call]] returns false for nonintegers", () => {
146 assertStrictEquals(isArrayIndexString("0.25"), false);
147 assertStrictEquals(isArrayIndexString("1.1"), false);
150 it("[[Call]] returns false for numbers greater than or equal to -1 >>> 0", () => {
151 assertStrictEquals(isArrayIndexString(String(-1 >>> 0)), false);
153 isArrayIndexString(String((-1 >>> 0) + 1)),
158 it("[[Call]] returns true for array lengths less than -1 >>> 0", () => {
159 assertStrictEquals(isArrayIndexString("0"), true);
161 isArrayIndexString(String((-1 >>> 0) - 1)),
167 describe("isArraylikeObject", () => {
168 it("[[Call]] returns false for primitives", () => {
169 assertStrictEquals(isArraylikeObject("failure"), false);
172 it("[[Call]] returns false if length throws", () => {
183 it("[[Call]] returns false if length is not a number and cannot be converted to one", () => {
184 assertStrictEquals(isArraylikeObject({ length
: 1n
}), false);
187 it("[[Call]] returns true if length is convertable to a number", () => {
188 assertStrictEquals(isArraylikeObject({ length
: -0 }), true);
189 assertStrictEquals(isArraylikeObject({ length
: 1 }), true);
190 assertStrictEquals(isArraylikeObject({ length
: -1.25 }), true);
192 isArraylikeObject({ length
: 9007199254740992 }),
195 assertStrictEquals(isArraylikeObject({ length
: Infinity
}), true);
196 assertStrictEquals(isArraylikeObject({ length
: "success" }), true);
200 describe("isCollection", () => {
201 it("[[Call]] returns false for primitives", () => {
202 assertStrictEquals(isCollection("failure"), false);
205 it("[[Call]] returns false if length throws", () => {
216 it("[[Call]] returns false if length is not an integer index and cannot be converted to one", () => {
218 isCollection({ length
: -1, [Symbol
.isConcatSpreadable
]: true }),
224 [Symbol
.isConcatSpreadable
]: true,
230 length
: 9007199254740992,
231 [Symbol
.isConcatSpreadable
]: true,
237 it("[[Call]] returns true if length is an integer index and the object is concat spreadable", () => {
239 isCollection({ length
: 1, [Symbol
.isConcatSpreadable
]: true }),
243 isCollection({ length
: 0, [Symbol
.isConcatSpreadable
]: true }),
248 length
: 9007199254740991,
249 [Symbol
.isConcatSpreadable
]: true,
255 it("[[Call]] returns true if length can be converted to an index without throwing an error and the object is concat spreadable", () => {
257 isCollection({ length
: -0, [Symbol
.isConcatSpreadable
]: true }),
261 isCollection({ length
: NaN
, [Symbol
.isConcatSpreadable
]: true }),
267 describe("isConcatSpreadable", () => {
268 it("[[Call]] returns false for primitives", () => {
269 assertStrictEquals(isConcatSpreadable("failure"), false);
272 it("[[Call]] returns false if [Symbol.isConcatSpreadable] is null or false", () => {
275 Object
.assign([], { [Symbol
.isConcatSpreadable
]: null }),
281 Object
.assign([], { [Symbol
.isConcatSpreadable
]: false }),
287 it("[[Call]] returns true if [Symbol.isConcatSpreadable] is undefined and the object is an array", () => {
290 Object
.assign([], { [Symbol
.isConcatSpreadable
]: undefined }),
296 it("[[Call]] returns true if [Symbol.isConcatSpreadable] is true", () => {
298 isConcatSpreadable({ [Symbol
.isConcatSpreadable
]: true }),
304 describe("isIntegerIndexString", () => {
305 it("[[Call]] returns false for nonstrings", () => {
306 assertStrictEquals(isIntegerIndexString(1), false);
309 it("[[Call]] returns false for noncanonical strings", () => {
310 assertStrictEquals(isIntegerIndexString(""), false);
311 assertStrictEquals(isIntegerIndexString("01"), false);
313 isIntegerIndexString("9007199254740993"),
318 it("[[Call]] returns false for nonfinite numbers", () => {
319 assertStrictEquals(isIntegerIndexString("NaN"), false);
320 assertStrictEquals(isIntegerIndexString("Infinity"), false);
321 assertStrictEquals(isIntegerIndexString("-Infinity"), false);
324 it("[[Call]] returns false for negative numbers", () => {
325 assertStrictEquals(isIntegerIndexString("-0"), false);
326 assertStrictEquals(isIntegerIndexString("-1"), false);
329 it("[[Call]] returns false for nonintegers", () => {
330 assertStrictEquals(isIntegerIndexString("0.25"), false);
331 assertStrictEquals(isIntegerIndexString("1.1"), false);
334 it("[[Call]] returns false for numbers greater than or equal to 2 ** 53", () => {
336 isIntegerIndexString("9007199254740992"),
341 it("[[Call]] returns true for safe canonical integer strings", () => {
342 assertStrictEquals(isIntegerIndexString("0"), true);
343 assertStrictEquals(isIntegerIndexString("9007199254740991"), true);
347 describe("lengthOfArraylike", () => {
348 it("[[Call]] returns the length", () => {
350 lengthOfArraylike({ length
: 9007199254740991 }),
355 it("[[Call]] returns a non·nan result", () => {
356 assertStrictEquals(lengthOfArraylike({ length
: NaN
}), 0);
357 assertStrictEquals(lengthOfArraylike({ length
: "failure" }), 0);
360 it("[[Call]] returns an integral result", () => {
361 assertStrictEquals(lengthOfArraylike({ length
: 0.25 }), 0);
362 assertStrictEquals(lengthOfArraylike({ length
: 1.1 }), 1);
365 it("[[Call]] returns a result greater than or equal to zero", () => {
366 assertStrictEquals(lengthOfArraylike({ length
: -0 }), 0);
367 assertStrictEquals(lengthOfArraylike({ length
: -1 }), 0);
368 assertStrictEquals(lengthOfArraylike({ length
: -Infinity
}), 0);
371 it("[[Call]] returns a result less than 2 ** 53", () => {
373 lengthOfArraylike({ length
: 9007199254740992 }),
377 lengthOfArraylike({ length
: Infinity
}),
383 describe("toIndex", () => {
384 it("[[Call]] returns an index", () => {
385 assertStrictEquals(toIndex(9007199254740991), 9007199254740991);
388 it("[[Call]] returns zero for a zerolike result", () => {
389 assertStrictEquals(toIndex(NaN
), 0);
390 assertStrictEquals(toIndex("failure"), 0);
391 assertStrictEquals(toIndex(-0), 0);
394 it("[[Call]] rounds down to the nearest integer", () => {
395 assertStrictEquals(toIndex(0.25), 0);
396 assertStrictEquals(toIndex(1.1), 1);
399 it("[[Call]] throws when provided a negative number", () => {
400 assertThrows(() => toIndex(-1));
401 assertThrows(() => toIndex(-Infinity
));
404 it("[[Call]] throws when provided a number greater than or equal to 2 ** 53", () => {
405 assertThrows(() => toIndex(9007199254740992));
406 assertThrows(() => toIndex(Infinity
));
410 describe("toLength", () => {
411 it("[[Call]] returns a length", () => {
412 assertStrictEquals(toLength(9007199254740991), 9007199254740991);
415 it("[[Call]] returns a non·nan result", () => {
416 assertStrictEquals(toLength(NaN
), 0);
417 assertStrictEquals(toLength("failure"), 0);
420 it("[[Call]] returns an integral result", () => {
421 assertStrictEquals(toLength(0.25), 0);
422 assertStrictEquals(toLength(1.1), 1);
425 it("[[Call]] returns a result greater than or equal to zero", () => {
426 assertStrictEquals(toLength(-0), 0);
427 assertStrictEquals(toLength(-1), 0);
428 assertStrictEquals(toLength(-Infinity
), 0);
431 it("[[Call]] returns a result less than 2 ** 53", () => {
432 assertStrictEquals(toLength(9007199254740992), 9007199254740991);
433 assertStrictEquals(toLength(Infinity
), 9007199254740991);