]> Lady’s Gitweb - Pisces/blob - value.test.js
Split some object code into value and unit test
[Pisces] / value.test.js
1 // ♓🌟 Piscēs ∷ value.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 assert,
12 assertStrictEquals,
13 assertThrows,
14 describe,
15 it,
16 } from "./dev-deps.js";
17 import {
18 NULL,
19 ordinaryToPrimitive,
20 sameValue,
21 sameValueZero,
22 toPrimitive,
23 type,
24 UNDEFINED,
25 } from "./value.js";
26
27 describe("NULL", () => {
28 it("[[Get]] is null", () => {
29 assertStrictEquals(NULL, null);
30 });
31 });
32
33 describe("UNDEFINED", () => {
34 it("[[Get]] is undefined", () => {
35 assertStrictEquals(UNDEFINED, void {});
36 });
37 });
38
39 describe("ordinaryToPrimitive", () => {
40 it("[[Call]] prefers `valueOf` by default", () => {
41 const obj = {
42 toString() {
43 return "failure";
44 },
45 valueOf() {
46 return "success";
47 },
48 };
49 assertStrictEquals(ordinaryToPrimitive(obj), "success");
50 assertStrictEquals(ordinaryToPrimitive(obj, "default"), "success");
51 });
52
53 it('[[Call]] prefers `valueOf` for a "number" hint', () => {
54 const obj = {
55 toString() {
56 return "failure";
57 },
58 valueOf() {
59 return "success";
60 },
61 };
62 assertStrictEquals(ordinaryToPrimitive(obj, "number"), "success");
63 });
64
65 it('[[Call]] prefers `toString` for a "string" hint', () => {
66 const obj = {
67 toString() {
68 return "success";
69 },
70 valueOf() {
71 return "failure";
72 },
73 };
74 assertStrictEquals(ordinaryToPrimitive(obj, "string"), "success");
75 });
76
77 it("[[Call]] falls back to the other method if the first isn’t callable", () => {
78 const obj = {
79 toString() {
80 return "success";
81 },
82 valueOf: "failure",
83 };
84 assertStrictEquals(ordinaryToPrimitive(obj), "success");
85 });
86
87 it("[[Call]] falls back to the other method if the first returns an object", () => {
88 const obj = {
89 toString() {
90 return "success";
91 },
92 valueOf() {
93 return new String("failure");
94 },
95 };
96 assertStrictEquals(ordinaryToPrimitive(obj), "success");
97 });
98
99 it("[[Call]] throws an error if neither method is callable", () => {
100 const obj = {
101 toString: "failure",
102 valueOf: "failure",
103 };
104 assertThrows(() => ordinaryToPrimitive(obj));
105 });
106
107 it("[[Call]] throws an error if neither method returns an object", () => {
108 const obj = {
109 toString() {
110 return new String("failure");
111 },
112 valueOf() {
113 return new String("failure");
114 },
115 };
116 assertThrows(() => ordinaryToPrimitive(obj));
117 });
118 });
119
120 describe("sameValue", () => {
121 it("[[Call]] returns false for null 🆚 undefined", () => {
122 assert(!sameValue(null, void {}));
123 });
124
125 it("[[Call]] returns false for null 🆚 an object", () => {
126 assert(!sameValue(null, {}));
127 });
128
129 it("[[Call]] returns true for null 🆚 null", () => {
130 assert(sameValue(null, null));
131 });
132
133 it("[[Call]] returns false for two different objects", () => {
134 assert(!sameValue({}, {}));
135 });
136
137 it("[[Call]] returns true for the same object", () => {
138 const obj = {};
139 assert(sameValue(obj, obj));
140 });
141
142 it("[[Call]] returns false for ±0", () => {
143 assert(!sameValue(0, -0));
144 });
145
146 it("[[Call]] returns true for -0", () => {
147 assert(sameValue(-0, -0));
148 });
149
150 it("[[Call]] returns true for nan", () => {
151 assert(sameValue(0 / 0, 0 / 0));
152 });
153
154 it("[[Call]] returns false for a primitive and its wrapped object", () => {
155 assert(!sameValue(false, new Boolean(false)));
156 });
157 });
158
159 describe("sameValueZero", () => {
160 it("[[Call]] returns false for null 🆚 undefined", () => {
161 assert(!sameValueZero(null, void {}));
162 });
163
164 it("[[Call]] returns false for null 🆚 an object", () => {
165 assert(!sameValueZero(null, {}));
166 });
167
168 it("[[Call]] returns true for null 🆚 null", () => {
169 assert(sameValueZero(null, null));
170 });
171
172 it("[[Call]] returns false for two different objects", () => {
173 assert(!sameValueZero({}, {}));
174 });
175
176 it("[[Call]] returns true for the same object", () => {
177 const obj = {};
178 assert(sameValueZero(obj, obj));
179 });
180
181 it("[[Call]] returns true for ±0", () => {
182 assert(sameValueZero(0, -0));
183 });
184
185 it("[[Call]] returns true for -0", () => {
186 assert(sameValueZero(-0, -0));
187 });
188
189 it("[[Call]] returns true for nan", () => {
190 assert(sameValueZero(0 / 0, 0 / 0));
191 });
192
193 it("[[Call]] returns false for a primitive and its wrapped object", () => {
194 assert(!sameValueZero(false, new Boolean(false)));
195 });
196 });
197
198 describe("toPrimitive", () => {
199 it("[[Call]] returns the argument when passed a primitive", () => {
200 const value = Symbol();
201 assertStrictEquals(toPrimitive(value), value);
202 });
203
204 it("[[Call]] works with nullish values", () => {
205 assertStrictEquals(toPrimitive(null), null);
206 assertStrictEquals(toPrimitive(), void {});
207 });
208
209 it("[[Call]] calls ordinaryToPrimitive by default", () => {
210 const value = Object.assign(
211 Object.create(null),
212 {
213 valueOf() {
214 return "success";
215 },
216 },
217 );
218 assertStrictEquals(toPrimitive(value), "success");
219 });
220
221 it("[[Call]] accepts a hint", () => {
222 const value = Object.assign(
223 Object.create(null),
224 {
225 toString() {
226 return "success";
227 },
228 valueOf() {
229 return "failure";
230 },
231 },
232 );
233 assertStrictEquals(toPrimitive(value, "string"), "success");
234 });
235
236 it("[[Call]] uses the exotic toPrimitive method if available", () => {
237 const value = Object.assign(
238 Object.create(null),
239 {
240 [Symbol.toPrimitive]() {
241 return "success";
242 },
243 },
244 );
245 assertStrictEquals(toPrimitive(value), "success");
246 });
247
248 it("[[Call]] passes the hint to the exotic toPrimitive", () => {
249 const value = Object.assign(
250 Object.create(null),
251 {
252 [Symbol.toPrimitive](hint) {
253 return hint === "string" ? "success" : "failure";
254 },
255 },
256 );
257 assertStrictEquals(toPrimitive(value, "string"), "success");
258 });
259
260 it('[[Call]] passes a "default" hint by default', () => {
261 const value = Object.assign(
262 Object.create(null),
263 {
264 [Symbol.toPrimitive](hint) {
265 return hint === "default" ? "success" : "failure";
266 },
267 },
268 );
269 assertStrictEquals(toPrimitive(value, "default"), "success");
270 });
271
272 it("[[Call]] throws for an invalid hint", () => {
273 const value1 = Object.assign(
274 Object.create(null),
275 {
276 [Symbol.toPrimitive]() {
277 return "success";
278 },
279 },
280 );
281 const value2 = Object.assign(
282 Object.create(null),
283 {
284 valueOf() {
285 return true;
286 },
287 },
288 );
289 assertThrows(() => toPrimitive(value1, "badhint"));
290 assertThrows(() => toPrimitive(value2, "badhint"));
291 assertThrows(() => toPrimitive(true, "badhint"));
292 });
293 });
294
295 describe("type", () => {
296 it('[[Call]] returns "null" for null', () => {
297 assertStrictEquals(type(null), "null");
298 });
299
300 it('[[Call]] returns "undefined" for undefined', () => {
301 assertStrictEquals(type(void {}), "undefined");
302 });
303
304 it('[[Call]] returns "object" for non‐callable objects', () => {
305 assertStrictEquals(type(Object.create(null)), "object");
306 });
307
308 it('[[Call]] returns "object" for callable objects', () => {
309 assertStrictEquals(type(() => {}), "object");
310 });
311
312 it('[[Call]] returns "object" for constructable objects', () => {
313 assertStrictEquals(type(class {}), "object");
314 });
315 });
This page took 0.074289 seconds and 5 git commands to generate.