@capillarytech/creatives-library 8.0.345-alpha.12 → 8.0.345-alpha.13

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 (138) hide show
  1. package/constants/unified.js +0 -29
  2. package/package.json +1 -1
  3. package/services/api.js +20 -0
  4. package/services/tests/api.test.js +59 -13
  5. package/utils/commonUtils.js +1 -19
  6. package/v2Components/CapActionButton/constants.js +0 -7
  7. package/v2Components/CapActionButton/index.js +109 -167
  8. package/v2Components/CapActionButton/index.scss +6 -157
  9. package/v2Components/CapActionButton/messages.js +3 -19
  10. package/v2Components/CapActionButton/tests/index.test.js +17 -41
  11. package/v2Components/CapCustomSkeleton/index.js +1 -1
  12. package/v2Components/CapCustomSkeleton/tests/__snapshots__/index.test.js.snap +12 -12
  13. package/v2Components/CapTagList/index.js +0 -10
  14. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +49 -70
  15. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +2 -8
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +21 -207
  17. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +0 -16
  18. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +10 -85
  19. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +0 -30
  20. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +11 -79
  21. package/v2Components/CommonTestAndPreview/SendTestMessage.js +5 -10
  22. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +15 -160
  23. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +76 -341
  24. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +4 -133
  25. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +0 -11
  26. package/v2Components/CommonTestAndPreview/constants.js +2 -38
  27. package/v2Components/CommonTestAndPreview/index.js +186 -676
  28. package/v2Components/CommonTestAndPreview/messages.js +3 -49
  29. package/v2Components/CommonTestAndPreview/sagas.js +6 -15
  30. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +284 -308
  31. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +65 -231
  32. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +5 -118
  33. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +0 -341
  34. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +1 -8
  35. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +13 -34
  36. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +283 -281
  37. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +1 -199
  38. package/v2Components/CommonTestAndPreview/tests/index.test.js +4 -132
  39. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
  40. package/v2Components/FormBuilder/index.js +10 -8
  41. package/v2Components/TemplatePreview/_templatePreview.scss +23 -33
  42. package/v2Components/TemplatePreview/index.js +28 -143
  43. package/v2Components/TemplatePreview/tests/index.test.js +0 -142
  44. package/v2Components/TestAndPreviewSlidebox/index.js +1 -13
  45. package/v2Components/TestAndPreviewSlidebox/sagas.js +4 -11
  46. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +1 -3
  47. package/v2Containers/Assets/images/archive_Empty_Illustration.svg +9 -0
  48. package/v2Containers/CreativesContainer/SlideBoxContent.js +4 -36
  49. package/v2Containers/CreativesContainer/SlideBoxFooter.js +4 -11
  50. package/v2Containers/CreativesContainer/SlideBoxHeader.js +4 -29
  51. package/v2Containers/CreativesContainer/constants.js +0 -9
  52. package/v2Containers/CreativesContainer/index.js +108 -300
  53. package/v2Containers/CreativesContainer/index.scss +1 -51
  54. package/v2Containers/CreativesContainer/messages.js +4 -0
  55. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +34 -78
  56. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +16 -79
  57. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -8
  58. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +98 -357
  59. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +18 -20
  60. package/v2Containers/CreativesContainer/tests/index.test.js +9 -71
  61. package/v2Containers/Rcs/constants.js +8 -119
  62. package/v2Containers/Rcs/index.js +812 -2375
  63. package/v2Containers/Rcs/index.scss +6 -276
  64. package/v2Containers/Rcs/messages.js +3 -38
  65. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +70345 -98302
  66. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +5 -0
  67. package/v2Containers/Rcs/tests/index.test.js +121 -152
  68. package/v2Containers/Rcs/tests/mockData.js +0 -38
  69. package/v2Containers/Rcs/tests/utils.test.js +30 -646
  70. package/v2Containers/Rcs/utils.js +11 -478
  71. package/v2Containers/Sms/Create/index.js +40 -100
  72. package/v2Containers/SmsTrai/Create/index.js +4 -9
  73. package/v2Containers/SmsTrai/Edit/constants.js +0 -2
  74. package/v2Containers/SmsTrai/Edit/index.js +130 -636
  75. package/v2Containers/SmsTrai/Edit/messages.js +4 -14
  76. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +2296 -4249
  77. package/v2Containers/SmsWrapper/index.js +8 -37
  78. package/v2Containers/TagList/index.js +0 -6
  79. package/v2Containers/Templates/ChannelTypeIllustration.js +23 -6
  80. package/v2Containers/Templates/_templates.scss +126 -181
  81. package/v2Containers/Templates/actions.js +36 -11
  82. package/v2Containers/Templates/constants.js +23 -2
  83. package/v2Containers/Templates/index.js +333 -142
  84. package/v2Containers/Templates/messages.js +68 -0
  85. package/v2Containers/Templates/reducer.js +68 -0
  86. package/v2Containers/Templates/sagas.js +98 -55
  87. package/v2Containers/Templates/selectors.js +12 -0
  88. package/v2Containers/Templates/tests/ChannelTypeIllustration.test.js +12 -0
  89. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1256 -1042
  90. package/v2Containers/Templates/tests/index.test.js +6 -0
  91. package/v2Containers/Templates/tests/reducer.test.js +178 -0
  92. package/v2Containers/Templates/tests/sagas.test.js +436 -200
  93. package/v2Containers/Templates/tests/selector.test.js +32 -0
  94. package/v2Containers/TemplatesV2/TemplatesV2.style.js +1 -72
  95. package/v2Containers/TemplatesV2/index.js +23 -86
  96. package/v2Containers/Whatsapp/index.js +20 -3
  97. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -578
  98. package/utils/rcsPayloadUtils.js +0 -92
  99. package/utils/templateVarUtils.js +0 -201
  100. package/utils/tests/templateVarUtils.test.js +0 -204
  101. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js.rej +0 -18
  102. package/v2Components/CommonTestAndPreview/previewApiUtils.js +0 -59
  103. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +0 -67
  104. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +0 -87
  105. package/v2Components/SmsFallback/constants.js +0 -73
  106. package/v2Components/SmsFallback/index.js +0 -955
  107. package/v2Components/SmsFallback/index.scss +0 -265
  108. package/v2Components/SmsFallback/messages.js +0 -78
  109. package/v2Components/SmsFallback/smsFallbackUtils.js +0 -118
  110. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +0 -50
  111. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +0 -147
  112. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +0 -304
  113. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +0 -197
  114. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +0 -277
  115. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +0 -422
  116. package/v2Components/SmsFallback/useLocalTemplateList.js +0 -92
  117. package/v2Components/TemplatePreview/constants.js +0 -2
  118. package/v2Components/VarSegmentMessageEditor/constants.js +0 -2
  119. package/v2Components/VarSegmentMessageEditor/index.js +0 -125
  120. package/v2Components/VarSegmentMessageEditor/index.scss +0 -46
  121. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +0 -43
  122. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +0 -67
  123. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +0 -90
  124. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +0 -258
  125. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +0 -125
  126. package/v2Containers/Rcs/index.js.rej +0 -1336
  127. package/v2Containers/Rcs/index.scss.rej +0 -74
  128. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +0 -225
  129. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap.rej +0 -128
  130. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +0 -318
  131. package/v2Containers/Sms/smsFormDataHelpers.js +0 -67
  132. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +0 -253
  133. package/v2Containers/SmsTrai/Edit/index.scss +0 -121
  134. package/v2Containers/Templates/TemplatesActionBar.js +0 -101
  135. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +0 -120
  136. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +0 -180
  137. package/v2Containers/Templates/utils/smsTemplatesListApi.js +0 -79
  138. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +0 -131
@@ -301,6 +301,11 @@ exports[`RCS utils getRCSContent renders RCS content with no media 1`] = `
301
301
  <div
302
302
  className="cap-rcs-creatives"
303
303
  >
304
+ <div
305
+ className="CapLabel-n7zsf5-0 gtGqsG rcs-listing-content title"
306
+ fontWeight="bold"
307
+ type="label19"
308
+ />
304
309
  <div
305
310
  className="CapLabel-n7zsf5-0 ekUKMg rcs-listing-content desc"
306
311
  type="label19"
@@ -14,19 +14,6 @@ import TagList from '../../../v2Containers/TagList/index.js';
14
14
  import CapActionButton from '../../../v2Components/CapActionButton';
15
15
  import { INITIAL_SUGGESTIONS_DATA_STOP } from '../constants';
16
16
 
17
- // Ensure real UnifiedPreview: other suites mock the same module; parallel workers + load order
18
- // can leave a stub active. This factory wins for this file's resolution of UnifiedPreview.
19
- jest.mock('../../../v2Components/CommonTestAndPreview/UnifiedPreview', () =>
20
- jest.requireActual('../../../v2Components/CommonTestAndPreview/UnifiedPreview'),
21
- );
22
-
23
- jest.mock('react-redux', () => {
24
- const actual = jest.requireActual('react-redux');
25
- return {
26
- ...actual,
27
- useDispatch: jest.fn(() => jest.fn()),
28
- };
29
- });
30
17
 
31
18
  jest.mock('../../../v2Containers/TagList/index.js', () => ({
32
19
  __esModule: true,
@@ -155,7 +142,7 @@ const renderHelper = (args) => {
155
142
  isEditFlow={args.isEditFlow || false}
156
143
  loadingTags={false}
157
144
  metaEntities={[]}
158
- {...(args.omitGetDefaultTags ? {} : { getDefaultTags: true })}
145
+ getDefaultTags
159
146
  isDltEnabled={args.isDltEnabled || false}
160
147
  smsRegister={'DLT'}
161
148
  />
@@ -199,13 +186,13 @@ describe('Creatives rcs test/>', () => {
199
186
  renderedComponent.update();
200
187
  expect(renderedComponent).toMatchSnapshot();
201
188
 
202
- // Carousel option exists
189
+ // Carousel option exists but is disabled
203
190
  const options = radioGroup.props().options;
204
191
  expect(options).toHaveLength(3);
205
192
  expect(options[0].value).toBe('text_message');
206
193
  expect(options[1].value).toBe('rich_card');
207
194
  expect(options[2].value).toBe('carousel');
208
- expect(options[2].disabled).toBeFalsy();
195
+ expect(options[2].disabled).toBe(true);
209
196
 
210
197
  // Disabled state in edit mode
211
198
  renderHelper({
@@ -458,8 +445,8 @@ describe('Creatives rcs test/>', () => {
458
445
  });
459
446
 
460
447
  it('should call fetchSchemaForEntity when TagList context changes (non-full mode)', () => {
461
- // omitGetDefaultTags: when getDefaultTags is true it overwrites query.context and blocks context switches
462
- renderHelper({ isFullMode: false, omitGetDefaultTags: true });
448
+ // Re-render in non-full mode so TagList is visible
449
+ renderHelper({ isFullMode: false });
463
450
  const tagList = renderedComponent.find('.tag-mock').at(0);
464
451
  expect(tagList.exists()).toBe(true);
465
452
  const before = fetchSchemaForEntity.mock.calls.length;
@@ -467,126 +454,13 @@ describe('Creatives rcs test/>', () => {
467
454
  tagList.prop('onContextChange')('ALL');
468
455
  });
469
456
  const after = fetchSchemaForEntity.mock.calls.length;
470
- expect(after).toBeGreaterThan(before);
457
+ expect(after).toBe(before + 1);
471
458
  const lastArg = fetchSchemaForEntity.mock.calls[after - 1][0];
472
459
  expect(lastArg).toEqual(expect.objectContaining({ layout: 'SMS', type: 'TAG', context: 'default' }));
473
460
  });
474
461
  });
475
462
  });
476
463
 
477
- describe('RCS carousel label resolution in non-full mode', () => {
478
- it('should resolve shared variables across multiple carousel cards in both inline preview and Test&Preview slidebox', async () => {
479
- const templateData = {
480
- name: 'CarouselVarsTemplate',
481
- versions: {
482
- base: {
483
- content: {
484
- RCS: {
485
- rcsContent: {
486
- cardType: 'CAROUSEL',
487
- cardSettings: { cardOrientation: 'VERTICAL', cardWidth: 'SMALL' },
488
- cardContent: [
489
- {
490
- title: 'Hi {{name}}',
491
- description: 'Welcome {{name}}',
492
- mediaType: 'IMAGE',
493
- media: { mediaUrl: 'https://cdn.example.com/c1.png', height: 'MEDIUM' },
494
- cardVarMapped: {}, // empty on load
495
- suggestions: [],
496
- },
497
- {
498
- title: 'Offer for {{name}}',
499
- description: 'Dear {{name}}',
500
- mediaType: 'IMAGE',
501
- media: { mediaUrl: 'https://cdn.example.com/c2.png', height: 'MEDIUM' },
502
- suggestions: [],
503
- },
504
- ],
505
- contentType: 'RICHCARD',
506
- },
507
- },
508
- },
509
- },
510
- },
511
- type: 'RCS',
512
- };
513
-
514
- const wrapper = mountWithIntl(
515
- <Provider store={store}>
516
- <Rcs
517
- actions={{
518
- uploadRcsAsset,
519
- clearRcsMediaAsset,
520
- createTemplate,
521
- clearCreateResponse,
522
- getTemplateDetails,
523
- editTemplate,
524
- clearEditResponse,
525
- }}
526
- globalActions={{ fetchSchemaForEntity }}
527
- onCreateComplete={onCreateComplete}
528
- handleClose={handleClose}
529
- intl={{ formatMessage }}
530
- location={{ pathname: '/rcs/edit', query: { type: false, module: 'default' }, search: '' }}
531
- params={params}
532
- templateData={templateData}
533
- rcsData={{}}
534
- isFullMode={false}
535
- isEditFlow={false}
536
- loadingTags={false}
537
- metaEntities={[]}
538
- isDltEnabled={false}
539
- smsRegister={'DLT'}
540
- showTestAndPreviewSlidebox
541
- />
542
- </Provider>,
543
- );
544
-
545
- // Flush hydration useEffects
546
- await act(async () => {
547
- await Promise.resolve();
548
- });
549
- wrapper.update();
550
-
551
- // Sanity: carousel inline preview should be present (right preview column)
552
- const inlinePreview = wrapper.find('.rcs-preview-container').find('UnifiedPreview').at(0);
553
- expect(inlinePreview.exists()).toBe(true);
554
- expect(inlinePreview.props().content?.carouselData?.length).toBeGreaterThanOrEqual(2);
555
-
556
- // Variable slot id may live on `id` or React `key` depending on CapInput/TextArea wiring.
557
- const nameVarAreas = wrapper.find('TextArea').filterWhere((n) => {
558
- const id = String(n.prop('id') || '');
559
- const key = String(n.key() || '');
560
- return id.includes('{{name}}_') || key.includes('{{name}}_');
561
- });
562
- expect(nameVarAreas.length).toBeGreaterThanOrEqual(1);
563
-
564
- act(() => {
565
- const slotId = nameVarAreas.at(0).prop('id') || nameVarAreas.at(0).key();
566
- nameVarAreas.at(0).props().onChange({ target: { id: slotId, value: 'madhavi' } });
567
- });
568
- wrapper.update();
569
-
570
- // Inline preview should now show resolved values across BOTH cards
571
- const updatedInlinePreview = wrapper.find('.rcs-preview-container').find('UnifiedPreview').at(0);
572
- const inlineCards = updatedInlinePreview.props().content.carouselData;
573
- expect(inlineCards[0].title).toBe('Hi madhavi');
574
- expect(inlineCards[0].bodyText).toBe('Welcome madhavi');
575
- expect(inlineCards[1].title).toBe('Offer for madhavi');
576
- expect(inlineCards[1].bodyText).toBe('Dear madhavi');
577
-
578
- // Slidebox content should also be resolved (same underlying mapping)
579
- const slidebox = wrapper.find('TestAndPreviewSlidebox').at(0);
580
- expect(slidebox.exists()).toBe(true);
581
- const slideboxContent = slidebox.props().content;
582
- expect(slideboxContent?.carouselData?.length).toBeGreaterThanOrEqual(2);
583
- expect(slideboxContent.carouselData[0].title).toBe('Hi madhavi');
584
- expect(slideboxContent.carouselData[0].bodyText).toBe('Welcome madhavi');
585
- expect(slideboxContent.carouselData[1].title).toBe('Offer for madhavi');
586
- expect(slideboxContent.carouselData[1].bodyText).toBe('Dear madhavi');
587
- });
588
- });
589
-
590
464
  describe('RCS orientation tests', () => {
591
465
  it('should default to MEDIUM_HEIGHT (vertical) orientation', () => {
592
466
  renderHelper({ isEditFlow: false }); // force CapSelect to render
@@ -673,7 +547,7 @@ describe('RCS orientation tests', () => {
673
547
  });
674
548
 
675
549
  describe('RCS createPayload', () => {
676
- it('should build expected payload in full mode (IMAGE)', async () => {
550
+ it('should build expected payload in full mode (IMAGE, horizontal-left)', async () => {
677
551
  const createRcsTemplate = jest.fn();
678
552
  const getTemplateDetails = jest.fn();
679
553
  const getFormData = jest.fn();
@@ -756,10 +630,15 @@ describe('RCS createPayload', () => {
756
630
  expect(payloadArg.versions.base.content.RCS.rcsContent.accessToken).toBe('secret-token');
757
631
  expect(payloadArg.versions.base.content.RCS.rcsContent.hostName).toBe('rcs.host.example.com');
758
632
  expect(payloadArg.versions.base.content.RCS.rcsContent.accountName).toBe('Brand RCS Account');
759
- expect(payloadArg.versions.base.content.RCS.rcsContent.cardSettings).toBeDefined();
760
- // SMS fallback is only included when smsFallbackData is set (SmsFallback), not an empty stub
761
- expect(payloadArg.versions.base.content.RCS.smsFallBackContent).toBeUndefined();
762
- }, 30000);
633
+ expect(payloadArg.versions.base.content.RCS.rcsContent.cardSettings).toEqual(
634
+ expect.objectContaining({ cardOrientation: 'HORIZONTAL', mediaAlignment: 'LEFT', cardWidth: 'SMALL' }),
635
+ );
636
+ expect(card.mediaType).toBe('IMAGE');
637
+ expect(card.media).toEqual(expect.objectContaining({ mediaUrl: 'https://cdn.example.com/img.png' }));
638
+ expect(payloadArg.versions.base.content.RCS.smsFallBackContent).toEqual(
639
+ expect.objectContaining({ message: '' }),
640
+ );
641
+ });
763
642
 
764
643
  it('should include empty account metadata when no account is selected', async () => {
765
644
  const createRcsTemplate = jest.fn();
@@ -825,7 +704,7 @@ describe('RCS createPayload', () => {
825
704
  expect(rcsContent.accountName).toBe('');
826
705
  });
827
706
 
828
- it('does not add smsFallBackContent until SmsFallback data is set (isDltEnabled is not wired on Rcs)', async () => {
707
+ it('should attach DLT template configs when enabled', async () => {
829
708
  const createRcsTemplate = jest.fn();
830
709
  const getFormData = jest.fn();
831
710
  const { createPayloadFullMode } = mockData;
@@ -878,7 +757,16 @@ describe('RCS createPayload', () => {
878
757
  createRcsTemplate.mock.calls[0]?.[0] ||
879
758
  getFormData.mock.calls[0]?.[0]?.value;
880
759
  expect(payloadArg).toBeDefined();
881
- expect(payloadArg.versions.base.content.RCS.smsFallBackContent).toBeUndefined();
760
+ expect(payloadArg.versions.base.content.RCS.smsFallBackContent).toEqual(
761
+ expect.objectContaining({
762
+ templateConfigs: expect.objectContaining({
763
+ templateId: '',
764
+ templateName: '',
765
+ template: '',
766
+ registeredSenderIds: [],
767
+ }),
768
+ }),
769
+ );
882
770
  });
883
771
 
884
772
  it('should build expected payload in non-full mode (VIDEO, vertical medium)', () => {
@@ -930,7 +818,7 @@ describe('RCS createPayload', () => {
930
818
  expect(payloadArg.type).toBe('RCS');
931
819
  expect(payloadArg.versions.base.content.RCS.rcsContent.contentType).toBe('RICHCARD');
932
820
  expect(payloadArg.versions.base.content.RCS.rcsContent.cardSettings).toEqual(
933
- expect.objectContaining({ cardOrientation: 'VERTICAL', cardWidth: 'MEDIUM' }),
821
+ expect.objectContaining({ cardOrientation: 'VERTICAL', cardWidth: 'SMALL' }),
934
822
  );
935
823
  expect(card.mediaType).toBe('VIDEO');
936
824
  expect(card.media).toEqual(
@@ -955,9 +843,7 @@ describe('RCS createPayload', () => {
955
843
  // same placeholder appears twice
956
844
  title: 'Hello {{user_name}} and {{user_name}}',
957
845
  description: 'Hi {{user_name}}',
958
- // Rich card so title VarSegment row mounts (NONE → text_message hides title slots)
959
- mediaType: 'IMAGE',
960
- media: { mediaUrl: 'https://cdn.example.com/card.png' },
846
+ mediaType: 'NONE',
961
847
  cardVarMapped: {}, // empty on load
962
848
  suggestions: [],
963
849
  },
@@ -1024,10 +910,91 @@ describe('RCS createPayload', () => {
1024
910
  expect(updatedTitleVarAreas.at(1).prop('value')).toBe('Alice');
1025
911
  });
1026
912
 
1027
- // Skipped: title + body can both emit id `{{user_name}}_1`; onTagSelect relies on titleTextAreaId from
1028
- // focus, which is brittle under Enzyme + mocked TagList. Tag insert behaviour is covered by TagList
1029
- // context test above and cardVarMapped sync test below.
1030
- it.skip('should insert TagList label into focused placeholder and sync duplicates in non-full mode', () => {});
913
+ it('should insert TagList label into focused placeholder and sync duplicates in non-full mode', () => {
914
+ const templateData = {
915
+ name: 'DupVarsTemplate2',
916
+ versions: {
917
+ base: {
918
+ content: {
919
+ RCS: {
920
+ rcsContent: {
921
+ cardType: 'STANDALONE',
922
+ cardSettings: { cardOrientation: 'VERTICAL', cardWidth: 'SMALL' },
923
+ cardContent: [
924
+ {
925
+ title: 'Hello {{user_name}} and {{user_name}}',
926
+ description: 'Hi {{user_name}}',
927
+ mediaType: 'NONE',
928
+ cardVarMapped: {},
929
+ suggestions: [],
930
+ },
931
+ ],
932
+ contentType: 'RICHCARD',
933
+ },
934
+ },
935
+ },
936
+ },
937
+ },
938
+ type: 'RCS',
939
+ };
940
+
941
+ const wrapper = mountWithIntl(
942
+ <Provider store={store}>
943
+ <Rcs
944
+ actions={{
945
+ clearCreateResponse: jest.fn(),
946
+ getTemplateDetails: jest.fn(),
947
+ uploadRcsAsset: jest.fn(),
948
+ clearRcsMediaAsset: jest.fn(),
949
+ editTemplate: jest.fn(),
950
+ clearEditResponse: jest.fn(),
951
+ }}
952
+ globalActions={{ fetchSchemaForEntity }}
953
+ onCreateComplete={onCreateComplete}
954
+ handleClose={handleClose}
955
+ intl={{ formatMessage }}
956
+ location={{ pathname: '/rcs/create', query: { type: false, module: 'default' }, search: '' }}
957
+ params={params}
958
+ templateData={templateData}
959
+ rcsData={{}}
960
+ isFullMode={false}
961
+ isEditFlow={false}
962
+ loadingTags={false}
963
+ metaEntities={[]}
964
+ isDltEnabled={false}
965
+ smsRegister={'DLT'}
966
+ getFormData={jest.fn()}
967
+ />
968
+ </Provider>,
969
+ );
970
+
971
+ const titleVarAreas = wrapper.find('TextArea').filterWhere((n) => {
972
+ const id = n.prop('id') || '';
973
+ return id.includes('{{user_name}}_');
974
+ });
975
+ expect(titleVarAreas.length).toBeGreaterThanOrEqual(2);
976
+
977
+ // Focus the first variable textarea so TagList knows where to insert
978
+ act(() => {
979
+ const id = titleVarAreas.at(0).prop('id');
980
+ titleVarAreas.at(0).props().onFocus({ target: { id } });
981
+ });
982
+ wrapper.update();
983
+
984
+ // Trigger TagList selection (mocked TagList calls onTagSelect with string)
985
+ const tagList = wrapper.find('.tag-mock').at(0);
986
+ act(() => {
987
+ tagList.props().onTagSelect('first_name');
988
+ });
989
+ wrapper.update();
990
+
991
+ const updatedTitleVarAreas = wrapper.find('TextArea').filterWhere((n) => {
992
+ const id = n.prop('id') || '';
993
+ return id.includes('{{user_name}}_');
994
+ });
995
+ expect(updatedTitleVarAreas.at(0).prop('value')).toBe('{{first_name}}');
996
+ expect(updatedTitleVarAreas.at(1).prop('value')).toBe('{{first_name}}');
997
+ });
1031
998
 
1032
999
  it('should keep two tags + freetext inside the variable textarea in non-full mode edit (not merged into static text)', () => {
1033
1000
  const templateData = {
@@ -1094,11 +1061,13 @@ describe('RCS createPayload', () => {
1094
1061
 
1095
1062
  wrapper.update();
1096
1063
 
1097
- // At least one variable slot is rendered (ids like `{{token}}_0`)
1098
- const varSlotAreas = wrapper.find('TextArea').filterWhere((n) =>
1099
- /\{\{[^}]+\}}_\d+/.test(String(n.prop('id') || '')),
1100
- );
1101
- expect(varSlotAreas.length).toBeGreaterThan(0);
1064
+ // The placeholder {{service_type}} should exist as a variable textarea id, and its value should be the mixed string.
1065
+ const serviceTypeAreas = wrapper.find('TextArea').filterWhere((n) => {
1066
+ const id = n.prop('id') || '';
1067
+ return id.includes('{{service_type}}_');
1068
+ });
1069
+ expect(serviceTypeAreas.length).toBeGreaterThanOrEqual(1);
1070
+ expect(serviceTypeAreas.at(0).prop('value')).toBe('{{first_name}}{{adv}}freeText');
1102
1071
 
1103
1072
  // Ensure freetext does NOT leak into static text blocks.
1104
1073
  const staticAreas = wrapper.find('TextArea').filterWhere((n) => !!n.prop('disabled'));
@@ -148,7 +148,6 @@ export const mockData = {
148
148
  },
149
149
  accountData: {
150
150
  selectedRcsAccount: {
151
- id: 'we-crm-account-id-42',
152
151
  sourceAccountIdentifier: 'rcs-account-123',
153
152
  configs: { accessToken: 'secret-token' },
154
153
  hostName: 'rcs.host.example.com',
@@ -286,41 +285,4 @@ export const mockData = {
286
285
  },
287
286
  },
288
287
  },
289
- // RCS template with SMS fallback for edit-flow tests
290
- rcsTemplateWithSmsFallback: {
291
- templateDetails: {
292
- _id: 'rcs_with_fallback_1',
293
- name: 'RCSWithFallback',
294
- type: 'RCS',
295
- versions: {
296
- base: {
297
- content: {
298
- RCS: {
299
- rcsContent: {
300
- cardSettings: { cardOrientation: 'VERTICAL' },
301
- cardContent: [
302
- {
303
- description: 'RCS description',
304
- mediaType: 'TEXT',
305
- suggestions: [],
306
- },
307
- ],
308
- contentType: 'text_message',
309
- },
310
- smsFallBackContent: {
311
- smsTemplateId: 'sms_fb_001',
312
- smsTemplateName: 'Fallback Template',
313
- smsContent: 'SMS fallback message',
314
- message: 'SMS fallback message',
315
- smsTemplateContent: 'SMS fallback message',
316
- smsVariables: [],
317
- smsVarMapped: {},
318
- smsUnicodeValidity: true,
319
- },
320
- },
321
- },
322
- },
323
- },
324
- },
325
- },
326
288
  };