@capillarytech/creatives-library 8.0.298 → 8.0.299-alpha.0

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 (34) hide show
  1. package/constants/unified.js +1 -0
  2. package/package.json +1 -1
  3. package/services/api.js +17 -0
  4. package/services/tests/api.test.js +85 -0
  5. package/utils/common.js +12 -5
  6. package/utils/commonUtils.js +10 -0
  7. package/utils/tests/commonUtil.test.js +169 -0
  8. package/v2Components/CapDeviceContent/index.js +10 -7
  9. package/v2Components/CommonTestAndPreview/AddTestCustomer.js +42 -0
  10. package/v2Components/CommonTestAndPreview/CustomerCreationModal.js +284 -0
  11. package/v2Components/CommonTestAndPreview/ExistingCustomerModal.js +72 -0
  12. package/v2Components/CommonTestAndPreview/SendTestMessage.js +78 -49
  13. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +189 -4
  14. package/v2Components/CommonTestAndPreview/actions.js +10 -0
  15. package/v2Components/CommonTestAndPreview/constants.js +18 -1
  16. package/v2Components/CommonTestAndPreview/index.js +259 -14
  17. package/v2Components/CommonTestAndPreview/messages.js +94 -0
  18. package/v2Components/CommonTestAndPreview/reducer.js +10 -0
  19. package/v2Components/CommonTestAndPreview/tests/AddTestCustomer.test.js +66 -0
  20. package/v2Components/CommonTestAndPreview/tests/CommonTestAndPreview.addTestCustomer.test.js +653 -0
  21. package/v2Components/CommonTestAndPreview/tests/CustomerCreationModal.test.js +316 -0
  22. package/v2Components/CommonTestAndPreview/tests/ExistingCustomerModal.test.js +114 -0
  23. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +53 -0
  24. package/v2Components/CommonTestAndPreview/tests/constants.test.js +25 -2
  25. package/v2Components/CommonTestAndPreview/tests/index.test.js +7 -0
  26. package/v2Components/CommonTestAndPreview/tests/reducer.test.js +71 -0
  27. package/v2Components/CommonTestAndPreview/tests/selectors.test.js +17 -0
  28. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +320 -0
  29. package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +132 -0
  30. package/v2Containers/CreativesContainer/SlideBoxContent.js +35 -3
  31. package/v2Containers/InApp/index.js +182 -13
  32. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +1408 -1276
  33. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +321 -288
  34. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +5246 -4872
@@ -0,0 +1,284 @@
1
+ import CapModal from "@capillarytech/cap-ui-library/CapModal";
2
+ import CapButton from "@capillarytech/cap-ui-library/CapButton";
3
+ import CapInput from "@capillarytech/cap-ui-library/CapInput";
4
+ import CapLabel from "@capillarytech/cap-ui-library/CapLabel";
5
+ import CapRow from "@capillarytech/cap-ui-library/CapRow";
6
+ import CapColumn from "@capillarytech/cap-ui-library/CapColumn";
7
+ import CapSpin from "@capillarytech/cap-ui-library/CapSpin";
8
+ import { FormattedMessage, injectIntl } from "react-intl";
9
+ import messages from "./messages";
10
+ import React, { useState, useCallback, useEffect, useRef } from "react";
11
+ import { CHANNELS, IDENTIFIER_TYPE_EMAIL, IDENTIFIER_TYPE_MOBILE, INPUT_HAS_ERROR_CLASS } from "./constants";
12
+ import { getMembersLookup } from '../../services/api';
13
+ import { isValidEmail, isValidMobile, formatPhoneNumber } from "../../utils/commonUtils";
14
+
15
+ const CustomerCreationModal = ({
16
+ customerModal,
17
+ setCustomerModal,
18
+ channel,
19
+ customerData,
20
+ setCustomerData,
21
+ onSave,
22
+ intl,
23
+ }) => {
24
+ const [validationErrors, setValidationErrors] = useState({
25
+ email: "",
26
+ mobile: ""
27
+ });
28
+ const [isLoading, setIsLoading] = useState(false);
29
+ const [lookupLoading, setLookupLoading] = useState(null); // null | IDENTIFIER_TYPE_EMAIL | IDENTIFIER_TYPE_MOBILE
30
+
31
+ // Refs to track the latest values for async validation
32
+ const latestEmailRef = useRef(customerData.email || "");
33
+ const latestMobileRef = useRef(customerData.mobile || "");
34
+
35
+ // Helper function to render validation errors
36
+ const renderValidationError = (error) => {
37
+ if (!error) return null;
38
+
39
+ return (
40
+ <div className="customer-creation-modal-validation-error">
41
+ {typeof error === 'string' ? error : <FormattedMessage {...error} />}
42
+ </div>
43
+ );
44
+ };
45
+
46
+ // Check if required fields are filled based on channel
47
+ const isRequiredFieldMissing = () => {
48
+ if (channel === CHANNELS.EMAIL && !customerData.email) {
49
+ return true;
50
+ }
51
+ if (channel === CHANNELS.SMS && !customerData.mobile) {
52
+ return true;
53
+ }
54
+ return false;
55
+ };
56
+
57
+ // Check if save button should be disabled
58
+ const isSaveDisabled = () => {
59
+ return (
60
+ validationErrors.email ||
61
+ validationErrors.mobile ||
62
+ isRequiredFieldMissing() ||
63
+ !!lookupLoading
64
+ );
65
+ };
66
+
67
+ // Perform lookup (same logic as in index.js)
68
+ const performLookup = useCallback(async (identifierType, value) => {
69
+ try {
70
+ const response = await getMembersLookup(identifierType, value);
71
+ const success = response?.success && !response?.status?.isError;
72
+ const res = response?.response || {};
73
+ const exists = res.exists || false;
74
+ const details = res.customerDetails || [];
75
+ if (!success) {
76
+ const errorMessage = response?.message || response?.status?.message
77
+ if (errorMessage.toLowerCase().includes("merged customer found")) {
78
+ return { success: true, exists: true, details: [] };
79
+ }
80
+ }
81
+
82
+ return { success, exists, details };
83
+ } catch (error) {
84
+ return { success: false, exists: false, details: [] };
85
+ }
86
+ }, []);
87
+
88
+ // Handle validation and lookup for email or mobile
89
+ const handleLookupValidation = useCallback(async (type, value) => {
90
+ const isEmail = type === IDENTIFIER_TYPE_EMAIL;
91
+ const ref = isEmail ? latestEmailRef : latestMobileRef;
92
+ const field = isEmail ? IDENTIFIER_TYPE_EMAIL : IDENTIFIER_TYPE_MOBILE;
93
+
94
+ if (!value) {
95
+ if (ref.current === value) {
96
+ setValidationErrors(prev => ({ ...prev, [field]: "" }));
97
+ }
98
+ return;
99
+ }
100
+
101
+ if (isEmail && !isValidEmail(value)) {
102
+ if (ref.current === value) {
103
+ setValidationErrors(prev => ({ ...prev, [IDENTIFIER_TYPE_EMAIL]: "Please enter a valid email address" }));
104
+ }
105
+ return;
106
+ }
107
+ if (!isEmail && !isValidMobile(value)) {
108
+ if (ref.current === value) {
109
+ setValidationErrors(prev => ({ ...prev, [IDENTIFIER_TYPE_MOBILE]: "Please enter a valid mobile number" }));
110
+ }
111
+ return;
112
+ }
113
+
114
+ setLookupLoading(field);
115
+ try {
116
+ const { success, exists } = await performLookup(type, value);
117
+
118
+ if (ref.current === value) {
119
+ if (success && exists) {
120
+ setValidationErrors(prev => ({
121
+ ...prev,
122
+ [field]: isEmail ? messages.emailAlreadyExists : messages.mobileAlreadyExists
123
+ }));
124
+ } else {
125
+ setValidationErrors(prev => ({ ...prev, [field]: "" }));
126
+ }
127
+ }
128
+ } finally {
129
+ setLookupLoading(null);
130
+ }
131
+ }, [performLookup]);
132
+
133
+ // Debounce timer refs
134
+ const emailTimeoutRef = React.useRef(null);
135
+ const mobileTimeoutRef = React.useRef(null);
136
+
137
+ // Handle email change with debounced validation
138
+ const handleEmailChange = (e) => {
139
+ const email = e.target.value;
140
+ latestEmailRef.current = email; // Update the latest email ref
141
+ setCustomerData({ ...customerData, email });
142
+
143
+ // Clear previous timeout
144
+ if (emailTimeoutRef.current) {
145
+ clearTimeout(emailTimeoutRef.current);
146
+ }
147
+
148
+ // Set new timeout for validation
149
+ emailTimeoutRef.current = setTimeout(() => {
150
+ handleLookupValidation(IDENTIFIER_TYPE_EMAIL, email);
151
+ }, 500);
152
+ };
153
+
154
+ // Handle mobile change with debounced validation
155
+ const handleMobileChange = (e) => {
156
+ const rawValue = e.target.value;
157
+ const formattedMobile = formatPhoneNumber(rawValue);
158
+ latestMobileRef.current = formattedMobile; // Update the latest mobile ref
159
+ setCustomerData({ ...customerData, mobile: formattedMobile });
160
+
161
+ // Clear previous timeout
162
+ if (mobileTimeoutRef.current) {
163
+ clearTimeout(mobileTimeoutRef.current);
164
+ }
165
+
166
+ // Set new timeout for validation
167
+ mobileTimeoutRef.current = setTimeout(() => {
168
+ handleLookupValidation(IDENTIFIER_TYPE_MOBILE, formattedMobile);
169
+ }, 500);
170
+ };
171
+
172
+ // Update refs when customerData changes externally
173
+ useEffect(() => {
174
+ latestEmailRef.current = customerData.email || "";
175
+ latestMobileRef.current = customerData.mobile || "";
176
+ }, [customerData.email, customerData.mobile]);
177
+
178
+ // Cleanup timeouts on unmount
179
+ useEffect(() => {
180
+ return () => {
181
+ if (emailTimeoutRef.current) {
182
+ clearTimeout(emailTimeoutRef.current);
183
+ }
184
+ if (mobileTimeoutRef.current) {
185
+ clearTimeout(mobileTimeoutRef.current);
186
+ }
187
+ };
188
+ }, []);
189
+
190
+ return (
191
+ <CapModal
192
+ visible={customerModal[0]}
193
+ onCancel={() => setCustomerModal([false, ""])}
194
+ centered={true}
195
+ width={500}
196
+ maskStyle={{ backgroundColor: 'rgba(244, 245, 247, 0.9)' }}
197
+ footer={
198
+ <CapRow justify="start" text-align="left" gutter={8}>
199
+ <CapButton
200
+ type="primary"
201
+ onClick={() => onSave(validationErrors, setIsLoading)}
202
+ disabled={isSaveDisabled() || lookupLoading}
203
+ loading={isLoading}
204
+ >
205
+ <FormattedMessage {...messages.saveButton} />
206
+ </CapButton>
207
+ <CapButton
208
+ type="secondary"
209
+ onClick={() => setCustomerModal([false, ""])}
210
+ disabled={isLoading || lookupLoading}
211
+ >
212
+ <FormattedMessage {...messages.cancelButton} />
213
+ </CapButton>
214
+ </CapRow>
215
+ }
216
+ title={<FormattedMessage {...messages.customerCreationModalTitle} />}
217
+ wrapClassName="common-test-preview-modal-wrap"
218
+ className="common-test-preview-modal"
219
+ >
220
+ <CapRow className="customer-creation-modal-row">
221
+ <CapColumn span={24}>
222
+ <span className="customer-creation-modal-description">
223
+ <FormattedMessage {...messages.customerCreationModalDescription} />
224
+ </span>
225
+ </CapColumn>
226
+ </CapRow>
227
+
228
+ <CapRow className="customer-creation-modal-row">
229
+ <CapColumn span={24}>
230
+ <CapLabel type="label1" className="customer-creation-modal-label">
231
+ <FormattedMessage {...messages.customerName} /> <span className="customer-creation-modal-optional">(Optional)</span>
232
+ </CapLabel>
233
+ <CapInput
234
+ value={customerData.name || ""}
235
+ onChange={e =>
236
+ setCustomerData({ ...customerData, name: e.target.value })
237
+ }
238
+ placeholder={intl.formatMessage(messages.customerNamePlaceholder)}
239
+ size="default"
240
+ className="customer-creation-modal-input"
241
+ />
242
+ </CapColumn>
243
+ </CapRow>
244
+
245
+ <CapRow className="customer-creation-modal-row">
246
+ <CapColumn span={24}>
247
+ <CapLabel type="label1" className="customer-creation-modal-label">
248
+ <FormattedMessage {...messages.customerEmail} /> {channel !== CHANNELS.EMAIL && <span className="customer-creation-modal-optional">(Optional)</span>}
249
+ </CapLabel>
250
+ <CapInput
251
+ value={customerData.email || ""}
252
+ onChange={handleEmailChange}
253
+ placeholder={intl.formatMessage(messages.customerEmailPlaceholder)}
254
+ size="default"
255
+ className={`customer-creation-modal-input${validationErrors.email ? INPUT_HAS_ERROR_CLASS : ''}`}
256
+ disabled={!!lookupLoading}
257
+ suffix={lookupLoading === IDENTIFIER_TYPE_EMAIL ? <CapSpin size="small" /> : null}
258
+ />
259
+ {renderValidationError(validationErrors.email)}
260
+ </CapColumn>
261
+ </CapRow>
262
+
263
+ <CapRow className="customer-creation-modal-row customer-creation-modal-row--last">
264
+ <CapColumn span={24}>
265
+ <CapLabel type="label1" className="customer-creation-modal-label">
266
+ <FormattedMessage {...messages.customerMobile} /> {channel !== CHANNELS.SMS && <span className="customer-creation-modal-optional">(Optional)</span>}
267
+ </CapLabel>
268
+ <CapInput
269
+ value={customerData.mobile || ""}
270
+ onChange={handleMobileChange}
271
+ placeholder={intl.formatMessage(messages.customerMobilePlaceholder)}
272
+ size="default"
273
+ className={`customer-creation-modal-input${validationErrors.mobile ? INPUT_HAS_ERROR_CLASS : ''}`}
274
+ disabled={!!lookupLoading}
275
+ suffix={lookupLoading === IDENTIFIER_TYPE_MOBILE ? <CapSpin size="small" /> : null}
276
+ />
277
+ {renderValidationError(validationErrors.mobile)}
278
+ </CapColumn>
279
+ </CapRow>
280
+ </CapModal>
281
+ );
282
+ };
283
+
284
+ export default injectIntl(CustomerCreationModal);
@@ -0,0 +1,72 @@
1
+ import CapModal from "@capillarytech/cap-ui-library/CapModal";
2
+ import { FormattedMessage, injectIntl } from "react-intl";
3
+ import messages from "./messages";
4
+ import React, { useState } from "react";
5
+ import { CapCard, CapRow, CapColumn, CapLabel } from "@capillarytech/cap-ui-library";
6
+ import { CHANNELS } from "./constants";
7
+ import CapButton from "@capillarytech/cap-ui-library/CapButton";
8
+ import CapIcon from "@capillarytech/cap-ui-library/CapIcon";
9
+
10
+
11
+ const ExistingCustomerModal = ({ customerModal, setCustomerModal, customerData, channel, onSave, intl }) => {
12
+ const [isLoading, setIsLoading] = useState(false);
13
+ return (
14
+ <CapModal
15
+ visible={customerModal[0]}
16
+ onCancel={() => setCustomerModal([false, ""])}
17
+ centered={true}
18
+ width={500}
19
+ maskStyle={{ backgroundColor: 'rgba(244, 245, 247, 0.9)' }}
20
+ footer={
21
+ <CapRow justify="start">
22
+ <CapButton
23
+ type="primary"
24
+ onClick={() => onSave({},setIsLoading)}
25
+ loading={isLoading}
26
+ >
27
+ <FormattedMessage {...messages.saveButton} />
28
+ </CapButton>
29
+ <CapButton
30
+ type="secondary"
31
+ onClick={() => setCustomerModal([false, ""])}
32
+ disabled={isLoading}
33
+ >
34
+ <FormattedMessage {...messages.cancelButton} />
35
+ </CapButton>
36
+ </CapRow>
37
+ }
38
+ title={intl.formatMessage(messages.customerCreationModalTitle)}
39
+ wrapClassName="common-test-preview-modal-wrap existing-customer-modal-wrap"
40
+ className="common-test-preview-modal"
41
+ >
42
+ <div className="existing-customer-modal">
43
+ <CapRow className="existing-customer-modal-intro-row">
44
+ <FormattedMessage {...messages.existingCustomerModalDescription} />
45
+ </CapRow>
46
+ <CapCard className="existing-customer-modal-card">
47
+ <CapRow className="existing-customer-modal-card-row">
48
+ <CapColumn className="existing-customer-modal-avatar">
49
+ <CapIcon type="user-profile" className="existing-customer-modal-avatar-icon" />
50
+ </CapColumn>
51
+ <CapColumn className="existing-customer-modal-details">
52
+ <CapRow className="existing-customer-modal-name">
53
+ {customerData.name || "-"}
54
+ </CapRow>
55
+ <CapColumn className="existing-customer-modal-meta">
56
+ {channel === CHANNELS.EMAIL && customerData.email && (
57
+ <CapRow><span className="existing-customer-modal-meta-label"><FormattedMessage {...messages.customerEmail} />: </span> {customerData.email}</CapRow>
58
+ )}
59
+ {channel === CHANNELS.SMS && customerData.mobile && (
60
+ <CapRow><span className="existing-customer-modal-meta-label"><FormattedMessage {...messages.customerMobile} />: </span>{customerData.mobile}</CapRow>
61
+ )}
62
+ <CapRow><span className="existing-customer-modal-meta-label"><FormattedMessage {...messages.customerID} />: </span>{customerData.customerId}</CapRow>
63
+ </CapColumn>
64
+ </CapColumn>
65
+ </CapRow>
66
+ </CapCard>
67
+ </div>
68
+ </CapModal>
69
+ );
70
+ };
71
+
72
+ export default injectIntl(ExistingCustomerModal);
@@ -24,6 +24,9 @@ const SendTestMessage = ({
24
24
  channel,
25
25
  isSendingTestMessage,
26
26
  formatMessage,
27
+ renderAddTestCustomerButton,
28
+ searchValue,
29
+ setSearchValue,
27
30
  deliverySettings,
28
31
  senderDetailsOptions,
29
32
  wecrmAccounts,
@@ -31,57 +34,77 @@ const SendTestMessage = ({
31
34
  isLoadingSenderDetails,
32
35
  smsTraiDltEnabled,
33
36
  registeredSenderIds,
34
- }) => (
35
- <CapStepsAccordian
36
- showNumberSteps={false}
37
- isChevronIcon
38
- expandIconPosition="right"
39
- items={[
40
- {
41
- header: <CapHeader
42
- size="regular"
43
- description={<FormattedMessage {...messages.testMessageDescription} />}
44
- title={<FormattedMessage {...messages.sendTestMessage} />}
45
- />,
46
- content: (
47
- <CapRow className="send-test-content">
48
- <CapHeader size="label1" title={<FormattedMessage {...messages.testCustomers} />} />
49
- <CapTreeSelect
50
- className="test-customers-tree-select"
51
- loading={isFetchingTestCustomers || isFetchingTestGroups}
52
- treeData={testEntitiesTreeData}
53
- onChange={handleTestEntitiesChange}
54
- value={selectedTestEntities}
55
- multiple
56
- placeholder={formatMessage(messages.testCustomersPlaceholder)}
37
+ }) => {
38
+ const addCustomerContent = renderAddTestCustomerButton ? renderAddTestCustomerButton() : null;
39
+ return (
40
+ <CapStepsAccordian
41
+ showNumberSteps={false}
42
+ isChevronIcon
43
+ expandIconPosition="right"
44
+ items={[
45
+ {
46
+ header: (
47
+ <CapHeader
48
+ size="regular"
49
+ description={<FormattedMessage {...messages.testMessageDescription} />}
50
+ title={<FormattedMessage {...messages.sendTestMessage} />}
57
51
  />
58
- {CHANNELS_WITH_DELIVERY_SETTINGS.includes(channel) && (
59
- <DeliverySettings
60
- channel={channel}
61
- deliverySettings={deliverySettings || {}}
62
- senderDetailsOptions={senderDetailsOptions || []}
63
- wecrmAccounts={wecrmAccounts || []}
64
- onSaveDeliverySettings={onSaveDeliverySettings}
65
- isLoadingSenderDetails={isLoadingSenderDetails}
66
- formatMessage={formatMessage}
67
- smsTraiDltEnabled={smsTraiDltEnabled}
68
- registeredSenderIds={registeredSenderIds}
69
- whatsappAccountFromForm={
70
- channel === CHANNELS.WHATSAPP && formData?.accountName
71
- ? { accountName: formData.accountName }
72
- : undefined
73
- }
52
+ ),
53
+ content: (
54
+ <CapRow className="send-test-content">
55
+ <CapHeader size="label1" title={<FormattedMessage {...messages.testCustomers} />} />
56
+ <CapTreeSelect
57
+ className="test-customers-tree-select"
58
+ dropdownMatchSelectWidth
59
+ dropdownClassName="test-customers-tree-select-dropdown"
60
+ listHeight={280}
61
+ loading={isFetchingTestCustomers || isFetchingTestGroups}
62
+ treeData={testEntitiesTreeData}
63
+ onChange={handleTestEntitiesChange}
64
+ value={selectedTestEntities}
65
+ showSearch
66
+ searchValue={searchValue}
67
+ onSearch={setSearchValue}
68
+ treeNodeFilterProp="title"
69
+ {...(addCustomerContent ? { notFoundContent: addCustomerContent } : {})}
70
+ multiple
71
+ placeholder={formatMessage(messages.testCustomersPlaceholder)}
72
+ dropdownStyle={{ zIndex: 900, maxHeight: 320 }}
73
+ placement="bottomLeft"
74
+ getPopupContainer={(node) => node.closest('.send-test-section') || document.body}
74
75
  />
75
- )}
76
- <CapButton onClick={handleSendTestMessage} disabled={isEmpty(selectedTestEntities) || isSendingTestMessage}>
77
- <FormattedMessage {...messages.sendTestButton} />
78
- </CapButton>
79
- </CapRow>),
80
- key: 1,
81
- },
82
- ]}
83
- />
84
- );
76
+ {CHANNELS_WITH_DELIVERY_SETTINGS.includes(channel) && (
77
+ <DeliverySettings
78
+ channel={channel}
79
+ deliverySettings={deliverySettings || {}}
80
+ senderDetailsOptions={senderDetailsOptions || []}
81
+ wecrmAccounts={wecrmAccounts || []}
82
+ onSaveDeliverySettings={onSaveDeliverySettings}
83
+ isLoadingSenderDetails={isLoadingSenderDetails}
84
+ formatMessage={formatMessage}
85
+ smsTraiDltEnabled={smsTraiDltEnabled}
86
+ registeredSenderIds={registeredSenderIds}
87
+ whatsappAccountFromForm={
88
+ channel === CHANNELS.WHATSAPP && formData?.accountName
89
+ ? { accountName: formData.accountName }
90
+ : undefined
91
+ }
92
+ />
93
+ )}
94
+ <CapButton
95
+ onClick={handleSendTestMessage}
96
+ disabled={isEmpty(selectedTestEntities) || isSendingTestMessage}
97
+ >
98
+ <FormattedMessage {...messages.sendTestButton} />
99
+ </CapButton>
100
+ </CapRow>
101
+ ),
102
+ key: 1,
103
+ },
104
+ ]}
105
+ />
106
+ );
107
+ };
85
108
 
86
109
  SendTestMessage.propTypes = {
87
110
  isFetchingTestCustomers: PropTypes.bool.isRequired,
@@ -94,6 +117,9 @@ SendTestMessage.propTypes = {
94
117
  channel: PropTypes.string,
95
118
  isSendingTestMessage: PropTypes.bool.isRequired,
96
119
  formatMessage: PropTypes.func.isRequired,
120
+ renderAddTestCustomerButton: PropTypes.func,
121
+ searchValue: PropTypes.string,
122
+ setSearchValue: PropTypes.func,
97
123
  deliverySettings: PropTypes.object,
98
124
  senderDetailsOptions: PropTypes.array,
99
125
  wecrmAccounts: PropTypes.array,
@@ -106,6 +132,9 @@ SendTestMessage.propTypes = {
106
132
  SendTestMessage.defaultProps = {
107
133
  formData: undefined,
108
134
  channel: undefined,
135
+ renderAddTestCustomerButton: undefined,
136
+ searchValue: '',
137
+ setSearchValue: undefined,
109
138
  deliverySettings: {},
110
139
  senderDetailsOptions: [],
111
140
  wecrmAccounts: [],