]> Lady’s Gitweb - Pisces/blob - function.test.js
e9286624b895a35c4a439c119f56760f558a6f00
[Pisces] / function.test.js
1 // ♓🌟 Piscēs ∷ function.test.js
2 // ====================================================================
3 //
4 // Copyright © 2022–2023 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 assertThrows,
14 describe,
15 it,
16 } from "./dev-deps.js";
17 import {
18 bind,
19 call,
20 completesNormally,
21 construct,
22 identity,
23 isCallable,
24 isConstructor,
25 makeCallable,
26 ordinaryHasInstance,
27 } from "./function.js";
28
29 describe("bind", () => {
30 it("[[Call]] binds this", () => {
31 assertStrictEquals(
32 bind(
33 function () {
34 return this;
35 },
36 "pass",
37 [],
38 ).call("fail"),
39 "pass",
40 );
41 });
42
43 it("[[Call]] binds arguments", () => {
44 assertEquals(
45 bind(
46 function (...args) {
47 return [this, ...args];
48 },
49 "etaoin",
50 ["shrdlu"],
51 ).call("failure", "cmfwyp"),
52 ["etaoin", "shrdlu", "cmfwyp"],
53 );
54 });
55
56 it("[[Call]] works with any arraylike third argument", () => {
57 assertEquals(
58 bind(
59 function (...args) {
60 return [this, ...args];
61 },
62 "etaoin",
63 {
64 1: "shrdlu",
65 3: "failure",
66 length: 3,
67 },
68 ).call("failure", "cmfwyp"),
69 ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"],
70 );
71 });
72
73 describe(".name", () => {
74 it("[[Get]] returns the correct name", () => {
75 assertStrictEquals(bind.name, "bind");
76 });
77 });
78 });
79
80 describe("call", () => {
81 it("[[Call]] calls with the provided this value", () => {
82 assertStrictEquals(
83 call(
84 function () {
85 return this;
86 },
87 "pass",
88 [],
89 ),
90 "pass",
91 );
92 });
93
94 it("[[Call]] calls with the provided arguments", () => {
95 assertEquals(
96 call(
97 function (...args) {
98 return [this, ...args];
99 },
100 "etaoin",
101 ["shrdlu", "cmfwyp"],
102 ),
103 ["etaoin", "shrdlu", "cmfwyp"],
104 );
105 });
106
107 it("[[Call]] works with any arraylike third argument", () => {
108 assertEquals(
109 call(
110 function (...args) {
111 return [this, ...args];
112 },
113 "etaoin",
114 {
115 1: "shrdlu",
116 3: "cmfwyp",
117 4: "failure",
118 length: 4,
119 },
120 ),
121 ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"],
122 );
123 });
124
125 describe(".name", () => {
126 it("[[Get]] returns the correct name", () => {
127 assertStrictEquals(call.name, "call");
128 });
129 });
130 });
131
132 describe("completesNormally", () => {
133 it("[[Call]] returns true for functions which complete normally", () => {
134 assertStrictEquals(completesNormally(() => {}), true);
135 });
136
137 it("[[Call]] returns false for functions which throw", () => {
138 assertStrictEquals(
139 completesNormally(() => {
140 throw null;
141 }),
142 false,
143 );
144 });
145
146 it("[[Call]] throws when the argument is not callable", () => {
147 assertThrows(() => {
148 completesNormally(null);
149 });
150 });
151
152 it("[[Call]] throws when the argument is not provided", () => {
153 assertThrows(() => {
154 completesNormally();
155 });
156 });
157
158 describe(".name", () => {
159 it("[[Get]] returns the correct name", () => {
160 assertStrictEquals(completesNormally.name, "completesNormally");
161 });
162 });
163 });
164
165 describe("construct", () => {
166 it("[[Call]] defaults to the constructor as the target", () => {
167 const constructor = class {};
168 assertStrictEquals(
169 Object.getPrototypeOf(construct(
170 constructor,
171 [],
172 )),
173 constructor.prototype,
174 );
175 });
176
177 it("[[Call]] constructs with the provided new target", () => {
178 const target = function () {};
179 assertStrictEquals(
180 construct(
181 function () {
182 return new.target;
183 },
184 [],
185 target,
186 ),
187 target,
188 );
189 });
190
191 it("[[Call]] constructs with the provided arguments", () => {
192 assertEquals(
193 construct(
194 function (...args) {
195 return [new.target.value, ...args];
196 },
197 ["shrdlu", "cmfwyp"],
198 Object.assign(function () {}, { value: "etaoin" }),
199 ),
200 ["etaoin", "shrdlu", "cmfwyp"],
201 );
202 });
203
204 it("[[Call]] works with any arraylike third argument", () => {
205 assertEquals(
206 construct(
207 function (...args) {
208 return [new.target.value, ...args];
209 },
210 {
211 1: "shrdlu",
212 3: "cmfwyp",
213 4: "failure",
214 length: 4,
215 },
216 Object.assign(function () {}, { value: "etaoin" }),
217 ),
218 ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"],
219 );
220 });
221
222 describe(".name", () => {
223 it("[[Get]] returns the correct name", () => {
224 assertStrictEquals(construct.name, "construct");
225 });
226 });
227 });
228
229 describe("identity", () => {
230 it("[[Call]] returns what it is given", () => {
231 const value = {};
232 assertStrictEquals(identity(value), value);
233 });
234
235 it("[[Construct]] is constructable", () => {
236 const value = {};
237 assertStrictEquals(new identity(value), value);
238 });
239
240 it("[[Construct]] is subclassable", () => {
241 const value = {};
242 assertStrictEquals(new class extends identity {}(value), value);
243 });
244
245 describe(".name", () => {
246 it("[[Get]] returns the correct name", () => {
247 assertStrictEquals(identity.name, "identity");
248 });
249 });
250 });
251
252 describe("isCallable", () => {
253 it("[[Call]] returns true for ordinary functions", () => {
254 assertStrictEquals(isCallable(function () {}), true);
255 });
256
257 it("[[Call]] returns true for arrow functions", () => {
258 assertStrictEquals(isCallable(() => {}), true);
259 });
260
261 it("[[Call]] returns true for generator functions", () => {
262 assertStrictEquals(isCallable(function* () {}), true);
263 });
264
265 it("[[Call]] returns true for classes", () => {
266 assertStrictEquals(isCallable(class {}), true);
267 });
268
269 it("[[Call]] returns true for builtin functions", () => {
270 assertStrictEquals(isCallable(Math.ceil), true);
271 });
272
273 it("[[Call]] returns true for getters", () => {
274 assertStrictEquals(
275 isCallable(
276 Object.getOwnPropertyDescriptor({
277 get foo() {
278 return undefined;
279 },
280 }, "foo").get,
281 ),
282 true,
283 );
284 });
285
286 it("[[Call]] returns true for setters", () => {
287 assertStrictEquals(
288 isCallable(
289 Object.getOwnPropertyDescriptor({
290 set foo($) {
291 /* do nothing */
292 },
293 }, "foo").set,
294 ),
295 true,
296 );
297 });
298
299 it("[[Call]] returns false for null", () => {
300 assertStrictEquals(isCallable(null), false);
301 });
302
303 it("[[Call]] returns false for objects", () => {
304 assertStrictEquals(isCallable({}), false);
305 });
306
307 describe(".name", () => {
308 it("[[Get]] returns the correct name", () => {
309 assertStrictEquals(isCallable.name, "isCallable");
310 });
311 });
312 });
313
314 describe("isConstructor", () => {
315 it("[[Call]] returns true for ordinary functions", () => {
316 assertStrictEquals(isConstructor(function () {}), true);
317 });
318
319 it("[[Call]] returns false for arrow functions", () => {
320 assertStrictEquals(isConstructor(() => {}), false);
321 });
322
323 it("[[Call]] returns false for generator functions", () => {
324 assertStrictEquals(isConstructor(function* () {}), false);
325 });
326
327 it("[[Call]] returns true for classes", () => {
328 assertStrictEquals(isConstructor(class {}), true);
329 });
330
331 it("[[Call]] returns false for builtin functions", () => {
332 assertStrictEquals(isConstructor(Math.ceil), false);
333 });
334
335 it("[[Call]] returns false for getters", () => {
336 assertStrictEquals(
337 isConstructor(
338 Object.getOwnPropertyDescriptor({
339 get foo() {
340 return undefined;
341 },
342 }, "foo").get,
343 ),
344 false,
345 );
346 });
347
348 it("[[Call]] returns false for setters", () => {
349 assertStrictEquals(
350 isConstructor(
351 Object.getOwnPropertyDescriptor({
352 set foo($) {
353 /* do nothing */
354 },
355 }, "foo").set,
356 ),
357 false,
358 );
359 });
360
361 it("[[Call]] returns false for null", () => {
362 assertStrictEquals(isConstructor(null), false);
363 });
364
365 it("[[Call]] returns false for objects", () => {
366 assertStrictEquals(isConstructor({}), false);
367 });
368
369 describe(".name", () => {
370 it("[[Get]] returns the correct name", () => {
371 assertStrictEquals(isConstructor.name, "isConstructor");
372 });
373 });
374 });
375
376 describe("makeCallable", () => {
377 it("[[Call]] transfers the first argument to this", () => {
378 assertStrictEquals(
379 makeCallable(
380 function () {
381 return this;
382 },
383 ).call("fail", "pass"),
384 "pass",
385 );
386 });
387
388 it("[[Call]] transfers the remaining arguments", () => {
389 assertEquals(
390 makeCallable(
391 function (...args) {
392 return [this, ...args];
393 },
394 ).call("failure", "etaoin", "shrdlu", "cmfwyp"),
395 ["etaoin", "shrdlu", "cmfwyp"],
396 );
397 });
398
399 describe(".name", () => {
400 it("[[Get]] returns the correct name", () => {
401 assertStrictEquals(makeCallable.name, "makeCallable");
402 });
403 });
404 });
405
406 describe("ordinaryHasInstance", () => {
407 it("[[Call]] walks the prototype chain", () => {
408 const constructor = class {
409 [Symbol.hasInstance]() {
410 return false;
411 }
412 };
413 assertStrictEquals(
414 ordinaryHasInstance(
415 constructor,
416 new class extends constructor {}(),
417 ),
418 true,
419 );
420 });
421
422 describe(".name", () => {
423 it("[[Get]] returns the correct name", () => {
424 assertStrictEquals(
425 ordinaryHasInstance.name,
426 "ordinaryHasInstance",
427 );
428 });
429 });
430 });
This page took 0.076081 seconds and 3 git commands to generate.