ts-data-forge 4.1.0 → 5.0.1
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/dist/array/impl/array-utils-element-access.mjs +1 -0
- package/dist/array/impl/array-utils-element-access.mjs.map +1 -1
- package/dist/array/impl/array-utils-modification.mjs +1 -0
- package/dist/array/impl/array-utils-modification.mjs.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.mjs +2 -1
- package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
- package/dist/array/impl/array-utils-search.mjs +1 -0
- package/dist/array/impl/array-utils-search.mjs.map +1 -1
- package/dist/array/impl/array-utils-transformation.mjs +1 -0
- package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
- package/dist/collections/imap-mapped.mjs +1 -0
- package/dist/collections/imap-mapped.mjs.map +1 -1
- package/dist/collections/imap.mjs +1 -0
- package/dist/collections/imap.mjs.map +1 -1
- package/dist/collections/queue.mjs +1 -0
- package/dist/collections/queue.mjs.map +1 -1
- package/dist/collections/stack.mjs +1 -0
- package/dist/collections/stack.mjs.map +1 -1
- package/dist/functional/result/impl/result-from-throwable.d.mts.map +1 -1
- package/dist/functional/result/impl/result-from-throwable.mjs +2 -1
- package/dist/functional/result/impl/result-from-throwable.mjs.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.d.mts.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.mjs +2 -1
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.mjs.map +1 -1
- package/dist/json/json.d.mts +9 -3
- package/dist/json/json.d.mts.map +1 -1
- package/dist/json/json.mjs +7 -0
- package/dist/json/json.mjs.map +1 -1
- package/dist/number/refined-number-utils.mjs +1 -0
- package/dist/number/refined-number-utils.mjs.map +1 -1
- package/dist/others/unknown-to-string.d.mts.map +1 -1
- package/dist/others/unknown-to-string.mjs +2 -1
- package/dist/others/unknown-to-string.mjs.map +1 -1
- package/dist/promise/promise.mjs +1 -0
- package/dist/promise/promise.mjs.map +1 -1
- package/package.json +18 -18
- package/src/array/impl/array-utils-creation.test.mts +187 -74
- package/src/array/impl/array-utils-element-access.test.mts +19 -3
- package/src/array/impl/array-utils-iterators.test.mts +44 -24
- package/src/array/impl/array-utils-modification.test.mts +36 -33
- package/src/array/impl/array-utils-reducing-value.mts +2 -1
- package/src/array/impl/array-utils-reducing-value.test.mts +47 -16
- package/src/array/impl/array-utils-search.test.mts +42 -9
- package/src/array/impl/array-utils-set-op.test.mts +54 -26
- package/src/array/impl/array-utils-size.test.mts +1 -0
- package/src/array/impl/array-utils-slice-clamped.test.mts +20 -11
- package/src/array/impl/array-utils-slicing.test.mts +27 -21
- package/src/array/impl/array-utils-transformation.test.mts +140 -92
- package/src/array/impl/array-utils-validation.test.mts +58 -10
- package/src/array/impl/array.test.mts +5 -5
- package/src/collections/imap-mapped.test.mts +63 -18
- package/src/collections/imap.test.mts +74 -26
- package/src/collections/iset-mapped.test.mts +81 -30
- package/src/collections/iset.test.mts +168 -68
- package/src/collections/queue.test.mts +32 -1
- package/src/collections/stack.test.mts +22 -8
- package/src/functional/match.test.mts +1 -1
- package/src/functional/optional.test.mts +61 -4
- package/src/functional/pipe.test.mts +10 -1
- package/src/functional/result/impl/result-from-throwable.mts +2 -1
- package/src/functional/result.test.mts +127 -4
- package/src/functional/ternary-result/impl/ternary-result-from-throwable.mts +2 -1
- package/src/functional/ternary-result.test.mts +34 -18
- package/src/guard/is-non-empty-string.test.mts +5 -2
- package/src/guard/is-non-null-object.test.mts +3 -5
- package/src/guard/is-primitive.test.mts +5 -3
- package/src/guard/is-record.test.mts +1 -1
- package/src/guard/is-type.test.mts +35 -20
- package/src/guard/key-is-in.test.mts +1 -1
- package/src/iterator/range.test.mts +22 -16
- package/src/json/json.mts +9 -3
- package/src/json/json.test.mts +140 -64
- package/src/number/branded-types/finite-number.test.mts +3 -2
- package/src/number/branded-types/int.test.mts +4 -3
- package/src/number/branded-types/int16.test.mts +9 -3
- package/src/number/branded-types/int32.test.mts +9 -3
- package/src/number/branded-types/non-negative-finite-number.test.mts +6 -4
- package/src/number/branded-types/non-negative-int16.test.mts +8 -3
- package/src/number/branded-types/non-negative-int32.test.mts +8 -3
- package/src/number/branded-types/non-zero-finite-number.test.mts +6 -3
- package/src/number/branded-types/non-zero-int.test.mts +6 -3
- package/src/number/branded-types/non-zero-int16.test.mts +9 -3
- package/src/number/branded-types/non-zero-int32.test.mts +9 -3
- package/src/number/branded-types/non-zero-safe-int.test.mts +10 -3
- package/src/number/branded-types/non-zero-uint16.test.mts +8 -3
- package/src/number/branded-types/non-zero-uint32.test.mts +8 -3
- package/src/number/branded-types/positive-finite-number.test.mts +7 -3
- package/src/number/branded-types/positive-int.test.mts +5 -3
- package/src/number/branded-types/positive-int16.test.mts +8 -3
- package/src/number/branded-types/positive-int32.test.mts +8 -3
- package/src/number/branded-types/positive-safe-int.test.mts +8 -3
- package/src/number/branded-types/positive-uint16.test.mts +8 -3
- package/src/number/branded-types/positive-uint32.test.mts +8 -3
- package/src/number/branded-types/safe-int.test.mts +8 -2
- package/src/number/branded-types/safe-uint.test.mts +8 -3
- package/src/number/branded-types/uint.test.mts +5 -3
- package/src/number/branded-types/uint16.test.mts +8 -3
- package/src/number/branded-types/uint32.test.mts +8 -3
- package/src/number/enum/int8.test.mts +8 -3
- package/src/number/enum/uint8.test.mts +6 -3
- package/src/number/num.test.mts +16 -2
- package/src/object/object.test.mts +26 -13
- package/src/others/cast-mutable.test.mts +10 -8
- package/src/others/cast-readonly.test.mts +9 -5
- package/src/others/if-then.test.mts +4 -1
- package/src/others/map-nullable.test.mts +28 -1
- package/src/others/memoize-function.test.mts +20 -17
- package/src/others/tuple.test.mts +3 -2
- package/src/others/unknown-to-string.mts +2 -1
- package/src/others/unknown-to-string.test.mts +15 -2
- package/src/promise/promise.test.mts +6 -1
package/src/json/json.test.mts
CHANGED
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
import { Arr } from '../array/index.mjs';
|
|
2
2
|
import { Result } from '../functional/index.mjs';
|
|
3
|
-
import { hasKey, isRecord } from '../guard/index.mjs';
|
|
3
|
+
import { hasKey, isRecord, isString } from '../guard/index.mjs';
|
|
4
4
|
import { Json } from './json.mjs';
|
|
5
5
|
|
|
6
6
|
describe('parse', () => {
|
|
7
7
|
test('should parse primitive values', () => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
assert.deepStrictEqual(Json.parse('"hello"'), Result.ok('hello'));
|
|
9
|
+
assert.deepStrictEqual(Json.parse('42'), Result.ok(42));
|
|
10
|
+
assert.deepStrictEqual(Json.parse('true'), Result.ok(true));
|
|
11
|
+
assert.deepStrictEqual(Json.parse('false'), Result.ok(false));
|
|
12
|
+
assert.deepStrictEqual(Json.parse('null'), Result.ok(null));
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
test('should parse arrays', () => {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
assert.deepStrictEqual(Json.parse('[1,2,3]'), Result.ok([1, 2, 3]));
|
|
17
|
+
assert.deepStrictEqual(
|
|
18
|
+
Json.parse('["a","b","c"]'),
|
|
18
19
|
Result.ok(['a', 'b', 'c']),
|
|
19
20
|
);
|
|
20
|
-
|
|
21
|
+
assert.deepStrictEqual(
|
|
22
|
+
Json.parse('[1,"two",true,null]'),
|
|
21
23
|
Result.ok([1, 'two', true, null]),
|
|
22
24
|
);
|
|
23
25
|
});
|
|
24
26
|
|
|
25
27
|
test('should parse objects', () => {
|
|
26
|
-
|
|
28
|
+
assert.deepStrictEqual(
|
|
29
|
+
Json.parse('{"a":1,"b":2}'),
|
|
27
30
|
Result.ok({ a: 1, b: 2 }),
|
|
28
31
|
);
|
|
29
|
-
|
|
32
|
+
assert.deepStrictEqual(
|
|
33
|
+
Json.parse('{"name":"test","value":42}'),
|
|
30
34
|
Result.ok({
|
|
31
35
|
name: 'test',
|
|
32
36
|
value: 42,
|
|
@@ -43,14 +47,17 @@ describe('parse', () => {
|
|
|
43
47
|
},
|
|
44
48
|
},
|
|
45
49
|
};
|
|
46
|
-
|
|
50
|
+
|
|
51
|
+
assert.deepStrictEqual(Json.parse(json), Result.ok(expected));
|
|
47
52
|
});
|
|
48
53
|
|
|
49
54
|
test('should handle whitespace', () => {
|
|
50
|
-
|
|
55
|
+
assert.deepStrictEqual(
|
|
56
|
+
Json.parse(' { "a" : 1 , "b" : 2 } '),
|
|
51
57
|
Result.ok({ a: 1, b: 2 }),
|
|
52
58
|
);
|
|
53
|
-
|
|
59
|
+
assert.deepStrictEqual(
|
|
60
|
+
Json.parse('\n[\n 1,\n 2,\n 3\n]\n'),
|
|
54
61
|
Result.ok([1, 2, 3]),
|
|
55
62
|
);
|
|
56
63
|
});
|
|
@@ -63,12 +70,12 @@ describe('parse', () => {
|
|
|
63
70
|
});
|
|
64
71
|
|
|
65
72
|
test('should return parsed value for valid JSON', () => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
assert.deepStrictEqual(Json.parse('{"a":1}'), Result.ok({ a: 1 }));
|
|
74
|
+
assert.deepStrictEqual(Json.parse('[1,2,3]'), Result.ok([1, 2, 3]));
|
|
75
|
+
assert.deepStrictEqual(Json.parse('"string"'), Result.ok('string'));
|
|
76
|
+
assert.deepStrictEqual(Json.parse('42'), Result.ok(42));
|
|
77
|
+
assert.deepStrictEqual(Json.parse('true'), Result.ok(true));
|
|
78
|
+
assert.deepStrictEqual(Json.parse('null'), Result.ok(null));
|
|
72
79
|
});
|
|
73
80
|
|
|
74
81
|
test('should return error for invalid JSON cases', () => {
|
|
@@ -80,10 +87,10 @@ describe('parse', () => {
|
|
|
80
87
|
});
|
|
81
88
|
|
|
82
89
|
test('should handle edge cases', () => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
assert.deepStrictEqual(Json.parse('0'), Result.ok(0));
|
|
91
|
+
assert.deepStrictEqual(Json.parse('""'), Result.ok(''));
|
|
92
|
+
assert.deepStrictEqual(Json.parse('[]'), Result.ok([]));
|
|
93
|
+
assert.deepStrictEqual(Json.parse('{}'), Result.ok({}));
|
|
87
94
|
});
|
|
88
95
|
|
|
89
96
|
test('should not throw errors', () => {
|
|
@@ -105,6 +112,7 @@ describe('parse', () => {
|
|
|
105
112
|
const result = Json.parse(jsonString, dateReviver);
|
|
106
113
|
|
|
107
114
|
expect(Result.isOk(result)).toBe(true);
|
|
115
|
+
|
|
108
116
|
if (
|
|
109
117
|
Result.isOk(result) &&
|
|
110
118
|
isRecord(result.value) &&
|
|
@@ -130,9 +138,11 @@ describe('parse', () => {
|
|
|
130
138
|
);
|
|
131
139
|
|
|
132
140
|
expect(Result.isOk(result)).toBe(true);
|
|
141
|
+
|
|
133
142
|
if (Result.isOk(result)) {
|
|
134
143
|
expect(result.value).toHaveProperty('number');
|
|
135
144
|
expect(result.value).toHaveProperty('text');
|
|
145
|
+
|
|
136
146
|
if (
|
|
137
147
|
isRecord(result.value) &&
|
|
138
148
|
hasKey(result.value, 'number') &&
|
|
@@ -147,27 +157,31 @@ describe('parse', () => {
|
|
|
147
157
|
|
|
148
158
|
describe('stringify', () => {
|
|
149
159
|
test('should stringify primitive values', () => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
160
|
+
assert.deepStrictEqual(Json.stringify('hello'), Result.ok('"hello"'));
|
|
161
|
+
assert.deepStrictEqual(Json.stringify(42), Result.ok('42'));
|
|
162
|
+
assert.deepStrictEqual(Json.stringify(true), Result.ok('true'));
|
|
163
|
+
assert.deepStrictEqual(Json.stringify(null), Result.ok('null'));
|
|
154
164
|
});
|
|
155
165
|
|
|
156
166
|
test('should stringify arrays', () => {
|
|
157
|
-
|
|
158
|
-
|
|
167
|
+
assert.deepStrictEqual(Json.stringify([1, 2, 3]), Result.ok('[1,2,3]'));
|
|
168
|
+
assert.deepStrictEqual(
|
|
169
|
+
Json.stringify(['a', 'b', 'c']),
|
|
159
170
|
Result.ok('["a","b","c"]'),
|
|
160
171
|
);
|
|
161
|
-
|
|
172
|
+
assert.deepStrictEqual(
|
|
173
|
+
Json.stringify([1, 'two', true, null]),
|
|
162
174
|
Result.ok('[1,"two",true,null]'),
|
|
163
175
|
);
|
|
164
176
|
});
|
|
165
177
|
|
|
166
178
|
test('should stringify objects', () => {
|
|
167
|
-
|
|
179
|
+
assert.deepStrictEqual(
|
|
180
|
+
Json.stringify({ a: 1, b: 2 }),
|
|
168
181
|
Result.ok('{"a":1,"b":2}'),
|
|
169
182
|
);
|
|
170
|
-
|
|
183
|
+
assert.deepStrictEqual(
|
|
184
|
+
Json.stringify({ name: 'test', value: 42 }),
|
|
171
185
|
Result.ok('{"name":"test","value":42}'),
|
|
172
186
|
);
|
|
173
187
|
});
|
|
@@ -180,41 +194,53 @@ describe('stringify', () => {
|
|
|
180
194
|
},
|
|
181
195
|
},
|
|
182
196
|
};
|
|
183
|
-
|
|
197
|
+
|
|
198
|
+
assert.deepStrictEqual(
|
|
199
|
+
Json.stringify(nested),
|
|
184
200
|
Result.ok('{"level1":{"level2":{"array":[1,2,{"level3":"deep"}]}}}'),
|
|
185
201
|
);
|
|
186
202
|
});
|
|
187
203
|
|
|
188
204
|
test('should handle empty structures', () => {
|
|
189
|
-
|
|
190
|
-
|
|
205
|
+
assert.deepStrictEqual(Json.stringify({}), Result.ok('{}'));
|
|
206
|
+
assert.deepStrictEqual(Json.stringify([]), Result.ok('[]'));
|
|
191
207
|
});
|
|
192
208
|
|
|
193
209
|
test('should handle special string values', () => {
|
|
194
|
-
|
|
210
|
+
assert.deepStrictEqual(
|
|
211
|
+
Json.stringify('with "quotes"'),
|
|
195
212
|
Result.ok(String.raw`"with \"quotes\""`),
|
|
196
213
|
);
|
|
197
|
-
|
|
214
|
+
assert.deepStrictEqual(
|
|
215
|
+
Json.stringify('with\nnewline'),
|
|
198
216
|
Result.ok(String.raw`"with\nnewline"`),
|
|
199
217
|
);
|
|
200
|
-
|
|
218
|
+
assert.deepStrictEqual(
|
|
219
|
+
Json.stringify('with\ttab'),
|
|
201
220
|
Result.ok(String.raw`"with\ttab"`),
|
|
202
221
|
);
|
|
203
222
|
});
|
|
204
223
|
|
|
205
224
|
test('should return stringified value for valid JSON values', () => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
225
|
+
assert.deepStrictEqual(Json.stringify({ a: 1 }), Result.ok('{"a":1}'));
|
|
226
|
+
assert.deepStrictEqual(Json.stringify([1, 2, 3]), Result.ok('[1,2,3]'));
|
|
227
|
+
assert.deepStrictEqual(Json.stringify('string'), Result.ok('"string"'));
|
|
228
|
+
assert.deepStrictEqual(Json.stringify(42), Result.ok('42'));
|
|
229
|
+
assert.deepStrictEqual(Json.stringify(true), Result.ok('true'));
|
|
230
|
+
assert.deepStrictEqual(Json.stringify(null), Result.ok('null'));
|
|
212
231
|
});
|
|
213
232
|
|
|
214
233
|
test('should handle non-serializable values', () => {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
234
|
+
assert.deepStrictEqual(Json.stringify(undefined), Result.ok(undefined));
|
|
235
|
+
assert.deepStrictEqual(
|
|
236
|
+
Json.stringify(Symbol('test')),
|
|
237
|
+
Result.ok(undefined),
|
|
238
|
+
);
|
|
239
|
+
assert.deepStrictEqual(
|
|
240
|
+
Json.stringify(() => {}),
|
|
241
|
+
Result.ok(undefined),
|
|
242
|
+
);
|
|
243
|
+
|
|
218
244
|
// BigInt should cause an error
|
|
219
245
|
expect(Result.isErr(Json.stringify(123n))).toBe(true);
|
|
220
246
|
});
|
|
@@ -223,6 +249,7 @@ describe('stringify', () => {
|
|
|
223
249
|
const mut_obj: any = { a: 1 };
|
|
224
250
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
225
251
|
mut_obj.circular = mut_obj;
|
|
252
|
+
|
|
226
253
|
expect(Result.isErr(Json.stringify(mut_obj))).toBe(true);
|
|
227
254
|
});
|
|
228
255
|
|
|
@@ -230,12 +257,18 @@ describe('stringify', () => {
|
|
|
230
257
|
const obj = {
|
|
231
258
|
toJSON: () => ({ custom: 'value' }),
|
|
232
259
|
};
|
|
233
|
-
|
|
260
|
+
|
|
261
|
+
assert.deepStrictEqual(
|
|
262
|
+
Json.stringify(obj),
|
|
263
|
+
Result.ok('{"custom":"value"}'),
|
|
264
|
+
);
|
|
234
265
|
});
|
|
235
266
|
|
|
236
267
|
test('should handle Date objects', () => {
|
|
237
268
|
const date = new Date('2023-01-01T00:00:00.000Z');
|
|
238
|
-
|
|
269
|
+
|
|
270
|
+
assert.deepStrictEqual(
|
|
271
|
+
Json.stringify(date),
|
|
239
272
|
Result.ok('"2023-01-01T00:00:00.000Z"'),
|
|
240
273
|
);
|
|
241
274
|
});
|
|
@@ -263,6 +296,7 @@ describe('stringify', () => {
|
|
|
263
296
|
const result = Json.stringify(data, secureReplacer);
|
|
264
297
|
|
|
265
298
|
expect(Result.isOk(result)).toBe(true);
|
|
299
|
+
|
|
266
300
|
if (Result.isOk(result)) {
|
|
267
301
|
expect(result.value).toContain('[REDACTED]');
|
|
268
302
|
expect(result.value).not.toContain('secret123');
|
|
@@ -274,6 +308,7 @@ describe('stringify', () => {
|
|
|
274
308
|
const result = Json.stringify(data, undefined, 2);
|
|
275
309
|
|
|
276
310
|
expect(Result.isOk(result)).toBe(true);
|
|
311
|
+
|
|
277
312
|
if (Result.isOk(result)) {
|
|
278
313
|
expect(result.value).toContain('\n');
|
|
279
314
|
expect(result.value).toContain(' '); // 2 spaces indentation
|
|
@@ -285,6 +320,7 @@ describe('stringify', () => {
|
|
|
285
320
|
const result = Json.stringify(data, undefined, '\t');
|
|
286
321
|
|
|
287
322
|
expect(Result.isOk(result)).toBe(true);
|
|
323
|
+
|
|
288
324
|
if (Result.isOk(result)) {
|
|
289
325
|
expect(result.value).toContain('\n');
|
|
290
326
|
expect(result.value).toContain('\t'); // tab indentation
|
|
@@ -305,13 +341,18 @@ describe('stringifySelected', () => {
|
|
|
305
341
|
const result = Json.stringifySelected(user, ['id', 'name', 'email']);
|
|
306
342
|
|
|
307
343
|
expect(Result.isOk(result)).toBe(true);
|
|
344
|
+
|
|
308
345
|
if (Result.isOk(result)) {
|
|
346
|
+
assert(isString(result.value));
|
|
347
|
+
|
|
309
348
|
const parsed: unknown = JSON.parse(result.value);
|
|
310
|
-
|
|
349
|
+
|
|
350
|
+
assert.deepStrictEqual(parsed, {
|
|
311
351
|
id: 1,
|
|
312
352
|
name: 'Alice',
|
|
313
353
|
email: 'alice@example.com',
|
|
314
354
|
});
|
|
355
|
+
|
|
315
356
|
expect(parsed).not.toHaveProperty('password');
|
|
316
357
|
expect(parsed).not.toHaveProperty('lastLogin');
|
|
317
358
|
}
|
|
@@ -335,17 +376,22 @@ describe('stringifySelected', () => {
|
|
|
335
376
|
]);
|
|
336
377
|
|
|
337
378
|
expect(Result.isOk(result)).toBe(true);
|
|
379
|
+
|
|
338
380
|
if (Result.isOk(result)) {
|
|
381
|
+
assert(isString(result.value));
|
|
339
382
|
const parsed: unknown = JSON.parse(result.value);
|
|
340
383
|
if (isRecord(parsed) && hasKey(parsed, 'users')) {
|
|
341
384
|
expect(isRecord(parsed.users)).toBe(false);
|
|
342
385
|
expect(parsed.users).toHaveLength(2);
|
|
386
|
+
|
|
343
387
|
if (Arr.isArray(parsed.users)) {
|
|
344
|
-
|
|
388
|
+
assert.deepStrictEqual(parsed.users[0], { id: 1, name: 'Alice' });
|
|
389
|
+
|
|
345
390
|
expect(parsed.users[0]).not.toHaveProperty('secret');
|
|
346
391
|
}
|
|
347
392
|
if (isRecord(parsed) && hasKey(parsed, 'metadata')) {
|
|
348
|
-
|
|
393
|
+
assert.deepStrictEqual(parsed.metadata, { total: 2 });
|
|
394
|
+
|
|
349
395
|
expect(parsed.metadata).not.toHaveProperty('page');
|
|
350
396
|
expect(parsed.metadata).not.toHaveProperty('internal');
|
|
351
397
|
}
|
|
@@ -363,8 +409,11 @@ describe('stringifySelected', () => {
|
|
|
363
409
|
const result = Json.stringifySelected(matrix, [0, 1]);
|
|
364
410
|
|
|
365
411
|
expect(Result.isOk(result)).toBe(true);
|
|
412
|
+
|
|
366
413
|
if (Result.isOk(result)) {
|
|
414
|
+
assert(isString(result.value));
|
|
367
415
|
const parsed: unknown = JSON.parse(result.value);
|
|
416
|
+
|
|
368
417
|
// Note: stringifySelected works with JSON.stringify's replacer parameter
|
|
369
418
|
// which may not work as expected with arrays
|
|
370
419
|
expect(Array.isArray(parsed)).toBe(true);
|
|
@@ -377,6 +426,7 @@ describe('stringifySelected', () => {
|
|
|
377
426
|
const result = Json.stringifySelected(data, ['a', 'b', 'c'], 2);
|
|
378
427
|
|
|
379
428
|
expect(Result.isOk(result)).toBe(true);
|
|
429
|
+
|
|
380
430
|
if (Result.isOk(result)) {
|
|
381
431
|
expect(result.value).toContain('\n');
|
|
382
432
|
expect(result.value).toContain(' ');
|
|
@@ -388,6 +438,7 @@ describe('stringifySelected', () => {
|
|
|
388
438
|
const result = Json.stringifySelected(data, []);
|
|
389
439
|
|
|
390
440
|
expect(Result.isOk(result)).toBe(true);
|
|
441
|
+
|
|
391
442
|
if (Result.isOk(result)) {
|
|
392
443
|
expect(result.value).toBe('{}');
|
|
393
444
|
}
|
|
@@ -398,9 +449,12 @@ describe('stringifySelected', () => {
|
|
|
398
449
|
const result = Json.stringifySelected(data, undefined);
|
|
399
450
|
|
|
400
451
|
expect(Result.isOk(result)).toBe(true);
|
|
452
|
+
|
|
401
453
|
if (Result.isOk(result)) {
|
|
454
|
+
assert(isString(result.value));
|
|
402
455
|
const parsed: unknown = JSON.parse(result.value);
|
|
403
|
-
|
|
456
|
+
|
|
457
|
+
assert.deepStrictEqual(parsed, { a: 1, b: 2 });
|
|
404
458
|
}
|
|
405
459
|
});
|
|
406
460
|
|
|
@@ -413,8 +467,9 @@ describe('stringifySelected', () => {
|
|
|
413
467
|
|
|
414
468
|
// Note: JSON.stringify may handle circular references differently depending on the replacer
|
|
415
469
|
expect(Result.isOk(result) || Result.isErr(result)).toBe(true);
|
|
470
|
+
|
|
416
471
|
if (Result.isErr(result)) {
|
|
417
|
-
|
|
472
|
+
expectTypeOf(result.value).toBeString();
|
|
418
473
|
}
|
|
419
474
|
});
|
|
420
475
|
});
|
|
@@ -431,6 +486,7 @@ describe('stringifySortedKey', () => {
|
|
|
431
486
|
const result = Json.stringifySortedKey(unsortedObj);
|
|
432
487
|
|
|
433
488
|
expect(Result.isOk(result)).toBe(true);
|
|
489
|
+
|
|
434
490
|
if (Result.isOk(result)) {
|
|
435
491
|
expect(result.value).toBe(
|
|
436
492
|
'{"aardvark":"animal","apple":"fruit","banana":"fruit","zebra":"animal"}',
|
|
@@ -458,19 +514,24 @@ describe('stringifySortedKey', () => {
|
|
|
458
514
|
const result = Json.stringifySortedKey(nestedObj);
|
|
459
515
|
|
|
460
516
|
expect(Result.isOk(result)).toBe(true);
|
|
517
|
+
|
|
461
518
|
if (Result.isOk(result)) {
|
|
519
|
+
assert(isString(result.value));
|
|
462
520
|
const parsed: unknown = JSON.parse(result.value);
|
|
463
521
|
if (isRecord(parsed)) {
|
|
464
522
|
const keys = Object.keys(parsed);
|
|
465
|
-
|
|
523
|
+
|
|
524
|
+
assert.deepStrictEqual(keys, ['settings', 'user']); // sorted top-level keys
|
|
466
525
|
|
|
467
526
|
if (hasKey(parsed, 'user') && isRecord(parsed.user)) {
|
|
468
527
|
const userKeys = Object.keys(parsed.user);
|
|
469
|
-
|
|
528
|
+
|
|
529
|
+
assert.deepStrictEqual(userKeys, ['address', 'age', 'name']); // sorted nested keys
|
|
470
530
|
|
|
471
531
|
if (hasKey(parsed.user, 'address') && isRecord(parsed.user.address)) {
|
|
472
532
|
const addressKeys = Object.keys(parsed.user.address);
|
|
473
|
-
|
|
533
|
+
|
|
534
|
+
assert.deepStrictEqual(addressKeys, ['city', 'country', 'zip']); // sorted deeper nested keys
|
|
474
535
|
}
|
|
475
536
|
}
|
|
476
537
|
}
|
|
@@ -493,18 +554,26 @@ describe('stringifySortedKey', () => {
|
|
|
493
554
|
const result = Json.stringifySortedKey(dataWithArrays);
|
|
494
555
|
|
|
495
556
|
expect(Result.isOk(result)).toBe(true);
|
|
557
|
+
|
|
496
558
|
if (Result.isOk(result)) {
|
|
559
|
+
assert(isString(result.value));
|
|
497
560
|
const parsed: unknown = JSON.parse(result.value);
|
|
498
561
|
|
|
499
562
|
if (isRecord(parsed)) {
|
|
500
563
|
// Check top-level keys are sorted
|
|
501
564
|
const topKeys = Object.keys(parsed);
|
|
502
|
-
|
|
565
|
+
|
|
566
|
+
assert.deepStrictEqual(topKeys, ['metadata', 'users']);
|
|
503
567
|
|
|
504
568
|
// Check metadata keys are sorted
|
|
505
569
|
if (hasKey(parsed, 'metadata') && isRecord(parsed.metadata)) {
|
|
506
570
|
const metadataKeys = Object.keys(parsed.metadata);
|
|
507
|
-
|
|
571
|
+
|
|
572
|
+
assert.deepStrictEqual(metadataKeys, [
|
|
573
|
+
'author',
|
|
574
|
+
'created',
|
|
575
|
+
'version',
|
|
576
|
+
]);
|
|
508
577
|
}
|
|
509
578
|
|
|
510
579
|
// Check user object keys are sorted
|
|
@@ -516,7 +585,8 @@ describe('stringifySortedKey', () => {
|
|
|
516
585
|
const firstUser = parsed.users[0];
|
|
517
586
|
if (isRecord(firstUser)) {
|
|
518
587
|
const userKeys = Object.keys(firstUser);
|
|
519
|
-
|
|
588
|
+
|
|
589
|
+
assert.deepStrictEqual(userKeys, ['active', 'id', 'name']);
|
|
520
590
|
}
|
|
521
591
|
}
|
|
522
592
|
}
|
|
@@ -528,6 +598,7 @@ describe('stringifySortedKey', () => {
|
|
|
528
598
|
const result = Json.stringifySortedKey(obj, 2);
|
|
529
599
|
|
|
530
600
|
expect(Result.isOk(result)).toBe(true);
|
|
601
|
+
|
|
531
602
|
if (Result.isOk(result)) {
|
|
532
603
|
expect(result.value).toContain('\n');
|
|
533
604
|
expect(result.value).toContain(' ');
|
|
@@ -566,8 +637,9 @@ describe('stringifySortedKey', () => {
|
|
|
566
637
|
|
|
567
638
|
// This may throw due to circular reference during key extraction
|
|
568
639
|
expect(Result.isErr(result)).toBe(true);
|
|
640
|
+
|
|
569
641
|
if (Result.isErr(result)) {
|
|
570
|
-
|
|
642
|
+
expectTypeOf(result.value).toBeString();
|
|
571
643
|
}
|
|
572
644
|
} catch (error) {
|
|
573
645
|
// Expected if circular reference causes stack overflow
|
|
@@ -579,6 +651,7 @@ describe('stringifySortedKey', () => {
|
|
|
579
651
|
const result = Json.stringifySortedKey({});
|
|
580
652
|
|
|
581
653
|
expect(Result.isOk(result)).toBe(true);
|
|
654
|
+
|
|
582
655
|
if (Result.isOk(result)) {
|
|
583
656
|
expect(result.value).toBe('{}');
|
|
584
657
|
}
|
|
@@ -600,12 +673,15 @@ describe('stringifySortedKey', () => {
|
|
|
600
673
|
const result = Json.stringifySortedKey(deep);
|
|
601
674
|
|
|
602
675
|
expect(Result.isOk(result)).toBe(true);
|
|
676
|
+
|
|
603
677
|
if (Result.isOk(result)) {
|
|
678
|
+
assert(isString(result.value));
|
|
604
679
|
const parsed: unknown = JSON.parse(result.value);
|
|
605
680
|
if (isRecord(parsed) && hasKey(parsed, 'level1')) {
|
|
606
681
|
const level1 = parsed.level1;
|
|
607
682
|
if (isRecord(level1)) {
|
|
608
|
-
|
|
683
|
+
assert.deepStrictEqual(Object.keys(level1), ['a', 'z']);
|
|
684
|
+
|
|
609
685
|
if (
|
|
610
686
|
hasKey(level1, 'a') &&
|
|
611
687
|
isRecord(level1.a) &&
|
|
@@ -613,7 +689,7 @@ describe('stringifySortedKey', () => {
|
|
|
613
689
|
) {
|
|
614
690
|
const nested = level1.a.nested;
|
|
615
691
|
if (isRecord(nested)) {
|
|
616
|
-
|
|
692
|
+
assert.deepStrictEqual(Object.keys(nested), ['x', 'y']);
|
|
617
693
|
}
|
|
618
694
|
}
|
|
619
695
|
}
|
|
@@ -3,8 +3,8 @@ import { range } from '../../iterator/index.mjs';
|
|
|
3
3
|
import { asFiniteNumber, FiniteNumber } from './finite-number.mjs';
|
|
4
4
|
import { asNonZeroFiniteNumber } from './non-zero-finite-number.mjs';
|
|
5
5
|
|
|
6
|
-
describe('FiniteNumber', () => {
|
|
7
|
-
describe(
|
|
6
|
+
describe('FiniteNumber test', () => {
|
|
7
|
+
describe(asFiniteNumber, () => {
|
|
8
8
|
test('accepts valid finite numbers', () => {
|
|
9
9
|
expect(() => asFiniteNumber(0)).not.toThrow();
|
|
10
10
|
expect(() => asFiniteNumber(1)).not.toThrow();
|
|
@@ -119,6 +119,7 @@ describe('FiniteNumber', () => {
|
|
|
119
119
|
|
|
120
120
|
for (const _ of range(10)) {
|
|
121
121
|
const result = FiniteNumber.random(min, max);
|
|
122
|
+
|
|
122
123
|
expect(result).toBeGreaterThanOrEqual(min);
|
|
123
124
|
expect(result).toBeLessThanOrEqual(max);
|
|
124
125
|
expect(FiniteNumber.is(result)).toBe(true);
|
|
@@ -3,8 +3,8 @@ import { range } from '../../iterator/index.mjs';
|
|
|
3
3
|
import { asInt, Int, isInt } from './int.mjs';
|
|
4
4
|
import { asNonZeroInt } from './non-zero-int.mjs';
|
|
5
5
|
|
|
6
|
-
describe('Int', () => {
|
|
7
|
-
describe(
|
|
6
|
+
describe('Int test', () => {
|
|
7
|
+
describe(asInt, () => {
|
|
8
8
|
test('accepts valid integers', () => {
|
|
9
9
|
expect(() => asInt(0)).not.toThrow();
|
|
10
10
|
expect(() => asInt(1)).not.toThrow();
|
|
@@ -42,7 +42,7 @@ describe('Int', () => {
|
|
|
42
42
|
});
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
describe(
|
|
45
|
+
describe(isInt, () => {
|
|
46
46
|
test('correctly identifies integers', () => {
|
|
47
47
|
expect(isInt(0)).toBe(true);
|
|
48
48
|
expect(isInt(1)).toBe(true);
|
|
@@ -123,6 +123,7 @@ describe('Int', () => {
|
|
|
123
123
|
|
|
124
124
|
for (const _ of range(10)) {
|
|
125
125
|
const result = Int.random(min, max);
|
|
126
|
+
|
|
126
127
|
expect(result).toBeGreaterThanOrEqual(min);
|
|
127
128
|
expect(result).toBeLessThanOrEqual(max);
|
|
128
129
|
expect(Int.is(result)).toBe(true);
|
|
@@ -3,8 +3,8 @@ import { range } from '../../iterator/index.mjs';
|
|
|
3
3
|
import { asInt16, Int16, isInt16 } from './int16.mjs';
|
|
4
4
|
import { asNonZeroInt16 } from './non-zero-int16.mjs';
|
|
5
5
|
|
|
6
|
-
describe('Int16', () => {
|
|
7
|
-
describe(
|
|
6
|
+
describe('Int16 test', () => {
|
|
7
|
+
describe(asInt16, () => {
|
|
8
8
|
test('accepts valid int16 values', () => {
|
|
9
9
|
expect(() => asInt16(0)).not.toThrow();
|
|
10
10
|
expect(() => asInt16(1)).not.toThrow();
|
|
@@ -49,7 +49,7 @@ describe('Int16', () => {
|
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
describe(
|
|
52
|
+
describe(isInt16, () => {
|
|
53
53
|
test('correctly identifies int16 values', () => {
|
|
54
54
|
expect(isInt16(0)).toBe(true);
|
|
55
55
|
expect(isInt16(1)).toBe(true);
|
|
@@ -109,18 +109,21 @@ describe('Int16', () => {
|
|
|
109
109
|
|
|
110
110
|
test('add (with clamping)', () => {
|
|
111
111
|
const result = Int16.add(asInt16(32_000), asInt16(1000));
|
|
112
|
+
|
|
112
113
|
expect(result).toBe(32_767); // clamped to max
|
|
113
114
|
expect(Int16.add(a, b)).toBe(150);
|
|
114
115
|
});
|
|
115
116
|
|
|
116
117
|
test('sub (with clamping)', () => {
|
|
117
118
|
const result = Int16.sub(asInt16(-32_000), asInt16(1000));
|
|
119
|
+
|
|
118
120
|
expect(result).toBe(-32_768); // clamped to min
|
|
119
121
|
expect(Int16.sub(a, b)).toBe(50);
|
|
120
122
|
});
|
|
121
123
|
|
|
122
124
|
test('mul (with clamping)', () => {
|
|
123
125
|
const result = Int16.mul(asInt16(1000), asInt16(100));
|
|
126
|
+
|
|
124
127
|
expect(result).toBe(32_767); // clamped to max
|
|
125
128
|
expect(Int16.mul(asInt16(10), asInt16(5))).toBe(50);
|
|
126
129
|
});
|
|
@@ -133,6 +136,7 @@ describe('Int16', () => {
|
|
|
133
136
|
|
|
134
137
|
test('pow (with clamping)', () => {
|
|
135
138
|
const result = Int16.pow(asInt16(200), asInt16(3));
|
|
139
|
+
|
|
136
140
|
expect(result).toBe(32_767); // clamped to max
|
|
137
141
|
expect(Int16.pow(asInt16(2), asInt16(3))).toBe(8);
|
|
138
142
|
});
|
|
@@ -145,6 +149,7 @@ describe('Int16', () => {
|
|
|
145
149
|
|
|
146
150
|
for (const _ of range(10)) {
|
|
147
151
|
const result = Int16.random(min, max);
|
|
152
|
+
|
|
148
153
|
expect(result).toBeGreaterThanOrEqual(min);
|
|
149
154
|
expect(result).toBeLessThanOrEqual(max);
|
|
150
155
|
expect(Int16.is(result)).toBe(true);
|
|
@@ -155,6 +160,7 @@ describe('Int16', () => {
|
|
|
155
160
|
test('generates values within Int16 range', () => {
|
|
156
161
|
for (const _ of range(10)) {
|
|
157
162
|
const result = Int16.random(-20, 20);
|
|
163
|
+
|
|
158
164
|
expect(result).toBeGreaterThanOrEqual(Int16.MIN_VALUE);
|
|
159
165
|
expect(result).toBeLessThanOrEqual(Int16.MAX_VALUE);
|
|
160
166
|
}
|