@gjsify/util 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,469 @@
1
+ // Ported from refs/node-test/parallel/test-util-inspect.js,
2
+ // test-util-format.js, test-util-types.js, test-util-callbackify.js
3
+ // Original: MIT license, Node.js contributors
4
+
5
+ import { describe, it, expect } from '@gjsify/unit';
6
+ import * as util from 'node:util';
7
+
8
+ export default async () => {
9
+
10
+ // ===================== inspect.colors =====================
11
+ await describe('util.inspect.colors', async () => {
12
+ await it('should be an object', async () => {
13
+ expect(typeof util.inspect.colors).toBe('object');
14
+ });
15
+
16
+ await it('should have standard color entries', async () => {
17
+ const colors = util.inspect.colors;
18
+ expect(colors.red).toBeDefined();
19
+ expect(colors.green).toBeDefined();
20
+ expect(colors.yellow).toBeDefined();
21
+ expect(colors.blue).toBeDefined();
22
+ expect(colors.cyan).toBeDefined();
23
+ expect(colors.magenta).toBeDefined();
24
+ expect(colors.white).toBeDefined();
25
+ expect(colors.gray).toBeDefined();
26
+ });
27
+
28
+ await it('each color should be [open, close] pair', async () => {
29
+ const red = util.inspect.colors.red;
30
+ expect(Array.isArray(red)).toBe(true);
31
+ expect(red.length).toBe(2);
32
+ expect(typeof red[0]).toBe('number');
33
+ expect(typeof red[1]).toBe('number');
34
+ });
35
+
36
+ await it('should have bold/dim/underline modifiers', async () => {
37
+ expect(util.inspect.colors.bold).toBeDefined();
38
+ expect(util.inspect.colors.dim).toBeDefined();
39
+ expect(util.inspect.colors.underline).toBeDefined();
40
+ });
41
+
42
+ await it('should have bright color variants', async () => {
43
+ expect(util.inspect.colors.redBright).toBeDefined();
44
+ expect(util.inspect.colors.greenBright).toBeDefined();
45
+ expect(util.inspect.colors.cyanBright).toBeDefined();
46
+ });
47
+
48
+ await it('should have background colors', async () => {
49
+ expect(util.inspect.colors.bgRed).toBeDefined();
50
+ expect(util.inspect.colors.bgGreen).toBeDefined();
51
+ expect(util.inspect.colors.bgBlue).toBeDefined();
52
+ });
53
+ });
54
+
55
+ // ===================== inspect.styles =====================
56
+ await describe('util.inspect.styles', async () => {
57
+ await it('should be an object', async () => {
58
+ expect(typeof util.inspect.styles).toBe('object');
59
+ });
60
+
61
+ await it('should map type names to color names', async () => {
62
+ const styles = util.inspect.styles;
63
+ expect(typeof styles.string).toBe('string');
64
+ expect(typeof styles.number).toBe('string');
65
+ expect(typeof styles.boolean).toBe('string');
66
+ expect(typeof styles.undefined).toBe('string');
67
+ expect(typeof styles.null).toBe('string');
68
+ });
69
+
70
+ await it('string style should be green', async () => {
71
+ expect(util.inspect.styles.string).toBe('green');
72
+ });
73
+
74
+ await it('number style should be yellow', async () => {
75
+ expect(util.inspect.styles.number).toBe('yellow');
76
+ });
77
+ });
78
+
79
+ // ===================== inspect.custom =====================
80
+ await describe('util.inspect.custom', async () => {
81
+ await it('should be a symbol', async () => {
82
+ expect(typeof util.inspect.custom).toBe('symbol');
83
+ });
84
+
85
+ await it('should equal Symbol.for nodejs.util.inspect.custom', async () => {
86
+ const expected = Symbol.for('nodejs.util.inspect.custom');
87
+ expect(util.inspect.custom === expected).toBe(true);
88
+ });
89
+
90
+ await it('should use custom inspect method', async () => {
91
+ const obj = {
92
+ [util.inspect.custom]() {
93
+ return 'custom-output';
94
+ },
95
+ };
96
+ const result = util.inspect(obj);
97
+ expect(result).toBe('custom-output');
98
+ });
99
+ });
100
+
101
+ // ===================== inspect.defaultOptions =====================
102
+ await describe('util.inspect.defaultOptions', async () => {
103
+ await it('should have expected default values', async () => {
104
+ const opts = util.inspect.defaultOptions;
105
+ expect(opts.showHidden).toBe(false);
106
+ expect(opts.depth).toBe(2);
107
+ expect(opts.colors).toBe(false);
108
+ expect(typeof opts.maxArrayLength).toBe('number');
109
+ expect(typeof opts.breakLength).toBe('number');
110
+ });
111
+ });
112
+
113
+ // ===================== inspect edge cases =====================
114
+ await describe('util.inspect edge cases', async () => {
115
+ await it('should inspect null', async () => {
116
+ expect(util.inspect(null)).toBe('null');
117
+ });
118
+
119
+ await it('should inspect undefined', async () => {
120
+ expect(util.inspect(undefined)).toBe('undefined');
121
+ });
122
+
123
+ await it('should inspect numbers', async () => {
124
+ expect(util.inspect(42)).toBe('42');
125
+ expect(util.inspect(0)).toBe('0');
126
+ expect(util.inspect(-1)).toBe('-1');
127
+ expect(util.inspect(Infinity)).toBe('Infinity');
128
+ expect(util.inspect(NaN)).toBe('NaN');
129
+ });
130
+
131
+ await it('should inspect strings with quotes', async () => {
132
+ const result = util.inspect('hello');
133
+ expect(result.includes('hello')).toBe(true);
134
+ });
135
+
136
+ await it('should inspect booleans', async () => {
137
+ expect(util.inspect(true)).toBe('true');
138
+ expect(util.inspect(false)).toBe('false');
139
+ });
140
+
141
+ await it('should inspect BigInt', async () => {
142
+ expect(util.inspect(42n)).toBe('42n');
143
+ });
144
+
145
+ await it('should inspect Symbol', async () => {
146
+ const result = util.inspect(Symbol('test'));
147
+ expect(result).toBe('Symbol(test)');
148
+ });
149
+
150
+ await it('should inspect functions', async () => {
151
+ function foo() {}
152
+ const result = util.inspect(foo);
153
+ expect(result).toContain('Function');
154
+ expect(result).toContain('foo');
155
+ });
156
+
157
+ await it('should inspect anonymous functions', async () => {
158
+ const result = util.inspect(() => {});
159
+ expect(result).toContain('Function');
160
+ });
161
+
162
+ await it('should inspect arrays', async () => {
163
+ const result = util.inspect([1, 2, 3]);
164
+ expect(result).toContain('1');
165
+ expect(result).toContain('2');
166
+ expect(result).toContain('3');
167
+ });
168
+
169
+ await it('should inspect empty object', async () => {
170
+ expect(util.inspect({})).toBe('{}');
171
+ });
172
+
173
+ await it('should inspect Date', async () => {
174
+ const d = new Date('2025-01-01T00:00:00.000Z');
175
+ const result = util.inspect(d);
176
+ expect(result).toContain('2025');
177
+ });
178
+
179
+ await it('should inspect RegExp', async () => {
180
+ const result = util.inspect(/test/gi);
181
+ expect(result).toContain('test');
182
+ });
183
+
184
+ await it('should inspect Error', async () => {
185
+ const result = util.inspect(new Error('oops'));
186
+ // Error inspect format varies between platforms
187
+ expect(typeof result).toBe('string');
188
+ expect(result.length).toBeGreaterThan(0);
189
+ });
190
+
191
+ await it('should inspect Map', async () => {
192
+ const result = util.inspect(new Map([['a', 1]]));
193
+ expect(result).toContain('Map');
194
+ });
195
+
196
+ await it('should inspect Set', async () => {
197
+ const result = util.inspect(new Set([1, 2]));
198
+ expect(result).toContain('Set');
199
+ });
200
+
201
+ await it('should respect depth option', async () => {
202
+ const deep = { a: { b: { c: { d: 'deep' } } } };
203
+ const shallow = util.inspect(deep, { depth: 0 });
204
+ expect(shallow).toContain('[Object]');
205
+ });
206
+ });
207
+
208
+ // ===================== format edge cases =====================
209
+ await describe('util.format edge cases', async () => {
210
+ await it('should handle %% as literal percent with args', async () => {
211
+ // %% only produces single % when formatting is applied (with extra args)
212
+ expect(util.format('100%%', 'extra')).toBe('100% extra');
213
+ });
214
+
215
+ await it('should handle %s with various types', async () => {
216
+ expect(util.format('%s', 'hello')).toBe('hello');
217
+ expect(util.format('%s', 42)).toBe('42');
218
+ expect(util.format('%s', true)).toBe('true');
219
+ expect(util.format('%s', null)).toBe('null');
220
+ expect(util.format('%s', undefined)).toBe('undefined');
221
+ });
222
+
223
+ await it('should handle %d for numbers', async () => {
224
+ expect(util.format('%d', 42)).toBe('42');
225
+ expect(util.format('%d', '42')).toBe('42');
226
+ });
227
+
228
+ await it('should handle %j for JSON', async () => {
229
+ expect(util.format('%j', { a: 1 })).toBe('{"a":1}');
230
+ expect(util.format('%j', [1, 2])).toBe('[1,2]');
231
+ });
232
+
233
+ await it('should append extra args', async () => {
234
+ const result = util.format('a', 'b', 'c');
235
+ expect(result).toBe('a b c');
236
+ });
237
+
238
+ await it('should handle no format string', async () => {
239
+ const result = util.format(42, 'hello');
240
+ expect(result).toContain('42');
241
+ expect(result).toContain('hello');
242
+ });
243
+
244
+ await it('should return empty string for no args', async () => {
245
+ expect(util.format()).toBe('');
246
+ });
247
+
248
+ await it('should handle %i for integer', async () => {
249
+ expect(util.format('%i', 42.9)).toBe('42');
250
+ });
251
+
252
+ await it('should handle %f for float', async () => {
253
+ expect(util.format('%f', 42.5)).toBe('42.5');
254
+ });
255
+ });
256
+
257
+ // ===================== util.types =====================
258
+ await describe('util.types', async () => {
259
+ await it('isDate should detect Date', async () => {
260
+ expect(util.types.isDate(new Date())).toBe(true);
261
+ expect(util.types.isDate('2025-01-01')).toBe(false);
262
+ expect(util.types.isDate({})).toBe(false);
263
+ });
264
+
265
+ await it('isRegExp should detect RegExp', async () => {
266
+ expect(util.types.isRegExp(/test/)).toBe(true);
267
+ expect(util.types.isRegExp('test')).toBe(false);
268
+ });
269
+
270
+ await it('isMap should detect Map', async () => {
271
+ expect(util.types.isMap(new Map())).toBe(true);
272
+ expect(util.types.isMap({})).toBe(false);
273
+ });
274
+
275
+ await it('isSet should detect Set', async () => {
276
+ expect(util.types.isSet(new Set())).toBe(true);
277
+ expect(util.types.isSet([])).toBe(false);
278
+ });
279
+
280
+ await it('isPromise should detect Promise', async () => {
281
+ expect(util.types.isPromise(Promise.resolve())).toBe(true);
282
+ expect(util.types.isPromise({ then() {} })).toBe(false);
283
+ });
284
+
285
+ await it('isArrayBuffer should detect ArrayBuffer', async () => {
286
+ expect(util.types.isArrayBuffer(new ArrayBuffer(8))).toBe(true);
287
+ expect(util.types.isArrayBuffer(new Uint8Array(8))).toBe(false);
288
+ });
289
+
290
+ await it('isTypedArray should detect typed arrays', async () => {
291
+ expect(util.types.isTypedArray(new Uint8Array(1))).toBe(true);
292
+ expect(util.types.isTypedArray(new Float32Array(1))).toBe(true);
293
+ expect(util.types.isTypedArray(new Int32Array(1))).toBe(true);
294
+ expect(util.types.isTypedArray([])).toBe(false);
295
+ });
296
+
297
+ await it('isAsyncFunction should detect async functions', async () => {
298
+ expect(util.types.isAsyncFunction(async () => {})).toBe(true);
299
+ expect(util.types.isAsyncFunction(() => {})).toBe(false);
300
+ });
301
+
302
+ await it('isGeneratorFunction should detect generators', async () => {
303
+ function* gen() { yield 1; }
304
+ expect(util.types.isGeneratorFunction(gen)).toBe(true);
305
+ expect(util.types.isGeneratorFunction(() => {})).toBe(false);
306
+ });
307
+
308
+ await it('isWeakMap should detect WeakMap', async () => {
309
+ expect(util.types.isWeakMap(new WeakMap())).toBe(true);
310
+ expect(util.types.isWeakMap(new Map())).toBe(false);
311
+ });
312
+
313
+ await it('isWeakSet should detect WeakSet', async () => {
314
+ expect(util.types.isWeakSet(new WeakSet())).toBe(true);
315
+ expect(util.types.isWeakSet(new Set())).toBe(false);
316
+ });
317
+
318
+ await it('isDataView should detect DataView', async () => {
319
+ expect(util.types.isDataView(new DataView(new ArrayBuffer(8)))).toBe(true);
320
+ expect(util.types.isDataView(new ArrayBuffer(8))).toBe(false);
321
+ });
322
+ });
323
+
324
+ // ===================== promisify =====================
325
+ await describe('util.promisify', async () => {
326
+ await it('should convert callback function to promise', async () => {
327
+ function asyncOp(val: string, cb: (err: Error | null, result: string) => void) {
328
+ setTimeout(() => cb(null, val.toUpperCase()), 10);
329
+ }
330
+ const promisified = util.promisify(asyncOp);
331
+ const result = await promisified('hello');
332
+ expect(result).toBe('HELLO');
333
+ });
334
+
335
+ await it('should reject on error', async () => {
336
+ function failOp(cb: (err: Error) => void) {
337
+ setTimeout(() => cb(new Error('fail')), 10);
338
+ }
339
+ const promisified = util.promisify(failOp);
340
+ let caught = false;
341
+ try {
342
+ await promisified();
343
+ } catch {
344
+ caught = true;
345
+ }
346
+ expect(caught).toBe(true);
347
+ });
348
+
349
+ await it('should respect custom promisify symbol', async () => {
350
+ function custom(cb: (err: Error | null) => void) {
351
+ cb(null);
352
+ }
353
+ (custom as any)[util.promisify.custom] = () => Promise.resolve('custom-result');
354
+ const promisified = util.promisify(custom);
355
+ const result = await promisified();
356
+ expect(result).toBe('custom-result');
357
+ });
358
+ });
359
+
360
+ // ===================== callbackify =====================
361
+ await describe('util.callbackify', async () => {
362
+ await it('should convert async function to callback style', async () => {
363
+ async function asyncFn() { return 'result'; }
364
+ const callbackified = util.callbackify(asyncFn);
365
+ const result = await new Promise<string>((resolve, reject) => {
366
+ callbackified((err: Error | null, val: string) => {
367
+ if (err) reject(err);
368
+ else resolve(val);
369
+ });
370
+ });
371
+ expect(result).toBe('result');
372
+ });
373
+
374
+ await it('should pass error for rejected promise', async () => {
375
+ async function failFn() { throw new Error('async-error'); }
376
+ const callbackified = util.callbackify(failFn);
377
+ const err = await new Promise<Error>((resolve) => {
378
+ callbackified((err: Error | null) => {
379
+ resolve(err!);
380
+ });
381
+ });
382
+ expect(err instanceof Error).toBe(true);
383
+ });
384
+ });
385
+
386
+ // ===================== deprecate =====================
387
+ await describe('util.deprecate', async () => {
388
+ await it('should return a function', async () => {
389
+ const deprecated = util.deprecate(() => 42, 'deprecated');
390
+ expect(typeof deprecated).toBe('function');
391
+ });
392
+
393
+ await it('deprecated function should preserve behavior', async () => {
394
+ const deprecated = util.deprecate(() => 42, 'deprecated');
395
+ expect(deprecated()).toBe(42);
396
+ });
397
+ });
398
+
399
+ // ===================== inherits =====================
400
+ await describe('util.inherits', async () => {
401
+ await it('should set up prototype chain', async () => {
402
+ function Parent(this: any) { this.name = 'parent'; }
403
+ Parent.prototype.greet = function() { return 'hello'; };
404
+ function Child(this: any) { (Parent as any).call(this); }
405
+ util.inherits(Child as any, Parent as any);
406
+ const child = new (Child as any)();
407
+ expect(child.greet()).toBe('hello');
408
+ expect(child instanceof (Child as any)).toBe(true);
409
+ });
410
+
411
+ await it('should set super_ property', async () => {
412
+ function A() {}
413
+ function B() {}
414
+ util.inherits(B as any, A as any);
415
+ expect((B as any).super_).toBe(A);
416
+ });
417
+ });
418
+
419
+ // ===================== isDeepStrictEqual =====================
420
+ await describe('util.isDeepStrictEqual', async () => {
421
+ await it('should compare primitives', async () => {
422
+ expect(util.isDeepStrictEqual(1, 1)).toBe(true);
423
+ expect(util.isDeepStrictEqual(1, 2)).toBe(false);
424
+ expect(util.isDeepStrictEqual('a', 'a')).toBe(true);
425
+ expect(util.isDeepStrictEqual(true, true)).toBe(true);
426
+ expect(util.isDeepStrictEqual(true, false)).toBe(false);
427
+ });
428
+
429
+ await it('should compare objects deeply', async () => {
430
+ expect(util.isDeepStrictEqual({ a: 1 }, { a: 1 })).toBe(true);
431
+ expect(util.isDeepStrictEqual({ a: 1 }, { a: 2 })).toBe(false);
432
+ expect(util.isDeepStrictEqual({ a: { b: 1 } }, { a: { b: 1 } })).toBe(true);
433
+ });
434
+
435
+ await it('should compare arrays', async () => {
436
+ expect(util.isDeepStrictEqual([1, 2, 3], [1, 2, 3])).toBe(true);
437
+ expect(util.isDeepStrictEqual([1, 2], [1, 2, 3])).toBe(false);
438
+ });
439
+
440
+ await it('should compare Date objects', async () => {
441
+ const d1 = new Date('2025-01-01');
442
+ const d2 = new Date('2025-01-01');
443
+ const d3 = new Date('2025-12-31');
444
+ expect(util.isDeepStrictEqual(d1, d2)).toBe(true);
445
+ expect(util.isDeepStrictEqual(d1, d3)).toBe(false);
446
+ });
447
+
448
+ await it('should compare RegExp', async () => {
449
+ expect(util.isDeepStrictEqual(/abc/g, /abc/g)).toBe(true);
450
+ expect(util.isDeepStrictEqual(/abc/g, /abc/i)).toBe(false);
451
+ });
452
+
453
+ await it('should distinguish null and undefined', async () => {
454
+ expect(util.isDeepStrictEqual(null, undefined)).toBe(false);
455
+ expect(util.isDeepStrictEqual(null, null)).toBe(true);
456
+ });
457
+ });
458
+
459
+ // ===================== TextEncoder/TextDecoder =====================
460
+ await describe('util TextEncoder/TextDecoder exports', async () => {
461
+ await it('should export TextEncoder', async () => {
462
+ expect(util.TextEncoder).toBeDefined();
463
+ });
464
+
465
+ await it('should export TextDecoder', async () => {
466
+ expect(util.TextDecoder).toBeDefined();
467
+ });
468
+ });
469
+ };