@usertour/helpers 0.0.34 → 0.0.36

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.
Files changed (36) hide show
  1. package/dist/__tests__/attribute.test.cjs +10 -1
  2. package/dist/__tests__/attribute.test.js +2 -1
  3. package/dist/__tests__/condition.test.cjs +1008 -21
  4. package/dist/__tests__/condition.test.js +902 -4
  5. package/dist/__tests__/get-attribute-type.test.cjs +195 -0
  6. package/dist/__tests__/get-attribute-type.test.d.cts +2 -0
  7. package/dist/__tests__/get-attribute-type.test.d.ts +2 -0
  8. package/dist/__tests__/get-attribute-type.test.js +133 -0
  9. package/dist/__tests__/time.test.cjs +482 -42
  10. package/dist/__tests__/time.test.js +349 -28
  11. package/dist/attribute.cjs +111 -0
  12. package/dist/attribute.d.cts +5 -0
  13. package/dist/attribute.d.ts +5 -0
  14. package/dist/attribute.js +12 -0
  15. package/dist/{chunk-A4KMGXB3.js → chunk-3UOSPZEP.js} +4 -4
  16. package/dist/chunk-EEYZG4JJ.js +78 -0
  17. package/dist/chunk-JQWKLXW6.js +147 -0
  18. package/dist/{chunk-7JXEY4A2.js → chunk-KYDXF7SU.js} +5 -1
  19. package/dist/conditions/attribute.cjs +10 -1
  20. package/dist/conditions/attribute.js +2 -1
  21. package/dist/conditions/condition.cjs +110 -20
  22. package/dist/conditions/condition.js +4 -3
  23. package/dist/conditions/index.cjs +152 -19
  24. package/dist/conditions/index.d.cts +1 -1
  25. package/dist/conditions/index.d.ts +1 -1
  26. package/dist/conditions/index.js +14 -5
  27. package/dist/conditions/time.cjs +150 -18
  28. package/dist/conditions/time.d.cts +29 -2
  29. package/dist/conditions/time.d.ts +29 -2
  30. package/dist/conditions/time.js +12 -3
  31. package/dist/index.cjs +209 -19
  32. package/dist/index.d.cts +2 -1
  33. package/dist/index.d.ts +2 -1
  34. package/dist/index.js +20 -4
  35. package/package.json +2 -2
  36. package/dist/chunk-CEK3SCQO.js +0 -31
@@ -2,11 +2,12 @@ import {
2
2
  evaluateRulesConditions,
3
3
  filterConditionsByType,
4
4
  isConditionsActived
5
- } from "../chunk-A4KMGXB3.js";
5
+ } from "../chunk-3UOSPZEP.js";
6
6
  import "../chunk-YYIGUZNZ.js";
7
7
  import "../chunk-PAESAL23.js";
8
- import "../chunk-7JXEY4A2.js";
9
- import "../chunk-CEK3SCQO.js";
8
+ import "../chunk-JQWKLXW6.js";
9
+ import "../chunk-KYDXF7SU.js";
10
+ import "../chunk-GFH3VWOC.js";
10
11
  import "../chunk-3KG2HTZ3.js";
11
12
  import "../chunk-XEO3YXBM.js";
12
13
 
@@ -230,7 +231,8 @@ describe("evaluateRulesConditions", () => {
230
231
  operators: "and",
231
232
  actived: false,
232
233
  data: {
233
- startDate: "2024-01-01",
234
+ startDate: "01/01/2024",
235
+ // MM/dd/yyyy format
234
236
  startDateHour: "00",
235
237
  startDateMinute: "00"
236
238
  }
@@ -372,6 +374,902 @@ describe("evaluateRulesConditions", () => {
372
374
  });
373
375
  expect(result[2].actived).toBe(true);
374
376
  });
377
+ test("should evaluate String type attribute conditions with all logic operators", async () => {
378
+ const conditions = [
379
+ {
380
+ id: "string-is",
381
+ type: "user-attr",
382
+ operators: "and",
383
+ actived: false,
384
+ data: {
385
+ attrId: "email",
386
+ logic: "is",
387
+ value: "user@example.com"
388
+ }
389
+ },
390
+ {
391
+ id: "string-not",
392
+ type: "user-attr",
393
+ operators: "and",
394
+ actived: false,
395
+ data: {
396
+ attrId: "name",
397
+ logic: "not",
398
+ value: "admin"
399
+ }
400
+ },
401
+ {
402
+ id: "string-contains",
403
+ type: "user-attr",
404
+ operators: "and",
405
+ actived: false,
406
+ data: {
407
+ attrId: "description",
408
+ logic: "contains",
409
+ value: "premium"
410
+ }
411
+ },
412
+ {
413
+ id: "string-notContain",
414
+ type: "user-attr",
415
+ operators: "and",
416
+ actived: false,
417
+ data: {
418
+ attrId: "title",
419
+ logic: "notContain",
420
+ value: "test"
421
+ }
422
+ },
423
+ {
424
+ id: "string-startsWith",
425
+ type: "user-attr",
426
+ operators: "and",
427
+ actived: false,
428
+ data: {
429
+ attrId: "path",
430
+ logic: "startsWith",
431
+ value: "/api"
432
+ }
433
+ },
434
+ {
435
+ id: "string-endsWith",
436
+ type: "user-attr",
437
+ operators: "and",
438
+ actived: false,
439
+ data: {
440
+ attrId: "filename",
441
+ logic: "endsWith",
442
+ value: ".pdf"
443
+ }
444
+ },
445
+ {
446
+ id: "string-empty",
447
+ type: "user-attr",
448
+ operators: "and",
449
+ actived: false,
450
+ data: {
451
+ attrId: "emptyString",
452
+ logic: "empty"
453
+ }
454
+ },
455
+ {
456
+ id: "string-any",
457
+ type: "user-attr",
458
+ operators: "and",
459
+ actived: false,
460
+ data: {
461
+ attrId: "hasString",
462
+ logic: "any"
463
+ }
464
+ }
465
+ ];
466
+ const options = {
467
+ clientContext: mockOptions.clientContext,
468
+ attributes: [
469
+ {
470
+ id: "email",
471
+ codeName: "email",
472
+ dataType: BizAttributeTypes.String,
473
+ bizType: AttributeBizTypes.User
474
+ },
475
+ {
476
+ id: "name",
477
+ codeName: "name",
478
+ dataType: BizAttributeTypes.String,
479
+ bizType: AttributeBizTypes.User
480
+ },
481
+ {
482
+ id: "description",
483
+ codeName: "description",
484
+ dataType: BizAttributeTypes.String,
485
+ bizType: AttributeBizTypes.User
486
+ },
487
+ {
488
+ id: "title",
489
+ codeName: "title",
490
+ dataType: BizAttributeTypes.String,
491
+ bizType: AttributeBizTypes.User
492
+ },
493
+ {
494
+ id: "path",
495
+ codeName: "path",
496
+ dataType: BizAttributeTypes.String,
497
+ bizType: AttributeBizTypes.User
498
+ },
499
+ {
500
+ id: "filename",
501
+ codeName: "filename",
502
+ dataType: BizAttributeTypes.String,
503
+ bizType: AttributeBizTypes.User
504
+ },
505
+ {
506
+ id: "emptyString",
507
+ codeName: "emptyString",
508
+ dataType: BizAttributeTypes.String,
509
+ bizType: AttributeBizTypes.User
510
+ },
511
+ {
512
+ id: "hasString",
513
+ codeName: "hasString",
514
+ dataType: BizAttributeTypes.String,
515
+ bizType: AttributeBizTypes.User
516
+ }
517
+ ],
518
+ userAttributes: {
519
+ email: "user@example.com",
520
+ name: "john",
521
+ description: "premium user account",
522
+ title: "Manager",
523
+ path: "/api/users",
524
+ filename: "document.pdf",
525
+ emptyString: "",
526
+ hasString: "some value"
527
+ },
528
+ typeControl: {
529
+ [RulesType.USER_ATTR]: true
530
+ }
531
+ };
532
+ const result = await evaluateRulesConditions(conditions, options);
533
+ expect(result[0].actived).toBe(true);
534
+ expect(result[1].actived).toBe(true);
535
+ expect(result[2].actived).toBe(true);
536
+ expect(result[3].actived).toBe(true);
537
+ expect(result[4].actived).toBe(true);
538
+ expect(result[5].actived).toBe(true);
539
+ expect(result[6].actived).toBe(true);
540
+ expect(result[7].actived).toBe(true);
541
+ });
542
+ test("should evaluate Number type attribute conditions with all logic operators", async () => {
543
+ const conditions = [
544
+ {
545
+ id: "number-is",
546
+ type: "user-attr",
547
+ operators: "and",
548
+ actived: false,
549
+ data: {
550
+ attrId: "age",
551
+ logic: "is",
552
+ value: 25
553
+ }
554
+ },
555
+ {
556
+ id: "number-not",
557
+ type: "user-attr",
558
+ operators: "and",
559
+ actived: false,
560
+ data: {
561
+ attrId: "age2",
562
+ logic: "not",
563
+ value: 30
564
+ }
565
+ },
566
+ {
567
+ id: "number-isLessThan",
568
+ type: "user-attr",
569
+ operators: "and",
570
+ actived: false,
571
+ data: {
572
+ attrId: "score",
573
+ logic: "isLessThan",
574
+ value: 100
575
+ }
576
+ },
577
+ {
578
+ id: "number-isLessThanOrEqualTo",
579
+ type: "user-attr",
580
+ operators: "and",
581
+ actived: false,
582
+ data: {
583
+ attrId: "score2",
584
+ logic: "isLessThanOrEqualTo",
585
+ value: 80
586
+ }
587
+ },
588
+ {
589
+ id: "number-isGreaterThan",
590
+ type: "user-attr",
591
+ operators: "and",
592
+ actived: false,
593
+ data: {
594
+ attrId: "score3",
595
+ logic: "isGreaterThan",
596
+ value: 50
597
+ }
598
+ },
599
+ {
600
+ id: "number-isGreaterThanOrEqualTo",
601
+ type: "user-attr",
602
+ operators: "and",
603
+ actived: false,
604
+ data: {
605
+ attrId: "score4",
606
+ logic: "isGreaterThanOrEqualTo",
607
+ value: 60
608
+ }
609
+ },
610
+ {
611
+ id: "number-between",
612
+ type: "user-attr",
613
+ operators: "and",
614
+ actived: false,
615
+ data: {
616
+ attrId: "price",
617
+ logic: "between",
618
+ value: 10,
619
+ value2: 100
620
+ }
621
+ },
622
+ {
623
+ id: "number-empty",
624
+ type: "user-attr",
625
+ operators: "and",
626
+ actived: false,
627
+ data: {
628
+ attrId: "emptyValue",
629
+ logic: "empty"
630
+ }
631
+ },
632
+ {
633
+ id: "number-any",
634
+ type: "user-attr",
635
+ operators: "and",
636
+ actived: false,
637
+ data: {
638
+ attrId: "hasValue",
639
+ logic: "any"
640
+ }
641
+ }
642
+ ];
643
+ const options = {
644
+ clientContext: mockOptions.clientContext,
645
+ attributes: [
646
+ {
647
+ id: "age",
648
+ codeName: "age",
649
+ dataType: BizAttributeTypes.Number,
650
+ bizType: AttributeBizTypes.User
651
+ },
652
+ {
653
+ id: "age2",
654
+ codeName: "age2",
655
+ dataType: BizAttributeTypes.Number,
656
+ bizType: AttributeBizTypes.User
657
+ },
658
+ {
659
+ id: "score",
660
+ codeName: "score",
661
+ dataType: BizAttributeTypes.Number,
662
+ bizType: AttributeBizTypes.User
663
+ },
664
+ {
665
+ id: "score2",
666
+ codeName: "score2",
667
+ dataType: BizAttributeTypes.Number,
668
+ bizType: AttributeBizTypes.User
669
+ },
670
+ {
671
+ id: "score3",
672
+ codeName: "score3",
673
+ dataType: BizAttributeTypes.Number,
674
+ bizType: AttributeBizTypes.User
675
+ },
676
+ {
677
+ id: "score4",
678
+ codeName: "score4",
679
+ dataType: BizAttributeTypes.Number,
680
+ bizType: AttributeBizTypes.User
681
+ },
682
+ {
683
+ id: "price",
684
+ codeName: "price",
685
+ dataType: BizAttributeTypes.Number,
686
+ bizType: AttributeBizTypes.User
687
+ },
688
+ {
689
+ id: "emptyValue",
690
+ codeName: "emptyValue",
691
+ dataType: BizAttributeTypes.Number,
692
+ bizType: AttributeBizTypes.User
693
+ },
694
+ {
695
+ id: "hasValue",
696
+ codeName: "hasValue",
697
+ dataType: BizAttributeTypes.Number,
698
+ bizType: AttributeBizTypes.User
699
+ }
700
+ ],
701
+ userAttributes: {
702
+ age: 25,
703
+ age2: 25,
704
+ score: 90,
705
+ score2: 80,
706
+ score3: 70,
707
+ score4: 60,
708
+ price: 50,
709
+ emptyValue: null,
710
+ hasValue: 42
711
+ },
712
+ typeControl: {
713
+ [RulesType.USER_ATTR]: true
714
+ }
715
+ };
716
+ const result = await evaluateRulesConditions(conditions, options);
717
+ expect(result[0].actived).toBe(true);
718
+ expect(result[1].actived).toBe(true);
719
+ expect(result[2].actived).toBe(true);
720
+ expect(result[3].actived).toBe(true);
721
+ expect(result[4].actived).toBe(true);
722
+ expect(result[5].actived).toBe(true);
723
+ expect(result[6].actived).toBe(true);
724
+ expect(result[7].actived).toBe(true);
725
+ expect(result[8].actived).toBe(true);
726
+ });
727
+ test("should evaluate Boolean type attribute conditions with all logic operators", async () => {
728
+ const conditions = [
729
+ {
730
+ id: "bool-true",
731
+ type: "user-attr",
732
+ operators: "and",
733
+ actived: false,
734
+ data: {
735
+ attrId: "isVip",
736
+ logic: "true"
737
+ }
738
+ },
739
+ {
740
+ id: "bool-false",
741
+ type: "user-attr",
742
+ operators: "and",
743
+ actived: false,
744
+ data: {
745
+ attrId: "isActive",
746
+ logic: "false"
747
+ }
748
+ },
749
+ {
750
+ id: "bool-empty",
751
+ type: "user-attr",
752
+ operators: "and",
753
+ actived: false,
754
+ data: {
755
+ attrId: "emptyBool",
756
+ logic: "empty"
757
+ }
758
+ },
759
+ {
760
+ id: "bool-any",
761
+ type: "user-attr",
762
+ operators: "and",
763
+ actived: false,
764
+ data: {
765
+ attrId: "hasBool",
766
+ logic: "any"
767
+ }
768
+ }
769
+ ];
770
+ const options = {
771
+ clientContext: mockOptions.clientContext,
772
+ attributes: [
773
+ {
774
+ id: "isVip",
775
+ codeName: "isVip",
776
+ dataType: BizAttributeTypes.Boolean,
777
+ bizType: AttributeBizTypes.User
778
+ },
779
+ {
780
+ id: "isActive",
781
+ codeName: "isActive",
782
+ dataType: BizAttributeTypes.Boolean,
783
+ bizType: AttributeBizTypes.User
784
+ },
785
+ {
786
+ id: "emptyBool",
787
+ codeName: "emptyBool",
788
+ dataType: BizAttributeTypes.Boolean,
789
+ bizType: AttributeBizTypes.User
790
+ },
791
+ {
792
+ id: "hasBool",
793
+ codeName: "hasBool",
794
+ dataType: BizAttributeTypes.Boolean,
795
+ bizType: AttributeBizTypes.User
796
+ }
797
+ ],
798
+ userAttributes: {
799
+ isVip: true,
800
+ isActive: false,
801
+ emptyBool: null,
802
+ hasBool: true
803
+ },
804
+ typeControl: {
805
+ [RulesType.USER_ATTR]: true
806
+ }
807
+ };
808
+ const result = await evaluateRulesConditions(conditions, options);
809
+ expect(result[0].actived).toBe(true);
810
+ expect(result[1].actived).toBe(true);
811
+ expect(result[2].actived).toBe(true);
812
+ expect(result[3].actived).toBe(true);
813
+ });
814
+ test("should evaluate List type attribute conditions with all logic operators", async () => {
815
+ const conditions = [
816
+ {
817
+ id: "list-includesAtLeastOne",
818
+ type: "user-attr",
819
+ operators: "and",
820
+ actived: false,
821
+ data: {
822
+ attrId: "tags",
823
+ logic: "includesAtLeastOne",
824
+ listValues: ["premium", "vip"]
825
+ }
826
+ },
827
+ {
828
+ id: "list-includesAll",
829
+ type: "user-attr",
830
+ operators: "and",
831
+ actived: false,
832
+ data: {
833
+ attrId: "roles",
834
+ logic: "includesAll",
835
+ listValues: ["admin", "editor"]
836
+ }
837
+ },
838
+ {
839
+ id: "list-notIncludesAtLeastOne",
840
+ type: "user-attr",
841
+ operators: "and",
842
+ actived: false,
843
+ data: {
844
+ attrId: "permissions",
845
+ logic: "notIncludesAtLeastOne",
846
+ listValues: ["delete", "modify"]
847
+ }
848
+ },
849
+ {
850
+ id: "list-notIncludesAll",
851
+ type: "user-attr",
852
+ operators: "and",
853
+ actived: false,
854
+ data: {
855
+ attrId: "categories",
856
+ logic: "notIncludesAll",
857
+ listValues: ["tech", "finance"]
858
+ }
859
+ },
860
+ {
861
+ id: "list-empty",
862
+ type: "user-attr",
863
+ operators: "and",
864
+ actived: false,
865
+ data: {
866
+ attrId: "emptyList",
867
+ logic: "empty"
868
+ }
869
+ },
870
+ {
871
+ id: "list-any",
872
+ type: "user-attr",
873
+ operators: "and",
874
+ actived: false,
875
+ data: {
876
+ attrId: "hasList",
877
+ logic: "any"
878
+ }
879
+ }
880
+ ];
881
+ const options = {
882
+ clientContext: mockOptions.clientContext,
883
+ attributes: [
884
+ {
885
+ id: "tags",
886
+ codeName: "tags",
887
+ dataType: BizAttributeTypes.List,
888
+ bizType: AttributeBizTypes.User
889
+ },
890
+ {
891
+ id: "roles",
892
+ codeName: "roles",
893
+ dataType: BizAttributeTypes.List,
894
+ bizType: AttributeBizTypes.User
895
+ },
896
+ {
897
+ id: "permissions",
898
+ codeName: "permissions",
899
+ dataType: BizAttributeTypes.List,
900
+ bizType: AttributeBizTypes.User
901
+ },
902
+ {
903
+ id: "categories",
904
+ codeName: "categories",
905
+ dataType: BizAttributeTypes.List,
906
+ bizType: AttributeBizTypes.User
907
+ },
908
+ {
909
+ id: "emptyList",
910
+ codeName: "emptyList",
911
+ dataType: BizAttributeTypes.List,
912
+ bizType: AttributeBizTypes.User
913
+ },
914
+ {
915
+ id: "hasList",
916
+ codeName: "hasList",
917
+ dataType: BizAttributeTypes.List,
918
+ bizType: AttributeBizTypes.User
919
+ }
920
+ ],
921
+ userAttributes: {
922
+ tags: ["premium", "basic"],
923
+ roles: ["admin", "editor", "viewer"],
924
+ permissions: ["read", "write"],
925
+ categories: ["other"],
926
+ emptyList: [],
927
+ hasList: ["item1", "item2"]
928
+ },
929
+ typeControl: {
930
+ [RulesType.USER_ATTR]: true
931
+ }
932
+ };
933
+ const result = await evaluateRulesConditions(conditions, options);
934
+ expect(result[0].actived).toBe(true);
935
+ expect(result[1].actived).toBe(true);
936
+ expect(result[2].actived).toBe(true);
937
+ expect(result[3].actived).toBe(true);
938
+ expect(result[4].actived).toBe(true);
939
+ expect(result[5].actived).toBe(true);
940
+ });
941
+ test("should evaluate DateTime type attribute conditions with all logic operators", async () => {
942
+ const now = /* @__PURE__ */ new Date();
943
+ const fiveDaysAgo = new Date(now.getTime() - 5 * 24 * 60 * 60 * 1e3);
944
+ const tenDaysAgo = new Date(now.getTime() - 10 * 24 * 60 * 60 * 1e3);
945
+ const threeDaysAgo = new Date(now.getTime() - 3 * 24 * 60 * 60 * 1e3);
946
+ const fifteenDaysAgo = new Date(now.getTime() - 15 * 24 * 60 * 60 * 1e3);
947
+ const futureDate = new Date(now.getTime() + 5 * 24 * 60 * 60 * 1e3);
948
+ const conditions = [
949
+ {
950
+ id: "datetime-lessThan",
951
+ type: "user-attr",
952
+ operators: "and",
953
+ actived: false,
954
+ data: {
955
+ attrId: "lastLogin",
956
+ logic: "lessThan",
957
+ value: 7
958
+ }
959
+ },
960
+ {
961
+ id: "datetime-exactly",
962
+ type: "user-attr",
963
+ operators: "and",
964
+ actived: false,
965
+ data: {
966
+ attrId: "exactDate",
967
+ logic: "exactly",
968
+ value: 3
969
+ }
970
+ },
971
+ {
972
+ id: "datetime-moreThan",
973
+ type: "user-attr",
974
+ operators: "and",
975
+ actived: false,
976
+ data: {
977
+ attrId: "oldDate",
978
+ logic: "moreThan",
979
+ value: 7
980
+ }
981
+ },
982
+ {
983
+ id: "datetime-before",
984
+ type: "user-attr",
985
+ operators: "and",
986
+ actived: false,
987
+ data: {
988
+ attrId: "createdAt",
989
+ logic: "before",
990
+ value: now.toISOString()
991
+ }
992
+ },
993
+ {
994
+ id: "datetime-on",
995
+ type: "user-attr",
996
+ operators: "and",
997
+ actived: false,
998
+ data: {
999
+ attrId: "onDate",
1000
+ logic: "on",
1001
+ value: threeDaysAgo.toISOString()
1002
+ }
1003
+ },
1004
+ {
1005
+ id: "datetime-after",
1006
+ type: "user-attr",
1007
+ operators: "and",
1008
+ actived: false,
1009
+ data: {
1010
+ attrId: "futureDate",
1011
+ logic: "after",
1012
+ value: now.toISOString()
1013
+ }
1014
+ },
1015
+ {
1016
+ id: "datetime-empty",
1017
+ type: "user-attr",
1018
+ operators: "and",
1019
+ actived: false,
1020
+ data: {
1021
+ attrId: "emptyDate",
1022
+ logic: "empty"
1023
+ }
1024
+ },
1025
+ {
1026
+ id: "datetime-any",
1027
+ type: "user-attr",
1028
+ operators: "and",
1029
+ actived: false,
1030
+ data: {
1031
+ attrId: "hasDate",
1032
+ logic: "any"
1033
+ }
1034
+ }
1035
+ ];
1036
+ const options = {
1037
+ clientContext: mockOptions.clientContext,
1038
+ attributes: [
1039
+ {
1040
+ id: "lastLogin",
1041
+ codeName: "lastLogin",
1042
+ dataType: BizAttributeTypes.DateTime,
1043
+ bizType: AttributeBizTypes.User
1044
+ },
1045
+ {
1046
+ id: "exactDate",
1047
+ codeName: "exactDate",
1048
+ dataType: BizAttributeTypes.DateTime,
1049
+ bizType: AttributeBizTypes.User
1050
+ },
1051
+ {
1052
+ id: "oldDate",
1053
+ codeName: "oldDate",
1054
+ dataType: BizAttributeTypes.DateTime,
1055
+ bizType: AttributeBizTypes.User
1056
+ },
1057
+ {
1058
+ id: "createdAt",
1059
+ codeName: "createdAt",
1060
+ dataType: BizAttributeTypes.DateTime,
1061
+ bizType: AttributeBizTypes.User
1062
+ },
1063
+ {
1064
+ id: "onDate",
1065
+ codeName: "onDate",
1066
+ dataType: BizAttributeTypes.DateTime,
1067
+ bizType: AttributeBizTypes.User
1068
+ },
1069
+ {
1070
+ id: "futureDate",
1071
+ codeName: "futureDate",
1072
+ dataType: BizAttributeTypes.DateTime,
1073
+ bizType: AttributeBizTypes.User
1074
+ },
1075
+ {
1076
+ id: "emptyDate",
1077
+ codeName: "emptyDate",
1078
+ dataType: BizAttributeTypes.DateTime,
1079
+ bizType: AttributeBizTypes.User
1080
+ },
1081
+ {
1082
+ id: "hasDate",
1083
+ codeName: "hasDate",
1084
+ dataType: BizAttributeTypes.DateTime,
1085
+ bizType: AttributeBizTypes.User
1086
+ }
1087
+ ],
1088
+ userAttributes: {
1089
+ lastLogin: fiveDaysAgo.toISOString(),
1090
+ exactDate: threeDaysAgo.toISOString(),
1091
+ oldDate: fifteenDaysAgo.toISOString(),
1092
+ createdAt: tenDaysAgo.toISOString(),
1093
+ onDate: threeDaysAgo.toISOString(),
1094
+ futureDate: futureDate.toISOString(),
1095
+ emptyDate: "",
1096
+ hasDate: fiveDaysAgo.toISOString()
1097
+ },
1098
+ typeControl: {
1099
+ [RulesType.USER_ATTR]: true
1100
+ }
1101
+ };
1102
+ const result = await evaluateRulesConditions(conditions, options);
1103
+ expect(result[0].actived).toBe(true);
1104
+ expect(result[1].actived).toBe(true);
1105
+ expect(result[2].actived).toBe(true);
1106
+ expect(result[3].actived).toBe(true);
1107
+ expect(result[4].actived).toBe(true);
1108
+ expect(result[5].actived).toBe(true);
1109
+ expect(result[6].actived).toBe(false);
1110
+ expect(result[7].actived).toBe(true);
1111
+ });
1112
+ test("should evaluate mixed attribute type conditions correctly", async () => {
1113
+ const conditions = [
1114
+ {
1115
+ id: "mixed-1",
1116
+ type: "user-attr",
1117
+ operators: "and",
1118
+ actived: false,
1119
+ data: {
1120
+ attrId: "email",
1121
+ logic: "is",
1122
+ value: "user@example.com"
1123
+ }
1124
+ },
1125
+ {
1126
+ id: "mixed-2",
1127
+ type: "user-attr",
1128
+ operators: "and",
1129
+ actived: false,
1130
+ data: {
1131
+ attrId: "age",
1132
+ logic: "isGreaterThan",
1133
+ value: 18
1134
+ }
1135
+ },
1136
+ {
1137
+ id: "mixed-3",
1138
+ type: "user-attr",
1139
+ operators: "and",
1140
+ actived: false,
1141
+ data: {
1142
+ attrId: "isVip",
1143
+ logic: "true"
1144
+ }
1145
+ },
1146
+ {
1147
+ id: "mixed-4",
1148
+ type: "user-attr",
1149
+ operators: "and",
1150
+ actived: false,
1151
+ data: {
1152
+ attrId: "tags",
1153
+ logic: "includesAtLeastOne",
1154
+ listValues: ["premium"]
1155
+ }
1156
+ }
1157
+ ];
1158
+ const options = {
1159
+ clientContext: mockOptions.clientContext,
1160
+ attributes: [
1161
+ {
1162
+ id: "email",
1163
+ codeName: "email",
1164
+ dataType: BizAttributeTypes.String,
1165
+ bizType: AttributeBizTypes.User
1166
+ },
1167
+ {
1168
+ id: "age",
1169
+ codeName: "age",
1170
+ dataType: BizAttributeTypes.Number,
1171
+ bizType: AttributeBizTypes.User
1172
+ },
1173
+ {
1174
+ id: "isVip",
1175
+ codeName: "isVip",
1176
+ dataType: BizAttributeTypes.Boolean,
1177
+ bizType: AttributeBizTypes.User
1178
+ },
1179
+ {
1180
+ id: "tags",
1181
+ codeName: "tags",
1182
+ dataType: BizAttributeTypes.List,
1183
+ bizType: AttributeBizTypes.User
1184
+ }
1185
+ ],
1186
+ userAttributes: {
1187
+ email: "user@example.com",
1188
+ age: 25,
1189
+ isVip: true,
1190
+ tags: ["premium", "basic"]
1191
+ },
1192
+ typeControl: {
1193
+ [RulesType.USER_ATTR]: true
1194
+ }
1195
+ };
1196
+ const result = await evaluateRulesConditions(conditions, options);
1197
+ expect(result[0].actived).toBe(true);
1198
+ expect(result[1].actived).toBe(true);
1199
+ expect(result[2].actived).toBe(true);
1200
+ expect(result[3].actived).toBe(true);
1201
+ });
1202
+ test("should evaluate mixed attribute types with OR logic correctly", async () => {
1203
+ const conditions = [
1204
+ {
1205
+ id: "or-1",
1206
+ type: "user-attr",
1207
+ operators: "or",
1208
+ actived: false,
1209
+ data: {
1210
+ attrId: "email",
1211
+ logic: "is",
1212
+ value: "wrong@example.com"
1213
+ }
1214
+ },
1215
+ {
1216
+ id: "or-2",
1217
+ type: "user-attr",
1218
+ operators: "or",
1219
+ actived: false,
1220
+ data: {
1221
+ attrId: "age",
1222
+ logic: "isGreaterThan",
1223
+ value: 18
1224
+ }
1225
+ },
1226
+ {
1227
+ id: "or-3",
1228
+ type: "user-attr",
1229
+ operators: "or",
1230
+ actived: false,
1231
+ data: {
1232
+ attrId: "isVip",
1233
+ logic: "false"
1234
+ }
1235
+ }
1236
+ ];
1237
+ const options = {
1238
+ clientContext: mockOptions.clientContext,
1239
+ attributes: [
1240
+ {
1241
+ id: "email",
1242
+ codeName: "email",
1243
+ dataType: BizAttributeTypes.String,
1244
+ bizType: AttributeBizTypes.User
1245
+ },
1246
+ {
1247
+ id: "age",
1248
+ codeName: "age",
1249
+ dataType: BizAttributeTypes.Number,
1250
+ bizType: AttributeBizTypes.User
1251
+ },
1252
+ {
1253
+ id: "isVip",
1254
+ codeName: "isVip",
1255
+ dataType: BizAttributeTypes.Boolean,
1256
+ bizType: AttributeBizTypes.User
1257
+ }
1258
+ ],
1259
+ userAttributes: {
1260
+ email: "user@example.com",
1261
+ age: 25,
1262
+ isVip: true
1263
+ },
1264
+ typeControl: {
1265
+ [RulesType.USER_ATTR]: true
1266
+ }
1267
+ };
1268
+ const result = await evaluateRulesConditions(conditions, options);
1269
+ expect(result[0].actived).toBe(false);
1270
+ expect(result[1].actived).toBe(true);
1271
+ expect(result[2].actived).toBe(false);
1272
+ });
375
1273
  test("should handle rules without ID", async () => {
376
1274
  const conditions = [
377
1275
  {