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