@capillarytech/creatives-library 8.0.307 → 8.0.308
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 +1 -5
- package/initialState.js +2 -0
- package/package.json +1 -1
- package/utils/common.js +8 -5
- package/utils/commonUtils.js +93 -36
- package/utils/tagValidations.js +223 -83
- package/utils/tests/commonUtil.test.js +124 -147
- package/utils/tests/tagValidations.test.js +358 -441
- package/v2Components/ErrorInfoNote/index.js +5 -2
- package/v2Components/FormBuilder/index.js +203 -137
- package/v2Components/FormBuilder/messages.js +8 -0
- package/v2Components/HtmlEditor/HTMLEditor.js +5 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +15 -0
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +2 -1
- package/v2Containers/Cap/mockData.js +14 -0
- package/v2Containers/Cap/reducer.js +55 -3
- package/v2Containers/Cap/tests/reducer.test.js +102 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +1 -5
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +5 -13
- package/v2Containers/CreativesContainer/constants.js +0 -6
- package/v2Containers/CreativesContainer/index.js +7 -47
- package/v2Containers/Email/index.js +5 -1
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +70 -23
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +120 -20
- package/v2Containers/FTP/index.js +51 -2
- package/v2Containers/FTP/messages.js +4 -0
- package/v2Containers/InApp/index.js +122 -35
- package/v2Containers/InApp/tests/index.test.js +6 -17
- package/v2Containers/InappAdvance/index.js +112 -4
- package/v2Containers/InappAdvance/tests/index.test.js +0 -2
- package/v2Containers/Line/Container/Text/index.js +1 -0
- package/v2Containers/MobilePush/Create/index.js +19 -59
- package/v2Containers/MobilePush/Edit/index.js +20 -48
- package/v2Containers/MobilePushNew/index.js +32 -12
- package/v2Containers/MobilepushWrapper/index.js +1 -3
- package/v2Containers/Rcs/index.js +37 -12
- package/v2Containers/Sms/Create/index.js +3 -39
- package/v2Containers/Sms/Create/messages.js +0 -4
- package/v2Containers/Sms/Edit/index.js +3 -35
- package/v2Containers/Sms/commonMethods.js +6 -3
- package/v2Containers/SmsTrai/Edit/index.js +47 -11
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
- package/v2Containers/SmsWrapper/index.js +0 -2
- package/v2Containers/TemplatesV2/index.js +13 -28
- package/v2Containers/Viber/index.js +1 -0
- package/v2Containers/WebPush/Create/hooks/useTagManagement.js +3 -1
- package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +7 -0
- package/v2Containers/WebPush/Create/index.js +2 -2
- package/v2Containers/WebPush/Create/utils/validation.js +8 -17
- package/v2Containers/WebPush/Create/utils/validation.test.js +24 -44
- package/v2Containers/Whatsapp/index.js +17 -9
- package/v2Containers/Zalo/index.js +11 -3
- package/v2Containers/Sms/tests/commonMethods.test.js +0 -122
|
@@ -4265,7 +4265,7 @@ FREE GIFTS-
|
|
|
4265
4265
|
<CapCheckbox
|
|
4266
4266
|
checked={false}
|
|
4267
4267
|
disabled={false}
|
|
4268
|
-
key=".
|
|
4268
|
+
key=".4"
|
|
4269
4269
|
labelType="h4"
|
|
4270
4270
|
onChange={[Function]}
|
|
4271
4271
|
>
|
|
@@ -4327,7 +4327,7 @@ FREE GIFTS-
|
|
|
4327
4327
|
</div>
|
|
4328
4328
|
</CapCheckbox>
|
|
4329
4329
|
<div
|
|
4330
|
-
key=".
|
|
4330
|
+
key=".6"
|
|
4331
4331
|
style={
|
|
4332
4332
|
Object {
|
|
4333
4333
|
"marginBottom": "100px",
|
|
@@ -15254,7 +15254,7 @@ FREE GIFTS-
|
|
|
15254
15254
|
<CapCheckbox
|
|
15255
15255
|
checked={false}
|
|
15256
15256
|
disabled={false}
|
|
15257
|
-
key=".
|
|
15257
|
+
key=".4"
|
|
15258
15258
|
labelType="h4"
|
|
15259
15259
|
onChange={[Function]}
|
|
15260
15260
|
>
|
|
@@ -15316,7 +15316,7 @@ FREE GIFTS-
|
|
|
15316
15316
|
</div>
|
|
15317
15317
|
</CapCheckbox>
|
|
15318
15318
|
<div
|
|
15319
|
-
key=".
|
|
15319
|
+
key=".6"
|
|
15320
15320
|
style={
|
|
15321
15321
|
Object {
|
|
15322
15322
|
"marginBottom": "100px",
|
|
@@ -26273,7 +26273,7 @@ FREE GIFTS-
|
|
|
26273
26273
|
<CapCheckbox
|
|
26274
26274
|
checked={false}
|
|
26275
26275
|
disabled={false}
|
|
26276
|
-
key=".
|
|
26276
|
+
key=".4"
|
|
26277
26277
|
labelType="h4"
|
|
26278
26278
|
onChange={[Function]}
|
|
26279
26279
|
>
|
|
@@ -26335,7 +26335,7 @@ FREE GIFTS-
|
|
|
26335
26335
|
</div>
|
|
26336
26336
|
</CapCheckbox>
|
|
26337
26337
|
<div
|
|
26338
|
-
key=".
|
|
26338
|
+
key=".6"
|
|
26339
26339
|
style={
|
|
26340
26340
|
Object {
|
|
26341
26341
|
"marginBottom": "100px",
|
|
@@ -36,7 +36,6 @@ const SmsWrapper = (props) => {
|
|
|
36
36
|
handleTestAndPreview,
|
|
37
37
|
handleCloseTestAndPreview,
|
|
38
38
|
isTestAndPreviewMode,
|
|
39
|
-
onValidationFail,
|
|
40
39
|
} = props;
|
|
41
40
|
|
|
42
41
|
const smsProps = {
|
|
@@ -59,7 +58,6 @@ const SmsWrapper = (props) => {
|
|
|
59
58
|
handleTestAndPreview,
|
|
60
59
|
handleCloseTestAndPreview,
|
|
61
60
|
isTestAndPreviewMode,
|
|
62
|
-
onValidationFail,
|
|
63
61
|
};
|
|
64
62
|
const isTraiDlt = isTraiDLTEnable(isFullMode, smsRegister);
|
|
65
63
|
return <>
|
|
@@ -29,18 +29,11 @@ import FTP from '../FTP';
|
|
|
29
29
|
import Gallery from '../Assets/Gallery';
|
|
30
30
|
import withStyles from '../../hoc/withStyles';
|
|
31
31
|
import styles, { CapTabStyle } from './TemplatesV2.style';
|
|
32
|
-
import { CREATIVES_UI_VIEW,
|
|
32
|
+
import { CREATIVES_UI_VIEW, LOYALTY, WHATSAPP, RCS, LINE, EMAIL, ASSETS, JP_LOCALE_HIDE_FEATURE, ZALO, INAPP, WEBPUSH } from '../App/constants';
|
|
33
33
|
import AccessForbidden from '../../v2Components/AccessForbidden';
|
|
34
34
|
import { getObjFromQueryParams } from '../../utils/v2common';
|
|
35
35
|
import { makeSelectAuthenticated, selectCurrentOrgDetails } from "../../v2Containers/Cap/selectors";
|
|
36
|
-
import {
|
|
37
|
-
CALL_TASK,
|
|
38
|
-
COMMON_CHANNELS,
|
|
39
|
-
LOYALTY_SUPPORTED_ACTION,
|
|
40
|
-
MOBILE_PUSH,
|
|
41
|
-
NORMALIZED_CHANNEL_ALIASES,
|
|
42
|
-
SMS,
|
|
43
|
-
} from "../CreativesContainer/constants";
|
|
36
|
+
import { LOYALTY_SUPPORTED_ACTION, COMMON_CHANNELS } from "../CreativesContainer/constants";
|
|
44
37
|
|
|
45
38
|
const {CapCustomCardList} = CapCustomCard;
|
|
46
39
|
|
|
@@ -102,16 +95,8 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
102
95
|
return str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').replace(/[^a-zA-Z0-9]+/g, '_').toLowerCase();
|
|
103
96
|
};
|
|
104
97
|
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
const withAliases = normalized.flatMap((norm) => {
|
|
108
|
-
const canonical = NORMALIZED_CHANNEL_ALIASES[norm];
|
|
109
|
-
return canonical ? [norm, canonical] : [norm];
|
|
110
|
-
});
|
|
111
|
-
return new Set(withAliases);
|
|
112
|
-
};
|
|
113
|
-
const normalizedChannelsToHideSet = buildChannelSet(channelsToHide);
|
|
114
|
-
const normalizedChannelsToDisableSet = buildChannelSet(channelsToDisable);
|
|
98
|
+
const normalizedChannelsToHideSet = new Set((channelsToHide || []).map((c) => normalizeChannel(c)));
|
|
99
|
+
const normalizedChannelsToDisableSet = new Set((channelsToDisable || []).map((c) => normalizeChannel(c)));
|
|
115
100
|
|
|
116
101
|
// Build filtered panes by examining each pane's `key` and checking against normalized hide set
|
|
117
102
|
let filteredPanes = Object.keys(defaultPanes).map((k) => defaultPanes[k]).filter((pane) => {
|
|
@@ -123,12 +108,12 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
123
108
|
filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.gallery), key: 'assets' });
|
|
124
109
|
} else {
|
|
125
110
|
// Add special-mode panes only when not hidden (use normalized checks)
|
|
126
|
-
if (!normalizedChannelsToHideSet.has(
|
|
127
|
-
filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.callTask), key:
|
|
111
|
+
if (!normalizedChannelsToHideSet.has('call_task')) {
|
|
112
|
+
filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.callTask), key: 'call_task' });
|
|
128
113
|
}
|
|
129
|
-
if (!normalizedChannelsToHideSet.has(
|
|
130
|
-
filteredPanes.push({ content: <></>, tab: intl.formatMessage(messages.FTP), key:
|
|
131
|
-
defaultChannel =
|
|
114
|
+
if (!normalizedChannelsToHideSet.has('ftp')) {
|
|
115
|
+
filteredPanes.push({ content: <></>, tab: intl.formatMessage(messages.FTP), key: 'ftp' });
|
|
116
|
+
defaultChannel = 'FTP';
|
|
132
117
|
}
|
|
133
118
|
|
|
134
119
|
// Create a local copy of COMMON_CHANNELS to avoid mutating the imported array
|
|
@@ -178,15 +163,15 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
178
163
|
|
|
179
164
|
// If audience is anonymous, prefer mobilepush as default (if not hidden)
|
|
180
165
|
if (isAnonymousType) {
|
|
181
|
-
const mobilePushNorm = normalizeChannel(
|
|
166
|
+
const mobilePushNorm = normalizeChannel('mobilepush');
|
|
182
167
|
if (!normalizedChannelsToHideSet.has(mobilePushNorm)) {
|
|
183
|
-
defaultChannel =
|
|
168
|
+
defaultChannel = 'mobilepush';
|
|
184
169
|
}
|
|
185
170
|
}
|
|
186
171
|
|
|
187
|
-
const
|
|
172
|
+
const channel = ['sms', 'email', 'mobilepush', 'line', 'call_task'];
|
|
188
173
|
if (normalizedChannelsToDisableSet.size > 0) {
|
|
189
|
-
|
|
174
|
+
channel.some((ch) => {
|
|
190
175
|
if (!normalizedChannelsToDisableSet.has(ch)) {
|
|
191
176
|
defaultChannel = ch;
|
|
192
177
|
return true;
|
|
@@ -105,10 +105,12 @@ export const useTagManagement = ({
|
|
|
105
105
|
const validationConfig = useMemo(
|
|
106
106
|
() => ({
|
|
107
107
|
tagsParam: tags,
|
|
108
|
+
injectedTagsParams: injectedTags,
|
|
108
109
|
location,
|
|
109
110
|
tagModule: getDefaultTags,
|
|
111
|
+
eventContextTags,
|
|
110
112
|
}),
|
|
111
|
-
[tags, location, getDefaultTags],
|
|
113
|
+
[tags, injectedTags, location, getDefaultTags, eventContextTags],
|
|
112
114
|
);
|
|
113
115
|
|
|
114
116
|
return {
|
|
@@ -528,19 +528,26 @@ describe('useTagManagement', () => {
|
|
|
528
528
|
|
|
529
529
|
describe('validationConfig', () => {
|
|
530
530
|
it('should return validation config with tags', () => {
|
|
531
|
+
const injectedTags = [{ id: 5, name: 'Injected Tag' }];
|
|
532
|
+
const eventContextTags = [{ id: 6, name: 'Event Tag' }];
|
|
533
|
+
|
|
531
534
|
const { result } = renderHook(() =>
|
|
532
535
|
useTagManagement({
|
|
533
536
|
location: defaultLocation,
|
|
534
537
|
globalActions: mockGlobalActions,
|
|
535
538
|
metaEntities: defaultMetaEntities,
|
|
539
|
+
injectedTags,
|
|
540
|
+
eventContextTags,
|
|
536
541
|
getDefaultTags: 'custom',
|
|
537
542
|
})
|
|
538
543
|
);
|
|
539
544
|
|
|
540
545
|
expect(result.current.validationConfig).toEqual({
|
|
541
546
|
tagsParam: defaultMetaEntities.tags.standard,
|
|
547
|
+
injectedTagsParams: injectedTags,
|
|
542
548
|
location: defaultLocation,
|
|
543
549
|
tagModule: 'custom',
|
|
550
|
+
eventContextTags,
|
|
544
551
|
});
|
|
545
552
|
});
|
|
546
553
|
|
|
@@ -295,8 +295,8 @@ const WebPushCreate = ({
|
|
|
295
295
|
const validateTemplateName = useCallback((value) => validateTemplateNameUtil(value), []);
|
|
296
296
|
|
|
297
297
|
const validateTitle = useCallback(
|
|
298
|
-
(value) => validateTitleUtil(value, formatMessage, messages, restrictPersonalization
|
|
299
|
-
[formatMessage, restrictPersonalization
|
|
298
|
+
(value) => validateTitleUtil(value, formatMessage, messages, restrictPersonalization),
|
|
299
|
+
[formatMessage, restrictPersonalization],
|
|
300
300
|
);
|
|
301
301
|
|
|
302
302
|
const validateUrl = useCallback(
|
|
@@ -11,34 +11,19 @@ import { hasPersonalizationTags } from '../../../../utils/commonUtils';
|
|
|
11
11
|
export const validateTemplateName = (value) => !value || value.trim() === '';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Validates notification title
|
|
14
|
+
* Validates notification title
|
|
15
15
|
* @param {string} value - The title value
|
|
16
16
|
* @param {Function} formatMessage - i18n format message function
|
|
17
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
|
|
20
18
|
* @returns {string} Error message if invalid, empty string if valid
|
|
21
19
|
*/
|
|
22
|
-
export const validateTitle = (value, formatMessage, messages, restrictPersonalization
|
|
20
|
+
export const validateTitle = (value, formatMessage, messages, restrictPersonalization) => {
|
|
23
21
|
if (!value || value.trim() === '') {
|
|
24
22
|
return formatMessage(messages.titleRequired);
|
|
25
23
|
}
|
|
26
24
|
if (restrictPersonalization && hasPersonalizationTags(value)) {
|
|
27
25
|
return formatMessage(messages.personalizationTokensErrorMessage);
|
|
28
26
|
}
|
|
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
|
-
|
|
42
27
|
return '';
|
|
43
28
|
};
|
|
44
29
|
|
|
@@ -80,6 +65,12 @@ export const validateMessageContent = (value, formatMessage, messages, validatio
|
|
|
80
65
|
isFullMode,
|
|
81
66
|
}) || {};
|
|
82
67
|
|
|
68
|
+
if (validationResponse?.unsupportedTags?.length) {
|
|
69
|
+
return formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
70
|
+
unsupportedTags: validationResponse.unsupportedTags.join(', '),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
83
74
|
if (validationResponse?.isBraceError) {
|
|
84
75
|
return formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
85
76
|
}
|
|
@@ -127,40 +127,6 @@ describe('validation', () => {
|
|
|
127
127
|
expect(result).toBe('Personalization tags are not supported for anonymous customers');
|
|
128
128
|
expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.personalizationTokensErrorMessage);
|
|
129
129
|
});
|
|
130
|
-
|
|
131
|
-
it('should return brace error when validationConfig is provided and validateTags returns isBraceError', () => {
|
|
132
|
-
const validationConfig = { tagsParam: [], location: {}, tagModule: '' };
|
|
133
|
-
validateTags.mockReturnValue({ isBraceError: true });
|
|
134
|
-
const result = validateTitle(
|
|
135
|
-
'Valid Title',
|
|
136
|
-
mockFormatMessage,
|
|
137
|
-
mockMessages,
|
|
138
|
-
false,
|
|
139
|
-
validationConfig,
|
|
140
|
-
false
|
|
141
|
-
);
|
|
142
|
-
expect(result).toBe('Unbalanced curly braces');
|
|
143
|
-
expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unbalanacedCurlyBraces);
|
|
144
|
-
expect(validateTags).toHaveBeenCalledWith({
|
|
145
|
-
content: 'Valid Title',
|
|
146
|
-
...validationConfig,
|
|
147
|
-
isFullMode: false,
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('should not run tag validation when validationConfig is null', () => {
|
|
152
|
-
validateTags.mockClear();
|
|
153
|
-
const result = validateTitle('Valid Title', mockFormatMessage, mockMessages, false, null);
|
|
154
|
-
expect(result).toBe('');
|
|
155
|
-
expect(validateTags).not.toHaveBeenCalled();
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('should not run tag validation when validationConfig is undefined', () => {
|
|
159
|
-
validateTags.mockClear();
|
|
160
|
-
const result = validateTitle('Valid Title', mockFormatMessage, mockMessages, false, undefined);
|
|
161
|
-
expect(result).toBe('');
|
|
162
|
-
expect(validateTags).not.toHaveBeenCalled();
|
|
163
|
-
});
|
|
164
130
|
});
|
|
165
131
|
|
|
166
132
|
describe('validateUrl', () => {
|
|
@@ -217,8 +183,10 @@ describe('validation', () => {
|
|
|
217
183
|
describe('validateMessageContent', () => {
|
|
218
184
|
const mockValidationConfig = {
|
|
219
185
|
tagsParam: [],
|
|
186
|
+
injectedTagsParams: [],
|
|
220
187
|
location: {},
|
|
221
188
|
tagModule: '',
|
|
189
|
+
eventContextTags: [],
|
|
222
190
|
};
|
|
223
191
|
|
|
224
192
|
beforeEach(() => {
|
|
@@ -257,6 +225,17 @@ describe('validation', () => {
|
|
|
257
225
|
});
|
|
258
226
|
});
|
|
259
227
|
|
|
228
|
+
it('should return error message for unsupported tags', () => {
|
|
229
|
+
validateTags.mockReturnValue({
|
|
230
|
+
unsupportedTags: ['tag1', 'tag2'],
|
|
231
|
+
});
|
|
232
|
+
const result = validateMessageContent('Message with {tag1} and {tag2}', mockFormatMessage, mockMessages, mockValidationConfig);
|
|
233
|
+
expect(result).toBe('Unsupported tags: tag1, tag2');
|
|
234
|
+
expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unsupportedTagsValidationError, {
|
|
235
|
+
unsupportedTags: 'tag1, tag2',
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
260
239
|
it('should return error message for unbalanced curly braces', () => {
|
|
261
240
|
validateTags.mockReturnValue({
|
|
262
241
|
isBraceError: true,
|
|
@@ -266,11 +245,22 @@ describe('validation', () => {
|
|
|
266
245
|
expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unbalanacedCurlyBraces);
|
|
267
246
|
});
|
|
268
247
|
|
|
248
|
+
it('should return error message for both unsupported tags and brace error (unsupported tags takes precedence)', () => {
|
|
249
|
+
validateTags.mockReturnValue({
|
|
250
|
+
unsupportedTags: ['tag1'],
|
|
251
|
+
isBraceError: true,
|
|
252
|
+
});
|
|
253
|
+
const result = validateMessageContent('Message with {tag1}', mockFormatMessage, mockMessages, mockValidationConfig);
|
|
254
|
+
expect(result).toBe('Unsupported tags: tag1');
|
|
255
|
+
});
|
|
256
|
+
|
|
269
257
|
it('should pass validation config to validateTags', () => {
|
|
270
258
|
const customConfig = {
|
|
271
259
|
tagsParam: [{ id: 1, name: 'Tag1' }],
|
|
260
|
+
injectedTagsParams: [{ id: 2, name: 'Tag2' }],
|
|
272
261
|
location: { query: { type: 'test' } },
|
|
273
262
|
tagModule: 'custom',
|
|
263
|
+
eventContextTags: [{ id: 3, name: 'Tag3' }],
|
|
274
264
|
};
|
|
275
265
|
validateTags.mockReturnValue({});
|
|
276
266
|
validateMessageContent('Valid message', mockFormatMessage, mockMessages, customConfig);
|
|
@@ -316,16 +306,6 @@ describe('validation', () => {
|
|
|
316
306
|
expect(result).toBe('Personalization tags are not supported for anonymous customers');
|
|
317
307
|
expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.personalizationTokensErrorMessage);
|
|
318
308
|
});
|
|
319
|
-
|
|
320
|
-
it('should pass isFullMode to validateTags when provided', () => {
|
|
321
|
-
validateTags.mockReturnValue({});
|
|
322
|
-
validateMessageContent('Valid message', mockFormatMessage, mockMessages, mockValidationConfig, true);
|
|
323
|
-
expect(validateTags).toHaveBeenCalledWith({
|
|
324
|
-
content: 'Valid message',
|
|
325
|
-
...mockValidationConfig,
|
|
326
|
-
isFullMode: true,
|
|
327
|
-
});
|
|
328
|
-
});
|
|
329
309
|
});
|
|
330
310
|
});
|
|
331
311
|
|
|
@@ -637,21 +637,22 @@ export const Whatsapp = (props) => {
|
|
|
637
637
|
validateTags({
|
|
638
638
|
content: contentData.join(""),
|
|
639
639
|
tagsParam: tags,
|
|
640
|
+
injectedTagsParams: injectedTags,
|
|
640
641
|
location,
|
|
641
642
|
tagModule: getDefaultTags,
|
|
643
|
+
eventContextTags,
|
|
642
644
|
isFullMode,
|
|
643
645
|
}) || {};
|
|
646
|
+
const unsupportedTagsLengthCheck =
|
|
647
|
+
validationResponse?.unsupportedTags?.length > 0;
|
|
644
648
|
if (type === HEADER_TEXT) {
|
|
645
649
|
headerTagValidationResponse = validationResponse;
|
|
646
|
-
updateIsHeaderTagValidationError(
|
|
650
|
+
updateIsHeaderTagValidationError(unsupportedTagsLengthCheck);
|
|
647
651
|
} else if (type === CAROUSEL_TEXT) {
|
|
648
|
-
return [
|
|
649
|
-
{ fieldName: "carouselTagValidationErrMessage", value: validationResponse.isBraceError ? validationResponse : {} },
|
|
650
|
-
{ fieldName: "carouselTagValidationErr", value: validationResponse.isBraceError },
|
|
651
|
-
];
|
|
652
|
+
return [{fieldName: "carouselTagValidationErrMessage", value: validationResponse}, {fieldName: "carouselTagValidationErr", value: unsupportedTagsLengthCheck}];
|
|
652
653
|
} else {
|
|
653
654
|
tagValidationResponse = validationResponse;
|
|
654
|
-
updateIsTagValidationError(
|
|
655
|
+
updateIsTagValidationError(unsupportedTagsLengthCheck);
|
|
655
656
|
}
|
|
656
657
|
}
|
|
657
658
|
};
|
|
@@ -2681,11 +2682,18 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
|
|
|
2681
2682
|
} else {
|
|
2682
2683
|
validationResponse = tagValidationResponse;
|
|
2683
2684
|
}
|
|
2684
|
-
const { isBraceError } = validationResponse
|
|
2685
|
+
const { unsupportedTags = [], isBraceError } = validationResponse;
|
|
2686
|
+
|
|
2687
|
+
let tagError = "";
|
|
2688
|
+
if (unsupportedTags.length > 0) {
|
|
2689
|
+
tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
2690
|
+
unsupportedTags,
|
|
2691
|
+
});
|
|
2692
|
+
}
|
|
2685
2693
|
if (isBraceError) {
|
|
2686
|
-
|
|
2694
|
+
tagError = formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
2687
2695
|
}
|
|
2688
|
-
return
|
|
2696
|
+
return <CapError>{tagError}</CapError>;
|
|
2689
2697
|
};
|
|
2690
2698
|
|
|
2691
2699
|
const editModeContent = () => (
|
|
@@ -270,15 +270,23 @@ export const Zalo = (props) => {
|
|
|
270
270
|
validateTags({
|
|
271
271
|
content: message,
|
|
272
272
|
tagsParam: tags,
|
|
273
|
+
injectedTagsParams: injectedTags,
|
|
273
274
|
location,
|
|
274
275
|
tagModule: getDefaultTags,
|
|
276
|
+
eventContextTags,
|
|
275
277
|
isFullMode,
|
|
276
278
|
}) || {};
|
|
277
|
-
const { isBraceError } = tagValidationResponse;
|
|
279
|
+
const { unsupportedTags = [], isBraceError } = tagValidationResponse;
|
|
280
|
+
let tagError = '';
|
|
281
|
+
if (unsupportedTags.length > 0) {
|
|
282
|
+
tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
283
|
+
unsupportedTags,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
278
286
|
if (isBraceError) {
|
|
279
|
-
|
|
287
|
+
tagError = formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
280
288
|
}
|
|
281
|
-
return
|
|
289
|
+
return tagError;
|
|
282
290
|
};
|
|
283
291
|
|
|
284
292
|
//this function is used for checking errror validation in this it validate tags error and length error
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
|
|
2
|
-
import { showError } from '../commonMethods';
|
|
3
|
-
|
|
4
|
-
jest.mock('@capillarytech/cap-ui-library/CapNotification', () => ({
|
|
5
|
-
error: jest.fn(),
|
|
6
|
-
}));
|
|
7
|
-
|
|
8
|
-
jest.mock('../Create/messages', () => ({
|
|
9
|
-
__esModule: true,
|
|
10
|
-
default: {
|
|
11
|
-
validationError: { defaultMessage: 'Validation error' },
|
|
12
|
-
},
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
describe('Sms commonMethods', () => {
|
|
16
|
-
describe('showError', () => {
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
jest.clearAllMocks();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('should call CapNotification.error when formData is not empty, isFormValid is false, and errorData has at least one true value', () => {
|
|
22
|
-
const context = {
|
|
23
|
-
props: {
|
|
24
|
-
intl: { formatMessage: jest.fn((msg) => msg.defaultMessage || 'Validation error') },
|
|
25
|
-
},
|
|
26
|
-
state: {
|
|
27
|
-
formData: { message: 'test' },
|
|
28
|
-
isFormValid: false,
|
|
29
|
-
errorData: [{ message: true }],
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
showError.call(context);
|
|
33
|
-
expect(CapNotification.error).toHaveBeenCalledWith({
|
|
34
|
-
key: 'validation-error',
|
|
35
|
-
message: 'Validation error',
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should not call CapNotification.error when formData is empty', () => {
|
|
40
|
-
const context = {
|
|
41
|
-
props: { intl: { formatMessage: jest.fn() } },
|
|
42
|
-
state: {
|
|
43
|
-
formData: {},
|
|
44
|
-
isFormValid: false,
|
|
45
|
-
errorData: [{ message: true }],
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
showError.call(context);
|
|
49
|
-
expect(CapNotification.error).not.toHaveBeenCalled();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('should not call CapNotification.error when isFormValid is true', () => {
|
|
53
|
-
const context = {
|
|
54
|
-
props: { intl: { formatMessage: jest.fn() } },
|
|
55
|
-
state: {
|
|
56
|
-
formData: { message: 'test' },
|
|
57
|
-
isFormValid: true,
|
|
58
|
-
errorData: [{ message: true }],
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
showError.call(context);
|
|
62
|
-
expect(CapNotification.error).not.toHaveBeenCalled();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('should not call CapNotification.error when no errorData entry has a true value', () => {
|
|
66
|
-
const context = {
|
|
67
|
-
props: { intl: { formatMessage: jest.fn() } },
|
|
68
|
-
state: {
|
|
69
|
-
formData: { message: 'test' },
|
|
70
|
-
isFormValid: false,
|
|
71
|
-
errorData: [{ message: false, title: false }],
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
showError.call(context);
|
|
75
|
-
expect(CapNotification.error).not.toHaveBeenCalled();
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should not call CapNotification.error when errorData is empty', () => {
|
|
79
|
-
const context = {
|
|
80
|
-
props: { intl: { formatMessage: jest.fn() } },
|
|
81
|
-
state: {
|
|
82
|
-
formData: { message: 'test' },
|
|
83
|
-
isFormValid: false,
|
|
84
|
-
errorData: [],
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
showError.call(context);
|
|
88
|
-
expect(CapNotification.error).not.toHaveBeenCalled();
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should not call CapNotification.error when errorData[0] is undefined', () => {
|
|
92
|
-
const context = {
|
|
93
|
-
props: { intl: { formatMessage: jest.fn() } },
|
|
94
|
-
state: {
|
|
95
|
-
formData: { message: 'test' },
|
|
96
|
-
isFormValid: false,
|
|
97
|
-
errorData: [],
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
showError.call(context);
|
|
101
|
-
expect(CapNotification.error).not.toHaveBeenCalled();
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('should call CapNotification.error when errorData[0] has multiple keys and one is true', () => {
|
|
105
|
-
const context = {
|
|
106
|
-
props: {
|
|
107
|
-
intl: { formatMessage: jest.fn((msg) => msg.defaultMessage || 'Validation error') },
|
|
108
|
-
},
|
|
109
|
-
state: {
|
|
110
|
-
formData: { message: 'hello' },
|
|
111
|
-
isFormValid: false,
|
|
112
|
-
errorData: [{ message: false, title: true }],
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
showError.call(context);
|
|
116
|
-
expect(CapNotification.error).toHaveBeenCalledWith({
|
|
117
|
-
key: 'validation-error',
|
|
118
|
-
message: 'Validation error',
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
});
|