@capillarytech/creatives-library 9.0.56-betaa.0 → 9.0.56
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/constants/unified.js +9 -4
- package/package.json +1 -1
- package/services/api.js +25 -4
- package/utils/common.js +0 -12
- package/utils/templateVarUtils.js +16 -0
- package/utils/tests/templateVarUtils.test.js +44 -0
- package/v2Components/CapActionButton/index.js +73 -60
- package/v2Components/CapActionButton/index.scss +44 -28
- package/v2Components/CapActionButton/messages.js +7 -3
- package/v2Components/CapActionButton/tests/index.test.js +17 -1
- package/v2Components/CapWhatsappCTA/messages.js +4 -0
- package/v2Components/CapWhatsappCarouselButton/index.js +42 -33
- package/v2Components/CapWhatsappCarouselButton/index.scss +44 -2
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +13 -0
- package/v2Components/CommonTestAndPreview/actions.js +13 -0
- package/v2Components/CommonTestAndPreview/constants.js +8 -0
- package/v2Components/CommonTestAndPreview/index.js +55 -3
- package/v2Components/CommonTestAndPreview/reducer.js +20 -0
- package/v2Components/CommonTestAndPreview/sagas.js +28 -0
- package/v2Components/CommonTestAndPreview/selectors.js +6 -0
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +106 -0
- package/v2Components/CommonTestAndPreview/tests/actions.test.js +15 -0
- package/v2Components/CommonTestAndPreview/tests/constants.test.js +9 -1
- package/v2Components/CommonTestAndPreview/tests/index.test.js +101 -0
- package/v2Components/CommonTestAndPreview/tests/reducer.test.js +41 -0
- package/v2Components/CommonTestAndPreview/tests/sagas.test.js +84 -0
- package/v2Components/CommonTestAndPreview/tests/selectors.test.js +12 -0
- package/v2Components/FormBuilder/Functional/FormBuilderShell.js +46 -320
- package/v2Components/FormBuilder/Functional/channels/registry.js +0 -2
- package/v2Components/FormBuilder/Functional/constants.js +8 -43
- package/v2Components/FormBuilder/Functional/core/schema/initializeFormState.js +28 -175
- package/v2Components/FormBuilder/Functional/core/store/formReducer.js +6 -75
- package/v2Components/FormBuilder/Functional/core/store/toLegacyFormData.js +20 -10
- package/v2Components/FormBuilder/Functional/layout/FieldSlot.js +1 -9
- package/v2Components/FormBuilder/Functional/layout/SchemaForm.js +3 -20
- package/v2Components/FormBuilder/Functional/layout/Section.js +1 -6
- package/v2Components/FormBuilder/Functional/tests/fieldSlot.test.js +2 -9
- package/v2Components/FormBuilder/Functional/tests/schemaForm.test.js +0 -17
- package/v2Components/FormBuilder/index.js +12 -34
- package/v2Components/FormBuilder/tests/entryGate.test.js +7 -94
- package/v2Components/TestAndPreviewSlidebox/index.js +9 -0
- package/v2Containers/CommunicationFlow/CommunicationFlow.js +140 -75
- package/v2Containers/CommunicationFlow/CommunicationFlow.scss +18 -2
- package/v2Containers/CommunicationFlow/CommunicationFlowCard.js +67 -28
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +503 -51
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlowCard.test.js +98 -4
- package/v2Containers/CommunicationFlow/Tests/constants.test.js +85 -0
- package/v2Containers/CommunicationFlow/constants.js +65 -4
- package/v2Containers/CommunicationFlow/index.js +16 -23
- package/v2Containers/CommunicationFlow/messages.js +11 -3
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +27 -11
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +4 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +176 -4
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +22 -4
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +14 -4
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +11 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +51 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +11 -4
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +19 -5
- package/v2Containers/CreativesContainer/SlideBoxContent.js +15 -0
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +6 -2
- package/v2Containers/CreativesContainer/index.js +29 -3
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +29 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +18 -5
- package/v2Containers/CreativesContainer/tests/index.test.js +12 -0
- package/v2Containers/MobilePush/Create/index.js +18 -1
- package/v2Containers/MobilePush/Create/test/contentValidity.test.js +96 -0
- package/v2Containers/MobilePush/Edit/index.js +18 -1
- package/v2Containers/MobilePush/Edit/test/contentValidity.test.js +116 -0
- package/v2Containers/MobilePush/commonMethods.js +49 -1
- package/v2Containers/MobilePushNew/index.js +29 -4
- package/v2Containers/MobilePushNew/tests/index.test.js +119 -0
- package/v2Containers/MobilePushNew/tests/utils.test.js +82 -0
- package/v2Containers/MobilePushNew/utils.js +34 -1
- package/v2Containers/MobilepushWrapper/index.js +3 -1
- package/v2Containers/Rcs/index.js +34 -0
- package/v2Containers/Rcs/index.scss +15 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +115 -19
- package/v2Containers/Rcs/tests/index.test.js +67 -0
- package/v2Containers/Sms/Create/index.js +3 -1
- package/v2Containers/Sms/Edit/index.js +25 -0
- package/v2Containers/Sms/Edit/tests/index.test.js +85 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +27 -3
- package/v2Containers/Viber/index.js +24 -1
- package/v2Containers/Viber/tests/index.test.js +103 -0
- package/v2Containers/WebPush/Create/index.js +19 -0
- package/v2Containers/WebPush/Create/preview/WebPushPreview.js +17 -12
- package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +5 -0
- package/v2Containers/WebPush/Create/tests/contentValidity.test.js +294 -0
- package/v2Containers/Whatsapp/index.js +25 -4
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +306 -34
- package/v2Containers/Whatsapp/tests/index.test.js +115 -0
- package/v2Containers/Zalo/index.js +28 -1
- package/v2Containers/Zalo/tests/index.test.js +99 -0
- package/v2Containers/mockdata.js +25 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/buildSubmitPayload.js +0 -10
- package/v2Components/FormBuilder/Functional/channels/mobilepush/config.js +0 -82
- package/v2Components/FormBuilder/Functional/channels/mobilepush/getEditorErrorDescriptor.js +0 -74
- package/v2Components/FormBuilder/Functional/channels/mobilepush/index.js +0 -28
- package/v2Components/FormBuilder/Functional/channels/mobilepush/modals.js +0 -19
- package/v2Components/FormBuilder/Functional/channels/mobilepush/runSubmitPipeline.js +0 -45
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/getEditorErrorDescriptor.test.js +0 -162
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/modals.test.js +0 -37
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/runSubmitPipeline.test.js +0 -70
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/validate.test.js +0 -274
- package/v2Components/FormBuilder/Functional/channels/mobilepush/validate.js +0 -251
- package/v2Components/FormBuilder/Functional/layout/TabsContainer.js +0 -89
- package/v2Components/FormBuilder/Functional/renderers/mpushRenderers.js +0 -440
- package/v2Components/FormBuilder/Functional/tests/mpush.crossFlowParity.test.js +0 -430
- package/v2Components/FormBuilder/Functional/tests/mpush.ctaFlows.parity.test.js +0 -282
- package/v2Components/FormBuilder/Functional/tests/mpush.editContainer.parity.test.js +0 -141
- package/v2Components/FormBuilder/Functional/tests/mpush.engine.test.js +0 -306
- package/v2Components/FormBuilder/Functional/tests/mpush.shellEvents.test.js +0 -151
- package/v2Components/FormBuilder/Functional/tests/mpushRenderers.test.js +0 -342
- package/v2Components/FormBuilder/Functional/tests/tabsContainer.test.js +0 -110
- package/v2Components/FormBuilder/tests/mpush.characterization.test.js +0 -459
|
@@ -37,7 +37,49 @@
|
|
|
37
37
|
height: auto;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
.whatsapp-
|
|
41
|
-
|
|
40
|
+
.whatsapp-saved-cta-cell {
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
min-width: 0;
|
|
44
|
+
|
|
45
|
+
> * {
|
|
46
|
+
min-width: 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.whatsapp-saved-cta-text-cell {
|
|
51
|
+
flex: 0 1 10rem;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.whatsapp-saved-cta-type-cell {
|
|
55
|
+
flex: 0 1 5.5rem;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.whatsapp-saved-cta-url-cell {
|
|
59
|
+
flex: 1 1 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.whatsapp-saved-cta-actions-cell {
|
|
63
|
+
flex: 0 0 4rem;
|
|
64
|
+
justify-content: flex-end;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.whatsapp-saved-cta-action-icons {
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
flex-shrink: 0;
|
|
71
|
+
gap: $CAP_SPACE_12;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// CapTooltip nests `.url` two levels down, so these — not `.url` — are the
|
|
75
|
+
// boxes that must be allowed to shrink for the ellipsis to apply.
|
|
76
|
+
.whatsapp-cta-url-tooltip-wrapper {
|
|
77
|
+
flex: 1 1 0;
|
|
78
|
+
min-width: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.whatsapp-cta-url-tooltip-trigger {
|
|
82
|
+
width: 100%;
|
|
83
|
+
min-width: 0;
|
|
42
84
|
}
|
|
43
85
|
}
|
|
@@ -139,6 +139,19 @@ const UnifiedPreview = ({
|
|
|
139
139
|
);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
case CHANNELS.LINE:
|
|
143
|
+
// LINE currently supports plain text only, so reuse the SMS bubble preview; rich message types are not rendered yet.
|
|
144
|
+
return (
|
|
145
|
+
<SmsPreviewContent
|
|
146
|
+
content={typeof content === 'string' ? content : (content?.resolvedBody || '')}
|
|
147
|
+
device={device}
|
|
148
|
+
isUpdating={isUpdating}
|
|
149
|
+
error={error}
|
|
150
|
+
formatMessage={formatMessage}
|
|
151
|
+
showHeader={showHeader}
|
|
152
|
+
/>
|
|
153
|
+
);
|
|
154
|
+
|
|
142
155
|
case CHANNELS.WHATSAPP: {
|
|
143
156
|
// WhatsApp content is an object with templateMsg, media, CTA, etc.
|
|
144
157
|
const whatsappContent = typeof content === 'object' ? content : {};
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
EXTRACT_TAGS_REQUESTED,
|
|
11
11
|
UPDATE_PREVIEW_REQUESTED,
|
|
12
12
|
SEND_TEST_MESSAGE_REQUESTED,
|
|
13
|
+
SEND_CCS_TEST_MESSAGE_REQUESTED,
|
|
13
14
|
CLEAR_CUSTOMER_SEARCH_STATE,
|
|
14
15
|
GET_TEST_CUSTOMERS_REQUESTED,
|
|
15
16
|
GET_TEST_GROUPS_REQUESTED,
|
|
@@ -65,6 +66,18 @@ export const sendTestMessageRequested = (payload, callback) => ({
|
|
|
65
66
|
callback,
|
|
66
67
|
});
|
|
67
68
|
|
|
69
|
+
/**
|
|
70
|
+
* notify/ui only — send a test message through CCS's send/transaction endpoint
|
|
71
|
+
* against a real CommDefinition, instead of the legacy createMessageMeta/sendTestMessage flow.
|
|
72
|
+
* @param {Object} payload - { commDefinitionId|referenceId, uniqueKey, isTest, recipient }
|
|
73
|
+
* @param {Function} callback - Success/error callback
|
|
74
|
+
*/
|
|
75
|
+
export const sendCcsTestMessageRequested = (payload, callback) => ({
|
|
76
|
+
type: SEND_CCS_TEST_MESSAGE_REQUESTED,
|
|
77
|
+
payload,
|
|
78
|
+
callback,
|
|
79
|
+
});
|
|
80
|
+
|
|
68
81
|
/**
|
|
69
82
|
* Clear all customer search state
|
|
70
83
|
*/
|
|
@@ -29,6 +29,11 @@ export const SEND_TEST_MESSAGE_REQUESTED = 'app/CommonTestAndPreview/SEND_TEST_M
|
|
|
29
29
|
export const SEND_TEST_MESSAGE_SUCCESS = 'app/CommonTestAndPreview/SEND_TEST_MESSAGE_SUCCESS';
|
|
30
30
|
export const SEND_TEST_MESSAGE_FAILURE = 'app/CommonTestAndPreview/SEND_TEST_MESSAGE_FAILURE';
|
|
31
31
|
|
|
32
|
+
// Send CCS Test Message (notify/ui — send/transaction against a real CommDefinition)
|
|
33
|
+
export const SEND_CCS_TEST_MESSAGE_REQUESTED = 'app/CommonTestAndPreview/SEND_CCS_TEST_MESSAGE_REQUESTED';
|
|
34
|
+
export const SEND_CCS_TEST_MESSAGE_SUCCESS = 'app/CommonTestAndPreview/SEND_CCS_TEST_MESSAGE_SUCCESS';
|
|
35
|
+
export const SEND_CCS_TEST_MESSAGE_FAILURE = 'app/CommonTestAndPreview/SEND_CCS_TEST_MESSAGE_FAILURE';
|
|
36
|
+
|
|
32
37
|
// Test Customers
|
|
33
38
|
export const GET_TEST_CUSTOMERS_REQUESTED = 'app/CommonTestAndPreview/GET_TEST_CUSTOMERS_REQUESTED';
|
|
34
39
|
export const GET_TEST_CUSTOMERS_SUCCESS = 'app/CommonTestAndPreview/GET_TEST_CUSTOMERS_SUCCESS';
|
|
@@ -85,6 +90,7 @@ export const CHANNELS = {
|
|
|
85
90
|
VIBER: 'VIBER',
|
|
86
91
|
ZALO: 'ZALO',
|
|
87
92
|
WEBPUSH: 'WEBPUSH',
|
|
93
|
+
LINE: 'LINE',
|
|
88
94
|
};
|
|
89
95
|
|
|
90
96
|
/** Unified preview tab keys when RCS shows RCS + SMS fallback panes. */
|
|
@@ -100,6 +106,7 @@ export const CHANNELS_USING_ANDROID_PREVIEW_DEVICE = [
|
|
|
100
106
|
CHANNELS.INAPP,
|
|
101
107
|
CHANNELS.MOBILEPUSH,
|
|
102
108
|
CHANNELS.VIBER,
|
|
109
|
+
CHANNELS.LINE,
|
|
103
110
|
];
|
|
104
111
|
|
|
105
112
|
/** RCS createMessageMeta test payload — rich card envelope literals. */
|
|
@@ -290,6 +297,7 @@ export const ERROR_MESSAGES = {
|
|
|
290
297
|
FAILED_TO_EXTRACT_TAGS: 'Failed to extract tags',
|
|
291
298
|
FAILED_TO_UPDATE_PREVIEW: 'Failed to update preview',
|
|
292
299
|
FAILED_TO_SEND_TEST_EMAIL: 'Failed to send test email',
|
|
300
|
+
FAILED_TO_SEND_CCS_TEST_MESSAGE: 'Failed to send test message',
|
|
293
301
|
PROFILE_IS_EMPTY: 'Profile is empty',
|
|
294
302
|
NO_TEST_CUSTOMERS_FOUND: 'No test customers found',
|
|
295
303
|
FAILED_TO_FETCH_TEST_CUSTOMERS: 'Failed to fetch test customers',
|
|
@@ -200,6 +200,7 @@ const CommonTestAndPreview = (props) => {
|
|
|
200
200
|
messageMetaConfigId,
|
|
201
201
|
prefilledValues,
|
|
202
202
|
isSendingTestMessage,
|
|
203
|
+
isSendingCcsTestMessage,
|
|
203
204
|
updatePreviewError,
|
|
204
205
|
updatePreviewErrors,
|
|
205
206
|
fetchPrefilledValuesError,
|
|
@@ -208,6 +209,8 @@ const CommonTestAndPreview = (props) => {
|
|
|
208
209
|
wecrmAccounts = [],
|
|
209
210
|
isLoadingSenderDetails = false,
|
|
210
211
|
orgUnitId = -1,
|
|
212
|
+
// notify/ui only:{commDefinitionId, referenceId} routes "Send test" to CCS's send/transaction endpoint.
|
|
213
|
+
ccsSendTransaction,
|
|
211
214
|
// Email-specific props
|
|
212
215
|
beeInstance,
|
|
213
216
|
currentTab = 1,
|
|
@@ -3621,11 +3624,53 @@ const CommonTestAndPreview = (props) => {
|
|
|
3621
3624
|
setIsCustomerDataLoading(false);
|
|
3622
3625
|
}
|
|
3623
3626
|
};
|
|
3624
|
-
|
|
3627
|
+
|
|
3625
3628
|
/**
|
|
3626
3629
|
* Handle send test message
|
|
3627
3630
|
*/
|
|
3631
|
+
// notify/ui sends tests via CCS's CommDefinition send/transaction endpoint using the standard action/saga flow, not the legacy messageMeta flow.
|
|
3632
|
+
const handleCcsSendTestMessage = () => {
|
|
3633
|
+
const allUserIds = [];
|
|
3634
|
+
selectedTestEntities.forEach((entityId) => {
|
|
3635
|
+
const group = testGroups.find((testGroup) => testEntityIdsEqual(testGroup.groupId, entityId));
|
|
3636
|
+
if (group) {
|
|
3637
|
+
allUserIds.push(...group.userIds);
|
|
3638
|
+
} else {
|
|
3639
|
+
allUserIds.push(entityId);
|
|
3640
|
+
}
|
|
3641
|
+
});
|
|
3642
|
+
const uniqueUserIds = [...new Set(allUserIds)];
|
|
3643
|
+
const { commDefinitionId, referenceId } = ccsSendTransaction;
|
|
3644
|
+
|
|
3645
|
+
actions.sendCcsTestMessageRequested(
|
|
3646
|
+
{
|
|
3647
|
+
...(commDefinitionId ? { commDefinitionId } : { referenceId }),
|
|
3648
|
+
uniqueKey: `test_${Date.now()}`,
|
|
3649
|
+
isTest: true,
|
|
3650
|
+
recipient: {
|
|
3651
|
+
identifiers: uniqueUserIds.map((userId) => ({ type: 'USER_ID', value: String(userId) })),
|
|
3652
|
+
tagValues: customValues,
|
|
3653
|
+
},
|
|
3654
|
+
},
|
|
3655
|
+
(success) => {
|
|
3656
|
+
if (success) {
|
|
3657
|
+
CapNotification.success({
|
|
3658
|
+
message: formatMessage(messages.testMessageSent),
|
|
3659
|
+
});
|
|
3660
|
+
} else {
|
|
3661
|
+
CapNotification.error({
|
|
3662
|
+
message: formatMessage(messages.testMessageFailed),
|
|
3663
|
+
});
|
|
3664
|
+
}
|
|
3665
|
+
},
|
|
3666
|
+
);
|
|
3667
|
+
};
|
|
3668
|
+
|
|
3628
3669
|
const handleSendTestMessage = () => {
|
|
3670
|
+
if (ccsSendTransaction) {
|
|
3671
|
+
handleCcsSendTestMessage();
|
|
3672
|
+
return;
|
|
3673
|
+
}
|
|
3629
3674
|
const allUserIds = [];
|
|
3630
3675
|
selectedTestEntities.forEach((entityId) => {
|
|
3631
3676
|
const group = testGroups.find((testGroup) => testEntityIdsEqual(testGroup.groupId, entityId));
|
|
@@ -3763,7 +3808,7 @@ const CommonTestAndPreview = (props) => {
|
|
|
3763
3808
|
formData={formDataForSendTest}
|
|
3764
3809
|
content={getCurrentContent}
|
|
3765
3810
|
channel={channel}
|
|
3766
|
-
isSendingTestMessage={isSendingTestMessage}
|
|
3811
|
+
isSendingTestMessage={isSendingTestMessage || isSendingCcsTestMessage}
|
|
3767
3812
|
renderAddTestCustomerButton={renderAddTestCustomerButton}
|
|
3768
3813
|
formatMessage={formatMessage}
|
|
3769
3814
|
deliverySettings={testPreviewDeliverySettings[channel]}
|
|
@@ -3816,7 +3861,7 @@ const CommonTestAndPreview = (props) => {
|
|
|
3816
3861
|
header={slideboxHeader}
|
|
3817
3862
|
handleClose={handleClose}
|
|
3818
3863
|
show={show}
|
|
3819
|
-
size="size-
|
|
3864
|
+
size="size-l"
|
|
3820
3865
|
content={(
|
|
3821
3866
|
<CapSpin
|
|
3822
3867
|
spinning={isCustomerDataLoading}
|
|
@@ -3913,11 +3958,16 @@ CommonTestAndPreview.propTypes = {
|
|
|
3913
3958
|
message: PropTypes.string,
|
|
3914
3959
|
})),
|
|
3915
3960
|
isSendingTestMessage: PropTypes.bool.isRequired,
|
|
3961
|
+
isSendingCcsTestMessage: PropTypes.bool,
|
|
3916
3962
|
intl: PropTypes.object.isRequired,
|
|
3917
3963
|
senderDetailsByChannel: PropTypes.object,
|
|
3918
3964
|
wecrmAccounts: PropTypes.array,
|
|
3919
3965
|
isLoadingSenderDetails: PropTypes.bool,
|
|
3920
3966
|
orgUnitId: PropTypes.number,
|
|
3967
|
+
ccsSendTransaction: PropTypes.shape({
|
|
3968
|
+
commDefinitionId: PropTypes.string,
|
|
3969
|
+
referenceId: PropTypes.string,
|
|
3970
|
+
}),
|
|
3921
3971
|
|
|
3922
3972
|
// Email-specific props
|
|
3923
3973
|
beeInstance: PropTypes.object,
|
|
@@ -3957,6 +4007,8 @@ CommonTestAndPreview.defaultProps = {
|
|
|
3957
4007
|
wecrmAccounts: [],
|
|
3958
4008
|
isLoadingSenderDetails: false,
|
|
3959
4009
|
orgUnitId: -1,
|
|
4010
|
+
ccsSendTransaction: null,
|
|
4011
|
+
isSendingCcsTestMessage: false,
|
|
3960
4012
|
};
|
|
3961
4013
|
|
|
3962
4014
|
// ============================================
|
|
@@ -15,6 +15,9 @@ import {
|
|
|
15
15
|
SEND_TEST_MESSAGE_REQUESTED,
|
|
16
16
|
SEND_TEST_MESSAGE_SUCCESS,
|
|
17
17
|
SEND_TEST_MESSAGE_FAILURE,
|
|
18
|
+
SEND_CCS_TEST_MESSAGE_REQUESTED,
|
|
19
|
+
SEND_CCS_TEST_MESSAGE_SUCCESS,
|
|
20
|
+
SEND_CCS_TEST_MESSAGE_FAILURE,
|
|
18
21
|
CLEAR_CUSTOMER_SEARCH_STATE,
|
|
19
22
|
CLEAR_SEARCH_RESULTS,
|
|
20
23
|
GET_TEST_CUSTOMERS_REQUESTED,
|
|
@@ -69,6 +72,10 @@ const initialState = fromJS({
|
|
|
69
72
|
sendTestMessageError: null,
|
|
70
73
|
testMessageResponse: null,
|
|
71
74
|
|
|
75
|
+
// CCS test message state (notify/ui)
|
|
76
|
+
isSendingCcsTestMessage: false,
|
|
77
|
+
sendCcsTestMessageError: null,
|
|
78
|
+
|
|
72
79
|
tags: {
|
|
73
80
|
loading: false,
|
|
74
81
|
error: null,
|
|
@@ -194,6 +201,19 @@ const previewAndTestReducer = (state = initialState, action) => {
|
|
|
194
201
|
.set('isSendingTestMessage', false)
|
|
195
202
|
.set('sendTestMessageError', action.payload.error);
|
|
196
203
|
|
|
204
|
+
// Send CCS Test Message (notify/ui)
|
|
205
|
+
case SEND_CCS_TEST_MESSAGE_REQUESTED:
|
|
206
|
+
return state.set('isSendingCcsTestMessage', true)
|
|
207
|
+
.set('sendCcsTestMessageError', null);
|
|
208
|
+
|
|
209
|
+
case SEND_CCS_TEST_MESSAGE_SUCCESS:
|
|
210
|
+
return state.set('isSendingCcsTestMessage', false)
|
|
211
|
+
.set('sendCcsTestMessageError', null);
|
|
212
|
+
|
|
213
|
+
case SEND_CCS_TEST_MESSAGE_FAILURE:
|
|
214
|
+
return state.set('isSendingCcsTestMessage', false)
|
|
215
|
+
.set('sendCcsTestMessageError', action.payload.error);
|
|
216
|
+
|
|
197
217
|
// Clear Actions
|
|
198
218
|
case CLEAR_SEARCH_RESULTS:
|
|
199
219
|
return state.set('customers', [])
|
|
@@ -21,6 +21,9 @@ import {
|
|
|
21
21
|
SEND_TEST_MESSAGE_REQUESTED,
|
|
22
22
|
SEND_TEST_MESSAGE_SUCCESS,
|
|
23
23
|
SEND_TEST_MESSAGE_FAILURE,
|
|
24
|
+
SEND_CCS_TEST_MESSAGE_REQUESTED,
|
|
25
|
+
SEND_CCS_TEST_MESSAGE_SUCCESS,
|
|
26
|
+
SEND_CCS_TEST_MESSAGE_FAILURE,
|
|
24
27
|
GET_TEST_CUSTOMERS_REQUESTED,
|
|
25
28
|
GET_TEST_GROUPS_REQUESTED,
|
|
26
29
|
GET_TEST_CUSTOMERS_SUCCESS,
|
|
@@ -144,6 +147,26 @@ export function* sendTestMessageSaga(action) {
|
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
149
|
|
|
150
|
+
// notify/ui: Send Test Message via CCS's send/transaction endpoint, against a real
|
|
151
|
+
// CommDefinition, instead of the legacy createMessageMeta/sendTestMessage flow above.
|
|
152
|
+
export function* sendCcsTestMessageSaga(action) {
|
|
153
|
+
try {
|
|
154
|
+
const { callback } = action;
|
|
155
|
+
const res = yield call(Api.sendTransactionalComm, action.payload);
|
|
156
|
+
if (res?.response?.success === false) {
|
|
157
|
+
const error = res?.response?.errors?.[0]?.message || ERROR_MESSAGES.FAILED_TO_SEND_CCS_TEST_MESSAGE;
|
|
158
|
+
yield put({ type: SEND_CCS_TEST_MESSAGE_FAILURE, payload: { error } });
|
|
159
|
+
callback(false);
|
|
160
|
+
} else {
|
|
161
|
+
yield put({ type: SEND_CCS_TEST_MESSAGE_SUCCESS });
|
|
162
|
+
callback(true);
|
|
163
|
+
}
|
|
164
|
+
} catch (error) {
|
|
165
|
+
yield put({ type: SEND_CCS_TEST_MESSAGE_FAILURE, payload: { error: error.message || ERROR_MESSAGES.NETWORK_ERROR } });
|
|
166
|
+
action.callback(false);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
147
170
|
export function* getBulkCustomerDetails({fetchedUserIds}) {
|
|
148
171
|
try {
|
|
149
172
|
const bulkCustomerDetails = yield call(Api.getBulkCustomerDetails, {
|
|
@@ -285,6 +308,10 @@ export function* watchSendTestMessage() {
|
|
|
285
308
|
yield takeLatest(SEND_TEST_MESSAGE_REQUESTED, sendTestMessageSaga);
|
|
286
309
|
}
|
|
287
310
|
|
|
311
|
+
export function* watchSendCcsTestMessage() {
|
|
312
|
+
yield takeLatest(SEND_CCS_TEST_MESSAGE_REQUESTED, sendCcsTestMessageSaga);
|
|
313
|
+
}
|
|
314
|
+
|
|
288
315
|
export function* watchFetchTestCustomers() {
|
|
289
316
|
yield takeLatest(GET_TEST_CUSTOMERS_REQUESTED, fetchTestCustomersSaga);
|
|
290
317
|
}
|
|
@@ -371,6 +398,7 @@ export function* commonTestAndPreviewSaga() {
|
|
|
371
398
|
watchExtractTags(),
|
|
372
399
|
watchUpdatePreview(),
|
|
373
400
|
watchSendTestMessage(),
|
|
401
|
+
watchSendCcsTestMessage(),
|
|
374
402
|
watchFetchTestCustomers(),
|
|
375
403
|
watchFetchTestGroups(),
|
|
376
404
|
watchCreateMessageMeta(),
|
|
@@ -124,6 +124,11 @@ const makeSelectIsSendingTestMessage = () => createSelector(
|
|
|
124
124
|
(substate) => substate.get('isSendingTestMessage'),
|
|
125
125
|
);
|
|
126
126
|
|
|
127
|
+
const makeSelectIsSendingCcsTestMessage = () => createSelector(
|
|
128
|
+
selectCommonTestAndPreviewDomain,
|
|
129
|
+
(substate) => substate.get('isSendingCcsTestMessage'),
|
|
130
|
+
);
|
|
131
|
+
|
|
127
132
|
const makeSelectUpdatePreviewError = () => createSelector(
|
|
128
133
|
selectCommonTestAndPreviewDomain,
|
|
129
134
|
(substate) => substate.get('updatePreviewError'),
|
|
@@ -212,6 +217,7 @@ export {
|
|
|
212
217
|
makeSelectPrefilledValues,
|
|
213
218
|
makeSelectTestMessageResponse,
|
|
214
219
|
makeSelectIsSendingTestMessage,
|
|
220
|
+
makeSelectIsSendingCcsTestMessage,
|
|
215
221
|
makeSelectUpdatePreviewError,
|
|
216
222
|
makeSelectUpdatePreviewErrors,
|
|
217
223
|
makeSelectFetchPrefilledValuesError,
|
|
@@ -479,6 +479,112 @@ describe('UnifiedPreview', () => {
|
|
|
479
479
|
});
|
|
480
480
|
});
|
|
481
481
|
|
|
482
|
+
describe('Channel Routing - LINE', () => {
|
|
483
|
+
it('should render SmsPreviewContent for LINE channel with string content', () => {
|
|
484
|
+
const props = {
|
|
485
|
+
...defaultProps,
|
|
486
|
+
channel: CHANNELS.LINE,
|
|
487
|
+
content: 'Hello world',
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
render(
|
|
491
|
+
<TestWrapper>
|
|
492
|
+
<ComponentToRender {...props} />
|
|
493
|
+
</TestWrapper>
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
497
|
+
expect(screen.getByTestId('sms-content')).toHaveTextContent('Hello world');
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
it('should handle object content with resolvedBody for LINE channel', () => {
|
|
501
|
+
const props = {
|
|
502
|
+
...defaultProps,
|
|
503
|
+
channel: CHANNELS.LINE,
|
|
504
|
+
content: {
|
|
505
|
+
resolvedBody: 'some text',
|
|
506
|
+
},
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
render(
|
|
510
|
+
<TestWrapper>
|
|
511
|
+
<ComponentToRender {...props} />
|
|
512
|
+
</TestWrapper>
|
|
513
|
+
);
|
|
514
|
+
|
|
515
|
+
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
516
|
+
expect(screen.getByTestId('sms-content')).toHaveTextContent('some text');
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
it('should not crash and render empty content for LINE channel when content is undefined', () => {
|
|
520
|
+
const props = {
|
|
521
|
+
...defaultProps,
|
|
522
|
+
channel: CHANNELS.LINE,
|
|
523
|
+
content: undefined,
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
render(
|
|
527
|
+
<TestWrapper>
|
|
528
|
+
<ComponentToRender {...props} />
|
|
529
|
+
</TestWrapper>
|
|
530
|
+
);
|
|
531
|
+
|
|
532
|
+
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
533
|
+
expect(screen.getByTestId('sms-content')).toHaveTextContent('');
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
it('should not crash and render empty content for LINE channel when content is null', () => {
|
|
537
|
+
const props = {
|
|
538
|
+
...defaultProps,
|
|
539
|
+
channel: CHANNELS.LINE,
|
|
540
|
+
content: null,
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
render(
|
|
544
|
+
<TestWrapper>
|
|
545
|
+
<ComponentToRender {...props} />
|
|
546
|
+
</TestWrapper>
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
550
|
+
expect(screen.getByTestId('sms-content')).toHaveTextContent('');
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
it('should render empty content for LINE channel when content is not a string and has no resolvedBody', () => {
|
|
554
|
+
const props = {
|
|
555
|
+
...defaultProps,
|
|
556
|
+
channel: CHANNELS.LINE,
|
|
557
|
+
content: { someOtherField: 'value' },
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
render(
|
|
561
|
+
<TestWrapper>
|
|
562
|
+
<ComponentToRender {...props} />
|
|
563
|
+
</TestWrapper>
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
567
|
+
expect(screen.getByTestId('sms-content')).toHaveTextContent('');
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
it('should not render the Unknown Channel fallback for LINE channel', () => {
|
|
571
|
+
const props = {
|
|
572
|
+
...defaultProps,
|
|
573
|
+
channel: CHANNELS.LINE,
|
|
574
|
+
content: 'Hello world',
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
render(
|
|
578
|
+
<TestWrapper>
|
|
579
|
+
<ComponentToRender {...props} />
|
|
580
|
+
</TestWrapper>
|
|
581
|
+
);
|
|
582
|
+
|
|
583
|
+
expect(screen.queryByText('Unknown Channel')).toBeNull();
|
|
584
|
+
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
|
|
482
588
|
describe('Channel Routing - WHATSAPP', () => {
|
|
483
589
|
it('should render WhatsAppPreviewContent for WHATSAPP channel', () => {
|
|
484
590
|
const props = {
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
extractTagsRequested,
|
|
10
10
|
updatePreviewRequested,
|
|
11
11
|
sendTestMessageRequested,
|
|
12
|
+
sendCcsTestMessageRequested,
|
|
12
13
|
clearCustomerSearchState,
|
|
13
14
|
clearSearchResults,
|
|
14
15
|
getTestCustomersRequested,
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
EXTRACT_TAGS_REQUESTED,
|
|
27
28
|
UPDATE_PREVIEW_REQUESTED,
|
|
28
29
|
SEND_TEST_MESSAGE_REQUESTED,
|
|
30
|
+
SEND_CCS_TEST_MESSAGE_REQUESTED,
|
|
29
31
|
CLEAR_CUSTOMER_SEARCH_STATE,
|
|
30
32
|
CLEAR_SEARCH_RESULTS,
|
|
31
33
|
GET_TEST_CUSTOMERS_REQUESTED,
|
|
@@ -205,6 +207,19 @@ describe('CommonTestAndPreview Actions', () => {
|
|
|
205
207
|
});
|
|
206
208
|
});
|
|
207
209
|
|
|
210
|
+
describe('sendCcsTestMessageRequested', () => {
|
|
211
|
+
it('should create an action to send a CCS test message with payload and callback', () => {
|
|
212
|
+
const payload = { commDefinitionId: 'cd_123', recipient: { identifiers: [] } };
|
|
213
|
+
const callback = jest.fn();
|
|
214
|
+
const expectedAction = {
|
|
215
|
+
type: SEND_CCS_TEST_MESSAGE_REQUESTED,
|
|
216
|
+
payload,
|
|
217
|
+
callback,
|
|
218
|
+
};
|
|
219
|
+
expect(sendCcsTestMessageRequested(payload, callback)).toEqual(expectedAction);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
208
223
|
describe('clearCustomerSearchState', () => {
|
|
209
224
|
it('should create an action to clear customer search state', () => {
|
|
210
225
|
const expectedAction = {
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
CLEAR_PREVIEW_ERRORS,
|
|
43
43
|
// Channel Constants
|
|
44
44
|
CHANNELS,
|
|
45
|
+
CHANNELS_USING_ANDROID_PREVIEW_DEVICE,
|
|
45
46
|
// Device Constants
|
|
46
47
|
DESKTOP,
|
|
47
48
|
MOBILE,
|
|
@@ -180,15 +181,22 @@ describe('CommonTestAndPreview Constants', () => {
|
|
|
180
181
|
expect(CHANNELS.VIBER).toBe('VIBER');
|
|
181
182
|
expect(CHANNELS.ZALO).toBe('ZALO');
|
|
182
183
|
expect(CHANNELS.WEBPUSH).toBe('WEBPUSH');
|
|
184
|
+
expect(CHANNELS.LINE).toBe('LINE');
|
|
183
185
|
});
|
|
184
186
|
|
|
185
187
|
it('should have all required channel keys', () => {
|
|
186
|
-
const expectedChannels = ['EMAIL', 'SMS', 'RCS', 'WHATSAPP', 'INAPP', 'MOBILEPUSH', 'VIBER', 'ZALO', 'WEBPUSH'];
|
|
188
|
+
const expectedChannels = ['EMAIL', 'SMS', 'RCS', 'WHATSAPP', 'INAPP', 'MOBILEPUSH', 'VIBER', 'ZALO', 'WEBPUSH', 'LINE'];
|
|
187
189
|
expect(Object.keys(CHANNELS)).toEqual(expect.arrayContaining(expectedChannels));
|
|
188
190
|
expect(Object.keys(CHANNELS).length).toBe(expectedChannels.length);
|
|
189
191
|
});
|
|
190
192
|
});
|
|
191
193
|
|
|
194
|
+
describe('CHANNELS_USING_ANDROID_PREVIEW_DEVICE', () => {
|
|
195
|
+
it('should include CHANNELS.LINE', () => {
|
|
196
|
+
expect(CHANNELS_USING_ANDROID_PREVIEW_DEVICE).toContain(CHANNELS.LINE);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
192
200
|
describe('Device Constants', () => {
|
|
193
201
|
it('should export all device constants with correct values', () => {
|
|
194
202
|
expect(DESKTOP).toBe('desktop');
|
|
@@ -128,6 +128,7 @@ describe('CommonTestAndPreview', () => {
|
|
|
128
128
|
extractTagsRequested: jest.fn(),
|
|
129
129
|
updatePreviewRequested: jest.fn(),
|
|
130
130
|
sendTestMessageRequested: jest.fn(),
|
|
131
|
+
sendCcsTestMessageRequested: jest.fn(),
|
|
131
132
|
clearCustomerSearchState: jest.fn(),
|
|
132
133
|
getTestCustomersRequested: jest.fn(),
|
|
133
134
|
getTestGroupsRequested: jest.fn(),
|
|
@@ -1686,6 +1687,106 @@ describe('CommonTestAndPreview', () => {
|
|
|
1686
1687
|
});
|
|
1687
1688
|
});
|
|
1688
1689
|
|
|
1690
|
+
describe('CCS Test Message Sending (notify/ui)', () => {
|
|
1691
|
+
it('dispatches sendCcsTestMessageRequested (not the legacy createMessageMeta/sendTestMessage flow) when ccsSendTransaction is set', async () => {
|
|
1692
|
+
const props = {
|
|
1693
|
+
...defaultProps,
|
|
1694
|
+
selectedTestEntities: ['user-1'],
|
|
1695
|
+
testGroups: [],
|
|
1696
|
+
ccsSendTransaction: { commDefinitionId: 'cd_123', referenceId: 'ORDER_PLACED' },
|
|
1697
|
+
};
|
|
1698
|
+
|
|
1699
|
+
render(
|
|
1700
|
+
<TestWrapper>
|
|
1701
|
+
<CommonTestAndPreview {...props} />
|
|
1702
|
+
</TestWrapper>
|
|
1703
|
+
);
|
|
1704
|
+
|
|
1705
|
+
lastSendTestMessageProps.handleSendTestMessage();
|
|
1706
|
+
|
|
1707
|
+
expect(mockActions.sendCcsTestMessageRequested).toHaveBeenCalledWith(
|
|
1708
|
+
expect.objectContaining({
|
|
1709
|
+
commDefinitionId: 'cd_123',
|
|
1710
|
+
isTest: true,
|
|
1711
|
+
recipient: expect.objectContaining({
|
|
1712
|
+
identifiers: expect.any(Array),
|
|
1713
|
+
}),
|
|
1714
|
+
}),
|
|
1715
|
+
expect.any(Function),
|
|
1716
|
+
);
|
|
1717
|
+
expect(mockActions.createMessageMetaRequested).not.toHaveBeenCalled();
|
|
1718
|
+
expect(mockActions.sendTestMessageRequested).not.toHaveBeenCalled();
|
|
1719
|
+
});
|
|
1720
|
+
|
|
1721
|
+
it('falls back to referenceId when commDefinitionId is absent', async () => {
|
|
1722
|
+
const props = {
|
|
1723
|
+
...defaultProps,
|
|
1724
|
+
selectedTestEntities: ['user-1'],
|
|
1725
|
+
testGroups: [],
|
|
1726
|
+
ccsSendTransaction: { referenceId: 'ORDER_PLACED' },
|
|
1727
|
+
};
|
|
1728
|
+
|
|
1729
|
+
render(
|
|
1730
|
+
<TestWrapper>
|
|
1731
|
+
<CommonTestAndPreview {...props} />
|
|
1732
|
+
</TestWrapper>
|
|
1733
|
+
);
|
|
1734
|
+
|
|
1735
|
+
lastSendTestMessageProps.handleSendTestMessage();
|
|
1736
|
+
|
|
1737
|
+
expect(mockActions.sendCcsTestMessageRequested).toHaveBeenCalledWith(
|
|
1738
|
+
expect.objectContaining({ referenceId: 'ORDER_PLACED' }),
|
|
1739
|
+
expect.any(Function),
|
|
1740
|
+
);
|
|
1741
|
+
});
|
|
1742
|
+
|
|
1743
|
+
it('shows a success notification when the callback receives true', async () => {
|
|
1744
|
+
const CapNotification = require('@capillarytech/cap-ui-library/CapNotification');
|
|
1745
|
+
mockActions.sendCcsTestMessageRequested.mockImplementation((payload, cb) => cb(true));
|
|
1746
|
+
const props = {
|
|
1747
|
+
...defaultProps,
|
|
1748
|
+
selectedTestEntities: ['user-1'],
|
|
1749
|
+
testGroups: [],
|
|
1750
|
+
ccsSendTransaction: { commDefinitionId: 'cd_123' },
|
|
1751
|
+
};
|
|
1752
|
+
|
|
1753
|
+
render(
|
|
1754
|
+
<TestWrapper>
|
|
1755
|
+
<CommonTestAndPreview {...props} />
|
|
1756
|
+
</TestWrapper>
|
|
1757
|
+
);
|
|
1758
|
+
|
|
1759
|
+
lastSendTestMessageProps.handleSendTestMessage();
|
|
1760
|
+
|
|
1761
|
+
await waitFor(() => {
|
|
1762
|
+
expect(CapNotification.success).toHaveBeenCalled();
|
|
1763
|
+
});
|
|
1764
|
+
});
|
|
1765
|
+
|
|
1766
|
+
it('shows an error notification when the callback receives false', async () => {
|
|
1767
|
+
const CapNotification = require('@capillarytech/cap-ui-library/CapNotification');
|
|
1768
|
+
mockActions.sendCcsTestMessageRequested.mockImplementation((payload, cb) => cb(false));
|
|
1769
|
+
const props = {
|
|
1770
|
+
...defaultProps,
|
|
1771
|
+
selectedTestEntities: ['user-1'],
|
|
1772
|
+
testGroups: [],
|
|
1773
|
+
ccsSendTransaction: { commDefinitionId: 'cd_123' },
|
|
1774
|
+
};
|
|
1775
|
+
|
|
1776
|
+
render(
|
|
1777
|
+
<TestWrapper>
|
|
1778
|
+
<CommonTestAndPreview {...props} />
|
|
1779
|
+
</TestWrapper>
|
|
1780
|
+
);
|
|
1781
|
+
|
|
1782
|
+
lastSendTestMessageProps.handleSendTestMessage();
|
|
1783
|
+
|
|
1784
|
+
await waitFor(() => {
|
|
1785
|
+
expect(CapNotification.error).toHaveBeenCalled();
|
|
1786
|
+
});
|
|
1787
|
+
});
|
|
1788
|
+
});
|
|
1789
|
+
|
|
1689
1790
|
describe('Content Extraction', () => {
|
|
1690
1791
|
it('should extract EMAIL content from formData', async () => {
|
|
1691
1792
|
const props = {
|