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
,
30 } from "./collection.js";
32 describe("canonicalNumericIndexString", () => {
33 it("[[Call]] returns undefined for nonstrings", () => {
34 assertStrictEquals(canonicalNumericIndexString(1), void {});
37 it("[[Call]] returns undefined for noncanonical strings", () => {
38 assertStrictEquals(canonicalNumericIndexString(""), void {});
39 assertStrictEquals(canonicalNumericIndexString("01"), void {});
41 canonicalNumericIndexString("9007199254740993"),
46 it('[[Call]] returns -0 for "-0"', () => {
47 assertStrictEquals(canonicalNumericIndexString("-0"), -0);
50 it("[[Call]] returns the corresponding number for canonical strings", () => {
51 assertStrictEquals(canonicalNumericIndexString("0"), 0);
52 assertStrictEquals(canonicalNumericIndexString("-0.25"), -0.25);
54 canonicalNumericIndexString("9007199254740992"),
57 assertStrictEquals(canonicalNumericIndexString("NaN"), 0 / 0);
58 assertStrictEquals(canonicalNumericIndexString("Infinity"), 1 / 0);
60 canonicalNumericIndexString("-Infinity"),
66 describe("findIndexedEntry", () => {
67 it("[[Call]] returns undefined if no matching entry exists", () => {
68 assertStrictEquals(findIndexedEntry([], () => true), void {});
69 assertStrictEquals(findIndexedEntry([1], () => false), void {});
72 it("[[Call]] returns an entry for the first match", () => {
74 findIndexedEntry([, true, false], ($) => $ ?? true),
78 findIndexedEntry(["failure", "success"], ($) => $ == "success"),
83 it("[[Call]] works on arraylike objects", () => {
85 findIndexedEntry({ 1: "success", length
: 2 }, ($) => $),
89 findIndexedEntry({ 1: "failure", length
: 1 }, ($) => $),
94 it("[[Call]] only gets the value once", () => {
95 const get1
= spy(() => true);
102 assertSpyCalls(get1
, 1);
105 it("[[Call]] passes the value, index, and this value to the callback", () => {
106 const arr
= ["failure", "success", "success"];
107 const callback
= spy(($) => $ === "success");
109 findIndexedEntry(arr
, callback
, thisArg
);
110 assertSpyCalls(callback
, 2);
111 assertSpyCall(callback
, 0, {
112 args
: ["failure", 0, arr
],
115 assertSpyCall(callback
, 1, {
116 args
: ["success", 1, arr
],
122 describe("isArrayIndexString", () => {
123 it("[[Call]] returns false for nonstrings", () => {
124 assertStrictEquals(isArrayIndexString(1), false);
127 it("[[Call]] returns false for noncanonical strings", () => {
128 assertStrictEquals(isArrayIndexString(""), false);
129 assertStrictEquals(isArrayIndexString("01"), false);
130 assertStrictEquals(isArrayIndexString("9007199254740993"), false);
133 it("[[Call]] returns false for nonfinite numbers", () => {
134 assertStrictEquals(isArrayIndexString("NaN"), false);
135 assertStrictEquals(isArrayIndexString("Infinity"), false);
136 assertStrictEquals(isArrayIndexString("-Infinity"), false);
139 it("[[Call]] returns false for negative numbers", () => {
140 assertStrictEquals(isArrayIndexString("-0"), false);
141 assertStrictEquals(isArrayIndexString("-1"), false);
144 it("[[Call]] returns false for nonintegers", () => {
145 assertStrictEquals(isArrayIndexString("0.25"), false);
146 assertStrictEquals(isArrayIndexString("1.1"), false);
149 it("[[Call]] returns false for numbers greater than or equal to -1 >>> 0", () => {
150 assertStrictEquals(isArrayIndexString(String(-1 >>> 0)), false);
152 isArrayIndexString(String((-1 >>> 0) + 1)),
157 it("[[Call]] returns true for array lengths less than -1 >>> 0", () => {
158 assertStrictEquals(isArrayIndexString("0"), true);
160 isArrayIndexString(String((-1 >>> 0) - 1)),
166 describe("isCollection", () => {
167 it("[[Call]] returns false for primitives", () => {
168 assertStrictEquals(isCollection("failure"), false);
171 it("[[Call]] returns false if length throws", () => {
182 it("[[Call]] returns false if length is not an integer index and cannot be converted to one", () => {
184 isCollection({ length
: -1, [Symbol
.isConcatSpreadable
]: true }),
190 [Symbol
.isConcatSpreadable
]: true,
196 length
: 9007199254740992,
197 [Symbol
.isConcatSpreadable
]: true,
203 it("[[Call]] returns true if length is an integer index and the object is concat spreadable", () => {
205 isCollection({ length
: 1, [Symbol
.isConcatSpreadable
]: true }),
209 isCollection({ length
: 0, [Symbol
.isConcatSpreadable
]: true }),
214 length
: 9007199254740991,
215 [Symbol
.isConcatSpreadable
]: true,
221 it("[[Call]] returns true if length can be converted to an index without throwing an error and the object is concat spreadable", () => {
223 isCollection({ length
: -0, [Symbol
.isConcatSpreadable
]: true }),
227 isCollection({ length
: NaN
, [Symbol
.isConcatSpreadable
]: true }),
233 describe("isConcatSpreadable", () => {
234 it("[[Call]] returns false for primitives", () => {
235 assertStrictEquals(isConcatSpreadable("failure"), false);
238 it("[[Call]] returns false if [Symbol.isConcatSpreadable] is null or false", () => {
241 Object
.assign([], { [Symbol
.isConcatSpreadable
]: null }),
247 Object
.assign([], { [Symbol
.isConcatSpreadable
]: false }),
253 it("[[Call]] returns true if [Symbol.isConcatSpreadable] is undefined and the object is an array", () => {
256 Object
.assign([], { [Symbol
.isConcatSpreadable
]: undefined }),
262 it("[[Call]] returns true if [Symbol.isConcatSpreadable] is true", () => {
264 isConcatSpreadable({ [Symbol
.isConcatSpreadable
]: true }),
270 describe("isIntegerIndexString", () => {
271 it("[[Call]] returns false for nonstrings", () => {
272 assertStrictEquals(isIntegerIndexString(1), false);
275 it("[[Call]] returns false for noncanonical strings", () => {
276 assertStrictEquals(isIntegerIndexString(""), false);
277 assertStrictEquals(isIntegerIndexString("01"), false);
279 isIntegerIndexString("9007199254740993"),
284 it("[[Call]] returns false for nonfinite numbers", () => {
285 assertStrictEquals(isIntegerIndexString("NaN"), false);
286 assertStrictEquals(isIntegerIndexString("Infinity"), false);
287 assertStrictEquals(isIntegerIndexString("-Infinity"), false);
290 it("[[Call]] returns false for negative numbers", () => {
291 assertStrictEquals(isIntegerIndexString("-0"), false);
292 assertStrictEquals(isIntegerIndexString("-1"), false);
295 it("[[Call]] returns false for nonintegers", () => {
296 assertStrictEquals(isIntegerIndexString("0.25"), false);
297 assertStrictEquals(isIntegerIndexString("1.1"), false);
300 it("[[Call]] returns false for numbers greater than or equal to 2 ** 53", () => {
302 isIntegerIndexString("9007199254740992"),
307 it("[[Call]] returns true for safe canonical integer strings", () => {
308 assertStrictEquals(isIntegerIndexString("0"), true);
309 assertStrictEquals(isIntegerIndexString("9007199254740991"), true);
313 describe("lengthOfArrayLike", () => {
314 it("[[Call]] returns the length", () => {
316 lengthOfArrayLike({ length
: 9007199254740991 }),
321 it("[[Call]] returns a non·nan result", () => {
322 assertStrictEquals(lengthOfArrayLike({ length
: NaN
}), 0);
323 assertStrictEquals(lengthOfArrayLike({ length
: "failure" }), 0);
326 it("[[Call]] returns an integral result", () => {
327 assertStrictEquals(lengthOfArrayLike({ length
: 0.25 }), 0);
328 assertStrictEquals(lengthOfArrayLike({ length
: 1.1 }), 1);
331 it("[[Call]] returns a result greater than or equal to zero", () => {
332 assertStrictEquals(lengthOfArrayLike({ length
: -0 }), 0);
333 assertStrictEquals(lengthOfArrayLike({ length
: -1 }), 0);
334 assertStrictEquals(lengthOfArrayLike({ length
: -Infinity
}), 0);
337 it("[[Call]] returns a result less than 2 ** 53", () => {
339 lengthOfArrayLike({ length
: 9007199254740992 }),
343 lengthOfArrayLike({ length
: Infinity
}),
349 describe("toIndex", () => {
350 it("[[Call]] returns an index", () => {
351 assertStrictEquals(toIndex(9007199254740991), 9007199254740991);
354 it("[[Call]] returns zero for a zerolike result", () => {
355 assertStrictEquals(toIndex(NaN
), 0);
356 assertStrictEquals(toIndex("failure"), 0);
357 assertStrictEquals(toIndex(-0), 0);
360 it("[[Call]] rounds down to the nearest integer", () => {
361 assertStrictEquals(toIndex(0.25), 0);
362 assertStrictEquals(toIndex(1.1), 1);
365 it("[[Call]] throws when provided a negative number", () => {
366 assertThrows(() => toIndex(-1));
367 assertThrows(() => toIndex(-Infinity
));
370 it("[[Call]] throws when provided a number greater than or equal to 2 ** 53", () => {
371 assertThrows(() => toIndex(9007199254740992));
372 assertThrows(() => toIndex(Infinity
));
376 describe("toLength", () => {
377 it("[[Call]] returns a length", () => {
378 assertStrictEquals(toLength(9007199254740991), 9007199254740991);
381 it("[[Call]] returns a non·nan result", () => {
382 assertStrictEquals(toLength(NaN
), 0);
383 assertStrictEquals(toLength("failure"), 0);
386 it("[[Call]] returns an integral result", () => {
387 assertStrictEquals(toLength(0.25), 0);
388 assertStrictEquals(toLength(1.1), 1);
391 it("[[Call]] returns a result greater than or equal to zero", () => {
392 assertStrictEquals(toLength(-0), 0);
393 assertStrictEquals(toLength(-1), 0);
394 assertStrictEquals(toLength(-Infinity
), 0);
397 it("[[Call]] returns a result less than 2 ** 53", () => {
398 assertStrictEquals(toLength(9007199254740992), 9007199254740991);
399 assertStrictEquals(toLength(Infinity
), 9007199254740991);