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