-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathtest_output_2.txt
More file actions
2475 lines (1994 loc) · 156 KB
/
test_output_2.txt
File metadata and controls
2475 lines (1994 loc) · 156 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
> creditra-backend@0.1.0 test
> vitest --run
[1m[46m RUN [49m[22m [36mv4.1.1 [39m[90m/home/edohwares/Desktop/Room/drips/Creditra-Backend[39m
TAP version 13
[31m❯[39m src/__test__/adminAuth.test.ts [2m([22m[2m11 tests[22m[2m | [22m[31m6 failed[39m[2m)[22m[32m 273[2mms[22m[39m
[31m [31m×[31m calls next() and returns 200 when the correct key is supplied[39m[32m 120[2mms[22m[39m
[31m [31m×[31m returns 401 when the X-Admin-Api-Key header is missing[39m[32m 14[2mms[22m[39m
[31m [31m×[31m returns 401 when the header value is wrong[39m[32m 19[2mms[22m[39m
[31m [31m×[31m returns 401 when the header is an empty string[39m[32m 12[2mms[22m[39m
[31m [31m×[31m returns 401 when the header is close but not equal to the secret[39m[32m 22[2mms[22m[39m
[31m [31m×[31m response body includes X-Admin-Api-Key in the error hint[39m[32m 18[2mms[22m[39m
[32m✓[39m returns JSON content-type on 401[32m 13[2mms[22m[39m
[32m✓[39m returns 503 regardless of what header is sent[32m 6[2mms[22m[39m
[32m✓[39m returns 503 even without a header[32m 19[2mms[22m[39m
[32m✓[39m body error mentions admin authentication is not configured[32m 10[2mms[22m[39m
[32m✓[39m returns JSON content-type on 503[32m 7[2mms[22m[39m
[31m❯[39m tests/cors.test.ts [2m([22m[2m11 tests[22m[2m | [22m[31m2 failed[39m[2m)[22m[33m 1043[2mms[22m[39m
[32m✓[39m allows requests without an Origin header[32m 9[2mms[22m[39m
[32m✓[39m falls back to loopback origins when CORS_ORIGINS is unset outside production[32m 2[2mms[22m[39m
[32m✓[39m parses, normalizes, and deduplicates an explicit allowlist[32m 2[2mms[22m[39m
[32m✓[39m rejects invalid allowlist entries that use unsupported protocols[32m 4[2mms[22m[39m
[32m✓[39m rejects allowlist entries that include a path or credentials[32m 1[2mms[22m[39m
[32m✓[39m rejects allowlist entries that include a path[32m 1[2mms[22m[39m
[32m✓[39m throws when CORS_ORIGINS is present but empty[32m 1[2mms[22m[39m
[32m✓[39m rejects non-loopback origins in loopback mode[32m 1[2mms[22m[39m
[32m✓[39m throws in production when CORS_ORIGINS is missing[32m 2[2mms[22m[39m
[31m [31m×[31m echoes localhost origins on preflight requests[39m[32m 79[2mms[22m[39m
[31m [31m×[31m omits CORS headers for disallowed browser origins[39m[32m 26[2mms[22m[39m
[31m❯[39m src/routes/__tests__/credit.test.ts [2m([22m[2m23 tests[22m[2m | [22m[31m21 failed[39m[2m)[22m[33m 391[2mms[22m[39m
[32m✓[39m should return empty array when no credit lines exist[32m 86[2mms[22m[39m
[32m✓[39m should return credit lines with pagination[32m 22[2mms[22m[39m
[31m [31m×[31m should return 400 for negative offset[39m[32m 16[2mms[22m[39m
[31m [31m×[31m should return 400 for zero limit[39m[32m 11[2mms[22m[39m
[31m [31m×[31m should return 400 for oversized limit[39m[32m 11[2mms[22m[39m
[31m [31m×[31m should handle server errors gracefully[39m[32m 9[2mms[22m[39m
[31m [31m×[31m should return credit line when found[39m[32m 8[2mms[22m[39m
[31m [31m×[31m should return 404 when credit line not found[39m[32m 8[2mms[22m[39m
[31m [31m×[31m should handle server errors gracefully[39m[32m 28[2mms[22m[39m
[31m [31m×[31m should create credit line successfully[39m[32m 49[2mms[22m[39m
[31m [31m×[31m should return 400 for missing required fields[39m[32m 10[2mms[22m[39m
[31m [31m×[31m should return 400 for invalid data[39m[32m 10[2mms[22m[39m
[31m [31m×[31m should handle service errors with generic message[39m[32m 13[2mms[22m[39m
[31m [31m×[31m should update credit line successfully[39m[32m 1[2mms[22m[39m
[31m [31m×[31m should return 404 when credit line not found[39m[32m 17[2mms[22m[39m
[31m [31m×[31m should return 400 for invalid update data[39m[32m 1[2mms[22m[39m
[31m [31m×[31m should handle service errors with generic message[39m[32m 5[2mms[22m[39m
[31m [31m×[31m should delete credit line successfully[39m[32m 1[2mms[22m[39m
[31m [31m×[31m should return 404 when credit line not found[39m[32m 27[2mms[22m[39m
[31m [31m×[31m should handle service errors gracefully[39m[32m 20[2mms[22m[39m
[31m [31m×[31m should return credit lines for wallet[39m[32m 1[2mms[22m[39m
[31m [31m×[31m should return empty array when no credit lines found for wallet[39m[32m 13[2mms[22m[39m
[31m [31m×[31m should handle service errors gracefully[39m[32m 11[2mms[22m[39m
[31m❯[39m src/__tests__/index.test.ts [2m([22m[2m3 tests[22m[2m | [22m[31m3 failed[39m[2m)[22m[33m 1208[2mms[22m[39m
[31m [31m×[31m should start server and respond to health check[39m[33m 1111[2mms[22m[39m
[31m [31m×[31m should handle credit routes[39m[32m 32[2mms[22m[39m
[31m [31m×[31m should handle risk routes[39m[32m 57[2mms[22m[39m
[31m❯[39m src/__test__/creditRoute.test.ts [2m([22m[2m41 tests[22m[2m | [22m[31m21 failed[39m[2m)[22m[33m 564[2mms[22m[39m
[31m [31m×[31m returns 200 with an empty array when store is empty[39m[32m 111[2mms[22m[39m
[31m [31m×[31m returns all credit lines[39m[32m 17[2mms[22m[39m
[32m✓[39m returns JSON content-type[32m 8[2mms[22m[39m
[31m [31m×[31m returns 200 with the credit line for a known id[39m[32m 15[2mms[22m[39m
[31m [31m×[31m returns 404 for an unknown id[39m[32m 16[2mms[22m[39m
[32m✓[39m returns JSON content-type on 404[32m 7[2mms[22m[39m
[32m✓[39m returns 401 when admin auth is denied[32m 8[2mms[22m[39m
[32m✓[39m does not suspend the line when auth is denied[32m 7[2mms[22m[39m
[31m [31m×[31m returns 200 and suspended line for an active credit line[39m[32m 14[2mms[22m[39m
[31m [31m×[31m response includes the full credit line object[39m[32m 21[2mms[22m[39m
[31m [31m×[31m returns 404 when the credit line does not exist[39m[32m 7[2mms[22m[39m
[31m [31m×[31m returns 409 when the line is already suspended[39m[32m 7[2mms[22m[39m
[31m [31m×[31m returns 409 when the line is already closed[39m[32m 8[2mms[22m[39m
[32m✓[39m returns 401 when admin auth is denied[32m 6[2mms[22m[39m
[32m✓[39m does not close the line when auth is denied[32m 6[2mms[22m[39m
[31m [31m×[31m returns 200 and closed line for an active credit line[39m[32m 7[2mms[22m[39m
[31m [31m×[31m returns 200 and closed line for a suspended credit line[39m[32m 7[2mms[22m[39m
[31m [31m×[31m response includes the full credit line object with events[39m[32m 21[2mms[22m[39m
[31m [31m×[31m returns 404 when the credit line does not exist[39m[32m 12[2mms[22m[39m
[31m [31m×[31m returns 409 when the line is already closed[39m[32m 8[2mms[22m[39m
[31m [31m×[31m full lifecycle: active → suspend → close via HTTP[39m[32m 16[2mms[22m[39m
[32m✓[39m returns 200 with the response envelope[32m 31[2mms[22m[39m
[32m✓[39m returns pagination metadata in the response[32m 13[2mms[22m[39m
[32m✓[39m returns the status_change transaction recorded on line creation[32m 8[2mms[22m[39m
[32m✓[39m returns populated history after suspend and close via service[32m 34[2mms[22m[39m
[32m✓[39m returns 404 with error containing id for an unknown credit line[32m 6[2mms[22m[39m
[32m✓[39m returns 404 with JSON content-type[32m 6[2mms[22m[39m
[32m✓[39m filters by type=status_change[32m 9[2mms[22m[39m
[32m✓[39m returns empty transactions array when type filter has no matches[32m 9[2mms[22m[39m
[31m [31m×[31m returns 400 for an invalid type filter value[39m[32m 11[2mms[22m[39m
[31m [31m×[31m returns 400 for an invalid 'from' date[39m[32m 12[2mms[22m[39m
[31m [31m×[31m returns 400 for an invalid 'to' date[39m[32m 11[2mms[22m[39m
[31m [31m×[31m returns 400 for a non-numeric 'page' value[39m[32m 10[2mms[22m[39m
[32m✓[39m returns 400 for page=0[32m 9[2mms[22m[39m
[31m [31m×[31m returns 400 for a non-numeric 'limit' value[39m[32m 9[2mms[22m[39m
[32m✓[39m returns 400 for limit=0[32m 9[2mms[22m[39m
[32m✓[39m returns 400 for limit exceeding 100[32m 10[2mms[22m[39m
[32m✓[39m respects custom page and limit query params[32m 8[2mms[22m[39m
[31m [31m×[31m returns second page of results correctly[39m[32m 9[2mms[22m[39m
[32m✓[39m filters by valid 'from' date excluding older transactions[32m 7[2mms[22m[39m
[32m✓[39m filters by valid 'to' date excluding newer transactions[32m 7[2mms[22m[39m
[31m❯[39m tests/routes/routes.test.ts [2m([22m[2m17 tests[22m[2m | [22m[31m11 failed[39m[2m)[22m[33m 380[2mms[22m[39m
[32m✓[39m returns 200 with ok status[32m 65[2mms[22m[39m
[32m✓[39m returns empty array[32m 14[2mms[22m[39m
[31m [31m×[31m returns 404[39m[32m 33[2mms[22m[39m
[31m [31m×[31m returns 201 with valid body[39m[32m 69[2mms[22m[39m
[31m [31m×[31m returns 400 when walletAddress is missing[39m[32m 16[2mms[22m[39m
[32m✓[39m returns 400 when requestedLimit is non-numeric[32m 10[2mms[22m[39m
[32m✓[39m returns 400 when body is empty[32m 9[2mms[22m[39m
[31m [31m×[31m returns 200 with valid amount[39m[32m 14[2mms[22m[39m
[31m [31m×[31m returns 400 when amount is missing[39m[32m 21[2mms[22m[39m
[31m [31m×[31m returns 400 when amount is not numeric string[39m[32m 14[2mms[22m[39m
[31m [31m×[31m returns 200 with valid amount[39m[32m 12[2mms[22m[39m
[31m [31m×[31m returns 400 when amount is missing[39m[32m 13[2mms[22m[39m
[31m [31m×[31m returns 400 when amount is a number (not string)[39m[32m 10[2mms[22m[39m
[31m [31m×[31m returns placeholder risk data for valid walletAddress[39m[32m 32[2mms[22m[39m
[31m [31m×[31m returns 400 when walletAddress is missing[39m[32m 22[2mms[22m[39m
[32m✓[39m returns 400 when walletAddress is empty string[32m 8[2mms[22m[39m
[32m✓[39m returns 400 when walletAddress is not a string[32m 7[2mms[22m[39m
[31m❯[39m tests/rateLimit.test.ts [2m([22m[2m8 tests[22m[2m | [22m[31m6 failed[39m[2m)[22m[33m 363[2mms[22m[39m
[31m [31m×[31m sets X-RateLimit-* headers on GET /api/credit/lines[39m[32m 111[2mms[22m[39m
[31m [31m×[31m sets X-RateLimit-* headers on GET /api/credit/lines/:id[39m[32m 19[2mms[22m[39m
[31m [31m×[31m sets X-RateLimit-* headers on POST /api/credit/lines[39m[32m 45[2mms[22m[39m
[31m [31m×[31m sets X-RateLimit-* headers on POST /api/risk/evaluate[39m[32m 13[2mms[22m[39m
[31m [31m×[31m sets X-RateLimit-* headers on GET /api/risk/wallet/:address/latest[39m[32m 21[2mms[22m[39m
[31m [31m×[31m sets X-RateLimit-* headers on GET /api/risk/wallet/:address/history[39m[32m 13[2mms[22m[39m
[32m✓[39m POST /api/risk/admin/recalibrate does not apply rate limiting[32m 13[2mms[22m[39m
[32m✓[39m returns correct 429 response body when rate limit is exceeded on /api/risk/evaluate[32m 119[2mms[22m[39m
[31m❯[39m tests/schemas/schemas.test.ts [2m([22m[2m37 tests[22m[2m | [22m[31m4 failed[39m[2m)[22m[32m 108[2mms[22m[39m
[31m [31m×[31m accepts a valid walletAddress[39m[32m 42[2mms[22m[39m
[32m✓[39m rejects missing walletAddress[32m 2[2mms[22m[39m
[32m✓[39m rejects empty walletAddress[32m 1[2mms[22m[39m
[32m✓[39m rejects walletAddress exceeding 256 chars[32m 1[2mms[22m[39m
[32m✓[39m rejects non-string walletAddress[32m 1[2mms[22m[39m
[31m [31m×[31m accepts optional forceRefresh[39m[32m 4[2mms[22m[39m
[32m✓[39m rejects unknown keys[32m 2[2mms[22m[39m
[31m [31m×[31m accepts valid body[39m[32m 4[2mms[22m[39m
[31m [31m×[31m accepts decimal requestedLimit[39m[32m 4[2mms[22m[39m
[32m✓[39m rejects missing walletAddress[32m 1[2mms[22m[39m
[32m✓[39m rejects missing requestedLimit[32m 1[2mms[22m[39m
[32m✓[39m rejects non-numeric requestedLimit[32m 1[2mms[22m[39m
[32m✓[39m rejects negative requestedLimit[32m 1[2mms[22m[39m
[32m✓[39m rejects unknown keys[32m 1[2mms[22m[39m
[32m✓[39m accepts a valid amount[32m 1[2mms[22m[39m
[32m✓[39m accepts a decimal amount[32m 0[2mms[22m[39m
[32m✓[39m rejects missing amount[32m 1[2mms[22m[39m
[32m✓[39m rejects non-numeric amount[32m 1[2mms[22m[39m
[32m✓[39m rejects numeric (non-string) amount[32m 1[2mms[22m[39m
[32m✓[39m rejects unknown keys[32m 1[2mms[22m[39m
[32m✓[39m accepts a valid amount[32m 1[2mms[22m[39m
[32m✓[39m rejects missing amount[32m 1[2mms[22m[39m
[32m✓[39m rejects non-numeric amount[32m 1[2mms[22m[39m
[32m✓[39m rejects unknown keys[32m 1[2mms[22m[39m
[32m✓[39m accepts empty query[32m 2[2mms[22m[39m
[32m✓[39m coerces numeric query strings[32m 2[2mms[22m[39m
[32m✓[39m rejects invalid limit[32m 1[2mms[22m[39m
[32m✓[39m rejects unknown keys[32m 1[2mms[22m[39m
[32m✓[39m accepts valid filters and pagination[32m 3[2mms[22m[39m
[32m✓[39m rejects invalid transaction type[32m 1[2mms[22m[39m
[32m✓[39m rejects invalid date[32m 1[2mms[22m[39m
[32m✓[39m rejects invalid page/limit bounds[32m 1[2mms[22m[39m
[32m✓[39m rejects unknown keys[32m 1[2mms[22m[39m
[32m✓[39m accepts empty query[32m 1[2mms[22m[39m
[32m✓[39m coerces valid pagination values[32m 1[2mms[22m[39m
[32m✓[39m rejects negative offset[32m 1[2mms[22m[39m
[32m✓[39m rejects unknown keys[32m 1[2mms[22m[39m
[31m❯[39m src/__tests__/credit.test.ts [2m([22m[2m9 tests[22m[2m | [22m[31m3 failed[39m[2m)[22m[32m 256[2mms[22m[39m
[31m [31m×[31m returns 200 without any API key[39m[32m 146[2mms[22m[39m
[32m✓[39m returns 404 without any API key[32m 13[2mms[22m[39m
[32m✓[39m returns 401 when x-api-key header is missing[32m 16[2mms[22m[39m
[32m✓[39m returns 403 when x-api-key header has a wrong value[32m 9[2mms[22m[39m
[32m✓[39m does not expose the wrong key value in the 403 body[32m 11[2mms[22m[39m
[31m [31m×[31m returns 200 with the valid API key[39m[32m 17[2mms[22m[39m
[32m✓[39m returns 401 when x-api-key header is missing[32m 6[2mms[22m[39m
[32m✓[39m returns 403 when x-api-key header has a wrong value[32m 7[2mms[22m[39m
[31m [31m×[31m returns 200 with the valid API key[39m[32m 18[2mms[22m[39m
[31m❯[39m src/__test__/riskRoute.test.ts [2m([22m[2m8 tests[22m[2m | [22m[31m7 failed[39m[2m)[22m[32m 204[2mms[22m[39m
[31m [31m×[31m returns 400 when body is empty[39m[32m 109[2mms[22m[39m
[31m [31m×[31m returns 400 when walletAddress is blank[39m[32m 15[2mms[22m[39m
[31m [31m×[31m returns 400 for invalid format and does not call evaluateWallet[39m[32m 15[2mms[22m[39m
[31m [31m×[31m returns 200 with the service result on a valid address[39m[32m 16[2mms[22m[39m
[31m [31m×[31m normalizes walletAddress and calls evaluateWallet with trimmed value[39m[32m 14[2mms[22m[39m
[31m [31m×[31m returns 400 when service throws InvalidWalletAddressError[39m[32m 11[2mms[22m[39m
[31m [31m×[31m returns 500 with a generic message when service throws unexpected errors[39m[32m 8[2mms[22m[39m
[32m✓[39m returns JSON content-type on 400 error[32m 10[2mms[22m[39m
[31m❯[39m tests/draw-credit.test.ts [2m([22m[2m8 tests[22m[2m | [22m[31m7 failed[39m[2m)[22m[32m 187[2mms[22m[39m
[31m [31m×[31m should draw successfully[39m[32m 101[2mms[22m[39m
[31m [31m×[31m should reject over-limit draw[39m[32m 20[2mms[22m[39m
[31m [31m×[31m should reject wrong borrower[39m[32m 11[2mms[22m[39m
[31m [31m×[31m should reject inactive credit line[39m[32m 11[2mms[22m[39m
[32m✓[39m should return 404 if credit line not found[32m 13[2mms[22m[39m
[31m [31m×[31m should reject invalid amount[39m[32m 10[2mms[22m[39m
[31m [31m×[31m should reject zero amount[39m[32m 8[2mms[22m[39m
[31m [31m×[31m should fail if body missing[39m[32m 7[2mms[22m[39m
[31m❯[39m src/__tests__/risk.test.ts [2m([22m[2m9 tests[22m[2m | [22m[31m3 failed[39m[2m)[22m[32m 178[2mms[22m[39m
[31m [31m×[31m returns 200 with a valid Stellar walletAddress[39m[32m 92[2mms[22m[39m
[32m✓[39m returns 400 with an invalid Stellar walletAddress[32m 13[2mms[22m[39m
[31m [31m×[31m returns 400 when walletAddress is missing[39m[32m 17[2mms[22m[39m
[32m✓[39m returns 400 when body is empty[32m 8[2mms[22m[39m
[32m✓[39m does not require an API key[32m 7[2mms[22m[39m
[32m✓[39m returns 401 when x-api-key header is missing[32m 6[2mms[22m[39m
[32m✓[39m returns 403 when x-api-key header has a wrong value[32m 7[2mms[22m[39m
[32m✓[39m does not expose the wrong key value in the 403 body[32m 6[2mms[22m[39m
[31m [31m×[31m returns 200 with the valid API key[39m[32m 12[2mms[22m[39m
[31m❯[39m src/tests/api.test.ts [2m([22m[2m6 tests[22m[2m | [22m[31m4 failed[39m[2m)[22m[32m 165[2mms[22m[39m
[31m [31m×[31m returns 200 with status ok[39m[32m 81[2mms[22m[39m
[32m✓[39m returns the parsed OpenAPI spec[32m 11[2mms[22m[39m
[31m [31m×[31m returns 200 with empty creditLines array[39m[32m 13[2mms[22m[39m
[32m✓[39m returns 404 for unknown id[32m 9[2mms[22m[39m
[31m [31m×[31m returns 400 when walletAddress is missing[39m[32m 34[2mms[22m[39m
[31m [31m×[31m returns 200 with risk fields when walletAddress provided[39m[32m 11[2mms[22m[39m
[31m❯[39m tests/api.test.ts [2m([22m[2m5 tests[22m[2m | [22m[31m4 failed[39m[2m)[22m[32m 183[2mms[22m[39m
[32m✓[39m returns a successful envelope with health status[32m 72[2mms[22m[39m
[31m [31m×[31m GET /api/credit/lines returns a successful envelope[39m[32m 38[2mms[22m[39m
[31m [31m×[31m GET /api/credit/lines/:id returns a standard failure envelope for 404[39m[32m 15[2mms[22m[39m
[31m [31m×[31m POST /api/risk/evaluate returns a standard failure envelope for missing body[39m[32m 39[2mms[22m[39m
[31m [31m×[31m POST /api/risk/evaluate returns a successful envelope with risk status[39m[32m 13[2mms[22m[39m
[31m❯[39m src/services/__tests__/drawWebhookService.test.ts [2m([22m[2m20 tests[22m[2m | [22m[31m5 failed[39m[2m)[22m[32m 123[2mms[22m[39m
[32m✓[39m should resolve configuration from environment variables[32m 17[2mms[22m[39m
[32m✓[39m should use default values when environment variables are not set[32m 4[2mms[22m[39m
[32m✓[39m should throw error when URLs are configured but secret is missing[32m 4[2mms[22m[39m
[32m✓[39m should handle empty URLs gracefully[32m 1[2mms[22m[39m
[32m✓[39m should trim and filter URLs[32m 2[2mms[22m[39m
[32m✓[39m should initialize webhooks successfully with valid configuration[32m 2[2mms[22m[39m
[32m✓[39m should handle missing configuration gracefully[32m 2[2mms[22m[39m
[32m✓[39m should log initialization details[32m 9[2mms[22m[39m
[32m✓[39m should skip webhook delivery when no URLs are configured[32m 21[2mms[22m[39m
[32m✓[39m should skip non-draw confirmation events[32m 4[2mms[22m[39m
[32m✓[39m should successfully deliver webhook for draw confirmation event[32m 8[2mms[22m[39m
[32m✓[39m should handle HTTP errors properly[32m 2[2mms[22m[39m
[31m [31m×[31m should retry failed requests with exponential backoff[39m[32m 17[2mms[22m[39m
[32m✓[39m should handle malformed event data gracefully[32m 2[2mms[22m[39m
[31m [31m×[31m should handle multiple webhook URLs[39m[32m 6[2mms[22m[39m
[31m [31m×[31m should test connectivity to all webhook URLs[39m[32m 5[2mms[22m[39m
[31m [31m×[31m should handle network errors during connectivity test[39m[32m 4[2mms[22m[39m
[32m✓[39m should return empty array when no URLs are configured[32m 1[2mms[22m[39m
[32m✓[39m should generate consistent signatures for the same payload[32m 2[2mms[22m[39m
[31m [31m×[31m should handle request timeouts[39m[32m 3[2mms[22m[39m
[31m❯[39m src/__test__/horizonListener.test.ts [2m([22m[2m49 tests[22m[2m | [22m[31m49 failed[39m[2m)[22m[32m 94[2mms[22m[39m
[31m [31m×[31m returns sensible defaults when no env vars are set[39m[32m 17[2mms[22m[39m
[31m [31m×[31m reads HORIZON_URL from env[39m[32m 2[2mms[22m[39m
[31m [31m×[31m parses a single CONTRACT_ID[39m[32m 2[2mms[22m[39m
[31m [31m×[31m parses multiple CONTRACT_IDS separated by commas[39m[32m 2[2mms[22m[39m
[31m [31m×[31m trims whitespace from CONTRACT_IDS entries[39m[32m 2[2mms[22m[39m
[31m [31m×[31m returns empty contractIds for an empty CONTRACT_IDS string[39m[32m 2[2mms[22m[39m
[31m [31m×[31m parses POLL_INTERVAL_MS from env[39m[32m 1[2mms[22m[39m
[31m [31m×[31m reads HORIZON_START_LEDGER from env[39m[32m 1[2mms[22m[39m
[31m [31m×[31m returns false and null config before start[39m[32m 2[2mms[22m[39m
[31m [31m×[31m returns true and a config object after start[39m[32m 1[2mms[22m[39m
[31m [31m×[31m returns false and null config after stop[39m[32m 1[2mms[22m[39m
[31m [31m×[31m sets running to true[39m[32m 1[2mms[22m[39m
[31m [31m×[31m executes an immediate first poll on start[39m[32m 1[2mms[22m[39m
[31m [31m×[31m fires handlers on subsequent interval ticks[39m[32m 1[2mms[22m[39m
[31m [31m×[31m is a no-op (warns) if called when already running[39m[32m 1[2mms[22m[39m
[31m [31m×[31m logs startup config information[39m[32m 1[2mms[22m[39m
[31m [31m×[31m sets running to false[39m[32m 2[2mms[22m[39m
[31m [31m×[31m clears the polling interval so no more events fire[39m[32m 2[2mms[22m[39m
[31m [31m×[31m is a no-op (warns) if called when not running[39m[32m 1[2mms[22m[39m
[31m [31m×[31m logs a stopped message[39m[32m 1[2mms[22m[39m
[31m [31m×[31m allows the listener to be restarted after stop[39m[32m 1[2mms[22m[39m
[31m [31m×[31m registers a handler that receives simulated events[39m[32m 1[2mms[22m[39m
[31m [31m×[31m supports multiple handlers and invokes all of them[39m[32m 1[2mms[22m[39m
[31m [31m×[31m clearEventHandlers() removes all registered handlers[39m[32m 1[2mms[22m[39m
[31m [31m×[31m catches and logs errors thrown by a handler without stopping dispatch[39m[32m 1[2mms[22m[39m
[31m [31m×[31m handles async handlers that reject gracefully[39m[32m 1[2mms[22m[39m
[31m [31m×[31m completes without throwing when contractIds is empty[39m[32m 1[2mms[22m[39m
[31m [31m×[31m logs a polling message on every call[39m[32m 1[2mms[22m[39m
[31m [31m×[31m emits a simulated event when contractIds is non-empty[39m[32m 1[2mms[22m[39m
[31m [31m×[31m does not emit events when contractIds is empty[39m[32m 1[2mms[22m[39m
[31m [31m×[31m logs 'none' for contracts when contractIds is empty[39m[32m 1[2mms[22m[39m
[31m [31m×[31m includes simulated event data with a walletAddress field[39m[32m 1[2mms[22m[39m
[31m [31m×[31m sets a valid ISO timestamp on the simulated event[39m[32m 1[2mms[22m[39m
[31m [31m×[31m returns initial metrics state[39m[32m 1[2mms[22m[39m
[31m [31m×[31m tracks metrics during polling[39m[32m 6[2mms[22m[39m
[31m [31m×[31m resets metrics to initial state[39m[32m 1[2mms[22m[39m
[31m [31m×[31m prevents duplicate event processing[39m[32m 1[2mms[22m[39m
[31m [31m×[31m generates unique event IDs[39m[32m 1[2mms[22m[39m
[31m [31m×[31m reads resilience configuration from environment[39m[32m 1[2mms[22m[39m
[31m [31m×[31m uses default values for resilience configuration[39m[32m 1[2mms[22m[39m
[31m [31m×[31m handles rate limit errors with proper backoff[39m[32m 1[2mms[22m[39m
[31m [31m×[31m handles transient errors with exponential backoff[39m[32m 3[2mms[22m[39m
[31m [31m×[31m handles cursor gap errors and recovery[39m[32m 1[2mms[22m[39m
[31m [31m×[31m respects maximum retry limits[39m[32m 1[2mms[22m[39m
[31m [31m×[31m logs metrics when enabled[39m[32m 1[2mms[22m[39m
[31m [31m×[31m does not log metrics when disabled[39m[32m 1[2mms[22m[39m
[31m [31m×[31m tracks ledger cursor progression[39m[32m 1[2mms[22m[39m
[31m [31m×[31m handles different start ledger configurations[39m[32m 1[2mms[22m[39m
[31m [31m×[31m limits processed event ID cache size[39m[32m 1[2mms[22m[39m
[31m❯[39m tests/health.test.ts [2m([22m[2m3 tests[22m[2m | [22m[31m1 failed[39m[2m)[22m[32m 120[2mms[22m[39m
[32m✓[39m should return health status 200[32m 65[2mms[22m[39m
[31m [31m×[31m should return correct JSON structure[39m[32m 38[2mms[22m[39m
[32m✓[39m should have content-type application/json[32m 12[2mms[22m[39m
[32m✓[39m src/__tests__/app.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 163[2mms[22m[39m
[31m❯[39m src/routes/__tests__/risk.test.ts [2m([22m[2m18 tests[22m[2m | [22m[31m1 failed[39m[2m)[22m[32m 117[2mms[22m[39m
[32m✓[39m evaluates risk and returns enveloped response[32m 31[2mms[22m[39m
[32m✓[39m uses cached evaluation when available[32m 2[2mms[22m[39m
[32m✓[39m forces refresh when requested[32m 2[2mms[22m[39m
[32m✓[39m rejects missing walletAddress via schema validation[32m 7[2mms[22m[39m
[32m✓[39m rejects unknown keys via strict schema[32m 2[2mms[22m[39m
[32m✓[39m returns 500 when service throws[32m 3[2mms[22m[39m
[32m✓[39m returns evaluation by id[32m 1[2mms[22m[39m
[32m✓[39m returns 404 when evaluation is missing[32m 1[2mms[22m[39m
[32m✓[39m returns 500 when evaluation fetch throws[32m 3[2mms[22m[39m
[32m✓[39m returns latest evaluation for wallet[32m 2[2mms[22m[39m
[31m [31m×[31m returns 404 for missing latest evaluation[39m[32m 32[2mms[22m[39m
[32m✓[39m returns 500 when latest evaluation fetch throws[32m 2[2mms[22m[39m
[32m✓[39m returns history with pagination[32m 7[2mms[22m[39m
[32m✓[39m rejects invalid query types for history[32m 2[2mms[22m[39m
[32m✓[39m returns 500 when history fetch throws[32m 1[2mms[22m[39m
[32m✓[39m requires API key[32m 1[2mms[22m[39m
[32m✓[39m rejects invalid API key[32m 1[2mms[22m[39m
[32m✓[39m accepts valid API key[32m 1[2mms[22m[39m
[32m✓[39m tests/middleware/validate.test.ts [2m([22m[2m8 tests[22m[2m)[22m[33m 325[2mms[22m[39m
[31m❯[39m src/__tests__/health.test.ts [2m([22m[2m1 test[22m[2m | [22m[31m1 failed[39m[2m)[22m[32m 110[2mms[22m[39m
[31m [31m×[31m returns 200 with correct service name[39m[32m 99[2mms[22m[39m
[32m✓[39m src/__test__/creditService.test.ts [2m([22m[2m73 tests[22m[2m)[22m[33m 317[2mms[22m[39m
[32m✓[39m src/__tests__/stellar_validation.test.ts [2m([22m[2m10 tests[22m[2m)[22m[32m 199[2mms[22m[39m
[32m✓[39m tests/middleware/errorHandler.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 96[2mms[22m[39m
[32m✓[39m src/db/migrations.test.ts [2m([22m[2m10 tests[22m[2m)[22m[32m 49[2mms[22m[39m
[32m✓[39m tests/middleware/validate.unit.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 55[2mms[22m[39m
[32m✓[39m src/__test__/jobQueue.test.ts [2m([22m[2m14 tests[22m[2m)[22m[32m 72[2mms[22m[39m
[32m✓[39m src/repositories/memory/__tests__/InMemoryTransactionRepository.test.ts [2m([22m[2m20 tests[22m[2m)[22m[32m 75[2mms[22m[39m
[32m✓[39m src/services/__tests__/CreditLineService.test.ts [2m([22m[2m17 tests[22m[2m)[22m[32m 92[2mms[22m[39m
[32m✓[39m tests/middleware/rateLimit.test.ts [2m([22m[2m14 tests[22m[2m)[22m[32m 49[2mms[22m[39m
[32m✓[39m src/__test__/riskService.test.ts [2m([22m[2m33 tests[22m[2m)[22m[32m 43[2mms[22m[39m
[32m✓[39m src/__tests__/auth.test.ts [2m([22m[2m11 tests[22m[2m)[22m[32m 71[2mms[22m[39m
[32m✓[39m src/services/__tests__/RiskEvaluationService.test.ts [2m([22m[2m9 tests[22m[2m)[22m[32m 69[2mms[22m[39m
[32m✓[39m src/repositories/memory/__tests__/InMemoryCreditLineRepository.test.ts [2m([22m[2m14 tests[22m[2m)[22m[32m 46[2mms[22m[39m
[32m✓[39m tests/response.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 41[2mms[22m[39m
[32m✓[39m src/container/__tests__/Container.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 49[2mms[22m[39m
[32m✓[39m src/repositories/memory/__tests__/InMemoryRiskEvaluationRepository.test.ts [2m([22m[2m13 tests[22m[2m)[22m[32m 42[2mms[22m[39m
[32m✓[39m src/db/validate-schema.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 35[2mms[22m[39m
[32m✓[39m src/__test__/stellarAddress.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 18[2mms[22m[39m
[32m✓[39m tests/config/rateLimit.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 22[2mms[22m[39m
[32m✓[39m src/db/client.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 13[2mms[22m[39m
[32m✓[39m tests/schemas/index.exports.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 7[2mms[22m[39m
[31m⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Tests 159 [49m[22m[31m⎯⎯⎯⎯⎯⎯[39m
[41m[1m FAIL [22m[49m tests/api.test.ts[2m > [22mAPI Integration Tests[2m > [22mCredit Routes[2m > [22mGET /api/credit/lines returns a successful envelope
[31m[1mAssertionError[22m: expected { …(2) } to deeply equal { data: { creditLines: [] }, …(1) }[39m
[32m- Expected[39m
[31m+ Received[39m
[2m {[22m
[2m "data": {[22m
[2m "creditLines": [],[22m
[31m+ "pagination": {[39m
[31m+ "limit": 100,[39m
[31m+ "offset": 0,[39m
[31m+ "total": 0,[39m
[31m+ },[39m
[2m },[22m
[2m "error": null,[22m
[2m }[22m
[36m [2m❯[22m tests/api.test.ts:[2m24:35[22m[39m
[90m 22|[39m
[90m 23|[39m [34mexpect[39m(response[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m 24|[39m [34mexpect[39m(response[33m.[39mbody)[33m.[39m[34mtoEqual[39m({
[90m |[39m [31m^[39m
[90m 25|[39m data[33m:[39m { creditLines[33m:[39m [] }[33m,[39m
[90m 26|[39m error[33m:[39m [35mnull[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/api.test.ts[2m > [22mAPI Integration Tests[2m > [22mCredit Routes[2m > [22mGET /api/credit/lines/:id returns a standard failure envelope for 404
[31m[1mAssertionError[22m: expected { Object (error, id) } to deeply equal { data: null, …(1) }[39m
[32m- Expected[39m
[31m+ Received[39m
[2m {[22m
[32m- "data": null,[39m
[32m- "error": "Credit line not found: 123",[39m
[31m+ "error": "Credit line not found",[39m
[31m+ "id": "123",[39m
[2m }[22m
[36m [2m❯[22m tests/api.test.ts:[2m34:35[22m[39m
[90m 32|[39m
[90m 33|[39m [34mexpect[39m(response[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m404[39m)[33m;[39m
[90m 34|[39m [34mexpect[39m(response[33m.[39mbody)[33m.[39m[34mtoEqual[39m({
[90m |[39m [31m^[39m
[90m 35|[39m data[33m:[39m [35mnull[39m[33m,[39m
[90m 36|[39m error[33m:[39m [32m'Credit line not found: 123'[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/api.test.ts[2m > [22mAPI Integration Tests[2m > [22mRisk Routes[2m > [22mPOST /api/risk/evaluate returns a standard failure envelope for missing body
[31m[1mAssertionError[22m: expected { error: 'Validation failed', …(1) } to deeply equal { data: null, …(1) }[39m
[32m- Expected[39m
[31m+ Received[39m
[2m {[22m
[32m- "data": null,[39m
[32m- "error": "walletAddress required",[39m
[31m+ "details": [[39m
[31m+ {[39m
[31m+ "field": "walletAddress",[39m
[31m+ "message": "Invalid input: expected string, received undefined",[39m
[31m+ },[39m
[31m+ ],[39m
[31m+ "error": "Validation failed",[39m
[2m }[22m
[36m [2m❯[22m tests/api.test.ts:[2m46:35[22m[39m
[90m 44|[39m
[90m 45|[39m [34mexpect[39m(response[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m400[39m)[33m;[39m
[90m 46|[39m [34mexpect[39m(response[33m.[39mbody)[33m.[39m[34mtoEqual[39m({
[90m |[39m [31m^[39m
[90m 47|[39m data[33m:[39m [35mnull[39m[33m,[39m
[90m 48|[39m error[33m:[39m [32m'walletAddress required'[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/api.test.ts[2m > [22mAPI Integration Tests[2m > [22mRisk Routes[2m > [22mPOST /api/risk/evaluate returns a successful envelope with risk status
[31m[1mAssertionError[22m: expected 400 to be 200 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 200[39m
[31m+ 400[39m
[36m [2m❯[22m tests/api.test.ts:[2m57:37[22m[39m
[90m 55|[39m [33m.[39m[34msend[39m({ walletAddress[33m:[39m [32m'0x123'[39m })[33m;[39m
[90m 56|[39m
[90m 57|[39m [34mexpect[39m(response[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 58|[39m [34mexpect[39m(response[33m.[39mbody)[33m.[39m[34mtoEqual[39m({
[90m 59|[39m data[33m:[39m {
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/cors.test.ts[2m > [22mapplication CORS behavior[2m > [22mechoes localhost origins on preflight requests
[31m[1mAssertionError[22m: expected '*' to be 'http://localhost:5173' // Object.is equality[39m
Expected: [32m"http://localhost:5173"[39m
Received: [31m"*"[39m
[36m [2m❯[22m tests/cors.test.ts:[2m136:61[22m[39m
[90m134|[39m
[90m135|[39m [34mexpect[39m(response[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m204[39m)[33m;[39m
[90m136|[39m expect(response.headers['access-control-allow-origin']).toBe('http…
[90m |[39m [31m^[39m
[90m137|[39m })[33m;[39m
[90m138|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/cors.test.ts[2m > [22mapplication CORS behavior[2m > [22momits CORS headers for disallowed browser origins
[31m[1mAssertionError[22m: expected '*' to be undefined[39m
[32m- Expected:[39m
undefined
[31m+ Received:[39m
"*"
[36m [2m❯[22m tests/cors.test.ts:[2m145:61[22m[39m
[90m143|[39m
[90m144|[39m [34mexpect[39m(response[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m145|[39m expect(response.headers['access-control-allow-origin']).toBeUndefi…
[90m |[39m [31m^[39m
[90m146|[39m })[33m;[39m
[90m147|[39m })[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/draw-credit.test.ts[2m > [22mPOST /api/credit/lines/:id/draw[2m > [22mshould draw successfully
[31m[1mAssertionError[22m: expected 404 to be 200 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 200[39m
[31m+ 404[39m
[36m [2m❯[22m tests/draw-credit.test.ts:[2m21:30[22m[39m
[90m 19|[39m [33m.[39m[34msend[39m({ borrowerId[33m:[39m [32m'user-1'[39m[33m,[39m amount[33m:[39m [34m200[39m })[33m;[39m
[90m 20|[39m
[90m 21|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 22|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39mcreditLine[33m.[39mutilized)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m 23|[39m })[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/draw-credit.test.ts[2m > [22mPOST /api/credit/lines/:id/draw[2m > [22mshould reject over-limit draw
[31m[1mAssertionError[22m: expected 404 to be 400 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 400[39m
[31m+ 404[39m
[36m [2m❯[22m tests/draw-credit.test.ts:[2m30:30[22m[39m
[90m 28|[39m [33m.[39m[34msend[39m({ borrowerId[33m:[39m [32m'user-1'[39m[33m,[39m amount[33m:[39m [34m2000[39m })[33m;[39m
[90m 29|[39m
[90m 30|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m400[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 31|[39m })[33m;[39m
[90m 32|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[8/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/draw-credit.test.ts[2m > [22mPOST /api/credit/lines/:id/draw[2m > [22mshould reject wrong borrower
[31m[1mAssertionError[22m: expected 404 to be 403 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 403[39m
[31m+ 404[39m
[36m [2m❯[22m tests/draw-credit.test.ts:[2m38:30[22m[39m
[90m 36|[39m [33m.[39m[34msend[39m({ borrowerId[33m:[39m [32m'hacker'[39m[33m,[39m amount[33m:[39m [34m100[39m })[33m;[39m
[90m 37|[39m
[90m 38|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m403[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 39|[39m })[33m;[39m
[90m 40|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[9/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/draw-credit.test.ts[2m > [22mPOST /api/credit/lines/:id/draw[2m > [22mshould reject inactive credit line
[31m[1mAssertionError[22m: expected 404 to be 400 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 400[39m
[31m+ 404[39m
[36m [2m❯[22m tests/draw-credit.test.ts:[2m48:30[22m[39m
[90m 46|[39m [33m.[39m[34msend[39m({ borrowerId[33m:[39m [32m'user-1'[39m[33m,[39m amount[33m:[39m [34m100[39m })[33m;[39m
[90m 47|[39m
[90m 48|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m400[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 49|[39m })[33m;[39m
[90m 50|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[10/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/draw-credit.test.ts[2m > [22mPOST /api/credit/lines/:id/draw[2m > [22mshould reject invalid amount
[31m[1mAssertionError[22m: expected 404 to be 400 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 400[39m
[31m+ 404[39m
[36m [2m❯[22m tests/draw-credit.test.ts:[2m64:30[22m[39m
[90m 62|[39m [33m.[39m[34msend[39m({ borrowerId[33m:[39m [32m'user-1'[39m[33m,[39m amount[33m:[39m [33m-[39m[34m50[39m })[33m;[39m
[90m 63|[39m
[90m 64|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m400[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 65|[39m })[33m;[39m
[90m 66|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[11/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/draw-credit.test.ts[2m > [22mPOST /api/credit/lines/:id/draw[2m > [22mshould reject zero amount
[31m[1mAssertionError[22m: expected 404 to be 400 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 400[39m
[31m+ 404[39m
[36m [2m❯[22m tests/draw-credit.test.ts:[2m72:30[22m[39m
[90m 70|[39m [33m.[39m[34msend[39m({ borrowerId[33m:[39m [32m'user-1'[39m[33m,[39m amount[33m:[39m [34m0[39m })[33m;[39m
[90m 71|[39m
[90m 72|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m400[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 73|[39m })[33m;[39m
[90m 74|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[12/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/draw-credit.test.ts[2m > [22mPOST /api/credit/lines/:id/draw[2m > [22mshould fail if body missing
[31m[1mAssertionError[22m: expected 404 to be 403 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 403[39m
[31m+ 404[39m
[36m [2m❯[22m tests/draw-credit.test.ts:[2m80:30[22m[39m
[90m 78|[39m [33m.[39m[34msend[39m({})[33m;[39m
[90m 79|[39m
[90m 80|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m403[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 81|[39m })[33m;[39m
[90m 82|[39m })[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[13/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/health.test.ts[2m > [22mGET /health[2m > [22mshould return correct JSON structure
[31m[1mAssertionError[22m: expected { data: { status: 'ok', …(1) }, …(1) } to deeply equal { status: 'ok', …(1) }[39m
[32m- Expected[39m
[31m+ Received[39m
[2m {[22m
[31m+ "data": {[39m
[2m "service": "creditra-backend",[22m
[2m "status": "ok",[22m
[31m+ },[39m
[31m+ "error": null,[39m
[2m }[22m
[36m [2m❯[22m tests/health.test.ts:[2m19:28[22m[39m
[90m 17|[39m [35mconst[39m res [33m=[39m [35mawait[39m [34mrequest[39m(app)[33m.[39m[35mget[39m([32m'/health'[39m)[33m;[39m
[90m 18|[39m
[90m 19|[39m [34mexpect[39m(res[33m.[39mbody)[33m.[39m[34mtoEqual[39m({
[90m |[39m [31m^[39m
[90m 20|[39m status[33m:[39m [32m'ok'[39m[33m,[39m
[90m 21|[39m service[33m:[39m [32m'creditra-backend'[39m[33m,[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[14/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/rateLimit.test.ts[2m > [22mRate Limiting Integration Tests[2m > [22mRate limit headers on credit endpoints[2m > [22msets X-RateLimit-* headers on GET /api/credit/lines
[31m[1mAssertionError[22m: expected { 'x-powered-by': 'Express', …(6) } to have property "x-ratelimit-limit"[39m
[36m [2m❯[22m tests/rateLimit.test.ts:[2m22:32[22m[39m
[90m 20|[39m
[90m 21|[39m [34mexpect[39m(response[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m 22|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-limit'[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 23|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-remaining'[39m)[33m;[39m
[90m 24|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-reset'[39m)[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[15/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/rateLimit.test.ts[2m > [22mRate Limiting Integration Tests[2m > [22mRate limit headers on credit endpoints[2m > [22msets X-RateLimit-* headers on GET /api/credit/lines/:id
[31m[1mAssertionError[22m: expected { 'x-powered-by': 'Express', …(6) } to have property "x-ratelimit-limit"[39m
[36m [2m❯[22m tests/rateLimit.test.ts:[2m31:32[22m[39m
[90m 29|[39m
[90m 30|[39m [34mexpect[39m(response[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m404[39m)[33m;[39m
[90m 31|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-limit'[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 32|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-remaining'[39m)[33m;[39m
[90m 33|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-reset'[39m)[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[16/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/rateLimit.test.ts[2m > [22mRate Limiting Integration Tests[2m > [22mRate limit headers on credit endpoints[2m > [22msets X-RateLimit-* headers on POST /api/credit/lines
[31m[1mAssertionError[22m: expected 400 to be 201 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 201[39m
[31m+ 400[39m
[36m [2m❯[22m tests/rateLimit.test.ts:[2m41:31[22m[39m
[90m 39|[39m [33m.[39m[34msend[39m({ walletAddress[33m:[39m [32m'0x123'[39m[33m,[39m requestedLimit[33m:[39m [32m'1000'[39m })[33m;[39m
[90m 40|[39m
[90m 41|[39m [34mexpect[39m(response[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m201[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 42|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-limit'[39m)[33m;[39m
[90m 43|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-remaining'[39m)[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[17/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/rateLimit.test.ts[2m > [22mRate Limiting Integration Tests[2m > [22mRate limit headers on risk endpoints[2m > [22msets X-RateLimit-* headers on POST /api/risk/evaluate
[31m[1mAssertionError[22m: expected 400 to be 200 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 200[39m
[31m+ 400[39m
[36m [2m❯[22m tests/rateLimit.test.ts:[2m54:31[22m[39m
[90m 52|[39m [33m.[39m[34msend[39m({ walletAddress[33m:[39m [32m'0x123'[39m })[33m;[39m
[90m 53|[39m
[90m 54|[39m [34mexpect[39m(response[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 55|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-limit'[39m)[33m;[39m
[90m 56|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-remaining'[39m)[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[18/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/rateLimit.test.ts[2m > [22mRate Limiting Integration Tests[2m > [22mRate limit headers on risk endpoints[2m > [22msets X-RateLimit-* headers on GET /api/risk/wallet/:address/latest
[31m[1mAssertionError[22m: expected [ 200, 404, 500 ] to include 400[39m
[36m [2m❯[22m tests/rateLimit.test.ts:[2m63:31[22m[39m
[90m 61|[39m const response = await request(app).get('/api/risk/wallet/0x123/…
[90m 62|[39m
[90m 63|[39m [34mexpect[39m([[34m200[39m[33m,[39m [34m404[39m[33m,[39m [34m500[39m])[33m.[39m[34mtoContain[39m(response[33m.[39mstatus)[33m;[39m
[90m |[39m [31m^[39m
[90m 64|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-limit'[39m)[33m;[39m
[90m 65|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-remaining'[39m)[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[19/208]⎯[22m[39m
[41m[1m FAIL [22m[49m tests/rateLimit.test.ts[2m > [22mRate Limiting Integration Tests[2m > [22mRate limit headers on risk endpoints[2m > [22msets X-RateLimit-* headers on GET /api/risk/wallet/:address/history
[31m[1mAssertionError[22m: expected [ 200, 500 ] to include 400[39m
[36m [2m❯[22m tests/rateLimit.test.ts:[2m72:26[22m[39m
[90m 70|[39m const response = await request(app).get('/api/risk/wallet/0x123/…
[90m 71|[39m
[90m 72|[39m [34mexpect[39m([[34m200[39m[33m,[39m [34m500[39m])[33m.[39m[34mtoContain[39m(response[33m.[39mstatus)[33m;[39m
[90m |[39m [31m^[39m
[90m 73|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-limit'[39m)[33m;[39m
[90m 74|[39m [34mexpect[39m(response[33m.[39mheaders)[33m.[39m[34mtoHaveProperty[39m([32m'x-ratelimit-remaining'[39m)[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[20/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/adminAuth.test.ts[2m > [22madminAuth middleware[2m > [22mwhen ADMIN_API_KEY env var is configured[2m > [22mcalls next() and returns 200 when the correct key is supplied
[31m[1mAssertionError[22m: expected 503 to be 200 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 200[39m
[31m+ 503[39m
[36m [2m❯[22m src/__test__/adminAuth.test.ts:[2m44:28[22m[39m
[90m 42|[39m [33m.[39m[35mset[39m([33mADMIN_KEY_HEADER[39m[33m,[39m [33mSECRET[39m)[33m;[39m
[90m 43|[39m
[90m 44|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 45|[39m [34mexpect[39m(res[33m.[39mbody)[33m.[39m[34mtoEqual[39m({ ok[33m:[39m [35mtrue[39m })[33m;[39m
[90m 46|[39m })[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[21/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/adminAuth.test.ts[2m > [22madminAuth middleware[2m > [22mwhen ADMIN_API_KEY env var is configured[2m > [22mreturns 401 when the X-Admin-Api-Key header is missing
[31m[1mAssertionError[22m: expected 503 to be 401 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 401[39m
[31m+ 503[39m
[36m [2m❯[22m src/__test__/adminAuth.test.ts:[2m51:28[22m[39m
[90m 49|[39m [35mconst[39m res [33m=[39m [35mawait[39m [34mrequest[39m([34mbuildApp[39m())[33m.[39m[34mpost[39m([32m"/protected"[39m)[33m;[39m
[90m 50|[39m
[90m 51|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m401[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 52|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39merror)[33m.[39m[34mtoContain[39m([32m"Unauthorized"[39m)[33m;[39m
[90m 53|[39m })[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[22/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/adminAuth.test.ts[2m > [22madminAuth middleware[2m > [22mwhen ADMIN_API_KEY env var is configured[2m > [22mreturns 401 when the header value is wrong
[31m[1mAssertionError[22m: expected 503 to be 401 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 401[39m
[31m+ 503[39m
[36m [2m❯[22m src/__test__/adminAuth.test.ts:[2m60:28[22m[39m
[90m 58|[39m [33m.[39m[35mset[39m([33mADMIN_KEY_HEADER[39m[33m,[39m [32m"wrong-key"[39m)[33m;[39m
[90m 59|[39m
[90m 60|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m401[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 61|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39merror)[33m.[39m[34mtoContain[39m([32m"Unauthorized"[39m)[33m;[39m
[90m 62|[39m })[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[23/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/adminAuth.test.ts[2m > [22madminAuth middleware[2m > [22mwhen ADMIN_API_KEY env var is configured[2m > [22mreturns 401 when the header is an empty string
[31m[1mAssertionError[22m: expected 503 to be 401 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 401[39m
[31m+ 503[39m
[36m [2m❯[22m src/__test__/adminAuth.test.ts:[2m69:28[22m[39m
[90m 67|[39m [33m.[39m[35mset[39m([33mADMIN_KEY_HEADER[39m[33m,[39m [32m""[39m)[33m;[39m
[90m 68|[39m
[90m 69|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m401[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 70|[39m })[33m;[39m
[90m 71|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[24/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/adminAuth.test.ts[2m > [22madminAuth middleware[2m > [22mwhen ADMIN_API_KEY env var is configured[2m > [22mreturns 401 when the header is close but not equal to the secret
[31m[1mAssertionError[22m: expected 503 to be 401 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 401[39m
[31m+ 503[39m
[36m [2m❯[22m src/__test__/adminAuth.test.ts:[2m77:28[22m[39m
[90m 75|[39m [33m.[39m[35mset[39m([33mADMIN_KEY_HEADER[39m[33m,[39m [33mSECRET[39m [33m+[39m [32m" "[39m)[33m;[39m
[90m 76|[39m
[90m 77|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m401[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 78|[39m })[33m;[39m
[90m 79|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[25/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/adminAuth.test.ts[2m > [22madminAuth middleware[2m > [22mwhen ADMIN_API_KEY env var is configured[2m > [22mresponse body includes X-Admin-Api-Key in the error hint
[31m[1mAssertionError[22m: expected 'Admin authentication is not configure…' to match /X-Admin-Api-Key/[39m
[32m- Expected:[39m
/X-Admin-Api-Key/
[31m+ Received:[39m
"Admin authentication is not configured on this server."
[36m [2m❯[22m src/__test__/adminAuth.test.ts:[2m83:32[22m[39m
[90m 81|[39m [35mconst[39m res [33m=[39m [35mawait[39m [34mrequest[39m([34mbuildApp[39m())[33m.[39m[34mpost[39m([32m"/protected"[39m)[33m;[39m
[90m 82|[39m
[90m 83|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39merror)[33m.[39m[34mtoMatch[39m([36m/X-Admin-Api-Key/[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 84|[39m })[33m;[39m
[90m 85|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[26/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/creditRoute.test.ts[2m > [22mGET /api/credit/lines[2m > [22mreturns 200 with an empty array when store is empty
[31m[1mAssertionError[22m: expected { creditLines: [], …(1) } to deeply equal [][39m
[32m- Expected:[39m
[]
[31m+ Received:[39m
{
"creditLines": [],
"pagination": {
"limit": 100,
"offset": 0,
"total": 0,
},
}
[36m [2m❯[22m src/__test__/creditRoute.test.ts:[2m60:27[22m[39m
[90m 58|[39m [35mconst[39m res [33m=[39m [35mawait[39m [34mrequest[39m([34mbuildApp[39m())[33m.[39m[35mget[39m([32m"/api/credit/lines"[39m)[33m;[39m
[90m 59|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m 60|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39mdata)[33m.[39m[34mtoEqual[39m([])[33m;[39m
[90m |[39m [31m^[39m
[90m 61|[39m })[33m;[39m
[90m 62|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[27/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/creditRoute.test.ts[2m > [22mGET /api/credit/lines[2m > [22mreturns all credit lines
[31m[1mAssertionError[22m: expected { creditLines: [], …(1) } to have property 'length'[39m
[36m [2m❯[22m src/__test__/creditRoute.test.ts:[2m67:27[22m[39m
[90m 65|[39m [34mcreateCreditLine[39m([32m"b"[39m)[33m;[39m
[90m 66|[39m [35mconst[39m res [33m=[39m [35mawait[39m [34mrequest[39m([34mbuildApp[39m())[33m.[39m[35mget[39m([32m"/api/credit/lines"[39m)[33m;[39m
[90m 67|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39mdata)[33m.[39m[34mtoHaveLength[39m([34m2[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 68|[39m })[33m;[39m
[90m 69|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[28/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/creditRoute.test.ts[2m > [22mGET /api/credit/lines/:id[2m > [22mreturns 200 with the credit line for a known id
[31m[1mAssertionError[22m: expected 404 to be 200 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 200[39m
[31m+ 404[39m
[36m [2m❯[22m src/__test__/creditRoute.test.ts:[2m81:24[22m[39m
[90m 79|[39m [34mcreateCreditLine[39m([33mVALID_ID[39m)[33m;[39m
[90m 80|[39m const res = await request(buildApp()).get(`/api/credit/lines/${VAL…
[90m 81|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 82|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39mdata[33m.[39mid)[33m.[39m[34mtoBe[39m([33mVALID_ID[39m)[33m;[39m
[90m 83|[39m })[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[29/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/creditRoute.test.ts[2m > [22mGET /api/credit/lines/:id[2m > [22mreturns 404 for an unknown id
[31m[1mAssertionError[22m: expected 'Credit line not found' to contain 'does-not-exist'[39m
Expected: [32m"does-not-exist"[39m
Received: [31m"Credit line not found"[39m
[36m [2m❯[22m src/__test__/creditRoute.test.ts:[2m88:28[22m[39m
[90m 86|[39m const res = await request(buildApp()).get(`/api/credit/lines/${MIS…
[90m 87|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m404[39m)[33m;[39m
[90m 88|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39merror)[33m.[39m[34mtoContain[39m([33mMISSING_ID[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m 89|[39m })[33m;[39m
[90m 90|[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[30/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/creditRoute.test.ts[2m > [22mPOST /api/credit/lines/:id/suspend — business logic[2m > [22mreturns 200 and suspended line for an active credit line
[31m[1mAssertionError[22m: expected 401 to be 200 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 200[39m
[31m+ 401[39m
[36m [2m❯[22m src/__test__/creditRoute.test.ts:[2m122:24[22m[39m
[90m120|[39m [33m.[39m[35mset[39m([32m"x-admin-api-key"[39m[33m,[39m [33mADMIN_KEY[39m)[33m;[39m
[90m121|[39m
[90m122|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m200[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m123|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39mdata[33m.[39mstatus)[33m.[39m[34mtoBe[39m([32m"suspended"[39m)[33m;[39m
[90m124|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39mmessage)[33m.[39m[34mtoBe[39m([32m"Credit line suspended."[39m)[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[31/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/creditRoute.test.ts[2m > [22mPOST /api/credit/lines/:id/suspend — business logic[2m > [22mresponse includes the full credit line object
[31m[1mAssertionError[22m: expected undefined to match object { id: 'line-abc', status: 'suspended' }[39m
[32m- Expected:[39m
{
"id": "line-abc",
"status": "suspended",
}
[31m+ Received:[39m
undefined
[36m [2m❯[22m src/__test__/creditRoute.test.ts:[2m133:27[22m[39m
[90m131|[39m [33m.[39m[35mset[39m([32m"x-admin-api-key"[39m[33m,[39m [33mADMIN_KEY[39m)[33m;[39m
[90m132|[39m
[90m133|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39mdata)[33m.[39m[34mtoMatchObject[39m({
[90m |[39m [31m^[39m
[90m134|[39m id[33m:[39m [33mVALID_ID[39m[33m,[39m
[90m135|[39m status[33m:[39m [32m"suspended"[39m[33m,[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[32/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/creditRoute.test.ts[2m > [22mPOST /api/credit/lines/:id/suspend — business logic[2m > [22mreturns 404 when the credit line does not exist
[31m[1mAssertionError[22m: expected 401 to be 404 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 404[39m
[31m+ 401[39m
[36m [2m❯[22m src/__test__/creditRoute.test.ts:[2m145:24[22m[39m
[90m143|[39m [33m.[39m[35mset[39m([32m"x-admin-api-key"[39m[33m,[39m [33mADMIN_KEY[39m)[33m;[39m
[90m144|[39m
[90m145|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m404[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m146|[39m [34mexpect[39m(res[33m.[39mbody[33m.[39merror)[33m.[39m[34mtoContain[39m([33mMISSING_ID[39m)[33m;[39m
[90m147|[39m })[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[33/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/creditRoute.test.ts[2m > [22mPOST /api/credit/lines/:id/suspend — business logic[2m > [22mreturns 409 when the line is already suspended
[31m[1mAssertionError[22m: expected 401 to be 409 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 409[39m
[31m+ 401[39m
[36m [2m❯[22m src/__test__/creditRoute.test.ts:[2m155:24[22m[39m
[90m153|[39m [33m.[39m[35mset[39m([32m"x-admin-api-key"[39m[33m,[39m [33mADMIN_KEY[39m)[33m;[39m
[90m154|[39m
[90m155|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m409[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m156|[39m expect(res.body.error).toMatch(/suspend.*suspended|suspended.*susp…
[90m157|[39m })[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[34/208]⎯[22m[39m
[41m[1m FAIL [22m[49m src/__test__/creditRoute.test.ts[2m > [22mPOST /api/credit/lines/:id/suspend — business logic[2m > [22mreturns 409 when the line is already closed
[31m[1mAssertionError[22m: expected 401 to be 409 // Object.is equality[39m
[32m- Expected[39m
[31m+ Received[39m
[32m- 409[39m
[31m+ 401[39m
[36m [2m❯[22m src/__test__/creditRoute.test.ts:[2m165:24[22m[39m
[90m163|[39m [33m.[39m[35mset[39m([32m"x-admin-api-key"[39m[33m,[39m [33mADMIN_KEY[39m)[33m;[39m
[90m164|[39m
[90m165|[39m [34mexpect[39m(res[33m.[39mstatus)[33m.[39m[34mtoBe[39m([34m409[39m)[33m;[39m
[90m |[39m [31m^[39m
[90m166|[39m })[33m;[39m
[90m167|[39m })[33m;[39m
[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[35/208]⎯[22m[39m