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.
- package/.github/workflows/pr-title-check.yml +88 -0
- package/app/constants/unified.js +21 -1
- package/app/containers/App/constants.js +0 -1
- package/app/containers/Login/test/index.test.js +123 -0
- package/app/containers/Login/test/selectors.test.js +165 -0
- package/app/initialState.js +0 -2
- package/app/services/api.js +6 -0
- package/app/services/tests/api.test.js +7 -0
- package/app/services/tests/getSchema.test.js +95 -0
- package/app/utils/common.js +23 -9
- package/app/utils/commonUtils.js +64 -93
- package/app/utils/tagValidations.js +83 -219
- package/app/utils/templateVarUtils.js +172 -0
- package/app/utils/tests/common.test.js +265 -323
- package/app/utils/tests/commonUtil.test.js +461 -118
- package/app/utils/tests/commonUtils.test.js +581 -0
- package/app/utils/tests/messageUtils.test.js +95 -0
- package/app/utils/tests/smsCharCount.test.js +304 -0
- package/app/utils/tests/smsCharCountV2.test.js +213 -10
- package/app/utils/tests/tagValidations.test.js +474 -357
- package/app/utils/tests/templateVarUtils.test.js +160 -0
- package/app/v2Components/CapDeviceContent/index.js +10 -7
- package/app/v2Components/CapTagList/index.js +32 -24
- package/app/v2Components/CapTagList/style.scss +48 -0
- package/app/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
- package/app/v2Components/CapTagListWithInput/index.js +8 -0
- package/app/v2Components/CapWhatsappCTA/index.js +2 -0
- package/app/v2Components/CapWhatsappCarouselButton/index.js +32 -14
- package/app/v2Components/CapWhatsappCarouselButton/tests/index.test.js +120 -2
- package/app/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +39 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +606 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.scss +36 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +79 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/index.js +314 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +141 -0
- package/app/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +156 -0
- package/app/v2Components/CommonTestAndPreview/SendTestMessage.js +57 -1
- package/app/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
- package/app/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
- package/app/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +210 -4
- package/app/v2Components/CommonTestAndPreview/actions.js +20 -0
- package/app/v2Components/CommonTestAndPreview/constants.js +57 -1
- package/app/v2Components/CommonTestAndPreview/index.js +878 -156
- package/app/v2Components/CommonTestAndPreview/messages.js +41 -3
- package/app/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
- package/app/v2Components/CommonTestAndPreview/reducer.js +47 -0
- package/app/v2Components/CommonTestAndPreview/sagas.js +75 -5
- package/app/v2Components/CommonTestAndPreview/selectors.js +51 -0
- package/app/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +352 -0
- package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +1156 -0
- package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +334 -0
- package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +576 -0
- package/app/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +156 -0
- package/app/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
- package/app/v2Components/CommonTestAndPreview/tests/actions.test.js +50 -0
- package/app/v2Components/CommonTestAndPreview/tests/constants.test.js +18 -7
- package/app/v2Components/CommonTestAndPreview/tests/index.test.js +914 -5
- package/app/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
- package/app/v2Components/CommonTestAndPreview/tests/reducer.test.js +118 -0
- package/app/v2Components/CommonTestAndPreview/tests/sagas.test.js +146 -378
- package/app/v2Components/CommonTestAndPreview/tests/selectors.test.js +146 -0
- package/app/v2Components/ErrorInfoNote/index.js +24 -26
- package/app/v2Components/FormBuilder/index.js +182 -204
- package/app/v2Components/FormBuilder/messages.js +4 -8
- package/app/v2Components/HtmlEditor/HTMLEditor.js +7 -6
- package/app/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -1
- package/app/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +928 -17
- package/app/v2Components/HtmlEditor/components/CodeEditorPane/index.js +4 -2
- package/app/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +452 -3
- package/app/v2Components/HtmlEditor/hooks/useValidation.js +12 -9
- package/app/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +132 -0
- package/app/v2Components/HtmlEditor/utils/htmlValidator.js +4 -2
- package/app/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
- package/app/v2Components/SmsFallback/constants.js +73 -0
- package/app/v2Components/SmsFallback/index.js +956 -0
- package/app/v2Components/SmsFallback/index.scss +265 -0
- package/app/v2Components/SmsFallback/messages.js +78 -0
- package/app/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
- package/app/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
- package/app/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
- package/app/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
- package/app/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
- package/app/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
- package/app/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
- package/app/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
- package/app/v2Components/TestAndPreviewSlidebox/index.js +22 -1
- package/app/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
- package/app/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
- package/app/v2Components/VarSegmentMessageEditor/constants.js +2 -0
- package/app/v2Components/VarSegmentMessageEditor/index.js +125 -0
- package/app/v2Components/VarSegmentMessageEditor/index.scss +46 -0
- package/app/v2Containers/BeeEditor/index.js +3 -0
- package/app/v2Containers/BeePopupEditor/index.js +9 -2
- package/app/v2Containers/Cap/mockData.js +0 -14
- package/app/v2Containers/Cap/reducer.js +3 -55
- package/app/v2Containers/Cap/tests/reducer.test.js +0 -102
- package/app/v2Containers/CommunicationFlow/CommunicationFlow.js +291 -0
- package/app/v2Containers/CommunicationFlow/CommunicationFlow.scss +25 -0
- package/app/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +255 -0
- package/app/v2Containers/CommunicationFlow/constants.js +200 -0
- package/app/v2Containers/CommunicationFlow/index.js +102 -0
- package/app/v2Containers/CommunicationFlow/messages.js +346 -0
- package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +522 -0
- package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +170 -0
- package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +796 -0
- package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/index.js +5 -0
- package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/CommunicationStrategyStep.js +95 -0
- package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/Tests/CommunicationStrategyStep.test.js +133 -0
- package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/index.js +5 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +289 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.scss +70 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +319 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.scss +69 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +616 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +577 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +1111 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +696 -0
- package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/index.js +7 -0
- package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.js +102 -0
- package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.scss +36 -0
- package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/Tests/DynamicControlsStep.test.js +91 -0
- package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/index.js +5 -0
- package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/MessageTypeStep.js +86 -0
- package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/Tests/MessageTypeStep.test.js +100 -0
- package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/index.js +5 -0
- package/app/v2Containers/CommunicationFlow/utils/getEnabledSteps.js +30 -0
- package/app/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
- package/app/v2Containers/CreativesContainer/SlideBoxContent.js +127 -11
- package/app/v2Containers/CreativesContainer/SlideBoxFooter.js +62 -9
- package/app/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
- package/app/v2Containers/CreativesContainer/constants.js +24 -0
- package/app/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
- package/app/v2Containers/CreativesContainer/index.js +346 -71
- package/app/v2Containers/CreativesContainer/index.scss +51 -1
- package/app/v2Containers/CreativesContainer/messages.js +12 -0
- package/app/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
- package/app/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +69 -1
- package/app/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +443 -0
- package/app/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
- package/app/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +147 -4
- package/app/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
- package/app/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +57 -10
- package/app/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
- package/app/v2Containers/CreativesContainer/tests/index.test.js +71 -9
- package/app/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
- package/app/v2Containers/Email/index.js +2 -5
- package/app/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +58 -77
- package/app/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
- package/app/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +158 -89
- package/app/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
- package/app/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +17 -12
- package/app/v2Containers/EmailWrapper/index.js +4 -0
- package/app/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
- package/app/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +133 -0
- package/app/v2Containers/FTP/index.js +2 -51
- package/app/v2Containers/FTP/messages.js +0 -4
- package/app/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +110 -155
- package/app/v2Containers/InApp/index.js +297 -118
- package/app/v2Containers/InApp/tests/index.test.js +17 -6
- package/app/v2Containers/InApp/tests/mockData.js +1 -1
- package/app/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +19 -0
- package/app/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +3 -0
- package/app/v2Containers/InAppWrapper/index.js +3 -0
- package/app/v2Containers/InappAdvance/index.js +5 -104
- package/app/v2Containers/InappAdvance/tests/index.test.js +2 -0
- package/app/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +24 -3
- package/app/v2Containers/Line/Container/Text/index.js +0 -1
- package/app/v2Containers/MobilePush/Create/index.js +105 -28
- package/app/v2Containers/MobilePush/Create/messages.js +4 -0
- package/app/v2Containers/MobilePush/Edit/index.js +250 -68
- package/app/v2Containers/MobilePush/Edit/messages.js +4 -0
- package/app/v2Containers/MobilePushNew/components/PlatformContentFields.js +36 -12
- package/app/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +68 -27
- package/app/v2Containers/MobilePushNew/index.js +78 -35
- package/app/v2Containers/MobilePushNew/messages.js +8 -0
- package/app/v2Containers/MobilepushWrapper/index.js +11 -1
- package/app/v2Containers/Rcs/constants.js +32 -1
- package/app/v2Containers/Rcs/index.js +963 -916
- package/app/v2Containers/Rcs/index.scss +85 -6
- package/app/v2Containers/Rcs/messages.js +10 -1
- package/app/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
- package/app/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +41136 -1566
- package/app/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
- package/app/v2Containers/Rcs/tests/index.test.js +41 -38
- package/app/v2Containers/Rcs/tests/mockData.js +38 -0
- package/app/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
- package/app/v2Containers/Rcs/tests/utils.test.js +379 -1
- package/app/v2Containers/Rcs/utils.js +358 -10
- package/app/v2Containers/Sms/Create/index.js +122 -39
- package/app/v2Containers/Sms/Create/messages.js +4 -0
- package/app/v2Containers/Sms/Edit/index.js +37 -3
- package/app/v2Containers/Sms/commonMethods.js +3 -6
- package/app/v2Containers/Sms/smsFormDataHelpers.js +67 -0
- package/app/v2Containers/Sms/tests/commonMethods.test.js +122 -0
- package/app/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
- package/app/v2Containers/SmsTrai/Create/index.js +9 -4
- package/app/v2Containers/SmsTrai/Create/index.scss +1 -1
- package/app/v2Containers/SmsTrai/Edit/constants.js +2 -0
- package/app/v2Containers/SmsTrai/Edit/index.js +667 -160
- package/app/v2Containers/SmsTrai/Edit/index.scss +121 -0
- package/app/v2Containers/SmsTrai/Edit/messages.js +9 -4
- package/app/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4590 -2436
- package/app/v2Containers/SmsWrapper/index.js +41 -8
- package/app/v2Containers/TagList/index.js +63 -2
- package/app/v2Containers/TagList/messages.js +8 -0
- package/app/v2Containers/TagList/tests/TagList.test.js +122 -20
- package/app/v2Containers/TagList/tests/mockdata.js +17 -0
- package/app/v2Containers/Templates/TemplatesActionBar.js +101 -0
- package/app/v2Containers/Templates/_templates.scss +61 -2
- package/app/v2Containers/Templates/actions.js +11 -0
- package/app/v2Containers/Templates/constants.js +2 -0
- package/app/v2Containers/Templates/index.js +90 -40
- package/app/v2Containers/Templates/reducer.js +3 -1
- package/app/v2Containers/Templates/sagas.js +57 -12
- package/app/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
- package/app/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
- package/app/v2Containers/Templates/tests/reducer.test.js +12 -0
- package/app/v2Containers/Templates/tests/sagas.test.js +193 -12
- package/app/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
- package/app/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
- package/app/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
- package/app/v2Containers/TemplatesV2/index.js +147 -49
- package/app/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
- package/app/v2Containers/Viber/index.js +9 -10
- package/app/v2Containers/Viber/index.scss +1 -1
- package/app/v2Containers/WebPush/Create/components/BrandIconSection.test.js +264 -0
- package/app/v2Containers/WebPush/Create/components/MessageSection.js +78 -19
- package/app/v2Containers/WebPush/Create/components/MessageSection.test.js +82 -0
- package/app/v2Containers/WebPush/Create/components/__snapshots__/BrandIconSection.test.js.snap +187 -0
- package/app/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +25 -17
- package/app/v2Containers/WebPush/Create/hooks/useAiraTriggerPosition.js +80 -0
- package/app/v2Containers/WebPush/Create/hooks/useAiraTriggerPosition.test.js +210 -0
- package/app/v2Containers/WebPush/Create/hooks/useTagManagement.js +1 -5
- package/app/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -7
- package/app/v2Containers/WebPush/Create/index.js +36 -6
- package/app/v2Containers/WebPush/Create/index.scss +5 -0
- package/app/v2Containers/WebPush/Create/messages.js +8 -1
- package/app/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +269 -0
- package/app/v2Containers/WebPush/Create/utils/validation.js +31 -15
- package/app/v2Containers/WebPush/Create/utils/validation.test.js +72 -24
- package/app/v2Containers/Whatsapp/index.js +28 -53
- package/app/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +26939 -3982
- package/app/v2Containers/Whatsapp/tests/index.test.js +172 -0
- package/app/v2Containers/Zalo/index.js +5 -11
- package/package.json +2 -2
- package/version +9 -0
|
@@ -72,6 +72,7 @@ import {
|
|
|
72
72
|
} from '../../Cap/selectors';
|
|
73
73
|
import './index.scss';
|
|
74
74
|
import { WEBPUSH } from '../../CreativesContainer/constants';
|
|
75
|
+
import { isAiContentBotDisabled } from '../../../utils/common';
|
|
75
76
|
|
|
76
77
|
// Memoized TagList wrapper components for better performance
|
|
77
78
|
const MemoizedTagList = memo(({
|
|
@@ -83,8 +84,12 @@ const MemoizedTagList = memo(({
|
|
|
83
84
|
injectedTags,
|
|
84
85
|
selectedOfferDetails,
|
|
85
86
|
eventContextTags,
|
|
87
|
+
waitEventContextTags,
|
|
86
88
|
forwardedTags,
|
|
87
89
|
onTagSelect,
|
|
90
|
+
restrictPersonalization = false,
|
|
91
|
+
disabled = false,
|
|
92
|
+
disableTooltipMsg,
|
|
88
93
|
}) => (
|
|
89
94
|
<TagList
|
|
90
95
|
moduleFilterEnabled={moduleFilterEnabled}
|
|
@@ -95,8 +100,12 @@ const MemoizedTagList = memo(({
|
|
|
95
100
|
injectedTags={injectedTags}
|
|
96
101
|
selectedOfferDetails={selectedOfferDetails}
|
|
97
102
|
eventContextTags={eventContextTags}
|
|
103
|
+
waitEventContextTags={waitEventContextTags}
|
|
98
104
|
forwardedTags={forwardedTags}
|
|
99
105
|
onTagSelect={onTagSelect}
|
|
106
|
+
restrictPersonalization={restrictPersonalization}
|
|
107
|
+
disabled={disabled || restrictPersonalization}
|
|
108
|
+
disableTooltipMsg={disableTooltipMsg}
|
|
100
109
|
/>
|
|
101
110
|
), (prevProps, nextProps) => {
|
|
102
111
|
// Custom comparison function for better memoization
|
|
@@ -109,8 +118,12 @@ const MemoizedTagList = memo(({
|
|
|
109
118
|
&& prevProps.injectedTags === nextProps.injectedTags
|
|
110
119
|
&& prevProps.selectedOfferDetails === nextProps.selectedOfferDetails
|
|
111
120
|
&& prevProps.eventContextTags === nextProps.eventContextTags
|
|
121
|
+
&& prevProps.waitEventContextTags === nextProps.waitEventContextTags
|
|
112
122
|
&& prevProps.forwardedTags === nextProps.forwardedTags
|
|
113
123
|
&& prevProps.onTagSelect === nextProps.onTagSelect
|
|
124
|
+
&& prevProps.restrictPersonalization === nextProps.restrictPersonalization
|
|
125
|
+
&& prevProps.disabled === nextProps.disabled
|
|
126
|
+
&& prevProps.disableTooltipMsg === nextProps.disableTooltipMsg
|
|
114
127
|
);
|
|
115
128
|
});
|
|
116
129
|
|
|
@@ -142,10 +155,13 @@ const WebPushCreate = ({
|
|
|
142
155
|
forwardedTags,
|
|
143
156
|
selectedOfferDetails = [],
|
|
144
157
|
eventContextTags = [],
|
|
158
|
+
waitEventContextTags = {},
|
|
145
159
|
templateActions: templateActionsProps,
|
|
146
160
|
Templates,
|
|
161
|
+
restrictPersonalization = false,
|
|
147
162
|
}) => {
|
|
148
163
|
const { formatMessage } = intl;
|
|
164
|
+
const aiContentBotDisabled = isAiContentBotDisabled();
|
|
149
165
|
|
|
150
166
|
// Form state - kept in main component for now
|
|
151
167
|
const [templateName, setTemplateName] = useState('');
|
|
@@ -220,6 +236,7 @@ const WebPushCreate = ({
|
|
|
220
236
|
supportedTags: memoizedSupportedTags,
|
|
221
237
|
injectedTags,
|
|
222
238
|
eventContextTags,
|
|
239
|
+
waitEventContextTags,
|
|
223
240
|
});
|
|
224
241
|
const { tags, handleOnTagsContextChange, validationConfig } = tagState;
|
|
225
242
|
const { weCrmAccounts } = Templates;
|
|
@@ -285,8 +302,8 @@ const WebPushCreate = ({
|
|
|
285
302
|
const validateTemplateName = useCallback((value) => validateTemplateNameUtil(value), []);
|
|
286
303
|
|
|
287
304
|
const validateTitle = useCallback(
|
|
288
|
-
(value) => validateTitleUtil(value, formatMessage, messages),
|
|
289
|
-
[formatMessage],
|
|
305
|
+
(value) => validateTitleUtil(value, formatMessage, messages, restrictPersonalization, validationConfig, isFullMode),
|
|
306
|
+
[formatMessage, restrictPersonalization, validationConfig, isFullMode],
|
|
290
307
|
);
|
|
291
308
|
|
|
292
309
|
const validateUrl = useCallback(
|
|
@@ -309,8 +326,8 @@ const WebPushCreate = ({
|
|
|
309
326
|
|
|
310
327
|
|
|
311
328
|
const validateMessageContent = useCallback(
|
|
312
|
-
(value) => validateMessageContentUtil(value, formatMessage, messages, validationConfig, isFullMode),
|
|
313
|
-
[formatMessage, validationConfig, isFullMode],
|
|
329
|
+
(value) => validateMessageContentUtil(value, formatMessage, messages, validationConfig, isFullMode, restrictPersonalization),
|
|
330
|
+
[formatMessage, validationConfig, isFullMode, restrictPersonalization],
|
|
314
331
|
);
|
|
315
332
|
|
|
316
333
|
useEffect(() => {
|
|
@@ -546,7 +563,7 @@ const WebPushCreate = ({
|
|
|
546
563
|
// Pure validator that returns boolean without setting error state
|
|
547
564
|
const validateFormSilent = () => {
|
|
548
565
|
const templateNameInvalid = isFullMode && validateTemplateName(templateName);
|
|
549
|
-
const titleValidation = validateTitle(notificationTitle);
|
|
566
|
+
const titleValidation = validateTitle(notificationTitle, restrictPersonalization);
|
|
550
567
|
const messageValidation = validateMessageContent(message);
|
|
551
568
|
|
|
552
569
|
return !(templateNameInvalid || titleValidation || messageValidation);
|
|
@@ -569,6 +586,7 @@ const WebPushCreate = ({
|
|
|
569
586
|
return;
|
|
570
587
|
}
|
|
571
588
|
|
|
589
|
+
|
|
572
590
|
// Set flag to indicate save/edit operation has been initiated
|
|
573
591
|
saveInitiatedRef.current = true;
|
|
574
592
|
|
|
@@ -824,9 +842,13 @@ const WebPushCreate = ({
|
|
|
824
842
|
injectedTags,
|
|
825
843
|
selectedOfferDetails,
|
|
826
844
|
eventContextTags,
|
|
845
|
+
waitEventContextTags,
|
|
827
846
|
forwardedTags,
|
|
847
|
+
restrictPersonalization,
|
|
848
|
+
disabled: restrictPersonalization,
|
|
849
|
+
disableTooltipMsg: restrictPersonalization ? formatMessage(messages.personalizationNotSupportedAnonymous) : undefined,
|
|
828
850
|
}),
|
|
829
|
-
[tags, injectedTags, selectedOfferDetails, eventContextTags, forwardedTags],
|
|
851
|
+
[tags, injectedTags, selectedOfferDetails, eventContextTags, waitEventContextTags, forwardedTags, restrictPersonalization, formatMessage],
|
|
830
852
|
);
|
|
831
853
|
|
|
832
854
|
// Memoized TagList components with optimized props
|
|
@@ -881,6 +903,7 @@ const WebPushCreate = ({
|
|
|
881
903
|
)
|
|
882
904
|
)
|
|
883
905
|
|| (onClickBehaviour === ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL && (!redirectUrl.trim() || redirectUrlError))
|
|
906
|
+
|| !!titleError || !!messageError
|
|
884
907
|
),
|
|
885
908
|
[
|
|
886
909
|
createTemplateInProgress,
|
|
@@ -906,6 +929,8 @@ const WebPushCreate = ({
|
|
|
906
929
|
onClickBehaviour,
|
|
907
930
|
redirectUrl,
|
|
908
931
|
redirectUrlError,
|
|
932
|
+
titleError,
|
|
933
|
+
messageError,
|
|
909
934
|
],
|
|
910
935
|
);
|
|
911
936
|
|
|
@@ -980,6 +1005,7 @@ const WebPushCreate = ({
|
|
|
980
1005
|
messageCountRef={messageCountRef}
|
|
981
1006
|
messageTextAreaRef={messageTextAreaRef}
|
|
982
1007
|
handleMessageTextAreaRef={handleMessageTextAreaRef}
|
|
1008
|
+
isAiContentBotDisabled={aiContentBotDisabled}
|
|
983
1009
|
/>
|
|
984
1010
|
<MediaSection
|
|
985
1011
|
mediaType={mediaType}
|
|
@@ -1063,7 +1089,9 @@ WebPushCreate.propTypes = {
|
|
|
1063
1089
|
forwardedTags: PropTypes.object,
|
|
1064
1090
|
selectedOfferDetails: PropTypes.array,
|
|
1065
1091
|
eventContextTags: PropTypes.array,
|
|
1092
|
+
waitEventContextTags: PropTypes.object,
|
|
1066
1093
|
templateActions: PropTypes.object,
|
|
1094
|
+
restrictPersonalization: PropTypes.bool,
|
|
1067
1095
|
};
|
|
1068
1096
|
|
|
1069
1097
|
WebPushCreate.defaultProps = {
|
|
@@ -1090,8 +1118,10 @@ WebPushCreate.defaultProps = {
|
|
|
1090
1118
|
forwardedTags: {},
|
|
1091
1119
|
selectedOfferDetails: [],
|
|
1092
1120
|
eventContextTags: [],
|
|
1121
|
+
waitEventContextTags: {},
|
|
1093
1122
|
templateActions: {},
|
|
1094
1123
|
Templates: {},
|
|
1124
|
+
restrictPersonalization: false,
|
|
1095
1125
|
};
|
|
1096
1126
|
|
|
1097
1127
|
const mapStateToProps = createStructuredSelector({
|
|
@@ -207,5 +207,12 @@ export default defineMessages({
|
|
|
207
207
|
id: `${scope}.templateIdMissingError`,
|
|
208
208
|
defaultMessage: 'Unable to save template: Template ID is missing. Please refresh the page and try again.',
|
|
209
209
|
},
|
|
210
|
+
personalizationTokensErrorMessage: {
|
|
211
|
+
id: `${scope}.personalizationTokensErrorMessage`,
|
|
212
|
+
defaultMessage: 'Personalization tags are not supported for anonymous customers, please remove the tags.',
|
|
213
|
+
},
|
|
214
|
+
personalizationNotSupportedAnonymous: {
|
|
215
|
+
id: `${scope}.personalizationNotSupportedAnonymous`,
|
|
216
|
+
defaultMessage: 'Personalization tags are not supported for anonymous customers',
|
|
217
|
+
},
|
|
210
218
|
});
|
|
211
|
-
|
|
@@ -1016,6 +1016,275 @@ describe('NotificationContainer', () => {
|
|
|
1016
1016
|
});
|
|
1017
1017
|
});
|
|
1018
1018
|
|
|
1019
|
+
describe('platform.browser getter — 2-part vs 3-part class names', () => {
|
|
1020
|
+
it('derives browser from 2-part class name (macos-chrome → parts[1])', () => {
|
|
1021
|
+
// 'macos-chrome'.split('-') = ['macos', 'chrome'] → length=2 → browser = parts[1] = 'chrome'
|
|
1022
|
+
const wrapper = mountWithIntl(
|
|
1023
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_MACOS} selectedBrowser={BROWSER_CHROME} />
|
|
1024
|
+
);
|
|
1025
|
+
expect(wrapper.find('.notification-container').hasClass('macos-chrome')).toBe(true);
|
|
1026
|
+
});
|
|
1027
|
+
|
|
1028
|
+
it('derives browser from 3-part class name (android-mobile-chrome → parts[2])', () => {
|
|
1029
|
+
// 'android-mobile-chrome'.split('-') = ['android', 'mobile', 'chrome'] → length=3 → browser = parts[2] = 'chrome'
|
|
1030
|
+
const wrapper = mountWithIntl(
|
|
1031
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_ANDROID_MOBILE} selectedBrowser={BROWSER_CHROME} />
|
|
1032
|
+
);
|
|
1033
|
+
expect(wrapper.find('.notification-container').hasClass('android-mobile-chrome')).toBe(true);
|
|
1034
|
+
});
|
|
1035
|
+
|
|
1036
|
+
it('derives browser from 3-part class name for Android Tablet (android-tablet-firefox → parts[2])', () => {
|
|
1037
|
+
const wrapper = mountWithIntl(
|
|
1038
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_ANDROID_TABLET} selectedBrowser={BROWSER_FIREFOX} />
|
|
1039
|
+
);
|
|
1040
|
+
expect(wrapper.find('.notification-container').hasClass('android-tablet-firefox')).toBe(true);
|
|
1041
|
+
});
|
|
1042
|
+
});
|
|
1043
|
+
|
|
1044
|
+
describe('platform.isIOS getter (selectedOS === OS_IOS)', () => {
|
|
1045
|
+
it('is true for iOS — renders IOSHeader', () => {
|
|
1046
|
+
const wrapper = mountWithIntl(
|
|
1047
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_IOS} selectedBrowser={BROWSER_CHROME} />
|
|
1048
|
+
);
|
|
1049
|
+
expect(wrapper.find(IOSHeader).exists()).toBe(true);
|
|
1050
|
+
});
|
|
1051
|
+
|
|
1052
|
+
it('is false for macOS — does not render IOSHeader', () => {
|
|
1053
|
+
const wrapper = mountWithIntl(
|
|
1054
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_MACOS} selectedBrowser={BROWSER_CHROME} />
|
|
1055
|
+
);
|
|
1056
|
+
expect(wrapper.find(IOSHeader).exists()).toBe(false);
|
|
1057
|
+
});
|
|
1058
|
+
|
|
1059
|
+
it('is false for Android Mobile — does not render IOSHeader', () => {
|
|
1060
|
+
const wrapper = mountWithIntl(
|
|
1061
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_ANDROID_MOBILE} selectedBrowser={BROWSER_CHROME} />
|
|
1062
|
+
);
|
|
1063
|
+
expect(wrapper.find(IOSHeader).exists()).toBe(false);
|
|
1064
|
+
});
|
|
1065
|
+
|
|
1066
|
+
it('is false for Windows — does not render IOSHeader', () => {
|
|
1067
|
+
const wrapper = mountWithIntl(
|
|
1068
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_WINDOWS} selectedBrowser={BROWSER_CHROME} />
|
|
1069
|
+
);
|
|
1070
|
+
expect(wrapper.find(IOSHeader).exists()).toBe(false);
|
|
1071
|
+
});
|
|
1072
|
+
});
|
|
1073
|
+
|
|
1074
|
+
describe('platform.isIPadOS getter (selectedOS === OS_IPADOS)', () => {
|
|
1075
|
+
it('is true for iPadOS — renders IOSHeader', () => {
|
|
1076
|
+
const wrapper = mountWithIntl(
|
|
1077
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_IPADOS} selectedBrowser={BROWSER_CHROME} />
|
|
1078
|
+
);
|
|
1079
|
+
expect(wrapper.find(IOSHeader).exists()).toBe(true);
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
it('is false for Android Tablet — does not render IOSHeader', () => {
|
|
1083
|
+
const wrapper = mountWithIntl(
|
|
1084
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_ANDROID_TABLET} selectedBrowser={BROWSER_CHROME} />
|
|
1085
|
+
);
|
|
1086
|
+
expect(wrapper.find(IOSHeader).exists()).toBe(false);
|
|
1087
|
+
expect(wrapper.find(AndroidMobileChromeHeader).exists()).toBe(true);
|
|
1088
|
+
});
|
|
1089
|
+
|
|
1090
|
+
it('is false for Windows — does not render IOSHeader', () => {
|
|
1091
|
+
const wrapper = mountWithIntl(
|
|
1092
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_WINDOWS} selectedBrowser={BROWSER_CHROME} />
|
|
1093
|
+
);
|
|
1094
|
+
expect(wrapper.find(IOSHeader).exists()).toBe(false);
|
|
1095
|
+
});
|
|
1096
|
+
|
|
1097
|
+
it('is false for macOS — does not render IOSHeader', () => {
|
|
1098
|
+
const wrapper = mountWithIntl(
|
|
1099
|
+
<NotificationContainer {...defaultProps} selectedOS={OS_MACOS} selectedBrowser={BROWSER_SAFARI} />
|
|
1100
|
+
);
|
|
1101
|
+
expect(wrapper.find(IOSHeader).exists()).toBe(false);
|
|
1102
|
+
});
|
|
1103
|
+
});
|
|
1104
|
+
|
|
1105
|
+
describe('platform.isMacOsBrandIconBrowser getter (isMacOs && supportsBrandIcon)', () => {
|
|
1106
|
+
it('is true for macOS + Chrome (Chrome is in BRAND_ICON_SUPPORTED_BROWSERS) — shows brand icon in expanded', () => {
|
|
1107
|
+
const wrapper = mountWithIntl(
|
|
1108
|
+
<NotificationContainer
|
|
1109
|
+
{...defaultProps}
|
|
1110
|
+
selectedOS={OS_MACOS}
|
|
1111
|
+
selectedBrowser={BROWSER_CHROME}
|
|
1112
|
+
notificationState={NOTIFICATION_STATE_EXPANDED}
|
|
1113
|
+
brandIcon="brand.png"
|
|
1114
|
+
enableBrandIconPreview={true}
|
|
1115
|
+
/>
|
|
1116
|
+
);
|
|
1117
|
+
expect(wrapper.find(NotificationExpandedContent).prop('shouldShowBrandIconInExpandedMac')).toBe(true);
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
it('is true for macOS + Edge (Edge is in BRAND_ICON_SUPPORTED_BROWSERS)', () => {
|
|
1121
|
+
const wrapper = mountWithIntl(
|
|
1122
|
+
<NotificationContainer
|
|
1123
|
+
{...defaultProps}
|
|
1124
|
+
selectedOS={OS_MACOS}
|
|
1125
|
+
selectedBrowser={BROWSER_EDGE}
|
|
1126
|
+
notificationState={NOTIFICATION_STATE_EXPANDED}
|
|
1127
|
+
brandIcon="brand.png"
|
|
1128
|
+
enableBrandIconPreview={true}
|
|
1129
|
+
/>
|
|
1130
|
+
);
|
|
1131
|
+
expect(wrapper.find(NotificationExpandedContent).prop('shouldShowBrandIconInExpandedMac')).toBe(true);
|
|
1132
|
+
});
|
|
1133
|
+
|
|
1134
|
+
it('is true for macOS + Opera (Opera is in BRAND_ICON_SUPPORTED_BROWSERS)', () => {
|
|
1135
|
+
const wrapper = mountWithIntl(
|
|
1136
|
+
<NotificationContainer
|
|
1137
|
+
{...defaultProps}
|
|
1138
|
+
selectedOS={OS_MACOS}
|
|
1139
|
+
selectedBrowser={BROWSER_OPERA}
|
|
1140
|
+
notificationState={NOTIFICATION_STATE_EXPANDED}
|
|
1141
|
+
brandIcon="brand.png"
|
|
1142
|
+
enableBrandIconPreview={true}
|
|
1143
|
+
/>
|
|
1144
|
+
);
|
|
1145
|
+
expect(wrapper.find(NotificationExpandedContent).prop('shouldShowBrandIconInExpandedMac')).toBe(true);
|
|
1146
|
+
});
|
|
1147
|
+
|
|
1148
|
+
it('is false for macOS + Safari (Safari is NOT in BRAND_ICON_SUPPORTED_BROWSERS)', () => {
|
|
1149
|
+
const wrapper = mountWithIntl(
|
|
1150
|
+
<NotificationContainer
|
|
1151
|
+
{...defaultProps}
|
|
1152
|
+
selectedOS={OS_MACOS}
|
|
1153
|
+
selectedBrowser={BROWSER_SAFARI}
|
|
1154
|
+
notificationState={NOTIFICATION_STATE_EXPANDED}
|
|
1155
|
+
brandIcon="brand.png"
|
|
1156
|
+
enableBrandIconPreview={true}
|
|
1157
|
+
/>
|
|
1158
|
+
);
|
|
1159
|
+
expect(wrapper.find(NotificationExpandedContent).prop('shouldShowBrandIconInExpandedMac')).toBe(false);
|
|
1160
|
+
});
|
|
1161
|
+
|
|
1162
|
+
it('is false for Windows + Chrome (not macOS) — renders WindowsChromeExpanded instead', () => {
|
|
1163
|
+
const wrapper = mountWithIntl(
|
|
1164
|
+
<NotificationContainer
|
|
1165
|
+
{...defaultProps}
|
|
1166
|
+
selectedOS={OS_WINDOWS}
|
|
1167
|
+
selectedBrowser={BROWSER_CHROME}
|
|
1168
|
+
notificationState={NOTIFICATION_STATE_EXPANDED}
|
|
1169
|
+
brandIcon="brand.png"
|
|
1170
|
+
enableBrandIconPreview={true}
|
|
1171
|
+
/>
|
|
1172
|
+
);
|
|
1173
|
+
expect(wrapper.find(NotificationExpandedContent).exists()).toBe(false);
|
|
1174
|
+
expect(wrapper.find(WindowsChromeExpanded).exists()).toBe(true);
|
|
1175
|
+
});
|
|
1176
|
+
|
|
1177
|
+
it('is false for macOS + Chrome when brandIcon is empty', () => {
|
|
1178
|
+
const wrapper = mountWithIntl(
|
|
1179
|
+
<NotificationContainer
|
|
1180
|
+
{...defaultProps}
|
|
1181
|
+
selectedOS={OS_MACOS}
|
|
1182
|
+
selectedBrowser={BROWSER_CHROME}
|
|
1183
|
+
notificationState={NOTIFICATION_STATE_EXPANDED}
|
|
1184
|
+
brandIcon=""
|
|
1185
|
+
enableBrandIconPreview={true}
|
|
1186
|
+
/>
|
|
1187
|
+
);
|
|
1188
|
+
expect(wrapper.find(NotificationExpandedContent).prop('shouldShowBrandIconInExpandedMac')).toBe(false);
|
|
1189
|
+
});
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
describe('shouldRenderSeparateIOSCTAs behavior', () => {
|
|
1193
|
+
const iosCollapsedWithCTAs = {
|
|
1194
|
+
...defaultProps,
|
|
1195
|
+
selectedOS: OS_IOS,
|
|
1196
|
+
selectedBrowser: BROWSER_CHROME,
|
|
1197
|
+
notificationState: NOTIFICATION_STATE_COLLAPSED,
|
|
1198
|
+
showSeparateIOSCTAs: true,
|
|
1199
|
+
enableCtas: true,
|
|
1200
|
+
buttons: [{ text: 'Accept' }, { text: 'Dismiss' }],
|
|
1201
|
+
};
|
|
1202
|
+
|
|
1203
|
+
it('renders ios-notification-wrapper when all conditions are satisfied', () => {
|
|
1204
|
+
const wrapper = mountWithIntl(<NotificationContainer {...iosCollapsedWithCTAs} />);
|
|
1205
|
+
expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(true);
|
|
1206
|
+
});
|
|
1207
|
+
|
|
1208
|
+
it('renders ios-cta-container inside the wrapper', () => {
|
|
1209
|
+
const wrapper = mountWithIntl(<NotificationContainer {...iosCollapsedWithCTAs} />);
|
|
1210
|
+
expect(wrapper.find('.ios-cta-container').exists()).toBe(true);
|
|
1211
|
+
});
|
|
1212
|
+
|
|
1213
|
+
it('renders one ios-cta-button per button', () => {
|
|
1214
|
+
const wrapper = mountWithIntl(<NotificationContainer {...iosCollapsedWithCTAs} />);
|
|
1215
|
+
expect(wrapper.find('.ios-cta-button').length).toBe(2);
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1218
|
+
it('renders the correct button label text', () => {
|
|
1219
|
+
const wrapper = mountWithIntl(
|
|
1220
|
+
<NotificationContainer
|
|
1221
|
+
{...iosCollapsedWithCTAs}
|
|
1222
|
+
buttons={[{ text: 'Confirm' }]}
|
|
1223
|
+
/>
|
|
1224
|
+
);
|
|
1225
|
+
expect(wrapper.find('.ios-cta-button').first().text()).toBe('Confirm');
|
|
1226
|
+
});
|
|
1227
|
+
|
|
1228
|
+
it('still renders the notification-container inside the wrapper', () => {
|
|
1229
|
+
const wrapper = mountWithIntl(<NotificationContainer {...iosCollapsedWithCTAs} />);
|
|
1230
|
+
const iosWrapper = wrapper.find('.ios-notification-wrapper');
|
|
1231
|
+
expect(iosWrapper.find('.notification-container').exists()).toBe(true);
|
|
1232
|
+
});
|
|
1233
|
+
|
|
1234
|
+
it('does NOT render ios-notification-wrapper when showSeparateIOSCTAs is false', () => {
|
|
1235
|
+
const wrapper = mountWithIntl(
|
|
1236
|
+
<NotificationContainer {...iosCollapsedWithCTAs} showSeparateIOSCTAs={false} />
|
|
1237
|
+
);
|
|
1238
|
+
expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
|
|
1239
|
+
});
|
|
1240
|
+
|
|
1241
|
+
it('does NOT render ios-notification-wrapper when expanded (isExpanded is true)', () => {
|
|
1242
|
+
const wrapper = mountWithIntl(
|
|
1243
|
+
<NotificationContainer
|
|
1244
|
+
{...iosCollapsedWithCTAs}
|
|
1245
|
+
notificationState={NOTIFICATION_STATE_EXPANDED}
|
|
1246
|
+
supportsExpanded={true}
|
|
1247
|
+
/>
|
|
1248
|
+
);
|
|
1249
|
+
expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
|
|
1250
|
+
});
|
|
1251
|
+
|
|
1252
|
+
it('does NOT render ios-notification-wrapper when enableCtas is false', () => {
|
|
1253
|
+
const wrapper = mountWithIntl(
|
|
1254
|
+
<NotificationContainer {...iosCollapsedWithCTAs} enableCtas={false} />
|
|
1255
|
+
);
|
|
1256
|
+
expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
|
|
1257
|
+
});
|
|
1258
|
+
|
|
1259
|
+
it('does NOT render ios-notification-wrapper when buttons array is empty', () => {
|
|
1260
|
+
const wrapper = mountWithIntl(
|
|
1261
|
+
<NotificationContainer {...iosCollapsedWithCTAs} buttons={[]} />
|
|
1262
|
+
);
|
|
1263
|
+
expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
|
|
1264
|
+
});
|
|
1265
|
+
|
|
1266
|
+
it('does NOT render ios-notification-wrapper for iPadOS (not an iOS browser)', () => {
|
|
1267
|
+
const wrapper = mountWithIntl(
|
|
1268
|
+
<NotificationContainer {...iosCollapsedWithCTAs} selectedOS={OS_IPADOS} />
|
|
1269
|
+
);
|
|
1270
|
+
expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
|
|
1271
|
+
});
|
|
1272
|
+
|
|
1273
|
+
it('does NOT render ios-notification-wrapper for macOS', () => {
|
|
1274
|
+
const wrapper = mountWithIntl(
|
|
1275
|
+
<NotificationContainer {...iosCollapsedWithCTAs} selectedOS={OS_MACOS} />
|
|
1276
|
+
);
|
|
1277
|
+
expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
|
|
1278
|
+
});
|
|
1279
|
+
|
|
1280
|
+
it('does NOT render ios-notification-wrapper for Android Mobile', () => {
|
|
1281
|
+
const wrapper = mountWithIntl(
|
|
1282
|
+
<NotificationContainer {...iosCollapsedWithCTAs} selectedOS={OS_ANDROID_MOBILE} />
|
|
1283
|
+
);
|
|
1284
|
+
expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
|
|
1285
|
+
});
|
|
1286
|
+
});
|
|
1287
|
+
|
|
1019
1288
|
describe('Snapshot Tests', () => {
|
|
1020
1289
|
it('should match snapshot for macOS Chrome collapsed', () => {
|
|
1021
1290
|
const wrapper = shallowWithIntl(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isValidHttpUrl } from './urlValidation';
|
|
2
2
|
import { validateTags } from '../../../../utils/tagValidations';
|
|
3
3
|
import globalMessages from '../../../Cap/messages';
|
|
4
|
+
import { hasPersonalizationTags } from '../../../../utils/commonUtils';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Validates template name (checks if empty)
|
|
@@ -10,16 +11,34 @@ import globalMessages from '../../../Cap/messages';
|
|
|
10
11
|
export const validateTemplateName = (value) => !value || value.trim() === '';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
* Validates notification title
|
|
14
|
+
* Validates notification title (required and optional tag validation)
|
|
14
15
|
* @param {string} value - The title value
|
|
15
16
|
* @param {Function} formatMessage - i18n format message function
|
|
16
17
|
* @param {Object} messages - Message definitions
|
|
18
|
+
* @param {Object} [validationConfig] - Optional config for tag validation
|
|
19
|
+
* @param {boolean} [isFullMode] - Optional; when set with validationConfig, runs tag validation
|
|
17
20
|
* @returns {string} Error message if invalid, empty string if valid
|
|
18
21
|
*/
|
|
19
|
-
export const validateTitle = (value, formatMessage, messages) => {
|
|
22
|
+
export const validateTitle = (value, formatMessage, messages, restrictPersonalization, validationConfig, isFullMode) => {
|
|
20
23
|
if (!value || value.trim() === '') {
|
|
21
24
|
return formatMessage(messages.titleRequired);
|
|
22
25
|
}
|
|
26
|
+
if (restrictPersonalization && hasPersonalizationTags(value)) {
|
|
27
|
+
return formatMessage(messages.personalizationTokensErrorMessage);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (validationConfig != null) {
|
|
31
|
+
const validationResponse = validateTags({
|
|
32
|
+
content: value,
|
|
33
|
+
...validationConfig,
|
|
34
|
+
isFullMode,
|
|
35
|
+
}) || {};
|
|
36
|
+
|
|
37
|
+
if (validationResponse?.isBraceError) {
|
|
38
|
+
return formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
23
42
|
return '';
|
|
24
43
|
};
|
|
25
44
|
|
|
@@ -34,11 +53,11 @@ export const validateUrl = (value, formatMessage, messages) => {
|
|
|
34
53
|
if (!value || value.trim() === '') {
|
|
35
54
|
return formatMessage(messages.urlRequired);
|
|
36
55
|
}
|
|
37
|
-
|
|
56
|
+
|
|
38
57
|
if (!isValidHttpUrl(value)) {
|
|
39
58
|
return formatMessage(messages.urlInvalid);
|
|
40
59
|
}
|
|
41
|
-
|
|
60
|
+
|
|
42
61
|
return '';
|
|
43
62
|
};
|
|
44
63
|
|
|
@@ -50,27 +69,24 @@ export const validateUrl = (value, formatMessage, messages) => {
|
|
|
50
69
|
* @param {Object} validationConfig - Configuration for tag validation
|
|
51
70
|
* @returns {string} Error message if invalid, empty string if valid
|
|
52
71
|
*/
|
|
53
|
-
export const validateMessageContent = (value, formatMessage, messages, validationConfig, isFullMode) => {
|
|
72
|
+
export const validateMessageContent = (value, formatMessage, messages, validationConfig, isFullMode, restrictPersonalization) => {
|
|
54
73
|
if (!value || value.trim() === '') {
|
|
55
74
|
return formatMessage(messages.messageRequired);
|
|
56
75
|
}
|
|
57
|
-
|
|
76
|
+
|
|
58
77
|
const validationResponse = validateTags({
|
|
59
78
|
content: value,
|
|
60
79
|
...validationConfig,
|
|
61
80
|
isFullMode,
|
|
62
81
|
}) || {};
|
|
63
|
-
|
|
64
|
-
if (validationResponse?.unsupportedTags?.length) {
|
|
65
|
-
return formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
66
|
-
unsupportedTags: validationResponse.unsupportedTags.join(', '),
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
82
|
+
|
|
70
83
|
if (validationResponse?.isBraceError) {
|
|
71
84
|
return formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
72
85
|
}
|
|
73
|
-
|
|
86
|
+
|
|
87
|
+
if (restrictPersonalization && hasPersonalizationTags(value)) {
|
|
88
|
+
return formatMessage(messages.personalizationTokensErrorMessage);
|
|
89
|
+
}
|
|
90
|
+
|
|
74
91
|
return '';
|
|
75
92
|
};
|
|
76
|
-
|