@capillarytech/creatives-library 9.0.29 → 9.0.31

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 (147) hide show
  1. package/constants/unified.js +29 -0
  2. package/global-styles.js +1 -1
  3. package/package.json +1 -1
  4. package/services/tests/api.test.js +35 -20
  5. package/utils/commonUtils.js +22 -1
  6. package/utils/rcsPayloadUtils.js +102 -0
  7. package/utils/templateVarUtils.js +198 -0
  8. package/utils/tests/rcsPayloadUtils.test.js +295 -0
  9. package/utils/tests/templateVarUtils.test.js +204 -0
  10. package/v2Components/CapActionButton/constants.js +21 -1
  11. package/v2Components/CapActionButton/index.js +261 -144
  12. package/v2Components/CapActionButton/index.scss +245 -14
  13. package/v2Components/CapActionButton/messages.js +32 -3
  14. package/v2Components/CapActionButton/tests/index.test.js +74 -19
  15. package/v2Components/CapImageUpload/index.js +2 -2
  16. package/v2Components/CapTagList/index.js +9 -0
  17. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -48
  18. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
  19. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +214 -21
  20. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
  21. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +83 -9
  22. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
  23. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +58 -11
  24. package/v2Components/CommonTestAndPreview/SendTestMessage.js +10 -5
  25. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +186 -22
  26. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +381 -80
  27. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +155 -8
  28. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +11 -0
  29. package/v2Components/CommonTestAndPreview/constants.js +35 -2
  30. package/v2Components/CommonTestAndPreview/index.js +774 -231
  31. package/v2Components/CommonTestAndPreview/messages.js +45 -3
  32. package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  33. package/v2Components/CommonTestAndPreview/sagas.js +25 -6
  34. package/v2Components/CommonTestAndPreview/tests/CommonTestAndPreview.addTestCustomer.test.js +1 -0
  35. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +412 -257
  36. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +337 -63
  37. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
  38. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
  39. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
  40. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +108 -15
  41. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
  42. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
  43. package/v2Components/CommonTestAndPreview/tests/index.test.js +133 -4
  44. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  45. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +31 -24
  46. package/v2Components/CommonTestAndPreview/tests/utils.test.js +151 -0
  47. package/v2Components/CommonTestAndPreview/utils.js +84 -0
  48. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +91 -0
  49. package/v2Components/SmsFallback/constants.js +94 -0
  50. package/v2Components/SmsFallback/index.js +958 -0
  51. package/v2Components/SmsFallback/index.scss +266 -0
  52. package/v2Components/SmsFallback/messages.js +78 -0
  53. package/v2Components/SmsFallback/smsFallbackUtils.js +120 -0
  54. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  55. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  56. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  57. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +208 -0
  58. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +309 -0
  59. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +471 -0
  60. package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  61. package/v2Components/TemplatePreview/_templatePreview.scss +45 -25
  62. package/v2Components/TemplatePreview/constants.js +2 -0
  63. package/v2Components/TemplatePreview/index.js +147 -32
  64. package/v2Components/TemplatePreview/tests/index.test.js +142 -0
  65. package/v2Components/TestAndPreviewSlidebox/CustomValuesEditor.js +6 -6
  66. package/v2Components/TestAndPreviewSlidebox/index.js +13 -1
  67. package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  68. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  69. package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  70. package/v2Components/VarSegmentMessageEditor/index.js +125 -0
  71. package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  72. package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +4 -1
  73. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +4 -0
  74. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +20 -20
  75. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +27 -0
  76. package/v2Containers/CreativesContainer/SlideBoxContent.js +37 -4
  77. package/v2Containers/CreativesContainer/SlideBoxFooter.js +14 -5
  78. package/v2Containers/CreativesContainer/SlideBoxHeader.js +36 -5
  79. package/v2Containers/CreativesContainer/constants.js +11 -0
  80. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +77 -0
  81. package/v2Containers/CreativesContainer/index.js +322 -106
  82. package/v2Containers/CreativesContainer/index.scss +102 -1
  83. package/v2Containers/CreativesContainer/tests/CreativesSlideBoxWrapper.test.js +58 -0
  84. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  85. package/v2Containers/CreativesContainer/tests/SlideBoxContent.smsDltPreview.test.js +73 -0
  86. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +37 -0
  87. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +103 -34
  88. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +193 -15
  89. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +88 -0
  90. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +549 -57
  91. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -15
  92. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  93. package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  94. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  95. package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
  96. package/v2Containers/Rcs/carouselUtils.js +224 -0
  97. package/v2Containers/Rcs/components/CarouselCard.js +317 -0
  98. package/v2Containers/Rcs/components/CarouselCardButtons.js +113 -0
  99. package/v2Containers/Rcs/components/CarouselCardMedia.js +136 -0
  100. package/v2Containers/Rcs/components/CarouselCharacterCount.js +31 -0
  101. package/v2Containers/Rcs/components/CarouselDimensionSelection.js +80 -0
  102. package/v2Containers/Rcs/constants.js +132 -16
  103. package/v2Containers/Rcs/index.js +1822 -946
  104. package/v2Containers/Rcs/index.scss +443 -8
  105. package/v2Containers/Rcs/messages.js +45 -22
  106. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +494 -0
  107. package/v2Containers/Rcs/tests/CarouselCard.test.js +464 -0
  108. package/v2Containers/Rcs/tests/CarouselCardButtons.test.js +211 -0
  109. package/v2Containers/Rcs/tests/CarouselCardMedia.test.js +160 -0
  110. package/v2Containers/Rcs/tests/CarouselCharacterCount.test.js +50 -0
  111. package/v2Containers/Rcs/tests/CarouselDimensionSelection.test.js +119 -0
  112. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +74440 -39387
  113. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +10 -74
  114. package/v2Containers/Rcs/tests/carouselUtils.test.js +916 -0
  115. package/v2Containers/Rcs/tests/index.test.js +275 -40
  116. package/v2Containers/Rcs/tests/mockData.js +38 -0
  117. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +912 -0
  118. package/v2Containers/Rcs/tests/utils.test.js +682 -30
  119. package/v2Containers/Rcs/utils.js +514 -12
  120. package/v2Containers/Sms/Create/index.js +115 -48
  121. package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  122. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  123. package/v2Containers/SmsTrai/Create/index.js +9 -4
  124. package/v2Containers/SmsTrai/Edit/constants.js +2 -0
  125. package/v2Containers/SmsTrai/Edit/index.js +678 -169
  126. package/v2Containers/SmsTrai/Edit/index.scss +126 -0
  127. package/v2Containers/SmsTrai/Edit/messages.js +14 -4
  128. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +5615 -3014
  129. package/v2Containers/SmsWrapper/index.js +37 -8
  130. package/v2Containers/TagList/index.js +5 -0
  131. package/v2Containers/Templates/TemplatesActionBar.js +101 -0
  132. package/v2Containers/Templates/_templates.scss +196 -12
  133. package/v2Containers/Templates/actions.js +11 -0
  134. package/v2Containers/Templates/constants.js +2 -0
  135. package/v2Containers/Templates/index.js +131 -59
  136. package/v2Containers/Templates/sagas.js +57 -13
  137. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +129 -0
  138. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1060 -1015
  139. package/v2Containers/Templates/tests/sagas.test.js +199 -16
  140. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  141. package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  142. package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  143. package/v2Containers/TemplatesV2/index.js +88 -25
  144. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  145. package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -9
  146. package/v2Containers/Whatsapp/index.js +3 -20
  147. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
@@ -187,7 +187,7 @@ describe('ModifyDeliverySettings', () => {
187
187
  const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
188
188
 
189
189
  renderComponent({
190
- channel: 'RCS',
190
+ channel: 'UNSUPPORTED_CHANNEL',
191
191
  onSaveDeliverySettings: onSave,
192
192
  });
193
193
 
@@ -468,6 +468,31 @@ describe('ModifyDeliverySettings', () => {
468
468
  const domainOptions = Array.from(getSelects()[0].querySelectorAll('option')).map((opt) => opt.textContent);
469
469
  expect(domainOptions).not.toEqual(expect.arrayContaining(['Domain One']));
470
470
  });
471
+
472
+ it('should keep full domain list when TRAI DLT is enabled but no sender IDs are registered', () => {
473
+ renderComponent({
474
+ channel: CHANNELS.SMS,
475
+ senderDetailsOptions: [
476
+ {
477
+ domainId: 11,
478
+ domainName: 'Domain One',
479
+ gsmSenders: [{ value: 'ID1' }],
480
+ cdmaSenders: [],
481
+ },
482
+ {
483
+ domainId: 22,
484
+ domainName: 'Domain Two',
485
+ gsmSenders: [{ value: 'ID2' }],
486
+ cdmaSenders: [],
487
+ },
488
+ ],
489
+ smsTraiDltEnabled: true,
490
+ registeredSenderIds: [],
491
+ });
492
+
493
+ const domainOptions = Array.from(getSelects()[0].querySelectorAll('option')).map((opt) => opt.textContent);
494
+ expect(domainOptions).toEqual(expect.arrayContaining(['Domain One', 'Domain Two']));
495
+ });
471
496
  });
472
497
 
473
498
  describe('EMAIL flow', () => {
@@ -614,6 +639,22 @@ describe('ModifyDeliverySettings', () => {
614
639
  expect(senderNameOptions).toEqual(expect.arrayContaining(['fallback@test.com']));
615
640
  expect(replyToOptions).toEqual(expect.arrayContaining(['Reply Label']));
616
641
  });
642
+
643
+ it('should use reply-to label when value is empty in reply-to options', () => {
644
+ renderComponent({
645
+ channel: CHANNELS.EMAIL,
646
+ senderDetailsOptions: [{
647
+ domainId: 90,
648
+ domainName: 'Reply Label Domain',
649
+ emailSenders: [{ value: 'a@test.com' }],
650
+ emailRepliers: [{ label: 'OnlyLabel', value: '' }],
651
+ }],
652
+ deliverySettings: { domainId: 90, domainGatewayMapId: 1 },
653
+ });
654
+
655
+ const replyToOptions = Array.from(getSelects()[3].querySelectorAll('option')).map((opt) => opt.textContent);
656
+ expect(replyToOptions).toEqual(expect.arrayContaining(['OnlyLabel']));
657
+ });
617
658
  });
618
659
 
619
660
  describe('WHATSAPP flow', () => {
@@ -838,6 +879,19 @@ describe('ModifyDeliverySettings', () => {
838
879
  sourceAccountIdentifier: 'waba-1',
839
880
  });
840
881
  });
882
+
883
+ it('should render disabled CapLabel with label3 for locked WhatsApp account row', () => {
884
+ renderComponent({
885
+ channel: CHANNELS.WHATSAPP,
886
+ senderDetailsOptions: whatsappDomains,
887
+ wecrmAccounts,
888
+ whatsappAccountFromForm: { accountName: 'Account One' },
889
+ });
890
+
891
+ const labels = screen.getAllByTestId('cap-label');
892
+ const disabledHint = labels.find((el) => el.getAttribute('data-type') === 'label3');
893
+ expect(disabledHint).toBeTruthy();
894
+ });
841
895
  });
842
896
 
843
897
  describe('Done and close handling', () => {
@@ -886,105 +940,325 @@ describe('ModifyDeliverySettings', () => {
886
940
  });
887
941
  });
888
942
 
889
- describe('onDomainChange — dgmId edge cases', () => {
890
- it('should not update domainGatewayMapId when selected SMS domain has no dgmId', () => {
943
+ describe('RCS flow', () => {
944
+ const rcsDomains = [
945
+ {
946
+ domainId: 51,
947
+ domainName: 'RCS Domain A',
948
+ dgmId: 511,
949
+ gsmSenders: [{ value: 'RCS_GSM_1' }, { value: 'RCS_GSM_2' }],
950
+ },
951
+ {
952
+ domainId: 52,
953
+ domainName: 'RCS Domain B',
954
+ dgmId: 522,
955
+ gsmSenders: [{ value: 'RCS_OTHER' }],
956
+ },
957
+ ];
958
+
959
+ const smsFallbackDomains = [
960
+ {
961
+ domainId: 61,
962
+ domainName: 'SMS Fallback',
963
+ gsmSenders: [{ value: 'SMS_FB_1' }],
964
+ },
965
+ ];
966
+
967
+ it('should render RCS domain and sender selects', () => {
968
+ renderComponent({
969
+ channel: CHANNELS.RCS,
970
+ senderDetailsOptions: rcsDomains,
971
+ });
972
+ expect(getSelects()).toHaveLength(2);
973
+ });
974
+
975
+ it('should set composite gsm sender id when RCS domain changes', () => {
891
976
  const onSave = jest.fn();
892
977
 
893
978
  renderComponent({
894
- channel: CHANNELS.SMS,
895
- senderDetailsOptions: [
896
- {
897
- domainId: 99,
898
- domainName: 'No DGM Domain',
899
- // dgmId intentionally absent
900
- gsmSenders: [{ value: 'GSM_99', default: true }],
901
- cdmaSenders: [{ value: 'CDMA_99', default: true }],
902
- },
903
- ],
979
+ channel: CHANNELS.RCS,
980
+ senderDetailsOptions: rcsDomains,
981
+ onSaveDeliverySettings: onSave,
982
+ });
983
+
984
+ fireEvent.change(getSelects()[0], { target: { value: '51' } });
985
+ fireEvent.click(screen.getByText('Done'));
986
+
987
+ expect(onSave).toHaveBeenCalledWith(
988
+ expect.objectContaining({
989
+ domainId: 51,
990
+ gsmSenderId: '51|RCS_GSM_1',
991
+ }),
992
+ );
993
+ });
994
+
995
+ it('should render SMS fallback domain and sender when fallback options exist', () => {
996
+ renderComponent({
997
+ channel: CHANNELS.RCS,
998
+ senderDetailsOptions: rcsDomains,
999
+ smsFallbackSenderDetailsOptions: smsFallbackDomains,
1000
+ });
1001
+ expect(getSelects()).toHaveLength(4);
1002
+ });
1003
+
1004
+ it('should strip gsm and fallback sender ids that are not in current options on Done', () => {
1005
+ const onSave = jest.fn();
1006
+
1007
+ renderComponent({
1008
+ channel: CHANNELS.RCS,
1009
+ senderDetailsOptions: rcsDomains,
1010
+ smsFallbackSenderDetailsOptions: smsFallbackDomains,
904
1011
  deliverySettings: {
905
- domainId: null,
906
- domainGatewayMapId: 555,
1012
+ domainId: 51,
1013
+ gsmSenderId: 'not-a-valid-composite',
1014
+ smsFallbackDomainId: 61,
1015
+ cdmaSenderId: '61|SMS_FB_1',
1016
+ },
1017
+ onSaveDeliverySettings: onSave,
1018
+ });
1019
+
1020
+ fireEvent.click(screen.getByText('Done'));
1021
+
1022
+ expect(onSave).toHaveBeenCalledWith(
1023
+ expect.objectContaining({
1024
+ domainId: 51,
907
1025
  gsmSenderId: '',
1026
+ smsFallbackDomainId: 61,
1027
+ cdmaSenderId: '61|SMS_FB_1',
1028
+ }),
1029
+ );
1030
+ });
1031
+
1032
+ it('should strip invalid SMS fallback composite sender on Done', () => {
1033
+ const onSave = jest.fn();
1034
+
1035
+ renderComponent({
1036
+ channel: CHANNELS.RCS,
1037
+ senderDetailsOptions: rcsDomains,
1038
+ smsFallbackSenderDetailsOptions: smsFallbackDomains,
1039
+ deliverySettings: {
1040
+ domainId: 51,
1041
+ gsmSenderId: '51|RCS_GSM_1',
1042
+ smsFallbackDomainId: 61,
1043
+ cdmaSenderId: 'bogus|value',
1044
+ },
1045
+ onSaveDeliverySettings: onSave,
1046
+ });
1047
+
1048
+ fireEvent.click(screen.getByText('Done'));
1049
+
1050
+ expect(onSave).toHaveBeenCalledWith(
1051
+ expect.objectContaining({
1052
+ gsmSenderId: '51|RCS_GSM_1',
908
1053
  cdmaSenderId: '',
1054
+ }),
1055
+ );
1056
+ });
1057
+
1058
+ it('should filter SMS fallback domains and GSM senders when TRAI DLT and registered sender IDs apply', () => {
1059
+ const fallbackDlt = [
1060
+ {
1061
+ domainId: 71,
1062
+ domainName: 'Has Registered GSM',
1063
+ gsmSenders: [{ value: 'REG_OK' }, { value: 'NOT_ON_DLT' }],
1064
+ },
1065
+ {
1066
+ domainId: 72,
1067
+ domainName: 'No Match',
1068
+ gsmSenders: [{ value: 'UNMATCHED' }],
1069
+ },
1070
+ ];
1071
+ const onSave = jest.fn();
1072
+
1073
+ renderComponent({
1074
+ channel: CHANNELS.RCS,
1075
+ senderDetailsOptions: rcsDomains,
1076
+ smsFallbackSenderDetailsOptions: fallbackDlt,
1077
+ smsTraiDltEnabled: true,
1078
+ registeredSenderIds: ['REG_OK'],
1079
+ deliverySettings: {
1080
+ domainId: 51,
1081
+ gsmSenderId: '51|RCS_GSM_1',
1082
+ smsFallbackDomainId: 71,
1083
+ cdmaSenderId: '71|REG_OK',
909
1084
  },
910
1085
  onSaveDeliverySettings: onSave,
911
1086
  });
912
1087
 
913
- fireEvent.change(getSelects()[0], { target: { value: '99' } });
914
1088
  fireEvent.click(screen.getByText('Done'));
915
1089
 
916
- expect(onSave).toHaveBeenCalledWith({
917
- domainId: 99,
918
- domainGatewayMapId: 555, // unchanged — domain has no dgmId
919
- gsmSenderId: 'GSM_99',
920
- cdmaSenderId: 'CDMA_99',
1090
+ expect(onSave).toHaveBeenCalledWith(
1091
+ expect.objectContaining({
1092
+ smsFallbackDomainId: 71,
1093
+ cdmaSenderId: '71|REG_OK',
1094
+ }),
1095
+ );
1096
+ });
1097
+
1098
+ it('should set SMS fallback composite to first GSM after skipping domain-name echo row', () => {
1099
+ const fallbackEcho = [
1100
+ {
1101
+ domainId: 80,
1102
+ domainName: 'Echo',
1103
+ gsmSenders: [{ value: 'Echo' }, { value: 'REAL_SENDER' }],
1104
+ },
1105
+ ];
1106
+ const onSave = jest.fn();
1107
+
1108
+ renderComponent({
1109
+ channel: CHANNELS.RCS,
1110
+ senderDetailsOptions: rcsDomains,
1111
+ smsFallbackSenderDetailsOptions: fallbackEcho,
1112
+ deliverySettings: {
1113
+ domainId: 51,
1114
+ gsmSenderId: '51|RCS_GSM_1',
1115
+ },
1116
+ onSaveDeliverySettings: onSave,
921
1117
  });
1118
+
1119
+ fireEvent.change(getSelects()[2], { target: { value: '80' } });
1120
+ fireEvent.click(screen.getByText('Done'));
1121
+
1122
+ expect(onSave).toHaveBeenCalledWith(
1123
+ expect.objectContaining({
1124
+ smsFallbackDomainId: 80,
1125
+ cdmaSenderId: '80|REAL_SENDER',
1126
+ }),
1127
+ );
922
1128
  });
923
1129
 
924
- it('should not update domainGatewayMapId when selected EMAIL domain has no dgmId', () => {
1130
+ it('should only list RCS sender options for the selected RCS domain', () => {
925
1131
  const onSave = jest.fn();
926
1132
 
927
1133
  renderComponent({
928
- channel: CHANNELS.EMAIL,
929
- senderDetailsOptions: [
930
- {
931
- domainId: 55,
932
- domainName: 'No DGM Email Domain',
933
- // no dgmId
934
- emailSenders: [{ value: 'sender@test.com', label: 'Sender', default: true }],
935
- emailRepliers: [{ value: 'reply@test.com', default: true }],
936
- },
937
- ],
1134
+ channel: CHANNELS.RCS,
1135
+ senderDetailsOptions: rcsDomains,
1136
+ onSaveDeliverySettings: onSave,
938
1137
  deliverySettings: {
939
- domainId: null,
940
- domainGatewayMapId: 777,
941
- senderEmail: '',
942
- senderLabel: '',
943
- senderReplyTo: '',
1138
+ domainId: 52,
1139
+ gsmSenderId: '52|RCS_OTHER',
1140
+ },
1141
+ });
1142
+
1143
+ fireEvent.click(screen.getByText('Done'));
1144
+
1145
+ expect(onSave).toHaveBeenCalledWith(
1146
+ expect.objectContaining({
1147
+ domainId: 52,
1148
+ gsmSenderId: '52|RCS_OTHER',
1149
+ }),
1150
+ );
1151
+ });
1152
+
1153
+ it('should set composite RCS gsm when domain id is numeric zero', () => {
1154
+ const rcsWithZero = [
1155
+ {
1156
+ domainId: 0,
1157
+ domainName: 'Zero Id',
1158
+ dgmId: 1,
1159
+ gsmSenders: [{ value: 'Z_GSM' }],
944
1160
  },
1161
+ ];
1162
+ const onSave = jest.fn();
1163
+
1164
+ renderComponent({
1165
+ channel: CHANNELS.RCS,
1166
+ senderDetailsOptions: rcsWithZero,
945
1167
  onSaveDeliverySettings: onSave,
946
1168
  });
947
1169
 
948
- fireEvent.change(getSelects()[0], { target: { value: '55' } });
1170
+ fireEvent.change(getSelects()[0], { target: { value: '0' } });
949
1171
  fireEvent.click(screen.getByText('Done'));
950
1172
 
951
- expect(onSave).toHaveBeenCalledWith({
952
- domainId: 55,
953
- domainGatewayMapId: 777, // unchanged — domain has no dgmId
954
- senderEmail: 'sender@test.com',
955
- senderLabel: 'Sender',
956
- senderReplyTo: 'reply@test.com',
1173
+ expect(onSave).toHaveBeenCalledWith(
1174
+ expect.objectContaining({
1175
+ domainId: 0,
1176
+ gsmSenderId: '0|Z_GSM',
1177
+ }),
1178
+ );
1179
+ });
1180
+
1181
+ it('should update RCS sender id directly when sender select changes', () => {
1182
+ const onSave = jest.fn();
1183
+
1184
+ renderComponent({
1185
+ channel: CHANNELS.RCS,
1186
+ senderDetailsOptions: rcsDomains,
1187
+ onSaveDeliverySettings: onSave,
1188
+ deliverySettings: {
1189
+ domainId: 51,
1190
+ gsmSenderId: '51|RCS_GSM_1',
1191
+ },
957
1192
  });
1193
+
1194
+ fireEvent.change(getSelects()[1], { target: { value: '51|RCS_GSM_2' } });
1195
+ fireEvent.click(screen.getByText('Done'));
1196
+
1197
+ expect(onSave).toHaveBeenCalledWith(
1198
+ expect.objectContaining({
1199
+ gsmSenderId: '51|RCS_GSM_2',
1200
+ }),
1201
+ );
958
1202
  });
959
- });
960
1203
 
961
- describe('findDefault fallback first item used when no default:true', () => {
962
- it('should use first gsm/cdma sender when none has default:true flag', () => {
1204
+ it('should update SMS fallback sender id directly when fallback sender select changes', () => {
963
1205
  const onSave = jest.fn();
964
1206
 
965
1207
  renderComponent({
966
- channel: CHANNELS.SMS,
967
- senderDetailsOptions: [
968
- {
969
- domainId: 77,
970
- domainName: 'No Default Domain',
971
- dgmId: 777,
972
- gsmSenders: [{ value: 'FIRST_GSM' }, { value: 'SECOND_GSM' }],
973
- cdmaSenders: [{ value: 'FIRST_CDMA' }, { value: 'SECOND_CDMA' }],
974
- },
975
- ],
1208
+ channel: CHANNELS.RCS,
1209
+ senderDetailsOptions: rcsDomains,
1210
+ smsFallbackSenderDetailsOptions: smsFallbackDomains,
976
1211
  onSaveDeliverySettings: onSave,
1212
+ deliverySettings: {
1213
+ domainId: 51,
1214
+ gsmSenderId: '51|RCS_GSM_1',
1215
+ smsFallbackDomainId: 61,
1216
+ cdmaSenderId: '61|SMS_FB_1',
1217
+ },
977
1218
  });
978
1219
 
979
- fireEvent.change(getSelects()[0], { target: { value: '77' } });
1220
+ fireEvent.change(getSelects()[3], { target: { value: '61|SMS_FB_1' } });
980
1221
  fireEvent.click(screen.getByText('Done'));
981
1222
 
982
- expect(onSave).toHaveBeenCalledWith({
983
- domainId: 77,
984
- domainGatewayMapId: 777,
985
- gsmSenderId: 'FIRST_GSM',
986
- cdmaSenderId: 'FIRST_CDMA',
1223
+ expect(onSave).toHaveBeenCalledWith(
1224
+ expect.objectContaining({
1225
+ cdmaSenderId: '61|SMS_FB_1',
1226
+ }),
1227
+ );
1228
+ });
1229
+
1230
+ it('should filter fallback GSM senders by registered sender IDs when changing SMS fallback domain in TRAI DLT mode', () => {
1231
+ const fallbackDlt = [
1232
+ {
1233
+ domainId: 90,
1234
+ domainName: 'Fallback DLT Domain',
1235
+ gsmSenders: [{ value: 'REG_SENDER' }, { value: 'UNREG_SENDER' }],
1236
+ },
1237
+ ];
1238
+ const onSave = jest.fn();
1239
+
1240
+ renderComponent({
1241
+ channel: CHANNELS.RCS,
1242
+ senderDetailsOptions: rcsDomains,
1243
+ smsFallbackSenderDetailsOptions: fallbackDlt,
1244
+ smsTraiDltEnabled: true,
1245
+ registeredSenderIds: ['REG_SENDER'],
1246
+ deliverySettings: {
1247
+ domainId: 51,
1248
+ gsmSenderId: '51|RCS_GSM_1',
1249
+ },
1250
+ onSaveDeliverySettings: onSave,
987
1251
  });
1252
+
1253
+ fireEvent.change(getSelects()[2], { target: { value: '90' } });
1254
+ fireEvent.click(screen.getByText('Done'));
1255
+
1256
+ expect(onSave).toHaveBeenCalledWith(
1257
+ expect.objectContaining({
1258
+ smsFallbackDomainId: 90,
1259
+ cdmaSenderId: '90|REG_SENDER',
1260
+ }),
1261
+ );
988
1262
  });
989
1263
  });
990
1264
  });
@@ -40,7 +40,7 @@ describe('DeliverySettings', () => {
40
40
  const defaultProps = {
41
41
  channel: CHANNELS.SMS,
42
42
  deliverySettings: {},
43
- senderDetailsOptions: [],
43
+ senderDetailsByChannel: {},
44
44
  wecrmAccounts: [],
45
45
  onSaveDeliverySettings: jest.fn(),
46
46
  isLoadingSenderDetails: false,
@@ -85,14 +85,14 @@ describe('DeliverySettings', () => {
85
85
  });
86
86
 
87
87
  it('should show summary values for SMS when deliverySettings and senderDetailsOptions match', () => {
88
- const senderDetailsOptions = [{ domainId: 1, domainName: 'SMS Domain' }];
88
+ const senderDetailsByChannel = { [CHANNELS.SMS]: [{ domainId: 1, domainName: 'SMS Domain' }] };
89
89
  const deliverySettings = { domainId: 1, gsmSenderId: 'SENDER1' };
90
90
  render(
91
91
  <DeliverySettings
92
92
  {...defaultProps}
93
93
  channel={CHANNELS.SMS}
94
94
  deliverySettings={deliverySettings}
95
- senderDetailsOptions={senderDetailsOptions}
95
+ senderDetailsByChannel={senderDetailsByChannel}
96
96
  />
97
97
  );
98
98
  expect(screen.getAllByText(/SMS Domain/).length).toBeGreaterThan(0);
@@ -105,7 +105,7 @@ describe('DeliverySettings', () => {
105
105
  });
106
106
 
107
107
  it('should show summary for EMAIL when has domain and sender', () => {
108
- const senderDetailsOptions = [{ domainId: 2, domainName: 'Email Domain' }];
108
+ const senderDetailsByChannel = { [CHANNELS.EMAIL]: [{ domainId: 2, domainName: 'Email Domain' }] };
109
109
  const deliverySettings = {
110
110
  domainId: 2,
111
111
  senderEmail: 'noreply@test.com',
@@ -117,7 +117,7 @@ describe('DeliverySettings', () => {
117
117
  {...defaultProps}
118
118
  channel={CHANNELS.EMAIL}
119
119
  deliverySettings={deliverySettings}
120
- senderDetailsOptions={senderDetailsOptions}
120
+ senderDetailsByChannel={senderDetailsByChannel}
121
121
  />
122
122
  );
123
123
  expect(screen.getAllByText(/Email Domain/).length).toBeGreaterThan(0);
@@ -141,6 +141,76 @@ describe('DeliverySettings', () => {
141
141
  expect(screen.getAllByText(/WABA One/).length).toBeGreaterThan(0);
142
142
  expect(screen.getAllByText(/\+1234567890/).length).toBeGreaterThan(0);
143
143
  });
144
+
145
+ it('RCS: when isChannelSmsFallbackPreviewEnabled is false, summary omits fallback SMS sender even if cdma is set', () => {
146
+ const rcsDomain = {
147
+ domainId: 10,
148
+ domainName: 'RCS D',
149
+ gsmSenders: [{ value: 'R1', default: true }],
150
+ };
151
+ const smsDomain = {
152
+ domainId: 20,
153
+ domainName: 'SMS D',
154
+ gsmSenders: [{ value: 'F1', default: true }],
155
+ };
156
+ const senderDetailsByChannel = {
157
+ [CHANNELS.RCS]: [rcsDomain],
158
+ [CHANNELS.SMS]: [smsDomain],
159
+ };
160
+ const deliverySettings = {
161
+ gsmSenderId: '10|R1',
162
+ cdmaSenderId: '20|F1',
163
+ };
164
+ render(
165
+ <IntlProvider locale="en" messages={{}}>
166
+ <DeliverySettings
167
+ {...defaultProps}
168
+ channel={CHANNELS.RCS}
169
+ deliverySettings={deliverySettings}
170
+ senderDetailsByChannel={senderDetailsByChannel}
171
+ isChannelSmsFallbackPreviewEnabled={false}
172
+ formatMessage={(m) => m?.defaultMessage || m?.id || ''}
173
+ />
174
+ </IntlProvider>,
175
+ );
176
+ expect(screen.getAllByText(/R1/).length).toBeGreaterThan(0);
177
+ expect(screen.queryByText(/F1/)).toBeNull();
178
+ });
179
+
180
+ it('RCS: when isChannelSmsFallbackPreviewEnabled is true, summary includes fallback SMS sender', () => {
181
+ const rcsDomain = {
182
+ domainId: 10,
183
+ domainName: 'RCS D',
184
+ gsmSenders: [{ value: 'R1', default: true }],
185
+ };
186
+ const smsDomain = {
187
+ domainId: 20,
188
+ domainName: 'SMS D',
189
+ gsmSenders: [{ value: 'F1', default: true }],
190
+ };
191
+ const senderDetailsByChannel = {
192
+ [CHANNELS.RCS]: [rcsDomain],
193
+ [CHANNELS.SMS]: [smsDomain],
194
+ };
195
+ const deliverySettings = {
196
+ gsmSenderId: '10|R1',
197
+ cdmaSenderId: '20|F1',
198
+ };
199
+ render(
200
+ <IntlProvider locale="en" messages={{}}>
201
+ <DeliverySettings
202
+ {...defaultProps}
203
+ channel={CHANNELS.RCS}
204
+ deliverySettings={deliverySettings}
205
+ senderDetailsByChannel={senderDetailsByChannel}
206
+ isChannelSmsFallbackPreviewEnabled
207
+ formatMessage={(m) => m?.defaultMessage || m?.id || ''}
208
+ />
209
+ </IntlProvider>,
210
+ );
211
+ expect(screen.getAllByText(/R1/).length).toBeGreaterThan(0);
212
+ expect(screen.getAllByText(/F1/).length).toBeGreaterThan(0);
213
+ });
144
214
  });
145
215
 
146
216
  describe('edit and slidebox', () => {
@@ -169,6 +239,49 @@ describe('DeliverySettings', () => {
169
239
  );
170
240
  });
171
241
 
242
+ it('RCS: should not pass smsFallbackSenderDetailsOptions when isChannelSmsFallbackPreviewEnabled is false', () => {
243
+ render(
244
+ <DeliverySettings
245
+ {...defaultProps}
246
+ channel={CHANNELS.RCS}
247
+ senderDetailsByChannel={{
248
+ [CHANNELS.RCS]: [{ domainId: 1, domainName: 'R', gsmSenders: [] }],
249
+ [CHANNELS.SMS]: [{ domainId: 2, domainName: 'S', gsmSenders: [] }],
250
+ }}
251
+ isChannelSmsFallbackPreviewEnabled={false}
252
+ />,
253
+ );
254
+ fireEvent.click(screen.getByTestId('delivery-settings-edit'));
255
+ expect(mockModifyDeliverySettings).toHaveBeenCalledWith(
256
+ expect.objectContaining({
257
+ channel: CHANNELS.RCS,
258
+ smsFallbackSenderDetailsOptions: undefined,
259
+ }),
260
+ );
261
+ });
262
+
263
+ it('RCS: should pass smsFallbackSenderDetailsOptions when isChannelSmsFallbackPreviewEnabled is true', () => {
264
+ const smsDomains = [{ domainId: 2, domainName: 'S', gsmSenders: [] }];
265
+ render(
266
+ <DeliverySettings
267
+ {...defaultProps}
268
+ channel={CHANNELS.RCS}
269
+ senderDetailsByChannel={{
270
+ [CHANNELS.RCS]: [{ domainId: 1, domainName: 'R', gsmSenders: [] }],
271
+ [CHANNELS.SMS]: smsDomains,
272
+ }}
273
+ isChannelSmsFallbackPreviewEnabled
274
+ />,
275
+ );
276
+ fireEvent.click(screen.getByTestId('delivery-settings-edit'));
277
+ expect(mockModifyDeliverySettings).toHaveBeenCalledWith(
278
+ expect.objectContaining({
279
+ channel: CHANNELS.RCS,
280
+ smsFallbackSenderDetailsOptions: smsDomains,
281
+ }),
282
+ );
283
+ });
284
+
172
285
  it('should call onSaveDeliverySettings and close slidebox when Done is clicked', () => {
173
286
  const onSave = jest.fn();
174
287
  render(