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