@capillarytech/creatives-library 8.0.285-alpha.0 → 8.0.285

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/utils/common.js +7 -0
  4. package/utils/commonUtils.js +79 -2
  5. package/utils/tagValidations.js +71 -92
  6. package/utils/tests/commonUtil.test.js +32 -79
  7. package/utils/tests/tagValidations.test.js +37 -18
  8. package/v2Components/FormBuilder/index.js +126 -47
  9. package/v2Containers/CreativesContainer/index.js +1 -0
  10. package/v2Containers/Email/index.js +5 -1
  11. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +18 -6
  12. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +106 -8
  13. package/v2Containers/FTP/index.js +51 -2
  14. package/v2Containers/InApp/index.js +23 -2
  15. package/v2Containers/InApp/tests/index.test.js +6 -17
  16. package/v2Containers/InappAdvance/index.js +24 -3
  17. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +24 -3
  18. package/v2Containers/Line/Container/Text/index.js +1 -0
  19. package/v2Containers/MobilePushNew/index.js +24 -4
  20. package/v2Containers/Rcs/index.js +37 -12
  21. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +18 -4
  22. package/v2Containers/SmsTrai/Create/index.scss +1 -1
  23. package/v2Containers/SmsTrai/Edit/index.js +17 -4
  24. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +0 -9
  25. package/v2Containers/Viber/index.js +1 -0
  26. package/v2Containers/Viber/index.scss +1 -1
  27. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +3 -1
  28. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +7 -0
  29. package/v2Containers/WebPush/Create/index.js +2 -2
  30. package/v2Containers/WebPush/Create/utils/validation.js +9 -18
  31. package/v2Containers/WebPush/Create/utils/validation.test.js +24 -0
  32. package/v2Containers/Whatsapp/index.js +17 -6
  33. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +624 -248
  34. package/v2Containers/Zalo/index.js +11 -3
@@ -77,6 +77,7 @@ import { getContent } from "../MobilePush/commonMethods";
77
77
  import { getMessageObject } from "../../utils/messageUtils";
78
78
  import { gtmPush } from "../../utils/gtmTrackers";
79
79
  import mobilePushReducer from "./reducer";
80
+ import { hasLiquidSupportFeature } from "../../utils/common";
80
81
  import formBuilderMessages from "../../v2Components/FormBuilder/messages";
81
82
  import { validateMobilePushContent } from "../../utils/commonUtils";
82
83
  import { getSingleTab } from "../InApp/utils";
@@ -93,7 +94,7 @@ import createMobilePushPayloadWithIntl from "../../utils/createMobilePushPayload
93
94
  import { MOBILEPUSH } from "../../v2Components/CapVideoUpload/constants";
94
95
  import { StyledCapTab } from "./style";
95
96
  import TestAndPreviewSlidebox from "../../v2Components/TestAndPreviewSlidebox";
96
- import { LIQUID_SUPPORTED_CHANNELS, MOBILE_PUSH } from "../CreativesContainer/constants";
97
+ import { MOBILE_PUSH } from "../CreativesContainer/constants";
97
98
  import creativesMessages from "../CreativesContainer/messages";
98
99
 
99
100
  // Helper function to extract deep link keys from URL where value equals key
@@ -798,9 +799,10 @@ const MobilePushNew = ({
798
799
  (value) => {
799
800
  let errorTemplateDescMessage = "";
800
801
 
801
- const { isBraceError } = validateTags({
802
+ const { unsupportedTags, isBraceError } = validateTags({
802
803
  content: value,
803
804
  tagsParam: tags,
805
+ injectedTagsParams: injectedTags,
804
806
  location,
805
807
  tagModule: getDefaultTags,
806
808
  isFullMode,
@@ -810,6 +812,14 @@ const MobilePushNew = ({
810
812
  messages.emptyTemplateDescErrorMessage
811
813
  );
812
814
  }
815
+ if (unsupportedTags?.length > 0) {
816
+ errorTemplateDescMessage = formatMessage(
817
+ globalMessages.unsupportedTagsValidationError,
818
+ {
819
+ unsupportedTags,
820
+ }
821
+ );
822
+ }
813
823
  if (isBraceError) {
814
824
  errorTemplateDescMessage = formatMessage(
815
825
  globalMessages.unbalanacedCurlyBraces
@@ -2598,8 +2608,18 @@ const MobilePushNew = ({
2598
2608
  messages: formBuilderMessages,
2599
2609
  tagLookupMap: metaEntities?.tagLookupMap || {},
2600
2610
  eventContextTags: metaEntities?.eventContextTags || [],
2601
- isLiquidFlow: LIQUID_SUPPORTED_CHANNELS.includes(MOBILE_PUSH),
2611
+ isLiquidFlow: hasLiquidSupportFeature(),
2602
2612
  forwardedTags: {},
2613
+ skipTags: (tag) => {
2614
+ const skipRegexes = [
2615
+ /dynamic_expiry_date_after_\d+_days\.FORMAT_\d/,
2616
+ /unsubscribe\(#[a-zA-Z\d]{6}\)/,
2617
+ /Link_to_[a-zA-z]/,
2618
+ /SURVEY.*\.TOKEN/,
2619
+ /^[A-Za-z].*\([a-zA-Z\d]*\)/,
2620
+ ];
2621
+ return skipRegexes.some((regex) => regex.test(tag));
2622
+ },
2603
2623
  singleTab: getSingleTab(accountData),
2604
2624
  });
2605
2625
  }, [
@@ -2612,7 +2632,7 @@ const MobilePushNew = ({
2612
2632
  accountData,
2613
2633
  ]);
2614
2634
 
2615
- const isLiquidFlow = LIQUID_SUPPORTED_CHANNELS.includes(MOBILE_PUSH);
2635
+ const isLiquidFlow = hasLiquidSupportFeature();
2616
2636
 
2617
2637
  useEffect(() => {
2618
2638
  // Always map to { label } for both platforms
@@ -394,15 +394,23 @@ export const Rcs = (props) => {
394
394
  const validationResponse =
395
395
  validateTags({
396
396
  content: contentForValidation,
397
- tagsParam: tags,
398
- location,
399
- tagModule: getDefaultTags,
400
- isFullMode,
401
- }) || {};
402
- const errorMsg =
403
- (validationResponse?.isBraceError &&
404
- formatMessage(globalMessages.unbalanacedCurlyBraces)) ||
405
- false;
397
+ tagsParam: tags,
398
+ injectedTagsParams: injectedTags,
399
+ location,
400
+ tagModule: getDefaultTags,
401
+ eventContextTags,
402
+ isFullMode,
403
+ }) || {};
404
+ const unsupportedTagsLengthCheck =
405
+ validationResponse?.unsupportedTags?.length > 0;
406
+ const errorMsg =
407
+ (unsupportedTagsLengthCheck &&
408
+ formatMessage(globalMessages.unsupportedTagsValidationError, {
409
+ unsupportedTags: validationResponse.unsupportedTags,
410
+ })) ||
411
+ (validationResponse.isBraceError &&
412
+ formatMessage(globalMessages.unbalanacedCurlyBraces)) ||
413
+ false;
406
414
  if (type === TITLE_TEXT) setTemplateTitleError(errorMsg);
407
415
  if (type === MESSAGE_TEXT) setTemplateDescError(errorMsg);
408
416
  };
@@ -827,9 +835,10 @@ export const Rcs = (props) => {
827
835
 
828
836
  const templateDescErrorHandler = (value) => {
829
837
  let errorMessage = false;
830
- const { isBraceError } = validateTags({
838
+ const { unsupportedTags, isBraceError } = validateTags({
831
839
  content: value,
832
840
  tagsParam: tags,
841
+ injectedTagsParams: injectedTags,
833
842
  location,
834
843
  tagModule: getDefaultTags,
835
844
  isFullMode,
@@ -859,10 +868,26 @@ export const Rcs = (props) => {
859
868
  };
860
869
 
861
870
  const fallbackMessageErrorHandler = (value) => {
871
+ let errorMessage = false;
872
+ const { unsupportedTags } = validateTags({
873
+ content: value,
874
+ tagsParam: tags,
875
+ injectedTagsParams: injectedTags,
876
+ location,
877
+ tagModule: getDefaultTags,
878
+ isFullMode,
879
+ }) || {};
862
880
  if (value?.length > FALLBACK_MESSAGE_MAX_LENGTH) {
863
- return formatMessage(messages.fallbackMsgLenError);
881
+ errorMessage = formatMessage(messages.fallbackMsgLenError);
882
+ } else if (unsupportedTags?.length > 0) {
883
+ errorMessage = formatMessage(
884
+ globalMessages.unsupportedTagsValidationError,
885
+ {
886
+ unsupportedTags,
887
+ },
888
+ );
864
889
  }
865
- return false;
890
+ return errorMessage;
866
891
  };
867
892
 
868
893
  // Check for forbidden characters: square brackets [] and single curly braces {}
@@ -86505,6 +86505,7 @@ new message content.",
86505
86505
  },
86506
86506
  ]
86507
86507
  }
86508
+ showTruncatedTooltip={false}
86508
86509
  size="large"
86509
86510
  style={
86510
86511
  Object {
@@ -86524,6 +86525,7 @@ new message content.",
86524
86525
  />
86525
86526
  }
86526
86527
  onChange={[Function]}
86528
+ onDropdownVisibleChange={[Function]}
86527
86529
  removeIcon={
86528
86530
  <_default
86529
86531
  size="s"
@@ -86589,6 +86591,7 @@ new message content.",
86589
86591
  onBlur={[Function]}
86590
86592
  onChange={[Function]}
86591
86593
  onDeselect={[Function]}
86594
+ onDropdownVisibleChange={[Function]}
86592
86595
  onFocus={[Function]}
86593
86596
  onInputKeyDown={[Function]}
86594
86597
  onSearch={[Function]}
@@ -86827,9 +86830,13 @@ new message content.",
86827
86830
  "opacity": 1,
86828
86831
  }
86829
86832
  }
86830
- title="Vertical Medium"
86833
+ title=""
86831
86834
  >
86832
- Vertical Medium
86835
+ <div
86836
+ className="cap-select-option-tooltip"
86837
+ >
86838
+ Vertical Medium
86839
+ </div>
86833
86840
  </div>
86834
86841
  </div>
86835
86842
  <span
@@ -105847,6 +105854,7 @@ new message content.",
105847
105854
  },
105848
105855
  ]
105849
105856
  }
105857
+ showTruncatedTooltip={false}
105850
105858
  size="large"
105851
105859
  style={
105852
105860
  Object {
@@ -105866,6 +105874,7 @@ new message content.",
105866
105874
  />
105867
105875
  }
105868
105876
  onChange={[Function]}
105877
+ onDropdownVisibleChange={[Function]}
105869
105878
  removeIcon={
105870
105879
  <_default
105871
105880
  size="s"
@@ -105931,6 +105940,7 @@ new message content.",
105931
105940
  onBlur={[Function]}
105932
105941
  onChange={[Function]}
105933
105942
  onDeselect={[Function]}
105943
+ onDropdownVisibleChange={[Function]}
105934
105944
  onFocus={[Function]}
105935
105945
  onInputKeyDown={[Function]}
105936
105946
  onSearch={[Function]}
@@ -106169,9 +106179,13 @@ new message content.",
106169
106179
  "opacity": 1,
106170
106180
  }
106171
106181
  }
106172
- title="Vertical Medium"
106182
+ title=""
106173
106183
  >
106174
- Vertical Medium
106184
+ <div
106185
+ className="cap-select-option-tooltip"
106186
+ >
106187
+ Vertical Medium
106188
+ </div>
106175
106189
  </div>
106176
106190
  </div>
106177
106191
  <span
@@ -98,5 +98,5 @@
98
98
  }
99
99
 
100
100
  .create-dlt-msg {
101
- margin-left: 120px;
101
+ margin-left: 100px;
102
102
  }
@@ -51,11 +51,11 @@ import {
51
51
  ALL,
52
52
  LIBRARY,
53
53
  } from './constants';
54
- import { LIQUID_SUPPORTED_CHANNELS } from '../../CreativesContainer/constants';
55
54
  import v2EditSmsReducer from '../../Sms/Edit/reducer';
56
55
  import { v2SmsEditSagas } from '../../Sms/Edit/sagas';
57
56
  import ErrorInfoNote from '../../../v2Components/ErrorInfoNote';
58
57
  import { validateLiquidTemplateContent } from '../../../utils/commonUtils';
58
+ import { hasLiquidSupportFeature } from '../../../utils/common';
59
59
  import { ANDROID } from '../../../v2Components/CommonTestAndPreview/constants';
60
60
 
61
61
  let varMap = {};
@@ -240,11 +240,15 @@ export const SmsTraiEdit = (props) => {
240
240
  validateTags({
241
241
  content: updatedSmsEditor.join(''),
242
242
  tagsParam: tags,
243
+ injectedTagsParams: injectedTags,
243
244
  location,
244
245
  tagModule: getDefaultTags,
246
+ eventContextTags,
245
247
  isFullMode,
246
248
  }) || {};
247
- updateIsTagValidationError(false);
249
+ updateIsTagValidationError(
250
+ tagValidationResponse.unsupportedTags.length > 0,
251
+ );
248
252
  }
249
253
  }, [updatedSmsEditor, tags]);
250
254
 
@@ -544,7 +548,16 @@ export const SmsTraiEdit = (props) => {
544
548
  return countVarChar;
545
549
  };
546
550
 
547
- const tagValidationErrorMessage = () => null;
551
+ const tagValidationErrorMessage = () => {
552
+ const { unsupportedTags = [] } = tagValidationResponse;
553
+ let tagError = '';
554
+ if (unsupportedTags.length > 0) {
555
+ tagError = formatMessage(messages.unsupportedTagsValidationError, {
556
+ unsupportedTags,
557
+ });
558
+ }
559
+ return <CapError>{tagError}</CapError>;
560
+ };
548
561
 
549
562
  const disablehandler = () => {
550
563
  if (traiData && !isEmpty(traiData)) {
@@ -591,7 +604,7 @@ export const SmsTraiEdit = (props) => {
591
604
  setShowTestAndPreviewSlidebox(false);
592
605
  };
593
606
 
594
- const isLiquidSupportFeatureEnabled = LIQUID_SUPPORTED_CHANNELS.includes(SMS);
607
+ const isLiquidSupportFeatureEnabled = hasLiquidSupportFeature();
595
608
  return (
596
609
  <>
597
610
  <CapSpin spinning={loading || fetchingLiquidTags} tip={fetchingLiquidTags && formatMessage(formBuilderMessages.liquidSpinText)}>
@@ -5817,7 +5817,6 @@ FREE GIFTS-
5817
5817
  </CapButton>
5818
5818
  <CapButton
5819
5819
  className="create-msg"
5820
- disabled={true}
5821
5820
  isAddBtn={false}
5822
5821
  onClick={[Function]}
5823
5822
  type="primary"
@@ -5825,7 +5824,6 @@ FREE GIFTS-
5825
5824
  <Button
5826
5825
  block={false}
5827
5826
  className="cap-button-v2 create-msg"
5828
- disabled={true}
5829
5827
  ghost={false}
5830
5828
  htmlType="button"
5831
5829
  loading={false}
@@ -5835,7 +5833,6 @@ FREE GIFTS-
5835
5833
  <Wave>
5836
5834
  <button
5837
5835
  className="ant-btn cap-button-v2 create-msg ant-btn-primary"
5838
- disabled={true}
5839
5836
  onClick={[Function]}
5840
5837
  type="button"
5841
5838
  >
@@ -16731,7 +16728,6 @@ FREE GIFTS-
16731
16728
  </CapButton>
16732
16729
  <CapButton
16733
16730
  className="create-msg"
16734
- disabled={true}
16735
16731
  isAddBtn={false}
16736
16732
  onClick={[Function]}
16737
16733
  type="primary"
@@ -16739,7 +16735,6 @@ FREE GIFTS-
16739
16735
  <Button
16740
16736
  block={false}
16741
16737
  className="cap-button-v2 create-msg"
16742
- disabled={true}
16743
16738
  ghost={false}
16744
16739
  htmlType="button"
16745
16740
  loading={false}
@@ -16749,7 +16744,6 @@ FREE GIFTS-
16749
16744
  <Wave>
16750
16745
  <button
16751
16746
  className="ant-btn cap-button-v2 create-msg ant-btn-primary"
16752
- disabled={true}
16753
16747
  onClick={[Function]}
16754
16748
  type="button"
16755
16749
  >
@@ -27735,7 +27729,6 @@ FREE GIFTS-
27735
27729
  </CapButton>
27736
27730
  <CapButton
27737
27731
  className="create-msg"
27738
- disabled={true}
27739
27732
  isAddBtn={false}
27740
27733
  onClick={[Function]}
27741
27734
  type="primary"
@@ -27743,7 +27736,6 @@ FREE GIFTS-
27743
27736
  <Button
27744
27737
  block={false}
27745
27738
  className="cap-button-v2 create-msg"
27746
- disabled={true}
27747
27739
  ghost={false}
27748
27740
  htmlType="button"
27749
27741
  loading={false}
@@ -27753,7 +27745,6 @@ FREE GIFTS-
27753
27745
  <Wave>
27754
27746
  <button
27755
27747
  className="ant-btn cap-button-v2 create-msg ant-btn-primary"
27756
- disabled={true}
27757
27748
  onClick={[Function]}
27758
27749
  type="button"
27759
27750
  >
@@ -234,6 +234,7 @@ export const Viber = (props) => {
234
234
  const { valid, isBraceError } = validateTags({
235
235
  content: value,
236
236
  tagsParam: tags,
237
+ injectedTagsParams: injectedTags,
237
238
  location,
238
239
  tagModule: 'outbound',
239
240
  isFullMode,
@@ -121,5 +121,5 @@
121
121
  margin-top: $CAP_SPACE_08;
122
122
  }
123
123
  .test-and-preview-button {
124
- margin-left: 120px;
124
+ margin-left: 100px;
125
125
  }
@@ -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
 
@@ -285,8 +285,8 @@ const WebPushCreate = ({
285
285
  const validateTemplateName = useCallback((value) => validateTemplateNameUtil(value), []);
286
286
 
287
287
  const validateTitle = useCallback(
288
- (value) => validateTitleUtil(value, formatMessage, messages, validationConfig, isFullMode),
289
- [formatMessage, validationConfig, isFullMode],
288
+ (value) => validateTitleUtil(value, formatMessage, messages),
289
+ [formatMessage],
290
290
  );
291
291
 
292
292
  const validateUrl = useCallback(
@@ -10,31 +10,16 @@ import globalMessages from '../../../Cap/messages';
10
10
  export const validateTemplateName = (value) => !value || value.trim() === '';
11
11
 
12
12
  /**
13
- * Validates notification title (required and optional tag validation)
13
+ * Validates notification title
14
14
  * @param {string} value - The title value
15
15
  * @param {Function} formatMessage - i18n format message function
16
16
  * @param {Object} messages - Message definitions
17
- * @param {Object} [validationConfig] - Optional config for tag validation
18
- * @param {boolean} [isFullMode] - Optional; when set with validationConfig, runs tag validation
19
17
  * @returns {string} Error message if invalid, empty string if valid
20
18
  */
21
- export const validateTitle = (value, formatMessage, messages, validationConfig, isFullMode) => {
19
+ export const validateTitle = (value, formatMessage, messages) => {
22
20
  if (!value || value.trim() === '') {
23
21
  return formatMessage(messages.titleRequired);
24
22
  }
25
-
26
- if (validationConfig != null) {
27
- const validationResponse = validateTags({
28
- content: value,
29
- ...validationConfig,
30
- isFullMode,
31
- }) || {};
32
-
33
- if (validationResponse?.isBraceError) {
34
- return formatMessage(globalMessages.unbalanacedCurlyBraces);
35
- }
36
- }
37
-
38
23
  return '';
39
24
  };
40
25
 
@@ -75,7 +60,13 @@ export const validateMessageContent = (value, formatMessage, messages, validatio
75
60
  ...validationConfig,
76
61
  isFullMode,
77
62
  }) || {};
78
-
63
+
64
+ if (validationResponse?.unsupportedTags?.length) {
65
+ return formatMessage(globalMessages.unsupportedTagsValidationError, {
66
+ unsupportedTags: validationResponse.unsupportedTags.join(', '),
67
+ });
68
+ }
69
+
79
70
  if (validationResponse?.isBraceError) {
80
71
  return formatMessage(globalMessages.unbalanacedCurlyBraces);
81
72
  }
@@ -169,8 +169,10 @@ describe('validation', () => {
169
169
  describe('validateMessageContent', () => {
170
170
  const mockValidationConfig = {
171
171
  tagsParam: [],
172
+ injectedTagsParams: [],
172
173
  location: {},
173
174
  tagModule: '',
175
+ eventContextTags: [],
174
176
  };
175
177
 
176
178
  beforeEach(() => {
@@ -209,6 +211,17 @@ describe('validation', () => {
209
211
  });
210
212
  });
211
213
 
214
+ it('should return error message for unsupported tags', () => {
215
+ validateTags.mockReturnValue({
216
+ unsupportedTags: ['tag1', 'tag2'],
217
+ });
218
+ const result = validateMessageContent('Message with {tag1} and {tag2}', mockFormatMessage, mockMessages, mockValidationConfig);
219
+ expect(result).toBe('Unsupported tags: tag1, tag2');
220
+ expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unsupportedTagsValidationError, {
221
+ unsupportedTags: 'tag1, tag2',
222
+ });
223
+ });
224
+
212
225
  it('should return error message for unbalanced curly braces', () => {
213
226
  validateTags.mockReturnValue({
214
227
  isBraceError: true,
@@ -218,11 +231,22 @@ describe('validation', () => {
218
231
  expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unbalanacedCurlyBraces);
219
232
  });
220
233
 
234
+ it('should return error message for both unsupported tags and brace error (unsupported tags takes precedence)', () => {
235
+ validateTags.mockReturnValue({
236
+ unsupportedTags: ['tag1'],
237
+ isBraceError: true,
238
+ });
239
+ const result = validateMessageContent('Message with {tag1}', mockFormatMessage, mockMessages, mockValidationConfig);
240
+ expect(result).toBe('Unsupported tags: tag1');
241
+ });
242
+
221
243
  it('should pass validation config to validateTags', () => {
222
244
  const customConfig = {
223
245
  tagsParam: [{ id: 1, name: 'Tag1' }],
246
+ injectedTagsParams: [{ id: 2, name: 'Tag2' }],
224
247
  location: { query: { type: 'test' } },
225
248
  tagModule: 'custom',
249
+ eventContextTags: [{ id: 3, name: 'Tag3' }],
226
250
  };
227
251
  validateTags.mockReturnValue({});
228
252
  validateMessageContent('Valid message', mockFormatMessage, mockMessages, customConfig);
@@ -637,18 +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(false);
650
+ updateIsHeaderTagValidationError(unsupportedTagsLengthCheck);
647
651
  } else if (type === CAROUSEL_TEXT) {
648
- return [{fieldName: "carouselTagValidationErrMessage", value: validationResponse}, {fieldName: "carouselTagValidationErr", value: false}];
652
+ return [{fieldName: "carouselTagValidationErrMessage", value: validationResponse}, {fieldName: "carouselTagValidationErr", value: unsupportedTagsLengthCheck}];
649
653
  } else {
650
654
  tagValidationResponse = validationResponse;
651
- updateIsTagValidationError(false);
655
+ updateIsTagValidationError(unsupportedTagsLengthCheck);
652
656
  }
653
657
  }
654
658
  };
@@ -2678,11 +2682,18 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
2678
2682
  } else {
2679
2683
  validationResponse = tagValidationResponse;
2680
2684
  }
2681
- 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
+ }
2682
2693
  if (isBraceError) {
2683
- return <CapError>{formatMessage(globalMessages.unbalanacedCurlyBraces)}</CapError>;
2694
+ tagError = formatMessage(globalMessages.unbalanacedCurlyBraces);
2684
2695
  }
2685
- return null;
2696
+ return <CapError>{tagError}</CapError>;
2686
2697
  };
2687
2698
 
2688
2699
  const editModeContent = () => (