@dungarees/core 0.11.5 → 0.12.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.
package/util.test.js DELETED
@@ -1,419 +0,0 @@
1
- import { assertDefined, assertImpossible, assertPredicate, assertTypeByGuard, boolFromThrow, boolFromThrowAsync, camelCase2kebabCase, capitalize, deepEqualPartial, findByPattern, isDeepEqual, isDefined, join, kebabCase2camelCase, makeObjectFromStringLiteral, mapConst, mapConstKeysToEntries, mapObjectFromKeys, objectFromConstEntries, optionalPatternToList, pluralize, split, unPrototypeProperties, } from './util.js';
2
- import { expect, expectTypeOf, test } from 'vitest';
3
- test('makeObjectFromStringLiteral', () => {
4
- const obj = makeObjectFromStringLiteral('key', 1);
5
- expect(obj['key']).toBe(1);
6
- });
7
- test('split is working in a typesafe way', () => {
8
- const splitted = split('a.a.a', '.');
9
- expectTypeOf().toEqualTypeOf();
10
- expect(splitted).toEqual(['a', 'a', 'a']);
11
- });
12
- test('join is working in a typesafe way', () => {
13
- const joined = join(['a', 'a', 'a'], '.');
14
- expectTypeOf().toEqualTypeOf();
15
- expect(joined).toBe('a.a.a');
16
- });
17
- test('capitalize', () => {
18
- const capitalized = capitalize('apple');
19
- expectTypeOf().toEqualTypeOf();
20
- expect(capitalized).toBe('Apple');
21
- });
22
- test('pluralize', () => {
23
- expect(pluralize('dog', -2)).toBe('dogs');
24
- expect(pluralize('dog', -1)).toBe('dog');
25
- expect(pluralize('dog', 0)).toBe('dogs');
26
- expect(pluralize('dog', 1)).toBe('dog');
27
- expect(pluralize('dog', 2)).toBe('dogs');
28
- expect(pluralize('dog', 1, true)).toBe('1 dog');
29
- expect(pluralize('dog', 2, true)).toBe('2 dogs');
30
- });
31
- test('kebabCase2camelCase', () => {
32
- const kebabCase = 'first-second-third';
33
- const camelCase = 'firstSecondThird';
34
- const output = kebabCase2camelCase(kebabCase);
35
- expect(output).toBe(camelCase);
36
- expectTypeOf().toEqualTypeOf();
37
- });
38
- test('camelCase2kebabCase', () => {
39
- const kebabCase = 'first-second-third';
40
- const camelCase = 'firstSecondThird';
41
- const output = camelCase2kebabCase(camelCase);
42
- expect(output).toBe(kebabCase);
43
- expectTypeOf().toEqualTypeOf();
44
- });
45
- test('deepEqualPartial', () => {
46
- expect(deepEqualPartial({}, {})).toBe(true);
47
- expect(deepEqualPartial(true, true)).toBe(true);
48
- expect(deepEqualPartial(true, false)).toBe(false);
49
- expect(deepEqualPartial({ baz: 54 }, { foo: 'bar', baz: 54 })).toBe(true);
50
- expect(deepEqualPartial({ baz: 55 }, { foo: 'bar', baz: 54 })).toBe(false);
51
- expect(deepEqualPartial({ foo: { baz: 'bar' } }, { foo: { baz: 'bar' }, quux: 'kill me' })).toBe(true);
52
- expect(deepEqualPartial({ foo: { baz: 'baz' } }, { foo: { baz: 'bar' }, quux: 'kill me' })).toBe(false);
53
- });
54
- test('deepEqualPartial treats a null expected as unequal rather than throwing', () => {
55
- expect(deepEqualPartial({ baz: 54 }, null)).toBe(false);
56
- expect(deepEqualPartial({ baz: 54 }, undefined)).toBe(false);
57
- expect(deepEqualPartial(null, null)).toBe(true);
58
- });
59
- test('findByPattern', () => {
60
- const value1 = findByPattern([], '');
61
- expectTypeOf().toEqualTypeOf();
62
- expect(value1).toBeUndefined();
63
- // @ts-expect-error itemToMatch has to follow the pattern type
64
- findByPattern([], {});
65
- // @ts-expect-error itemToMatch type has to be a serializable type
66
- const _ = (findByPattern);
67
- expect(_).toBeDefined();
68
- const value2 = findByPattern([{ pattern: 'ab', value: 1 }], 'ab');
69
- expectTypeOf().toEqualTypeOf();
70
- expect(value2).toBe(1);
71
- const value3 = findByPattern([{ pattern: 'ab', value: 1 }], 'no-match');
72
- expect(value3).toBe(undefined);
73
- const value4 = findByPattern([{ pattern: { a: 1 }, value: 1 }], { a: 1 });
74
- expect(value4).toBe(1);
75
- const value5 = findByPattern([{ value: 1 }], 'ab');
76
- expect(value5).toBe(1);
77
- const value6 = findByPattern([{ patternPartial: { a: 2 }, value: 1 }], { a: 1, b: 1 });
78
- expect(value6).toBe(undefined);
79
- const value7 = findByPattern([{ patternPartial: { a: 1 }, value: 1 }], { a: 1, b: 1 });
80
- expect(value7).toBe(1);
81
- const value8 = findByPattern([
82
- {
83
- patternPartial: { a: 1 },
84
- value: 1,
85
- },
86
- {
87
- pattern: { a: 1, b: 1 },
88
- value: 2,
89
- },
90
- ], { a: 1, b: 1 });
91
- expect(value8).toBe(2);
92
- const value9 = findByPattern([
93
- {
94
- value: 1,
95
- },
96
- {
97
- patternPartial: { a: 1 },
98
- value: 2,
99
- },
100
- {
101
- pattern: { a: 1, b: 1 },
102
- value: 3,
103
- },
104
- ], { a: 1, b: 1 });
105
- expect(value9).toBe(3);
106
- });
107
- test('optionalPatternToList', () => {
108
- const list1 = optionalPatternToList(1);
109
- expectTypeOf().toEqualTypeOf();
110
- expect(list1).toEqual([{ value: 1 }]);
111
- const list2 = optionalPatternToList([{ value: 1 }]);
112
- expectTypeOf().toEqualTypeOf();
113
- expect(list2).toEqual([{ value: 1 }]);
114
- expectTypeOf().toEqualTypeOf();
115
- });
116
- test('isDefined', () => {
117
- expect(isDefined(0)).toStrictEqual(true);
118
- expect(isDefined('')).toStrictEqual(true);
119
- expect(isDefined([])).toStrictEqual(true);
120
- expect(isDefined({})).toStrictEqual(true);
121
- expect(isDefined(undefined)).toStrictEqual(false);
122
- expect(isDefined(null)).toStrictEqual(false);
123
- });
124
- test('assertDefined', () => {
125
- expect(assertDefined(1, 'oops')).toBe(1);
126
- expect(() => assertDefined(undefined, 'oops')).toThrow('oops');
127
- expect(() => assertDefined(null, 'oops')).toThrow('oops');
128
- expect(() => assertDefined(undefined, (value) => `oops: ${value}`)).toThrow('oops: undefined');
129
- });
130
- test('assertTypeByGuard', () => {
131
- expect(assertTypeByGuard({
132
- value: 1,
133
- guard: (value) => typeof value === 'number',
134
- message: 'oops',
135
- })).toBe(1);
136
- expect(() => assertTypeByGuard({
137
- value: 'str',
138
- guard: (value) => typeof value === 'number',
139
- message: 'oops',
140
- })).toThrow('oops');
141
- expect(() => assertTypeByGuard({
142
- value: 'str',
143
- guard: (value) => typeof value === 'number',
144
- message: (value) => `oops: ${value}`,
145
- })).toThrow('oops: str');
146
- });
147
- test('assertPredicate', () => {
148
- const predicate = (value) => value > 0;
149
- expect(assertPredicate({ value: 1, predicate, message: 'oops' })).toBe(1);
150
- expect(() => assertPredicate({ value: -1, predicate, message: 'oops' })).toThrow('oops');
151
- expect(() => assertPredicate({ value: -1, predicate, message: (value) => `oops: ${value}` })).toThrow('oops: -1');
152
- });
153
- test('assertImpossible', () => {
154
- expect(() => assertImpossible('some message')).toThrow('some message');
155
- });
156
- test('unPrototypeProperties', () => {
157
- class Test {
158
- constructor(prop) {
159
- this.prop = prop;
160
- }
161
- method() {
162
- return this.prop;
163
- }
164
- method2() {
165
- return 'method2';
166
- }
167
- }
168
- const instance = new Test(1);
169
- const noPrototype = unPrototypeProperties(instance, ['method']);
170
- expectTypeOf().toEqualTypeOf();
171
- expect(noPrototype.method()).toBe(1);
172
- const method = noPrototype.method;
173
- expect(method()).toBe(1);
174
- expect(Object.hasOwn(noPrototype, 'method')).toBe(true);
175
- expect(Object.hasOwn(noPrototype, 'method2')).toBe(false);
176
- const clone = { ...noPrototype };
177
- expect(clone.method()).toBe(1);
178
- expect(Object.hasOwn(clone, 'method2')).toBe(false);
179
- // @ts-expect-error method3 is not a property of clone
180
- unPrototypeProperties(clone, ['method3']);
181
- });
182
- test('mapConst', () => {
183
- const input = ['a', 'b', 'c'];
184
- const output = mapConst(input)((value) => `${value}-const`);
185
- expectTypeOf().toEqualTypeOf();
186
- expect(output).toEqual(['a-const', 'b-const', 'c-const']);
187
- });
188
- test('mapConst expets a lambda with a correct return type', () => {
189
- const input = ['a', 'b', 'c'];
190
- // @ts-expect-error The return type of the lambda should depend on the input value
191
- mapConst(input)(() => 1);
192
- });
193
- test('mapConst infers input type from array', () => {
194
- const input = ['a', 'b', 'c'];
195
- const output = [];
196
- mapConst(input)((value, index) => {
197
- expectTypeOf().toEqualTypeOf();
198
- expectTypeOf(index).toEqualTypeOf();
199
- output.push(index);
200
- return `${value}-const`;
201
- });
202
- expect(output).toEqual([0, 1, 2]);
203
- });
204
- test('mapConst non-curried infers input type from array', () => {
205
- const input = ['a', 'b', 'c'];
206
- const output = [];
207
- const result = mapConst(input, (value, index) => {
208
- expectTypeOf().toEqualTypeOf();
209
- expectTypeOf(index).toEqualTypeOf();
210
- output.push(index);
211
- return 1;
212
- });
213
- expectTypeOf().toEqualTypeOf();
214
- expect(result).toEqual([1, 1, 1]);
215
- expect(output).toEqual([0, 1, 2]);
216
- });
217
- test('mapConstKeysToEntries infers input type from array', () => {
218
- const input = ['a', 'b', 'c'];
219
- const output = mapConstKeysToEntries(input)((value) => `${value}-const`);
220
- expectTypeOf().toEqualTypeOf();
221
- expect(output).toEqual([
222
- ['a', 'a-const'],
223
- ['b', 'b-const'],
224
- ['c', 'c-const'],
225
- ]);
226
- });
227
- test('mapConstKeysToEntries expets a lambda with a correct return type', () => {
228
- const input = ['a', 'b', 'c'];
229
- // @ts-expect-error The return type of the lambda should depend on the input value
230
- mapConstKeysToEntries(input)(() => 1);
231
- });
232
- test('mapConstKeysToEntries infers input type from array', () => {
233
- const input = ['a', 'b', 'c'];
234
- const output = [];
235
- const a = mapConstKeysToEntries(input, (value, index) => {
236
- expectTypeOf().toEqualTypeOf();
237
- expectTypeOf(index).toEqualTypeOf();
238
- output.push(index);
239
- return 1;
240
- });
241
- expectTypeOf().toEqualTypeOf();
242
- expect(a).toEqual([
243
- ['a', 1],
244
- ['b', 1],
245
- ['c', 1],
246
- ]);
247
- expect(output).toEqual([0, 1, 2]);
248
- });
249
- test('mapConstKeysToEntries infers input type from array', () => {
250
- const input = ['a', 'b', 'c'];
251
- const output = [];
252
- mapConstKeysToEntries(input)((value, index) => {
253
- expectTypeOf().toEqualTypeOf();
254
- expectTypeOf(index).toEqualTypeOf();
255
- output.push(index);
256
- return `${value}-const`;
257
- });
258
- expect(output).toEqual([0, 1, 2]);
259
- });
260
- test('objectFromConstEntries', () => {
261
- const entries = [
262
- ['a', 1],
263
- ['b', 2],
264
- ['c', 3],
265
- ];
266
- const obj = objectFromConstEntries(entries);
267
- expectTypeOf().toEqualTypeOf();
268
- expect(obj).toEqual({ a: 1, b: 2, c: 3 });
269
- });
270
- test('mapObjectFromKeys', () => {
271
- const keys = ['a', 'b', 'c'];
272
- const obj = mapObjectFromKeys(keys)((key, index) => {
273
- expectTypeOf().toEqualTypeOf();
274
- expectTypeOf(index).toEqualTypeOf();
275
- return `${key}-const`;
276
- });
277
- expectTypeOf().toEqualTypeOf();
278
- expect(obj).toEqual({ a: 'a-const', b: 'b-const', c: 'c-const' });
279
- });
280
- test('mapObjectFromKeys non-curried infers input type from array', () => {
281
- const keys = ['a', 'b', 'c'];
282
- const obj = mapObjectFromKeys(keys, (key, index) => {
283
- expectTypeOf().toEqualTypeOf();
284
- expectTypeOf(index).toEqualTypeOf();
285
- return 1;
286
- });
287
- expectTypeOf().toEqualTypeOf();
288
- expect(obj).toEqual({ a: 1, b: 1, c: 1 });
289
- });
290
- test('boolFromThrow returns true when function does not throw', () => {
291
- expect(boolFromThrow(() => { })).toBe(true);
292
- });
293
- test('boolFromThrow returns false when function throws', () => {
294
- expect(boolFromThrow(() => {
295
- throw new Error('fail');
296
- })).toBe(false);
297
- });
298
- test('boolFromThrowAsync returns true when async function does not throw', async () => {
299
- await expect(boolFromThrowAsync(async () => { })).resolves.toBe(true);
300
- });
301
- test('boolFromThrowAsync returns false when async function rejects', async () => {
302
- await expect(boolFromThrowAsync(async () => {
303
- throw new Error('fail');
304
- })).resolves.toBe(false);
305
- });
306
- test('isDeepEqual compares primitives by strict equality, with NaN equal to itself', () => {
307
- expect(isDeepEqual(1, 1)).toBe(true);
308
- expect(isDeepEqual(1, 2)).toBe(false);
309
- expect(isDeepEqual('a', 'a')).toBe(true);
310
- expect(isDeepEqual(1, '1')).toBe(false);
311
- expect(isDeepEqual(NaN, NaN)).toBe(true);
312
- expect(isDeepEqual(undefined, undefined)).toBe(true);
313
- expect(isDeepEqual(null, null)).toBe(true);
314
- expect(isDeepEqual(null, {})).toBe(false);
315
- expect(isDeepEqual({}, null)).toBe(false);
316
- });
317
- test('isDeepEqual compares plain objects by their own keys', () => {
318
- expect(isDeepEqual({ a: 1, b: 2 }, { a: 1, b: 2 })).toBe(true);
319
- expect(isDeepEqual({ a: 1 }, { a: 1, b: 2 })).toBe(false);
320
- expect(isDeepEqual({ a: 1, b: 2 }, { a: 1 })).toBe(false);
321
- expect(isDeepEqual({ a: { b: { c: 1 } } }, { a: { b: { c: 1 } } })).toBe(true);
322
- expect(isDeepEqual({ a: { b: { c: 1 } } }, { a: { b: { c: 2 } } })).toBe(false);
323
- });
324
- test('isDeepEqual compares arrays element-wise', () => {
325
- expect(isDeepEqual([1, 2, 3], [1, 2, 3])).toBe(true);
326
- expect(isDeepEqual([1, 2], [1, 2, 3])).toBe(false);
327
- expect(isDeepEqual([{ a: 1 }], [{ a: 1 }])).toBe(true);
328
- expect(isDeepEqual([{ a: 1 }], [{ a: 2 }])).toBe(false);
329
- expect(isDeepEqual([], [])).toBe(true);
330
- });
331
- test('isDeepEqual treats a different prototype as unequal', () => {
332
- class A {
333
- constructor(x) {
334
- this.x = x;
335
- }
336
- }
337
- class B {
338
- constructor(x) {
339
- this.x = x;
340
- }
341
- }
342
- expect(isDeepEqual(new A(1), new B(1))).toBe(false);
343
- expect(isDeepEqual([1], { 0: 1 })).toBe(false);
344
- });
345
- test('isDeepEqual compares Dates by time', () => {
346
- expect(isDeepEqual(new Date(1000), new Date(1000))).toBe(true);
347
- expect(isDeepEqual(new Date(1000), new Date(2000))).toBe(false);
348
- });
349
- test('isDeepEqual compares RegExps by source and flags', () => {
350
- expect(isDeepEqual(/ab+/g, /ab+/g)).toBe(true);
351
- expect(isDeepEqual(/ab+/g, /ab+/i)).toBe(false);
352
- expect(isDeepEqual(/ab+/g, /ac+/g)).toBe(false);
353
- });
354
- test('isDeepEqual compares Sets by size and membership', () => {
355
- expect(isDeepEqual(new Set([1, 2]), new Set([1, 2]))).toBe(true);
356
- expect(isDeepEqual(new Set([1, 2]), new Set([2, 1]))).toBe(true);
357
- expect(isDeepEqual(new Set([1, 2]), new Set([1, 3]))).toBe(false);
358
- expect(isDeepEqual(new Set([1]), new Set([1, 2]))).toBe(false);
359
- });
360
- test('isDeepEqual compares Maps by size and entries', () => {
361
- expect(isDeepEqual(new Map([['a', 1]]), new Map([['a', 1]]))).toBe(true);
362
- expect(isDeepEqual(new Map([['a', 1]]), new Map([['a', 2]]))).toBe(false);
363
- expect(isDeepEqual(new Map([['a', 1]]), new Map([['b', 1]]))).toBe(false);
364
- expect(isDeepEqual(new Map([['a', { b: 1 }]]), new Map([['a', { b: 1 }]]))).toBe(true);
365
- });
366
- test('isDeepEqual compares ArrayBuffers and typed arrays byte by byte', () => {
367
- const bufferOf = (bytes) => new Uint8Array(bytes).buffer;
368
- expect(isDeepEqual(bufferOf([1, 2, 3]), bufferOf([1, 2, 3]))).toBe(true);
369
- expect(isDeepEqual(bufferOf([1, 2, 3]), bufferOf([1, 2, 4]))).toBe(false);
370
- expect(isDeepEqual(bufferOf([1, 2]), bufferOf([1, 2, 3]))).toBe(false);
371
- expect(isDeepEqual(new Uint8Array([1, 2]), new Uint8Array([1, 2]))).toBe(true);
372
- expect(isDeepEqual(new Uint8Array([1, 2]), new Uint8Array([1, 3]))).toBe(false);
373
- expect(isDeepEqual(new DataView(bufferOf([9])), new DataView(bufferOf([9])))).toBe(true);
374
- expect(isDeepEqual(new DataView(bufferOf([9])), new DataView(bufferOf([8])))).toBe(false);
375
- });
376
- test('isDeepEqual survives circular references', () => {
377
- const a = { name: 'a' };
378
- a.self = a;
379
- const b = { name: 'a' };
380
- b.self = b;
381
- expect(isDeepEqual(a, b)).toBe(true);
382
- const c = { name: 'c' };
383
- c.self = c;
384
- expect(isDeepEqual(a, c)).toBe(false);
385
- });
386
- test('isDeepEqual prefers a custom valueOf when one is defined', () => {
387
- class Money {
388
- constructor(cents) {
389
- this.cents = cents;
390
- }
391
- valueOf() {
392
- return this.cents;
393
- }
394
- }
395
- expect(isDeepEqual(new Money(100), new Money(100))).toBe(true);
396
- expect(isDeepEqual(new Money(100), new Money(200))).toBe(false);
397
- });
398
- test('isDeepEqual falls back to a custom toString when one is defined', () => {
399
- class Tag {
400
- constructor(label) {
401
- this.label = label;
402
- }
403
- toString() {
404
- return this.label;
405
- }
406
- }
407
- expect(isDeepEqual(new Tag('x'), new Tag('x'))).toBe(true);
408
- expect(isDeepEqual(new Tag('x'), new Tag('y'))).toBe(false);
409
- });
410
- test('isDeepEqual compares subclasses of built-ins by their built-in semantics', () => {
411
- class MySet extends Set {
412
- }
413
- class MyMap extends Map {
414
- }
415
- expect(isDeepEqual(new MySet([1]), new MySet([1]))).toBe(true);
416
- expect(isDeepEqual(new MySet([1]), new MySet([2]))).toBe(false);
417
- expect(isDeepEqual(new MyMap([['a', 1]]), new MyMap([['a', 1]]))).toBe(true);
418
- expect(isDeepEqual(new MyMap([['a', 1]]), new MyMap([['a', 2]]))).toBe(false);
419
- });