cap-creatives-ui 8.0.280 → 8.0.321

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 (247) hide show
  1. package/.github/workflows/pr-title-check.yml +88 -0
  2. package/app/constants/unified.js +21 -1
  3. package/app/containers/App/constants.js +0 -1
  4. package/app/containers/Login/test/index.test.js +123 -0
  5. package/app/containers/Login/test/selectors.test.js +165 -0
  6. package/app/initialState.js +0 -2
  7. package/app/services/api.js +6 -0
  8. package/app/services/tests/api.test.js +7 -0
  9. package/app/services/tests/getSchema.test.js +95 -0
  10. package/app/utils/common.js +23 -9
  11. package/app/utils/commonUtils.js +64 -93
  12. package/app/utils/tagValidations.js +83 -219
  13. package/app/utils/templateVarUtils.js +172 -0
  14. package/app/utils/tests/common.test.js +265 -323
  15. package/app/utils/tests/commonUtil.test.js +461 -118
  16. package/app/utils/tests/commonUtils.test.js +581 -0
  17. package/app/utils/tests/messageUtils.test.js +95 -0
  18. package/app/utils/tests/smsCharCount.test.js +304 -0
  19. package/app/utils/tests/smsCharCountV2.test.js +213 -10
  20. package/app/utils/tests/tagValidations.test.js +474 -357
  21. package/app/utils/tests/templateVarUtils.test.js +160 -0
  22. package/app/v2Components/CapDeviceContent/index.js +10 -7
  23. package/app/v2Components/CapTagList/index.js +32 -24
  24. package/app/v2Components/CapTagList/style.scss +48 -0
  25. package/app/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
  26. package/app/v2Components/CapTagListWithInput/index.js +8 -0
  27. package/app/v2Components/CapWhatsappCTA/index.js +2 -0
  28. package/app/v2Components/CapWhatsappCarouselButton/index.js +32 -14
  29. package/app/v2Components/CapWhatsappCarouselButton/tests/index.test.js +120 -2
  30. package/app/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
  31. package/app/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +39 -0
  32. package/app/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +606 -0
  33. package/app/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.scss +36 -0
  34. package/app/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +79 -0
  35. package/app/v2Components/CommonTestAndPreview/DeliverySettings/index.js +314 -0
  36. package/app/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +141 -0
  37. package/app/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +156 -0
  38. package/app/v2Components/CommonTestAndPreview/SendTestMessage.js +57 -1
  39. package/app/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
  40. package/app/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
  41. package/app/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +210 -4
  42. package/app/v2Components/CommonTestAndPreview/actions.js +20 -0
  43. package/app/v2Components/CommonTestAndPreview/constants.js +57 -1
  44. package/app/v2Components/CommonTestAndPreview/index.js +878 -156
  45. package/app/v2Components/CommonTestAndPreview/messages.js +41 -3
  46. package/app/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  47. package/app/v2Components/CommonTestAndPreview/reducer.js +47 -0
  48. package/app/v2Components/CommonTestAndPreview/sagas.js +75 -5
  49. package/app/v2Components/CommonTestAndPreview/selectors.js +51 -0
  50. package/app/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +352 -0
  51. package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +1156 -0
  52. package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +334 -0
  53. package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +576 -0
  54. package/app/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +156 -0
  55. package/app/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
  56. package/app/v2Components/CommonTestAndPreview/tests/actions.test.js +50 -0
  57. package/app/v2Components/CommonTestAndPreview/tests/constants.test.js +18 -7
  58. package/app/v2Components/CommonTestAndPreview/tests/index.test.js +914 -5
  59. package/app/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  60. package/app/v2Components/CommonTestAndPreview/tests/reducer.test.js +118 -0
  61. package/app/v2Components/CommonTestAndPreview/tests/sagas.test.js +146 -378
  62. package/app/v2Components/CommonTestAndPreview/tests/selectors.test.js +146 -0
  63. package/app/v2Components/ErrorInfoNote/index.js +24 -26
  64. package/app/v2Components/FormBuilder/index.js +182 -204
  65. package/app/v2Components/FormBuilder/messages.js +4 -8
  66. package/app/v2Components/HtmlEditor/HTMLEditor.js +7 -6
  67. package/app/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -1
  68. package/app/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +928 -17
  69. package/app/v2Components/HtmlEditor/components/CodeEditorPane/index.js +4 -2
  70. package/app/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +452 -3
  71. package/app/v2Components/HtmlEditor/hooks/useValidation.js +12 -9
  72. package/app/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +132 -0
  73. package/app/v2Components/HtmlEditor/utils/htmlValidator.js +4 -2
  74. package/app/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
  75. package/app/v2Components/SmsFallback/constants.js +73 -0
  76. package/app/v2Components/SmsFallback/index.js +956 -0
  77. package/app/v2Components/SmsFallback/index.scss +265 -0
  78. package/app/v2Components/SmsFallback/messages.js +78 -0
  79. package/app/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
  80. package/app/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  81. package/app/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  82. package/app/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  83. package/app/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
  84. package/app/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
  85. package/app/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  86. package/app/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  87. package/app/v2Components/TestAndPreviewSlidebox/index.js +22 -1
  88. package/app/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  89. package/app/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  90. package/app/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  91. package/app/v2Components/VarSegmentMessageEditor/index.js +125 -0
  92. package/app/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  93. package/app/v2Containers/BeeEditor/index.js +3 -0
  94. package/app/v2Containers/BeePopupEditor/index.js +9 -2
  95. package/app/v2Containers/Cap/mockData.js +0 -14
  96. package/app/v2Containers/Cap/reducer.js +3 -55
  97. package/app/v2Containers/Cap/tests/reducer.test.js +0 -102
  98. package/app/v2Containers/CommunicationFlow/CommunicationFlow.js +291 -0
  99. package/app/v2Containers/CommunicationFlow/CommunicationFlow.scss +25 -0
  100. package/app/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +255 -0
  101. package/app/v2Containers/CommunicationFlow/constants.js +200 -0
  102. package/app/v2Containers/CommunicationFlow/index.js +102 -0
  103. package/app/v2Containers/CommunicationFlow/messages.js +346 -0
  104. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +522 -0
  105. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +170 -0
  106. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +796 -0
  107. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/index.js +5 -0
  108. package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/CommunicationStrategyStep.js +95 -0
  109. package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/Tests/CommunicationStrategyStep.test.js +133 -0
  110. package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/index.js +5 -0
  111. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +289 -0
  112. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.scss +70 -0
  113. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +319 -0
  114. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.scss +69 -0
  115. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +616 -0
  116. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +577 -0
  117. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +1111 -0
  118. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +696 -0
  119. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/index.js +7 -0
  120. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.js +102 -0
  121. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.scss +36 -0
  122. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/Tests/DynamicControlsStep.test.js +91 -0
  123. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/index.js +5 -0
  124. package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/MessageTypeStep.js +86 -0
  125. package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/Tests/MessageTypeStep.test.js +100 -0
  126. package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/index.js +5 -0
  127. package/app/v2Containers/CommunicationFlow/utils/getEnabledSteps.js +30 -0
  128. package/app/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  129. package/app/v2Containers/CreativesContainer/SlideBoxContent.js +127 -11
  130. package/app/v2Containers/CreativesContainer/SlideBoxFooter.js +62 -9
  131. package/app/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  132. package/app/v2Containers/CreativesContainer/constants.js +24 -0
  133. package/app/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
  134. package/app/v2Containers/CreativesContainer/index.js +346 -71
  135. package/app/v2Containers/CreativesContainer/index.scss +51 -1
  136. package/app/v2Containers/CreativesContainer/messages.js +12 -0
  137. package/app/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  138. package/app/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +69 -1
  139. package/app/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +443 -0
  140. package/app/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
  141. package/app/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +147 -4
  142. package/app/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
  143. package/app/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +57 -10
  144. package/app/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  145. package/app/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  146. package/app/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  147. package/app/v2Containers/Email/index.js +2 -5
  148. package/app/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +58 -77
  149. package/app/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
  150. package/app/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +158 -89
  151. package/app/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
  152. package/app/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +17 -12
  153. package/app/v2Containers/EmailWrapper/index.js +4 -0
  154. package/app/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
  155. package/app/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +133 -0
  156. package/app/v2Containers/FTP/index.js +2 -51
  157. package/app/v2Containers/FTP/messages.js +0 -4
  158. package/app/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +110 -155
  159. package/app/v2Containers/InApp/index.js +297 -118
  160. package/app/v2Containers/InApp/tests/index.test.js +17 -6
  161. package/app/v2Containers/InApp/tests/mockData.js +1 -1
  162. package/app/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +19 -0
  163. package/app/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +3 -0
  164. package/app/v2Containers/InAppWrapper/index.js +3 -0
  165. package/app/v2Containers/InappAdvance/index.js +5 -104
  166. package/app/v2Containers/InappAdvance/tests/index.test.js +2 -0
  167. package/app/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +24 -3
  168. package/app/v2Containers/Line/Container/Text/index.js +0 -1
  169. package/app/v2Containers/MobilePush/Create/index.js +105 -28
  170. package/app/v2Containers/MobilePush/Create/messages.js +4 -0
  171. package/app/v2Containers/MobilePush/Edit/index.js +250 -68
  172. package/app/v2Containers/MobilePush/Edit/messages.js +4 -0
  173. package/app/v2Containers/MobilePushNew/components/PlatformContentFields.js +36 -12
  174. package/app/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +68 -27
  175. package/app/v2Containers/MobilePushNew/index.js +78 -35
  176. package/app/v2Containers/MobilePushNew/messages.js +8 -0
  177. package/app/v2Containers/MobilepushWrapper/index.js +11 -1
  178. package/app/v2Containers/Rcs/constants.js +32 -1
  179. package/app/v2Containers/Rcs/index.js +963 -916
  180. package/app/v2Containers/Rcs/index.scss +85 -6
  181. package/app/v2Containers/Rcs/messages.js +10 -1
  182. package/app/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
  183. package/app/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +41136 -1566
  184. package/app/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  185. package/app/v2Containers/Rcs/tests/index.test.js +41 -38
  186. package/app/v2Containers/Rcs/tests/mockData.js +38 -0
  187. package/app/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
  188. package/app/v2Containers/Rcs/tests/utils.test.js +379 -1
  189. package/app/v2Containers/Rcs/utils.js +358 -10
  190. package/app/v2Containers/Sms/Create/index.js +122 -39
  191. package/app/v2Containers/Sms/Create/messages.js +4 -0
  192. package/app/v2Containers/Sms/Edit/index.js +37 -3
  193. package/app/v2Containers/Sms/commonMethods.js +3 -6
  194. package/app/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  195. package/app/v2Containers/Sms/tests/commonMethods.test.js +122 -0
  196. package/app/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  197. package/app/v2Containers/SmsTrai/Create/index.js +9 -4
  198. package/app/v2Containers/SmsTrai/Create/index.scss +1 -1
  199. package/app/v2Containers/SmsTrai/Edit/constants.js +2 -0
  200. package/app/v2Containers/SmsTrai/Edit/index.js +667 -160
  201. package/app/v2Containers/SmsTrai/Edit/index.scss +121 -0
  202. package/app/v2Containers/SmsTrai/Edit/messages.js +9 -4
  203. package/app/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4590 -2436
  204. package/app/v2Containers/SmsWrapper/index.js +41 -8
  205. package/app/v2Containers/TagList/index.js +63 -2
  206. package/app/v2Containers/TagList/messages.js +8 -0
  207. package/app/v2Containers/TagList/tests/TagList.test.js +122 -20
  208. package/app/v2Containers/TagList/tests/mockdata.js +17 -0
  209. package/app/v2Containers/Templates/TemplatesActionBar.js +101 -0
  210. package/app/v2Containers/Templates/_templates.scss +61 -2
  211. package/app/v2Containers/Templates/actions.js +11 -0
  212. package/app/v2Containers/Templates/constants.js +2 -0
  213. package/app/v2Containers/Templates/index.js +90 -40
  214. package/app/v2Containers/Templates/reducer.js +3 -1
  215. package/app/v2Containers/Templates/sagas.js +57 -12
  216. package/app/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  217. package/app/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
  218. package/app/v2Containers/Templates/tests/reducer.test.js +12 -0
  219. package/app/v2Containers/Templates/tests/sagas.test.js +193 -12
  220. package/app/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  221. package/app/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  222. package/app/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  223. package/app/v2Containers/TemplatesV2/index.js +147 -49
  224. package/app/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  225. package/app/v2Containers/Viber/index.js +9 -10
  226. package/app/v2Containers/Viber/index.scss +1 -1
  227. package/app/v2Containers/WebPush/Create/components/BrandIconSection.test.js +264 -0
  228. package/app/v2Containers/WebPush/Create/components/MessageSection.js +78 -19
  229. package/app/v2Containers/WebPush/Create/components/MessageSection.test.js +82 -0
  230. package/app/v2Containers/WebPush/Create/components/__snapshots__/BrandIconSection.test.js.snap +187 -0
  231. package/app/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +25 -17
  232. package/app/v2Containers/WebPush/Create/hooks/useAiraTriggerPosition.js +80 -0
  233. package/app/v2Containers/WebPush/Create/hooks/useAiraTriggerPosition.test.js +210 -0
  234. package/app/v2Containers/WebPush/Create/hooks/useTagManagement.js +1 -5
  235. package/app/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -7
  236. package/app/v2Containers/WebPush/Create/index.js +36 -6
  237. package/app/v2Containers/WebPush/Create/index.scss +5 -0
  238. package/app/v2Containers/WebPush/Create/messages.js +8 -1
  239. package/app/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +269 -0
  240. package/app/v2Containers/WebPush/Create/utils/validation.js +31 -15
  241. package/app/v2Containers/WebPush/Create/utils/validation.test.js +72 -24
  242. package/app/v2Containers/Whatsapp/index.js +28 -53
  243. package/app/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +26939 -3982
  244. package/app/v2Containers/Whatsapp/tests/index.test.js +172 -0
  245. package/app/v2Containers/Zalo/index.js +5 -11
  246. package/package.json +2 -2
  247. package/version +9 -0
@@ -1076,6 +1076,138 @@ line4`;
1076
1076
  expect(result).toBeDefined();
1077
1077
  expect(Array.isArray(result.warnings)).toBe(true);
1078
1078
  });
1079
+
1080
+ it('routes warning-severity issues to warnings array — exact item check (line 112-113)', () => {
1081
+ // Mock HTMLHint to return an issue with a warningRule ruleId
1082
+ // getSeverityLevel('error', 'tag-pair') → 'warning' (warningRules match)
1083
+ const htmlhint = require('htmlhint');
1084
+ const original = htmlhint.HTMLHint.verify;
1085
+ htmlhint.HTMLHint.verify = jest.fn(() => ([
1086
+ {
1087
+ type: 'error',
1088
+ message: 'Tag must be paired',
1089
+ line: 1,
1090
+ col: 5,
1091
+ rule: { id: 'tag-pair' },
1092
+ },
1093
+ ]));
1094
+
1095
+ const result = validateHTML('<p>unclosed');
1096
+
1097
+ expect(result.warnings.length).toBeGreaterThanOrEqual(1);
1098
+ const item = result.warnings.find((w) => w.rule === 'tag-pair');
1099
+ expect(item).toBeDefined();
1100
+ expect(item.severity).toBe('warning');
1101
+
1102
+ htmlhint.HTMLHint.verify = original;
1103
+ });
1104
+
1105
+ it('routes info-severity issues to info array — exact item check (line 114-115)', () => {
1106
+ // getSeverityLevel('warning', 'space-tab-mixed-disabled') → 'info'
1107
+ // (not in warningRules, type !== 'error')
1108
+ const htmlhint = require('htmlhint');
1109
+ const original = htmlhint.HTMLHint.verify;
1110
+ htmlhint.HTMLHint.verify = jest.fn(() => ([
1111
+ {
1112
+ type: 'warning',
1113
+ message: 'Mixed spaces and tabs',
1114
+ line: 1,
1115
+ col: 1,
1116
+ rule: { id: 'space-tab-mixed-disabled' },
1117
+ },
1118
+ ]));
1119
+
1120
+ const result = validateHTML('<div>test</div>');
1121
+
1122
+ expect(result.info.length).toBeGreaterThanOrEqual(1);
1123
+ const item = result.info.find((i) => i.rule === 'space-tab-mixed-disabled');
1124
+ expect(item).toBeDefined();
1125
+ expect(item.severity).toBe('info');
1126
+
1127
+ htmlhint.HTMLHint.verify = original;
1128
+ });
1129
+
1130
+ it('downgrades HTMLHint error type to warning for non-warningRule (line 163-164) — exact item check', () => {
1131
+ // getSeverityLevel('error', 'src-not-empty') → 'warning' (not in warningRules, but type === 'error')
1132
+ const htmlhint = require('htmlhint');
1133
+ const original = htmlhint.HTMLHint.verify;
1134
+ htmlhint.HTMLHint.verify = jest.fn(() => ([
1135
+ {
1136
+ type: 'error',
1137
+ message: 'The src attribute cannot be empty',
1138
+ line: 1,
1139
+ col: 1,
1140
+ rule: { id: 'src-not-empty' },
1141
+ },
1142
+ ]));
1143
+
1144
+ const result = validateHTML('<img src="">');
1145
+
1146
+ // Should be downgraded to warning (not error)
1147
+ expect(result.warnings.length).toBeGreaterThanOrEqual(1);
1148
+ const item = result.warnings.find((w) => w.rule === 'src-not-empty');
1149
+ expect(item).toBeDefined();
1150
+ expect(item.severity).toBe('warning');
1151
+ // Should NOT be in errors
1152
+ expect(result.errors.find((e) => e.rule === 'src-not-empty')).toBeUndefined();
1153
+
1154
+ htmlhint.HTMLHint.verify = original;
1155
+ });
1156
+
1157
+ it('returns info for HTMLHint warning type with unknown ruleId (line 165-166)', () => {
1158
+ // getSeverityLevel('warning', 'unknown-rule') → 'info' (no warningRules match, type !== 'error')
1159
+ const htmlhint = require('htmlhint');
1160
+ const original = htmlhint.HTMLHint.verify;
1161
+ htmlhint.HTMLHint.verify = jest.fn(() => ([
1162
+ {
1163
+ type: 'warning',
1164
+ message: 'Some custom warning',
1165
+ line: 2,
1166
+ col: 3,
1167
+ rule: { id: 'unknown-custom-rule' },
1168
+ },
1169
+ ]));
1170
+
1171
+ const result = validateHTML('<div>test</div>');
1172
+
1173
+ expect(result.info.length).toBeGreaterThanOrEqual(1);
1174
+ const item = result.info.find((i) => i.rule === 'unknown-custom-rule');
1175
+ expect(item).toBeDefined();
1176
+ expect(item.severity).toBe('info');
1177
+ expect(item.line).toBe(2);
1178
+ expect(item.column).toBe(3);
1179
+ // Should NOT be in errors or warnings
1180
+ expect(result.errors.find((e) => e.rule === 'unknown-custom-rule')).toBeUndefined();
1181
+ expect(result.warnings.find((w) => w.rule === 'unknown-custom-rule')).toBeUndefined();
1182
+
1183
+ htmlhint.HTMLHint.verify = original;
1184
+ });
1185
+
1186
+ it('processes multiple HTMLHint issues with mixed severity correctly (lines 101-118)', () => {
1187
+ const htmlhint = require('htmlhint');
1188
+ const original = htmlhint.HTMLHint.verify;
1189
+ htmlhint.HTMLHint.verify = jest.fn(() => ([
1190
+ { type: 'error', message: 'Tag pair', line: 1, col: 1, rule: { id: 'tag-pair' } }, // → warning
1191
+ { type: 'error', message: 'Src empty', line: 2, col: 1, rule: { id: 'src-not-empty' } }, // → warning (downgrade)
1192
+ { type: 'warning', message: 'Mixed tabs', line: 3, col: 1, rule: { id: 'space-tab-mixed-disabled' } }, // → info
1193
+ ]));
1194
+
1195
+ const result = validateHTML('<div>test</div>');
1196
+
1197
+ const tagPair = result.warnings.find((w) => w.rule === 'tag-pair');
1198
+ expect(tagPair).toBeDefined();
1199
+ expect(tagPair.severity).toBe('warning');
1200
+
1201
+ const srcEmpty = result.warnings.find((w) => w.rule === 'src-not-empty');
1202
+ expect(srcEmpty).toBeDefined();
1203
+ expect(srcEmpty.severity).toBe('warning');
1204
+
1205
+ const mixedTabs = result.info.find((i) => i.rule === 'space-tab-mixed-disabled');
1206
+ expect(mixedTabs).toBeDefined();
1207
+ expect(mixedTabs.severity).toBe('info');
1208
+
1209
+ htmlhint.HTMLHint.verify = original;
1210
+ });
1079
1211
  });
1080
1212
 
1081
1213
  describe('extractAndValidateCSS Advanced Tests', () => {
@@ -76,7 +76,7 @@ const CUSTOM_VALIDATIONS = {
76
76
  * @param {Function} formatMessage - Message formatter function for internationalization
77
77
  * @returns {Object} Validation result with errors and warnings
78
78
  */
79
- export const validateHTML = (html, variant = 'email', formatMessage = defaultMessageFormatter) => {
79
+ export const validateHTML = (html, variant = 'email', formatMessage = defaultMessageFormatter, options = {}) => {
80
80
  if (!html || typeof html !== 'string') {
81
81
  return {
82
82
  isValid: true,
@@ -133,7 +133,9 @@ export const validateHTML = (html, variant = 'email', formatMessage = defaultMes
133
133
  // Always run custom validations and Liquid validation, even if HTMLHint failed
134
134
  // This ensures unsafe protocol detection and other critical validations still run
135
135
  runCustomValidations(html, variant, results, formatMessage);
136
- runLiquidValidation(html, variant, results, formatMessage);
136
+ if (!options.skipLiquidValidation) {
137
+ runLiquidValidation(html, variant, results, formatMessage);
138
+ }
137
139
 
138
140
  return results;
139
141
  };
@@ -0,0 +1,87 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import CreativesContainer from '../../v2Containers/CreativesContainer';
4
+ import CapPageSpinner from '../CapPageSpinner';
5
+ import {
6
+ EMBEDDED_SMS_CREATIVES_LOCATION,
7
+ SMS_FALLBACK_CHANNEL_KEY,
8
+ SMS_FALLBACK_CREATIVE_EDITOR,
9
+ SMS_FALLBACK_ENABLE_NEW_CHANNELS,
10
+ } from './constants';
11
+
12
+ /**
13
+ * Reuse the exact embedded CreativesContainer SMS flow (same as normal SMS create).
14
+ * Avoid overriding Templates with local config so "Create new" follows built-in createTemplate path.
15
+ */
16
+ export function SmsFallbackLocalSelector({
17
+ hidden,
18
+ fetchDetailsLoading,
19
+ templateList,
20
+ channelsToHide,
21
+ smsRegister,
22
+ onCloseCreatives,
23
+ onSelectTemplate,
24
+ filterContent,
25
+ location,
26
+ /** Required when user completes embedded SMS create/edit — `CreativesContainer` calls this on save (see `processCentralCommsMetaId`). */
27
+ getCreativesData,
28
+ }) {
29
+ const rootClassName = [
30
+ 'sms-fallback-selector',
31
+ hidden ? 'sms-fallback-selector--visually-hidden' : '',
32
+ ]
33
+ .filter(Boolean)
34
+ .join(' ');
35
+
36
+ return (
37
+ <div className={rootClassName}>
38
+ {fetchDetailsLoading && (
39
+ <div className="sms-fallback-selector__loading" aria-busy="true" aria-live="polite">
40
+ <CapPageSpinner spinning />
41
+ </div>
42
+ )}
43
+ <CreativesContainer
44
+ creativesMode="create"
45
+ location={location || EMBEDDED_SMS_CREATIVES_LOCATION}
46
+ templateData={null}
47
+ handleCloseCreatives={onCloseCreatives}
48
+ isFullMode={false}
49
+ smsRegister={smsRegister}
50
+ editor={SMS_FALLBACK_CREATIVE_EDITOR}
51
+ enableNewChannels={SMS_FALLBACK_ENABLE_NEW_CHANNELS}
52
+ channel={SMS_FALLBACK_CHANNEL_KEY}
53
+ channelsToHide={channelsToHide}
54
+ selectedBadges={[]}
55
+ localTemplatesConfig={{
56
+ useLocalTemplates: true,
57
+ localTemplates: templateList.templates,
58
+ localTemplatesLoading: templateList.loading,
59
+ localTemplatesFilterContent: filterContent,
60
+ localTemplatesOnPageChange: templateList.loadMore,
61
+ localTemplatesUseSkeleton: true,
62
+ }}
63
+ onSelectTemplate={onSelectTemplate}
64
+ getCreativesData={getCreativesData}
65
+ />
66
+ </div>
67
+ );
68
+ }
69
+
70
+ SmsFallbackLocalSelector.propTypes = {
71
+ hidden: PropTypes.bool,
72
+ fetchDetailsLoading: PropTypes.bool,
73
+ templateList: PropTypes.shape({
74
+ templates: PropTypes.array,
75
+ loading: PropTypes.bool,
76
+ loadMore: PropTypes.func,
77
+ }).isRequired,
78
+ channelsToHide: PropTypes.arrayOf(PropTypes.string),
79
+ smsRegister: PropTypes.any,
80
+ onCloseCreatives: PropTypes.func.isRequired,
81
+ onSelectTemplate: PropTypes.func.isRequired,
82
+ filterContent: PropTypes.node,
83
+ location: PropTypes.object,
84
+ getCreativesData: PropTypes.func.isRequired,
85
+ };
86
+
87
+ export default SmsFallbackLocalSelector;
@@ -0,0 +1,73 @@
1
+ import {
2
+ WHATSAPP,
3
+ RCS,
4
+ ZALO,
5
+ WEBPUSH,
6
+ } from '../../v2Containers/CreativesContainer/constants';
7
+
8
+ /**
9
+ * View modes for the SMS fallback slidebox (template list, create, edit).
10
+ * Used by SmsFallback and any channel that reuses it (RCS, etc.).
11
+ */
12
+ export const SMS_FALLBACK_VIEW = {
13
+ SELECTING: 'selecting',
14
+ CREATING: 'creating',
15
+ EDITING: 'editing',
16
+ };
17
+
18
+ /**
19
+ * Channel keys to hide in TemplatesV2 so only SMS tab is shown.
20
+ * Uses normalized keys matching TemplatesV2 pane.key normalization (lowercase).
21
+ * Parent can override via channelsToHide prop.
22
+ */
23
+ export const CHANNELS_TO_HIDE_FOR_SMS_ONLY = [
24
+ 'email',
25
+ 'mobilepush',
26
+ 'webpush',
27
+ 'viber',
28
+ 'whatsapp',
29
+ 'zalo',
30
+ 'facebook',
31
+ 'rcs',
32
+ 'inapp',
33
+ 'line',
34
+ 'wechat',
35
+ 'call_task',
36
+ 'ftp',
37
+ 'assets',
38
+ ];
39
+
40
+ /** DLT category filter values — aligned with Templates `SMS_FILTERS` / `filterSMSTemplates`. */
41
+ export const SMS_CATEGORY_FILTERS = {
42
+ ALL: 'all',
43
+ PROMOTIONAL: 'promo',
44
+ SERVICE_EXPLICIT: 'explicit',
45
+ SERVICE_IMPLICIT: 'implicit',
46
+ };
47
+
48
+ /** `location` for embedded SMS creatives picker (CreativesContainer / TemplatesV2). */
49
+ export const EMBEDDED_SMS_CREATIVES_LOCATION = {
50
+ pathname: '/sms/create',
51
+ query: { type: 'embedded', module: 'library' },
52
+ search: '',
53
+ };
54
+
55
+ /** `location` for embedded SMS TRAI edit inside slidebox. */
56
+ export const EMBEDDED_SMS_CREATIVES_EDIT_LOCATION = {
57
+ pathname: '/sms/edit',
58
+ query: { type: 'embedded', module: 'library' },
59
+ search: '',
60
+ };
61
+
62
+ /** API `channel` param for `getTemplateDetails` when loading an SMS template by id. */
63
+ export const SMS_TEMPLATE_DETAILS_API_CHANNEL = 'Sms';
64
+
65
+ export const SMS_FALLBACK_CREATIVE_EDITOR = 'BEE';
66
+
67
+ export const SMS_FALLBACK_CHANNEL_KEY = 'sms';
68
+
69
+ /** Route shape passed to SmsWrapper / SmsTraiEdit for embedded SMS flows. */
70
+ export const SMS_FALLBACK_ROUTE = { name: SMS_FALLBACK_CHANNEL_KEY };
71
+
72
+ /** Channels enabled in the SMS-only embedded picker (hide others via `channelsToHide`). */
73
+ export const SMS_FALLBACK_ENABLE_NEW_CHANNELS = [WHATSAPP, RCS, ZALO, WEBPUSH];