chem-rx 0.0.23 → 0.2.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.
@@ -1,625 +0,0 @@
1
- import { ArrayAtom, Atom, BaseAtom, ReadOnlyAtom } from "../src/Atom";
2
- import { Signal } from "../src/Signal";
3
- import { BehaviorSubject, map } from "rxjs";
4
-
5
- test("Base Atom values test", () => {
6
- const atom = Atom("aweofij");
7
- expect(atom instanceof BaseAtom).toBe(true);
8
- expect(atom.value()).toBe("aweofij");
9
-
10
- atom.next("apro");
11
-
12
- expect(atom.value()).toBe("apro");
13
- });
14
-
15
- test("Test readonly", () => {
16
- const atom = Atom({ a: 10 }, true);
17
- expect(atom instanceof ReadOnlyAtom).toBe(true);
18
- expect(atom instanceof BaseAtom).toBe(false);
19
- expect(atom.get("a")).toBe(10);
20
-
21
- expect(atom).not.toHaveProperty("set");
22
- });
23
-
24
- test("Object Atom values test", () => {
25
- const atom = Atom<{ [key: string]: string }>({
26
- firstKey: "firstValue",
27
- secondKey: "secondValue",
28
- });
29
- expect(atom instanceof BaseAtom).toBe(true);
30
- expect(atom.value()["firstKey"]).toBe("firstValue");
31
-
32
- expect(atom.value()["secondKey"]).toBe("secondValue");
33
- atom.set("secondKey", "newSecondValue");
34
- expect(atom.value()["secondKey"]).toBe("newSecondValue");
35
-
36
- expect(atom.value()["thirdKey"]).toBeUndefined();
37
- expect(atom.value()).not.toHaveProperty("thirdKey");
38
- atom.set("thirdKey", "thirdValue");
39
- expect(atom.value()["thirdKey"]).toBe("thirdValue");
40
- });
41
-
42
- test("Object Atom get function test", () => {
43
- const atom = Atom<{ [key: string]: string }>({
44
- firstKey: "firstValue",
45
- secondKey: "secondValue",
46
- });
47
-
48
- expect(atom.get("firey")).toBe(undefined);
49
-
50
- expect(atom instanceof BaseAtom).toBe(true);
51
- expect(atom.get("firstKey")).toBe("firstValue");
52
-
53
- expect(atom.get("secondKey")).toBe("secondValue");
54
- atom.set("secondKey", "newSecondValue");
55
- expect(atom.get("secondKey")).toBe("newSecondValue");
56
-
57
- expect(atom.get("thirdKey")).toBeUndefined();
58
- expect(atom.value()).not.toHaveProperty("thirdKey");
59
- atom.set("thirdKey", "thirdValue");
60
- expect(atom.get("thirdKey")).toBe("thirdValue");
61
- });
62
-
63
- test("Object Enum Atom test", () => {
64
- enum testEnum {
65
- first,
66
- second,
67
- }
68
- const atom = Atom({
69
- [testEnum.first]: "firstValue",
70
- [testEnum.second]: "secondValue",
71
- });
72
-
73
- // this should always be defined as a string
74
- const kkk = atom.get(testEnum.first);
75
- kkk.toString();
76
-
77
- expect(atom instanceof BaseAtom).toBe(true);
78
- expect(atom.get(testEnum.first)).toBe("firstValue");
79
-
80
- expect(atom.get(testEnum.second)).toBe("secondValue");
81
- atom.set(testEnum.second, "newSecondValue");
82
- expect(atom.get(testEnum.second)).toBe("newSecondValue");
83
- });
84
-
85
- test("Optional keys Object Atom test", () => {
86
- enum testEnum {
87
- first,
88
- second,
89
- }
90
- const atom = Atom<{
91
- [testEnum.first]?: string;
92
- [testEnum.second]?: string;
93
- }>({
94
- [testEnum.first]: "firstValue",
95
- [testEnum.second]: "secondValue",
96
- });
97
-
98
- const kkk = atom.get(testEnum.first);
99
- // @ts-expect-error this should be possibly undefined
100
- kkk.toString();
101
-
102
- expect(atom instanceof BaseAtom).toBe(true);
103
- expect(atom.get(testEnum.first)).toBe("firstValue");
104
-
105
- expect(atom.get(testEnum.second)).toBe("secondValue");
106
- atom.set(testEnum.second, "newSecondValue");
107
- expect(atom.get(testEnum.second)).toBe("newSecondValue");
108
- });
109
-
110
- test("Uninitialized Object Enum Atom test", () => {
111
- enum testEnum {
112
- first,
113
- second,
114
- }
115
- const seedValue = {
116
- [testEnum.first]: "firstValue",
117
- [testEnum.second]: "secondValue",
118
- };
119
- const atom = Atom<{
120
- [testEnum.first]: string;
121
- [testEnum.second]: string;
122
- }>();
123
-
124
- const kkk = atom.get(testEnum.first);
125
- // this should be possibly undefined at this point,
126
- // so there should lbe type safety here
127
- expect(() => {
128
- // @ts-expect-error this should throw a type error
129
- // because it should be possibly undefined
130
- kkk.toString();
131
- }).toThrow();
132
-
133
- // atom.push({
134
- // [testEnum.first]: "firstValue",
135
- // [testEnum.second]: "secondValue",
136
- // });
137
- expect(atom instanceof BaseAtom).toBe(true);
138
-
139
- expect(atom.get(testEnum.first)).toBe(undefined);
140
- expect(atom.get(testEnum.second)).toBe(undefined);
141
- atom.next(seedValue);
142
- expect(atom.get(testEnum.first)).toBe("firstValue");
143
-
144
- expect(atom.get(testEnum.second)).toBe("secondValue");
145
- atom.set(testEnum.second, "newSecondValue");
146
- expect(atom.get(testEnum.second)).toBe("newSecondValue");
147
- });
148
-
149
- test("Array Atom values test", () => {
150
- const atom = Atom<string[]>(["first"]);
151
-
152
- expect(atom.get(10)).toBe(undefined);
153
-
154
- // this is not allowed
155
- // atom.push(1);
156
- expect(atom instanceof ArrayAtom).toBe(true);
157
- expect(atom.value().length).toBe(1);
158
- expect(atom.value()[0]).toBe("first");
159
-
160
- atom.push("second");
161
- expect(atom.value().length).toBe(2);
162
- expect(atom.value()[1]).toBe("second");
163
- });
164
-
165
- test("Array Atom get index test", () => {
166
- const atom = Atom<string[]>(["first"]);
167
-
168
- expect(atom instanceof ArrayAtom).toBe(true);
169
- expect(atom.value().length).toBe(1);
170
- expect(atom.get(0)).toBe("first");
171
-
172
- atom.push("second");
173
- expect(atom.value().length).toBe(2);
174
- expect(atom.get(1)).toBe("second");
175
-
176
- expect(atom.get(2)).toBe(undefined);
177
- });
178
-
179
- test("Test native pipe", () => {
180
- const atom = Atom(3);
181
- expect(atom instanceof BaseAtom).toBe(true);
182
- expect(atom.value()).toBe(3);
183
-
184
- const derivedAtom = atom.pipe(map((x) => x * x));
185
- expect(derivedAtom instanceof ReadOnlyAtom).toBe(true);
186
- expect(derivedAtom).not.toHaveProperty("set");
187
-
188
- expect(derivedAtom.value()).toBe(9);
189
- });
190
-
191
- test("Test derive", () => {
192
- const atom = Atom(3);
193
- expect(atom instanceof BaseAtom).toBe(true);
194
- expect(atom.value()).toBe(3);
195
-
196
- const derivedAtom = atom.derive((x) => x * x);
197
- expect(derivedAtom instanceof ReadOnlyAtom).toBe(true);
198
- expect(derivedAtom).not.toHaveProperty("set");
199
-
200
- expect(derivedAtom.value()).toBe(9);
201
- });
202
-
203
- test("Test derive update", () => {
204
- const atom = Atom(3);
205
- expect(atom instanceof BaseAtom).toBe(true);
206
- expect(atom.value()).toBe(3);
207
-
208
- const derivedAtom = atom.derive((x) => x * x);
209
- expect(derivedAtom instanceof ReadOnlyAtom).toBe(true);
210
- expect(derivedAtom).not.toHaveProperty("set");
211
-
212
- expect(derivedAtom.value()).toBe(9);
213
-
214
- atom.next(4);
215
- expect(derivedAtom.value()).toBe(16);
216
- });
217
-
218
- test("Test combine", () => {
219
- const normalizedData = Atom<{ [key: string]: { name: string } }>({
220
- a: { name: "a" },
221
- b: { name: "b" },
222
- c: { name: "c" },
223
- });
224
- const ids = Atom<string[]>(["a", "b", "c"]);
225
- const combined = Atom.combine(normalizedData, ids).derive(([normed, ids]) => {
226
- return ids.map((id) => normed[id]);
227
- });
228
- expect(combined).not.toHaveProperty("set");
229
-
230
- expect(combined instanceof ReadOnlyAtom).toBe(true);
231
-
232
- expect(combined instanceof ReadOnlyAtom).toBe(true);
233
- expect(combined).not.toHaveProperty("set");
234
- const combinedValue = combined.value();
235
- expect(combinedValue.length).toBe(3);
236
- expect(combinedValue[0].name).toBe("a");
237
- expect(combinedValue[1].name).toBe("b");
238
- expect(combinedValue[2].name).toBe("c");
239
- });
240
-
241
- test("Test combine example", () => {
242
- const pets$ = Atom<{ [name: string]: { type: "dog" | "cat"; age: number } }>({
243
- spot: { type: "dog", age: 5 },
244
- fido: { type: "dog", age: 3 },
245
- tabby: { type: "cat", age: 12 },
246
- });
247
-
248
- const people$ = Atom<{ [name: string]: { pets: string[] } }>({
249
- fred: { pets: [] },
250
- mary: { pets: ["spot", "fido"] },
251
- cam: { pets: ["tabby"] },
252
- });
253
-
254
- const mary$ = Atom.combine(pets$, people$.select("mary")).derive(
255
- ([pets, mary]) => {
256
- return {
257
- ...mary,
258
- pets: mary.pets.map((petName) => pets[petName]),
259
- };
260
- }
261
- );
262
- {
263
- mary: {
264
- pets: [
265
- {
266
- name: "spot",
267
- type: "dog",
268
- age: 5,
269
- },
270
- ];
271
- }
272
- }
273
-
274
- const a: number[] = [1, 3, 4, 5];
275
- const b = a[10];
276
-
277
- const pets = mary$.select("pets").get(0);
278
- expect(mary$.select("pets").value().length).toBe(2);
279
- expect(mary$.select("pets").get(0)).toHaveProperty("type");
280
- expect(mary$.select("pets").get(0)).toHaveProperty("age");
281
- expect(mary$.select("pets").get(0).type).toBe("dog");
282
- expect(mary$.select("pets").get(0).age).toBe(5);
283
- expect(mary$.select("pets").get(1)).toHaveProperty("type");
284
- expect(mary$.select("pets").get(1)).toHaveProperty("age");
285
- expect(mary$.select("pets").get(1).type).toBe("dog");
286
- expect(mary$.select("pets").get(1).age).toBe(3);
287
- });
288
-
289
- test("Test select (simple)", () => {
290
- enum TEST_ENUM {
291
- a = "weoifj",
292
- b = "oh",
293
- c = "ohoij",
294
- }
295
-
296
- // test types
297
- const enumTest = Atom(TEST_ENUM.a);
298
-
299
- const arrayTest = Atom([1, 2, 34]);
300
- const arrayTest2 = Atom([{ a: "jwoi" }, 2, 34]);
301
-
302
- const arrayAtom = Atom<{ [key: string]: number[] }>({
303
- a: [0, 1, 2],
304
- b: [1, 3, 4],
305
- c: [5, 3, 4],
306
- });
307
-
308
- const primitiveNum = new BehaviorSubject(4);
309
- const primitiveNumAtom = Atom<number>(primitiveNum);
310
-
311
- const primitiveStr = new BehaviorSubject("a");
312
- const primitiveStringAtom = Atom<string>(primitiveStr);
313
-
314
- const arrayObs = new BehaviorSubject(["a"]);
315
- const arrayObsAtom = Atom<string[]>(arrayObs);
316
-
317
- const objObs = new BehaviorSubject({ a: 1 });
318
- const objObsAtom2 = Atom(objObs);
319
- const objObsAtom1 = Atom<{ [id: string]: number }>(objObs);
320
-
321
- const stringData = Atom<{
322
- [key: string]: { [key: string]: string };
323
- }>({
324
- a: { a: "a" },
325
- b: { b: "b" },
326
- c: { c: "c" },
327
- });
328
-
329
- const selectedString: BaseAtom<{ [key: string]: string }> =
330
- stringData.select("b");
331
-
332
- const normalizedOptionalStringData = Atom<{
333
- [key: string]: { [key in "a" | "b" | "c"]?: string };
334
- }>({
335
- a: { a: "a" },
336
- b: { b: "b" },
337
- c: { c: "c" },
338
- });
339
-
340
- const selectedOptionalString = normalizedOptionalStringData.select("b");
341
-
342
- const normalizedEnumData = Atom<{
343
- [key: string]: { [key in TEST_ENUM]?: string };
344
- }>({
345
- a: { [TEST_ENUM.a]: "a" },
346
- b: { [TEST_ENUM.b]: "b" },
347
- c: { [TEST_ENUM.c]: "c" },
348
- });
349
- const selected = normalizedEnumData.select("b");
350
- const selected2 = normalizedEnumData.select("a");
351
- const selectedArray = arrayAtom.select("b");
352
-
353
- // THIS IS HTE LAST ONE THT STILL OES NOTWOK
354
- const selectedArr = arrayAtom.select("a");
355
-
356
- const sel3 = objObsAtom2.select("a");
357
-
358
- expect(selected instanceof BaseAtom).toBe(true);
359
-
360
- expect(selected instanceof BaseAtom).toBe(true);
361
-
362
- // const combined = Atom.combine(normalizedData, ids).derive(([normed, ids]) => {
363
- // return ids.map((id) => normed[id]);
364
- // });
365
- //
366
- // expect(combined).not.toHaveProperty("push");
367
- //
368
- // expect(combined instanceof ReadOnlyAtom).toBe(true);
369
- //
370
- // expect(combined instanceof ReadOnlyAtom).toBe(true);
371
- // expect(combined).not.toHaveProperty("push");
372
- // const combinedValue = combined.value();
373
- // expect(combinedValue.length).toBe(3);
374
- // expect(combinedValue[0].name).toBe("a");
375
- // expect(combinedValue[1].name).toBe("b");
376
- // expect(combinedValue[2].name).toBe("c");
377
- });
378
-
379
- test("Test select (nested objects)", () => {
380
- const nestedData = Atom<{
381
- [key: string]: {
382
- nickname: string;
383
- education: {
384
- school: string;
385
- graduation: number;
386
- };
387
- };
388
- }>({
389
- stacy: {
390
- nickname: "stace",
391
- education: {
392
- school: "Penn",
393
- graduation: 2014,
394
- },
395
- },
396
- annie: {
397
- nickname: "ann",
398
- education: {
399
- school: "Brown",
400
- graduation: 2015,
401
- },
402
- },
403
- prabhu: {
404
- nickname: "prab",
405
- education: {
406
- school: "MIT",
407
- graduation: 2016,
408
- },
409
- },
410
- });
411
- const stacy = nestedData.select("stacy");
412
- const stacySchool = nestedData.select("stacy").select("education");
413
-
414
- const nickname = stacy.get("nickname");
415
- const education = stacy.get("education");
416
- expect(stacy.get("nickname")).toBe("stace");
417
- expect(stacySchool.get("school")).toBe("Penn");
418
- expect(stacySchool.get("graduation")).toBe(2014);
419
- });
420
-
421
- test("Test parent value when updating child objects ", () => {
422
- const students = Atom<{
423
- [key: string]: {
424
- nickname: string;
425
- education: {
426
- school: string;
427
- graduation: number;
428
- };
429
- };
430
- }>({
431
- stacy: {
432
- nickname: "stace",
433
- education: {
434
- school: "Penn",
435
- graduation: 2014,
436
- },
437
- },
438
- annie: {
439
- nickname: "ann",
440
- education: {
441
- school: "Brown",
442
- graduation: 2015,
443
- },
444
- },
445
- prabhu: {
446
- nickname: "prab",
447
- education: {
448
- school: "MIT",
449
- graduation: 2016,
450
- },
451
- },
452
- });
453
- const stacy = students.select("stacy");
454
- const stacySchool = stacy.select("education");
455
-
456
- expect(stacy.get("nickname")).toBe("stace");
457
- expect(students.get("stacy").nickname).toBe("stace");
458
- expect(stacySchool.get("graduation")).toBe(2014);
459
-
460
- students.set("stacy", {
461
- nickname: "spacey",
462
- education: {
463
- ...students.get("stacy").education,
464
- graduation: 2015,
465
- },
466
- });
467
-
468
- expect(stacy.get("nickname")).toBe("spacey");
469
- expect(students.get("stacy").nickname).toBe("spacey");
470
- expect(stacySchool.get("graduation")).toBe(2015);
471
- });
472
-
473
- test("Test nullable object", () => {
474
- const nestedData = Atom<{
475
- [key: string]: {
476
- nickname: string;
477
- education: {
478
- school: string;
479
- graduation: number;
480
- };
481
- };
482
- }>();
483
-
484
- // TODO: This errors
485
- const newVal = nestedData.select("stacy");
486
-
487
- nestedData.next(undefined);
488
- const stacy = nestedData.select("stacy");
489
- const stacySchool = nestedData.select("stacy").select("education");
490
-
491
- expect(stacy.get("nickname")).toBe(undefined);
492
- expect(stacySchool.get("school")).toBe(undefined);
493
- expect(stacySchool.value()).toBe(undefined);
494
- nestedData.next(null);
495
- expect(nestedData.value()).toBe(null);
496
- });
497
-
498
- test("Test select nullable object", () => {
499
- const seedData = {
500
- stacy: {
501
- nickname: "stace",
502
- education: {
503
- school: "Penn",
504
- graduation: 2014,
505
- },
506
- },
507
- annie: {
508
- nickname: "ann",
509
- education: {
510
- school: "Brown",
511
- graduation: 2015,
512
- },
513
- },
514
- prabhu: {
515
- nickname: "prab",
516
- education: {
517
- school: "MIT",
518
- graduation: 2016,
519
- },
520
- },
521
- };
522
- const nestedData = Atom<{
523
- [key: string]: {
524
- nickname: string;
525
- education: {
526
- school: string;
527
- graduation: number;
528
- };
529
- };
530
- }>();
531
-
532
- // TODO: This errors
533
- const newVal = nestedData.select("stacy");
534
-
535
- nestedData.next(seedData);
536
- const stacy = nestedData.select("stacy");
537
- const stacySchool = nestedData.select("stacy").select("education");
538
-
539
- expect(stacy.get("nickname")).toBe("stace");
540
- expect(stacySchool.get("school")).toBe("Penn");
541
- expect(stacySchool.get("graduation")).toBe(2014);
542
- });
543
-
544
- describe("SignalWithId", () => {
545
- it("should broadcast messages to all subscribers when no ID is provided", (done) => {
546
- const signal = new Signal<string>();
547
- const mockCallback = jest.fn();
548
-
549
- signal.subscribe(mockCallback);
550
- signal.subscribe(mockCallback);
551
-
552
- signal.ping("test message");
553
-
554
- setImmediate(() => {
555
- expect(mockCallback).toHaveBeenCalledTimes(2);
556
- expect(mockCallback).toHaveBeenCalledWith("test message");
557
- done();
558
- });
559
- });
560
-
561
- it("should send messages only to subscribers with the specific ID", (done) => {
562
- const signal = new Signal<string>();
563
- const mockCallbackWithId = jest.fn();
564
- const mockCallbackWithoutId = jest.fn();
565
-
566
- signal.subscribe(mockCallbackWithId, "123");
567
- signal.subscribe(mockCallbackWithoutId);
568
-
569
- signal.ping("ID specific message", "123");
570
-
571
- setImmediate(() => {
572
- expect(mockCallbackWithId).toHaveBeenCalledTimes(1);
573
- expect(mockCallbackWithId).toHaveBeenCalledWith("ID specific message");
574
- expect(mockCallbackWithoutId).toHaveBeenCalledTimes(0);
575
- done();
576
- });
577
- });
578
-
579
- it("should not notify subscribers with different IDs", (done) => {
580
- const signal = new Signal<string>();
581
- const mockCallbackId123 = jest.fn();
582
- const mockCallbackId456 = jest.fn();
583
-
584
- signal.subscribe(mockCallbackId123, "123");
585
- signal.subscribe(mockCallbackId456, "456");
586
-
587
- signal.ping("Message for 123", "123");
588
-
589
- setImmediate(() => {
590
- expect(mockCallbackId123).toHaveBeenCalledTimes(1);
591
- expect(mockCallbackId123).toHaveBeenCalledWith("Message for 123");
592
- expect(mockCallbackId456).toHaveBeenCalledTimes(0);
593
- done();
594
- });
595
- });
596
-
597
- it("should notify all subscribers, including those with specific IDs, when pinging without an ID", (done) => {
598
- const signal = new Signal<string>();
599
- const mockCallback = jest.fn();
600
- const mockCallbackWithId = jest.fn();
601
-
602
- // Subscribe one callback without ID (for general broadcast)
603
- signal.subscribe(mockCallback);
604
- // Subscribe another callback with a specific ID
605
- signal.subscribe(mockCallbackWithId, "123");
606
-
607
- // Ping without specifying an ID should notify both subscribers
608
- signal.ping("broadcast message");
609
-
610
- setImmediate(() => {
611
- // Both callbacks should be called once
612
- expect(mockCallback).toHaveBeenCalledTimes(1);
613
- expect(mockCallback).toHaveBeenCalledWith("broadcast message");
614
- expect(mockCallbackWithId).toHaveBeenCalledTimes(1);
615
- expect(mockCallbackWithId).toHaveBeenCalledWith("broadcast message");
616
- done();
617
- });
618
- });
619
- });
620
-
621
- /*
622
- * TODO:
623
- * - test react hooks
624
- * - test subscriptions
625
- */