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