]> Lady’s Gitweb - Pisces/blob - collection.test.js
7c242cc987023ab23d35f01dbbf7c9809a6336b7
[Pisces] / collection.test.js
1 // ♓🌟 Piscēs ∷ collection.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 assertSpyCall,
13 assertSpyCalls,
14 assertStrictEquals,
15 describe,
16 it,
17 spy,
18 } from "./dev-deps.js";
19 import {
20 findIndexedEntry,
21 isArrayIndexString,
22 isArraylikeObject,
23 isCollection,
24 isConcatSpreadable,
25 } from "./collection.js";
26
27 describe("findIndexedEntry", () => {
28 it("[[Call]] returns undefined if no matching entry exists", () => {
29 assertStrictEquals(findIndexedEntry([], () => true), void {});
30 assertStrictEquals(findIndexedEntry([1], () => false), void {});
31 });
32
33 it("[[Call]] returns an entry for the first match", () => {
34 assertEquals(
35 findIndexedEntry([, true, false], ($) => $ ?? true),
36 [0, void {}],
37 );
38 assertEquals(
39 findIndexedEntry(["failure", "success"], ($) => $ == "success"),
40 [1, "success"],
41 );
42 });
43
44 it("[[Call]] works on arraylike objects", () => {
45 assertEquals(
46 findIndexedEntry({ 1: "success", length: 2 }, ($) => $),
47 [1, "success"],
48 );
49 assertEquals(
50 findIndexedEntry({ 1: "failure", length: 1 }, ($) => $),
51 void {},
52 );
53 });
54
55 it("[[Call]] only gets the value once", () => {
56 const get1 = spy(() => true);
57 findIndexedEntry({
58 get 1() {
59 return get1();
60 },
61 length: 2,
62 }, ($) => $);
63 assertSpyCalls(get1, 1);
64 });
65
66 it("[[Call]] passes the value, index, and this value to the callback", () => {
67 const arr = ["failure", "success", "success"];
68 const callback = spy(($) => $ === "success");
69 const thisArg = {};
70 findIndexedEntry(arr, callback, thisArg);
71 assertSpyCalls(callback, 2);
72 assertSpyCall(callback, 0, {
73 args: ["failure", 0, arr],
74 self: thisArg,
75 });
76 assertSpyCall(callback, 1, {
77 args: ["success", 1, arr],
78 self: thisArg,
79 });
80 });
81 });
82
83 describe("isArrayIndexString", () => {
84 it("[[Call]] returns false for nonstrings", () => {
85 assertStrictEquals(isArrayIndexString(1), false);
86 });
87
88 it("[[Call]] returns false for noncanonical strings", () => {
89 assertStrictEquals(isArrayIndexString(""), false);
90 assertStrictEquals(isArrayIndexString("01"), false);
91 assertStrictEquals(isArrayIndexString("9007199254740993"), false);
92 });
93
94 it("[[Call]] returns false for nonfinite numbers", () => {
95 assertStrictEquals(isArrayIndexString("NaN"), false);
96 assertStrictEquals(isArrayIndexString("Infinity"), false);
97 assertStrictEquals(isArrayIndexString("-Infinity"), false);
98 });
99
100 it("[[Call]] returns false for negative numbers", () => {
101 assertStrictEquals(isArrayIndexString("-0"), false);
102 assertStrictEquals(isArrayIndexString("-1"), false);
103 });
104
105 it("[[Call]] returns false for nonintegers", () => {
106 assertStrictEquals(isArrayIndexString("0.25"), false);
107 assertStrictEquals(isArrayIndexString("1.1"), false);
108 });
109
110 it("[[Call]] returns false for numbers greater than or equal to -1 >>> 0", () => {
111 assertStrictEquals(isArrayIndexString(String(-1 >>> 0)), false);
112 assertStrictEquals(
113 isArrayIndexString(String((-1 >>> 0) + 1)),
114 false,
115 );
116 });
117
118 it("[[Call]] returns true for array lengths less than -1 >>> 0", () => {
119 assertStrictEquals(isArrayIndexString("0"), true);
120 assertStrictEquals(
121 isArrayIndexString(String((-1 >>> 0) - 1)),
122 true,
123 );
124 });
125 });
126
127 describe("isArraylikeObject", () => {
128 it("[[Call]] returns false for primitives", () => {
129 assertStrictEquals(isArraylikeObject("failure"), false);
130 });
131
132 it("[[Call]] returns false if length throws", () => {
133 assertStrictEquals(
134 isArraylikeObject({
135 get length() {
136 throw void {};
137 },
138 }),
139 false,
140 );
141 });
142
143 it("[[Call]] returns false if length is not a number and cannot be converted to one", () => {
144 assertStrictEquals(isArraylikeObject({ length: 1n }), false);
145 });
146
147 it("[[Call]] returns true if length is convertable to a number", () => {
148 assertStrictEquals(isArraylikeObject({ length: -0 }), true);
149 assertStrictEquals(isArraylikeObject({ length: 1 }), true);
150 assertStrictEquals(isArraylikeObject({ length: -1.25 }), true);
151 assertStrictEquals(
152 isArraylikeObject({ length: 9007199254740992 }),
153 true,
154 );
155 assertStrictEquals(isArraylikeObject({ length: Infinity }), true);
156 assertStrictEquals(isArraylikeObject({ length: "success" }), true);
157 });
158 });
159
160 describe("isCollection", () => {
161 it("[[Call]] returns false for primitives", () => {
162 assertStrictEquals(isCollection("failure"), false);
163 });
164
165 it("[[Call]] returns false if length throws", () => {
166 assertStrictEquals(
167 isCollection({
168 get length() {
169 throw void {};
170 },
171 }),
172 false,
173 );
174 });
175
176 it("[[Call]] returns false if length is not an integer index and cannot be converted to one", () => {
177 assertStrictEquals(
178 isCollection({ length: -1, [Symbol.isConcatSpreadable]: true }),
179 false,
180 );
181 assertStrictEquals(
182 isCollection({
183 length: Infinity,
184 [Symbol.isConcatSpreadable]: true,
185 }),
186 false,
187 );
188 assertStrictEquals(
189 isCollection({
190 length: 9007199254740992,
191 [Symbol.isConcatSpreadable]: true,
192 }),
193 false,
194 );
195 });
196
197 it("[[Call]] returns true if length is an integer index and the object is concat spreadable", () => {
198 assertStrictEquals(
199 isCollection({ length: 1, [Symbol.isConcatSpreadable]: true }),
200 true,
201 );
202 assertStrictEquals(
203 isCollection({ length: 0, [Symbol.isConcatSpreadable]: true }),
204 true,
205 );
206 assertStrictEquals(
207 isCollection({
208 length: 9007199254740991,
209 [Symbol.isConcatSpreadable]: true,
210 }),
211 true,
212 );
213 });
214
215 it("[[Call]] returns true if length can be converted to an index without throwing an error and the object is concat spreadable", () => {
216 assertStrictEquals(
217 isCollection({ length: -0, [Symbol.isConcatSpreadable]: true }),
218 true,
219 );
220 assertStrictEquals(
221 isCollection({ length: NaN, [Symbol.isConcatSpreadable]: true }),
222 true,
223 );
224 });
225 });
226
227 describe("isConcatSpreadable", () => {
228 it("[[Call]] returns false for primitives", () => {
229 assertStrictEquals(isConcatSpreadable("failure"), false);
230 });
231
232 it("[[Call]] returns false if [Symbol.isConcatSpreadable] is null or false", () => {
233 assertStrictEquals(
234 isConcatSpreadable(
235 Object.assign([], { [Symbol.isConcatSpreadable]: null }),
236 ),
237 false,
238 );
239 assertStrictEquals(
240 isConcatSpreadable(
241 Object.assign([], { [Symbol.isConcatSpreadable]: false }),
242 ),
243 false,
244 );
245 });
246
247 it("[[Call]] returns true if [Symbol.isConcatSpreadable] is undefined and the object is an array", () => {
248 assertStrictEquals(
249 isConcatSpreadable(
250 Object.assign([], { [Symbol.isConcatSpreadable]: undefined }),
251 ),
252 true,
253 );
254 });
255
256 it("[[Call]] returns true if [Symbol.isConcatSpreadable] is true", () => {
257 assertStrictEquals(
258 isConcatSpreadable({ [Symbol.isConcatSpreadable]: true }),
259 true,
260 );
261 });
262 });
This page took 0.232446 seconds and 3 git commands to generate.