nalloc 0.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/README.md +282 -0
- package/build/devtools.cjs +79 -0
- package/build/devtools.cjs.map +1 -0
- package/build/devtools.d.ts +82 -0
- package/build/devtools.js +43 -0
- package/build/devtools.js.map +1 -0
- package/build/index.cjs +76 -0
- package/build/index.cjs.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.js +5 -0
- package/build/index.js.map +1 -0
- package/build/option.cjs +279 -0
- package/build/option.cjs.map +1 -0
- package/build/option.d.ts +356 -0
- package/build/option.js +157 -0
- package/build/option.js.map +1 -0
- package/build/result.cjs +381 -0
- package/build/result.cjs.map +1 -0
- package/build/result.d.ts +442 -0
- package/build/result.js +229 -0
- package/build/result.js.map +1 -0
- package/build/safe.cjs +88 -0
- package/build/safe.cjs.map +1 -0
- package/build/safe.d.ts +29 -0
- package/build/safe.js +18 -0
- package/build/safe.js.map +1 -0
- package/build/testing.cjs +111 -0
- package/build/testing.cjs.map +1 -0
- package/build/testing.d.ts +85 -0
- package/build/testing.js +81 -0
- package/build/testing.js.map +1 -0
- package/build/types.cjs +78 -0
- package/build/types.cjs.map +1 -0
- package/build/types.d.ts +137 -0
- package/build/types.js +36 -0
- package/build/types.js.map +1 -0
- package/build/unsafe.cjs +82 -0
- package/build/unsafe.cjs.map +1 -0
- package/build/unsafe.d.ts +27 -0
- package/build/unsafe.js +11 -0
- package/build/unsafe.js.map +1 -0
- package/package.json +93 -0
- package/src/__tests__/index.ts +13 -0
- package/src/__tests__/option.ts +610 -0
- package/src/__tests__/option.types.ts +120 -0
- package/src/__tests__/result.ts +721 -0
- package/src/__tests__/result.types.ts +249 -0
- package/src/__tests__/safe.ts +24 -0
- package/src/__tests__/tooling.ts +86 -0
- package/src/__tests__/unsafe.ts +24 -0
- package/src/devtools.ts +97 -0
- package/src/index.ts +18 -0
- package/src/option.ts +510 -0
- package/src/result.ts +676 -0
- package/src/safe.ts +58 -0
- package/src/testing.ts +159 -0
- package/src/types.ts +201 -0
- package/src/unsafe.ts +47 -0
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
of,
|
|
4
|
+
isSome,
|
|
5
|
+
isNone,
|
|
6
|
+
map,
|
|
7
|
+
flatMap,
|
|
8
|
+
andThen,
|
|
9
|
+
tap,
|
|
10
|
+
filter,
|
|
11
|
+
unwrap,
|
|
12
|
+
unwrapOr,
|
|
13
|
+
unwrapOrElse,
|
|
14
|
+
expect as expectOpt,
|
|
15
|
+
or,
|
|
16
|
+
orElse,
|
|
17
|
+
xor,
|
|
18
|
+
and,
|
|
19
|
+
zip,
|
|
20
|
+
unzip,
|
|
21
|
+
mapOr,
|
|
22
|
+
mapOrElse,
|
|
23
|
+
flatten,
|
|
24
|
+
contains,
|
|
25
|
+
isSomeAnd,
|
|
26
|
+
toArray,
|
|
27
|
+
toNullable,
|
|
28
|
+
toUndefined,
|
|
29
|
+
match,
|
|
30
|
+
okOr,
|
|
31
|
+
okOrElse,
|
|
32
|
+
ofOk,
|
|
33
|
+
ofErr,
|
|
34
|
+
fromNullable,
|
|
35
|
+
fromPromise,
|
|
36
|
+
unwrapOrReturn,
|
|
37
|
+
assertSome,
|
|
38
|
+
satisfiesOption,
|
|
39
|
+
filterMap
|
|
40
|
+
} from '../option.js';
|
|
41
|
+
import { formatOption, inspectOption } from '../devtools.js';
|
|
42
|
+
import { ok, err, some, none } from '../types.js';
|
|
43
|
+
|
|
44
|
+
describe('Option', () => {
|
|
45
|
+
describe('constructors', () => {
|
|
46
|
+
it('of creates Some from non-null value', () => {
|
|
47
|
+
const opt = of(42);
|
|
48
|
+
expect(isSome(opt)).toBe(true);
|
|
49
|
+
expect(opt).toBe(42);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('of creates None from null', () => {
|
|
53
|
+
const opt = of(null);
|
|
54
|
+
expect(isNone(opt)).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('of creates None from undefined', () => {
|
|
58
|
+
const opt = of(undefined);
|
|
59
|
+
expect(isNone(opt)).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('some creates Some from value', () => {
|
|
63
|
+
const opt = some(42);
|
|
64
|
+
expect(isSome(opt)).toBe(true);
|
|
65
|
+
expect(opt).toBe(42);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('some does not throw on null/undefined', () => {
|
|
69
|
+
expect(() => some(null as any)).not.toThrow();
|
|
70
|
+
expect(() => some(undefined as any)).not.toThrow();
|
|
71
|
+
expect(isNone(some(null as any))).toBe(true);
|
|
72
|
+
expect(isNone(some(undefined as any))).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('none creates None', () => {
|
|
76
|
+
const opt = none;
|
|
77
|
+
expect(isNone(opt)).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('type guards', () => {
|
|
82
|
+
it('isSome returns true for Some', () => {
|
|
83
|
+
expect(isSome(of(42))).toBe(true);
|
|
84
|
+
expect(isSome(of(0))).toBe(true);
|
|
85
|
+
expect(isSome(of(''))).toBe(true);
|
|
86
|
+
expect(isSome(of(false))).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('isSome returns false for None', () => {
|
|
90
|
+
expect(isSome(none)).toBe(false);
|
|
91
|
+
expect(isSome(of(null))).toBe(false);
|
|
92
|
+
expect(isSome(of(undefined))).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('isNone returns true for None', () => {
|
|
96
|
+
expect(isNone(none)).toBe(true);
|
|
97
|
+
expect(isNone(of(null))).toBe(true);
|
|
98
|
+
expect(isNone(of(undefined))).toBe(true);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('isNone returns false for Some', () => {
|
|
102
|
+
expect(isNone(of(42))).toBe(false);
|
|
103
|
+
expect(isNone(of(0))).toBe(false);
|
|
104
|
+
expect(isNone(of(''))).toBe(false);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('map', () => {
|
|
109
|
+
it('maps Some value', () => {
|
|
110
|
+
const result = map(of(2), x => x * 3);
|
|
111
|
+
expect(unwrap(result)).toBe(6);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('returns None for None', () => {
|
|
115
|
+
const result = map(none, (x: number) => x * 3);
|
|
116
|
+
expect(isNone(result)).toBe(true);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('returns None if mapper returns null', () => {
|
|
120
|
+
const result = map(of(2), () => null);
|
|
121
|
+
expect(isNone(result)).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('returns None if mapper returns undefined', () => {
|
|
125
|
+
const result = map(of(2), () => undefined);
|
|
126
|
+
expect(isNone(result)).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe('flatMap', () => {
|
|
131
|
+
it('flatMaps Some value', () => {
|
|
132
|
+
const result = flatMap(of(2), x => of(x * 3));
|
|
133
|
+
expect(unwrap(result)).toBe(6);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('returns None for None', () => {
|
|
137
|
+
const result = flatMap(none, (x: number) => of(x * 3));
|
|
138
|
+
expect(isNone(result)).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('can return None from mapper', () => {
|
|
142
|
+
const result = flatMap(of(2), () => none);
|
|
143
|
+
expect(isNone(result)).toBe(true);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe('andThen', () => {
|
|
148
|
+
it('aliases flatMap for Some', () => {
|
|
149
|
+
const result = andThen(of(3), x => of(x * 2));
|
|
150
|
+
expect(unwrap(result)).toBe(6);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('returns None for None', () => {
|
|
154
|
+
const result = andThen(none, x => of(x * 2));
|
|
155
|
+
expect(isNone(result)).toBe(true);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe('tap', () => {
|
|
160
|
+
it('runs for Some and returns original', () => {
|
|
161
|
+
let seen = 0;
|
|
162
|
+
const opt = of(5);
|
|
163
|
+
const result = tap(opt, value => {
|
|
164
|
+
seen = value;
|
|
165
|
+
});
|
|
166
|
+
expect(result).toBe(opt);
|
|
167
|
+
expect(seen).toBe(5);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('does not run for None', () => {
|
|
171
|
+
let called = false;
|
|
172
|
+
const result = tap(none, () => {
|
|
173
|
+
called = true;
|
|
174
|
+
});
|
|
175
|
+
expect(isNone(result)).toBe(true);
|
|
176
|
+
expect(called).toBe(false);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('filter', () => {
|
|
181
|
+
it('keeps Some if predicate is true', () => {
|
|
182
|
+
const result = filter(of(5), x => x > 3);
|
|
183
|
+
expect(unwrap(result)).toBe(5);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('returns None if predicate is false', () => {
|
|
187
|
+
const result = filter(of(2), x => x > 3);
|
|
188
|
+
expect(isNone(result)).toBe(true);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('returns None for None', () => {
|
|
192
|
+
const result = filter(none, () => true);
|
|
193
|
+
expect(isNone(result)).toBe(true);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe('unwrap', () => {
|
|
198
|
+
it('returns value for Some', () => {
|
|
199
|
+
expect(unwrap(of(42))).toBe(42);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('throws for None', () => {
|
|
203
|
+
expect(() => unwrap(none)).toThrow('Called unwrap on None');
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe('unwrapOr', () => {
|
|
208
|
+
it('returns value for Some', () => {
|
|
209
|
+
expect(unwrapOr(of(42), 0)).toBe(42);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('returns default for None', () => {
|
|
213
|
+
expect(unwrapOr(none, 99)).toBe(99);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe('unwrapOrElse', () => {
|
|
218
|
+
it('returns value for Some', () => {
|
|
219
|
+
expect(unwrapOrElse(of(42), () => 0)).toBe(42);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('calls function for None', () => {
|
|
223
|
+
let called = false;
|
|
224
|
+
const result = unwrapOrElse(none, () => {
|
|
225
|
+
called = true;
|
|
226
|
+
return 99;
|
|
227
|
+
});
|
|
228
|
+
expect(result).toBe(99);
|
|
229
|
+
expect(called).toBe(true);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
describe('expect', () => {
|
|
234
|
+
it('returns value for Some', () => {
|
|
235
|
+
expect(expectOpt(of(42), 'error')).toBe(42);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('throws with message for None', () => {
|
|
239
|
+
expect(() => expectOpt(none, 'custom error')).toThrow('custom error');
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
describe('or', () => {
|
|
244
|
+
it('returns first if Some', () => {
|
|
245
|
+
const result = or(of(1), of(2));
|
|
246
|
+
expect(unwrap(result)).toBe(1);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
it('returns second if first is None', () => {
|
|
250
|
+
const result = or(none, of(2));
|
|
251
|
+
expect(unwrap(result)).toBe(2);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('returns None if both None', () => {
|
|
255
|
+
const result = or(none, none);
|
|
256
|
+
expect(isNone(result)).toBe(true);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
describe('orElse', () => {
|
|
261
|
+
it('returns first if Some', () => {
|
|
262
|
+
const result = orElse(of(1), () => of(2));
|
|
263
|
+
expect(unwrap(result)).toBe(1);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('calls function if None', () => {
|
|
267
|
+
let called = false;
|
|
268
|
+
const result = orElse(none, () => {
|
|
269
|
+
called = true;
|
|
270
|
+
return of(2);
|
|
271
|
+
});
|
|
272
|
+
expect(unwrap(result)).toBe(2);
|
|
273
|
+
expect(called).toBe(true);
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
describe('xor', () => {
|
|
278
|
+
it('returns first if only first is Some', () => {
|
|
279
|
+
const result = xor(of(1), none);
|
|
280
|
+
expect(unwrap(result)).toBe(1);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('returns second if only second is Some', () => {
|
|
284
|
+
const result = xor(none, of(2));
|
|
285
|
+
expect(unwrap(result)).toBe(2);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('returns None if both Some', () => {
|
|
289
|
+
const result = xor(of(1), of(2));
|
|
290
|
+
expect(isNone(result)).toBe(true);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it('returns None if both None', () => {
|
|
294
|
+
const result = xor(none, none);
|
|
295
|
+
expect(isNone(result)).toBe(true);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
describe('and', () => {
|
|
300
|
+
it('returns second if first is Some', () => {
|
|
301
|
+
const result = and(of(1), of(2));
|
|
302
|
+
expect(unwrap(result)).toBe(2);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('returns None if first is None', () => {
|
|
306
|
+
const result = and(none, of(2));
|
|
307
|
+
expect(isNone(result)).toBe(true);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it('returns None if second is None', () => {
|
|
311
|
+
const result = and(of(1), none);
|
|
312
|
+
expect(isNone(result)).toBe(true);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
describe('zip', () => {
|
|
317
|
+
it('zips two Some values', () => {
|
|
318
|
+
const result = zip(of(1), of('a'));
|
|
319
|
+
expect(unwrap(result)).toEqual([1, 'a']);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it('returns None if first is None', () => {
|
|
323
|
+
const result = zip(none, of('a'));
|
|
324
|
+
expect(isNone(result)).toBe(true);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('returns None if second is None', () => {
|
|
328
|
+
const result = zip(of(1), none);
|
|
329
|
+
expect(isNone(result)).toBe(true);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
describe('unzip', () => {
|
|
334
|
+
it('unzips Some tuple', () => {
|
|
335
|
+
const [a, b] = unzip(of([1, 'a'] as [number, string]));
|
|
336
|
+
expect(unwrap(a)).toBe(1);
|
|
337
|
+
expect(unwrap(b)).toBe('a');
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('returns two Nones for None', () => {
|
|
341
|
+
const [a, b] = unzip(none);
|
|
342
|
+
expect(isNone(a)).toBe(true);
|
|
343
|
+
expect(isNone(b)).toBe(true);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('handles null/undefined in tuple', () => {
|
|
347
|
+
const [a, b] = unzip(of([null, undefined] as [null, undefined]));
|
|
348
|
+
expect(isNone(a)).toBe(true);
|
|
349
|
+
expect(isNone(b)).toBe(true);
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
describe('mapOr', () => {
|
|
354
|
+
it('maps Some value', () => {
|
|
355
|
+
expect(mapOr(of(2), 0, x => x * 3)).toBe(6);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('returns default for None', () => {
|
|
359
|
+
expect(mapOr(none, 99, (x: number) => x * 3)).toBe(99);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
describe('mapOrElse', () => {
|
|
364
|
+
it('maps Some value', () => {
|
|
365
|
+
expect(mapOrElse(of(2), () => 0, x => x * 3)).toBe(6);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it('calls default function for None', () => {
|
|
369
|
+
let called = false;
|
|
370
|
+
const result = mapOrElse(none, () => {
|
|
371
|
+
called = true;
|
|
372
|
+
return 99;
|
|
373
|
+
}, (x: number) => x * 3);
|
|
374
|
+
expect(result).toBe(99);
|
|
375
|
+
expect(called).toBe(true);
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
describe('flatten', () => {
|
|
380
|
+
it('flattens nested Some', () => {
|
|
381
|
+
const result = flatten(of(of(42)));
|
|
382
|
+
expect(unwrap(result)).toBe(42);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it('returns inner None', () => {
|
|
386
|
+
const result = flatten(of(none));
|
|
387
|
+
expect(isNone(result)).toBe(true);
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('returns None for outer None', () => {
|
|
391
|
+
const result = flatten(none);
|
|
392
|
+
expect(isNone(result)).toBe(true);
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
describe('contains', () => {
|
|
397
|
+
it('returns true if Some contains value', () => {
|
|
398
|
+
expect(contains(of(42), 42)).toBe(true);
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it('returns false if Some contains different value', () => {
|
|
402
|
+
expect(contains(of(42), 43)).toBe(false);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it('returns false for None', () => {
|
|
406
|
+
expect(contains(none, 42)).toBe(false);
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
describe('isSomeAnd', () => {
|
|
411
|
+
it('returns true if Some and predicate true', () => {
|
|
412
|
+
expect(isSomeAnd(of(5), x => x > 3)).toBe(true);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('returns false if Some and predicate false', () => {
|
|
416
|
+
expect(isSomeAnd(of(2), x => x > 3)).toBe(false);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it('returns false for None', () => {
|
|
420
|
+
expect(isSomeAnd(none, () => true)).toBe(false);
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
describe('toArray', () => {
|
|
425
|
+
it('returns array with value for Some', () => {
|
|
426
|
+
expect(toArray(of(42))).toEqual([42]);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('returns empty array for None', () => {
|
|
430
|
+
expect(toArray(none)).toEqual([]);
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
describe('toNullable', () => {
|
|
435
|
+
it('returns value for Some', () => {
|
|
436
|
+
expect(toNullable(of(42))).toBe(42);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
it('returns null for None', () => {
|
|
440
|
+
expect(toNullable(none)).toBe(null);
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
describe('toUndefined', () => {
|
|
445
|
+
it('returns value for Some', () => {
|
|
446
|
+
expect(toUndefined(of(42))).toBe(42);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it('returns undefined for None', () => {
|
|
450
|
+
expect(toUndefined(none)).toBe(undefined);
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
describe('match', () => {
|
|
455
|
+
it('calls some branch for Some', () => {
|
|
456
|
+
const result = match(
|
|
457
|
+
of(42),
|
|
458
|
+
x => `value: ${x}`,
|
|
459
|
+
() => 'nothing',
|
|
460
|
+
);
|
|
461
|
+
expect(result).toBe('value: 42');
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
it('calls none branch for None', () => {
|
|
465
|
+
const result = match(
|
|
466
|
+
none,
|
|
467
|
+
(x: number) => `value: ${x}`,
|
|
468
|
+
() => 'nothing',
|
|
469
|
+
);
|
|
470
|
+
expect(result).toBe('nothing');
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
describe('okOr', () => {
|
|
475
|
+
it('converts Some to Ok', () => {
|
|
476
|
+
const result = okOr(of(42), 'error');
|
|
477
|
+
expect(result).toBe(42);
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
it('converts None to Err', () => {
|
|
481
|
+
const result = okOr(none, 'error');
|
|
482
|
+
expect(result.error).toBe('error');
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
describe('okOrElse', () => {
|
|
487
|
+
it('converts Some to Ok', () => {
|
|
488
|
+
const result = okOrElse(of(42), () => 'error');
|
|
489
|
+
expect(result).toBe(42);
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
it('converts None to Err with lazy error', () => {
|
|
493
|
+
let called = false;
|
|
494
|
+
const result = okOrElse(none, () => {
|
|
495
|
+
called = true;
|
|
496
|
+
return 'error';
|
|
497
|
+
});
|
|
498
|
+
expect(result.error).toBe('error');
|
|
499
|
+
expect(called).toBe(true);
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
describe('ofOk', () => {
|
|
504
|
+
it('extracts Ok value as Some', () => {
|
|
505
|
+
const result = ofOk(ok(42));
|
|
506
|
+
expect(unwrap(result)).toBe(42);
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
it('returns None for Err', () => {
|
|
510
|
+
const result = ofOk(err('error'));
|
|
511
|
+
expect(isNone(result)).toBe(true);
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
it('returns None for Ok(null)', () => {
|
|
515
|
+
const result = ofOk(ok(null));
|
|
516
|
+
expect(isNone(result)).toBe(true);
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
it('returns None for Ok(undefined)', () => {
|
|
520
|
+
const result = ofOk(ok(undefined));
|
|
521
|
+
expect(isNone(result)).toBe(true);
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
describe('ofErr', () => {
|
|
526
|
+
it('extracts Err value as Some', () => {
|
|
527
|
+
const result = ofErr(err('error'));
|
|
528
|
+
expect(unwrap(result)).toBe('error');
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
it('returns None for Ok', () => {
|
|
532
|
+
const result = ofErr(ok(42));
|
|
533
|
+
expect(isNone(result)).toBe(true);
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
it('returns None for Err(null)', () => {
|
|
537
|
+
const result = ofErr(err(null));
|
|
538
|
+
expect(isNone(result)).toBe(true);
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
it('returns None for Err(undefined)', () => {
|
|
542
|
+
const result = ofErr(err(undefined));
|
|
543
|
+
expect(isNone(result)).toBe(true);
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
describe('from helpers', () => {
|
|
548
|
+
it('fromNullable mirrors of behavior', () => {
|
|
549
|
+
expect(isSome(fromNullable(3))).toBe(true);
|
|
550
|
+
expect(isNone(fromNullable(null))).toBe(true);
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
it('fromPromise resolves Some when promise fulfills', async () => {
|
|
554
|
+
const opt = await fromPromise(Promise.resolve(42));
|
|
555
|
+
expect(isSome(opt)).toBe(true);
|
|
556
|
+
expect(unwrap(opt)).toBe(42);
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
it('fromPromise uses fallback on rejection', async () => {
|
|
560
|
+
const opt = await fromPromise(
|
|
561
|
+
Promise.reject(new Error('boom')),
|
|
562
|
+
() => 99,
|
|
563
|
+
);
|
|
564
|
+
expect(isSome(opt)).toBe(true);
|
|
565
|
+
expect(unwrap(opt)).toBe(99);
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
describe('control helpers', () => {
|
|
570
|
+
it('unwrapOrReturn returns fallback for None', () => {
|
|
571
|
+
const result = unwrapOrReturn(none, () => 77);
|
|
572
|
+
expect(result).toBe(77);
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
it('assertSome narrows Some', () => {
|
|
576
|
+
const opt = of(15);
|
|
577
|
+
assertSome(opt);
|
|
578
|
+
expect(opt).toBe(15);
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
it('assertSome throws for None', () => {
|
|
582
|
+
expect(() => assertSome(none)).toThrow('Expected Option to contain a value');
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
it('satisfiesOption validates at runtime', () => {
|
|
586
|
+
const candidate: any = of(3);
|
|
587
|
+
expect(() => satisfiesOption(candidate)).not.toThrow();
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
describe('introspection helpers', () => {
|
|
592
|
+
it('inspectOption exposes discriminated metadata', () => {
|
|
593
|
+
expect(inspectOption(of(4))).toEqual({ kind: 'some', value: 4 });
|
|
594
|
+
expect(inspectOption(none)).toEqual({ kind: 'none' });
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
it('formatOption prints human friendly value', () => {
|
|
598
|
+
expect(formatOption(of(1))).toBe('Some(1)');
|
|
599
|
+
expect(formatOption(none)).toBe('None');
|
|
600
|
+
});
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
describe('filterMap', () => {
|
|
604
|
+
it('collects Some values from iterable', () => {
|
|
605
|
+
const items = [of(1), none, of(3)];
|
|
606
|
+
const result = filterMap(items, opt => opt);
|
|
607
|
+
expect(result).toEqual([1, 3]);
|
|
608
|
+
});
|
|
609
|
+
});
|
|
610
|
+
});
|