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

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 (129) hide show
  1. package/constants/unified.js +0 -29
  2. package/package.json +1 -1
  3. package/services/tests/api.test.js +0 -13
  4. package/utils/commonUtils.js +1 -19
  5. package/v2Components/CapActionButton/constants.js +0 -7
  6. package/v2Components/CapActionButton/index.js +109 -167
  7. package/v2Components/CapActionButton/index.scss +6 -157
  8. package/v2Components/CapActionButton/messages.js +3 -19
  9. package/v2Components/CapActionButton/tests/index.test.js +17 -41
  10. package/v2Components/CapTagList/index.js +0 -10
  11. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +49 -70
  12. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +2 -8
  13. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +21 -207
  14. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +0 -16
  15. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +10 -85
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +0 -30
  17. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +11 -79
  18. package/v2Components/CommonTestAndPreview/SendTestMessage.js +5 -10
  19. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +15 -160
  20. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +76 -341
  21. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +4 -133
  22. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +0 -11
  23. package/v2Components/CommonTestAndPreview/constants.js +2 -38
  24. package/v2Components/CommonTestAndPreview/index.js +186 -676
  25. package/v2Components/CommonTestAndPreview/messages.js +3 -49
  26. package/v2Components/CommonTestAndPreview/sagas.js +6 -15
  27. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +284 -308
  28. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +65 -231
  29. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +5 -118
  30. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +0 -341
  31. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +1 -8
  32. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +13 -34
  33. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +283 -281
  34. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +1 -199
  35. package/v2Components/CommonTestAndPreview/tests/index.test.js +4 -132
  36. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
  37. package/v2Components/FormBuilder/index.js +10 -8
  38. package/v2Components/TemplatePreview/_templatePreview.scss +23 -33
  39. package/v2Components/TemplatePreview/index.js +28 -143
  40. package/v2Components/TemplatePreview/tests/index.test.js +0 -142
  41. package/v2Components/TestAndPreviewSlidebox/index.js +1 -13
  42. package/v2Components/TestAndPreviewSlidebox/sagas.js +4 -11
  43. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +1 -3
  44. package/v2Containers/CreativesContainer/SlideBoxContent.js +4 -36
  45. package/v2Containers/CreativesContainer/SlideBoxFooter.js +1 -10
  46. package/v2Containers/CreativesContainer/SlideBoxHeader.js +4 -29
  47. package/v2Containers/CreativesContainer/constants.js +0 -9
  48. package/v2Containers/CreativesContainer/index.js +103 -300
  49. package/v2Containers/CreativesContainer/index.scss +1 -51
  50. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +34 -78
  51. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +16 -79
  52. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -8
  53. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +98 -357
  54. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +15 -20
  55. package/v2Containers/CreativesContainer/tests/index.test.js +9 -71
  56. package/v2Containers/Email/reducer.js +11 -3
  57. package/v2Containers/Email/sagas.js +9 -5
  58. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +4 -0
  59. package/v2Containers/Email/tests/sagas.test.js +21 -3
  60. package/v2Containers/Rcs/constants.js +8 -119
  61. package/v2Containers/Rcs/index.js +812 -2375
  62. package/v2Containers/Rcs/index.scss +6 -276
  63. package/v2Containers/Rcs/messages.js +3 -38
  64. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +70345 -98302
  65. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +5 -0
  66. package/v2Containers/Rcs/tests/index.test.js +121 -152
  67. package/v2Containers/Rcs/tests/mockData.js +0 -38
  68. package/v2Containers/Rcs/tests/utils.test.js +30 -646
  69. package/v2Containers/Rcs/utils.js +11 -478
  70. package/v2Containers/Sms/Create/index.js +40 -100
  71. package/v2Containers/SmsTrai/Create/index.js +4 -9
  72. package/v2Containers/SmsTrai/Edit/constants.js +0 -2
  73. package/v2Containers/SmsTrai/Edit/index.js +130 -636
  74. package/v2Containers/SmsTrai/Edit/messages.js +4 -14
  75. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +2296 -4249
  76. package/v2Containers/SmsWrapper/index.js +8 -37
  77. package/v2Containers/TagList/index.js +0 -6
  78. package/v2Containers/Templates/_templates.scss +2 -163
  79. package/v2Containers/Templates/actions.js +0 -11
  80. package/v2Containers/Templates/constants.js +0 -2
  81. package/v2Containers/Templates/index.js +54 -119
  82. package/v2Containers/Templates/sagas.js +12 -57
  83. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1079 -1043
  84. package/v2Containers/Templates/tests/sagas.test.js +123 -193
  85. package/v2Containers/TemplatesV2/TemplatesV2.style.js +1 -72
  86. package/v2Containers/TemplatesV2/index.js +23 -86
  87. package/v2Containers/Whatsapp/index.js +20 -3
  88. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -578
  89. package/utils/rcsPayloadUtils.js +0 -92
  90. package/utils/templateVarUtils.js +0 -201
  91. package/utils/tests/templateVarUtils.test.js +0 -204
  92. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js.rej +0 -18
  93. package/v2Components/CommonTestAndPreview/previewApiUtils.js +0 -59
  94. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +0 -67
  95. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +0 -87
  96. package/v2Components/SmsFallback/constants.js +0 -73
  97. package/v2Components/SmsFallback/index.js +0 -955
  98. package/v2Components/SmsFallback/index.scss +0 -265
  99. package/v2Components/SmsFallback/messages.js +0 -78
  100. package/v2Components/SmsFallback/smsFallbackUtils.js +0 -118
  101. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +0 -50
  102. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +0 -147
  103. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +0 -304
  104. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +0 -197
  105. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +0 -277
  106. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +0 -422
  107. package/v2Components/SmsFallback/useLocalTemplateList.js +0 -92
  108. package/v2Components/TemplatePreview/constants.js +0 -2
  109. package/v2Components/VarSegmentMessageEditor/constants.js +0 -2
  110. package/v2Components/VarSegmentMessageEditor/index.js +0 -125
  111. package/v2Components/VarSegmentMessageEditor/index.scss +0 -46
  112. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +0 -43
  113. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +0 -67
  114. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +0 -90
  115. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +0 -258
  116. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +0 -125
  117. package/v2Containers/Rcs/index.js.rej +0 -1336
  118. package/v2Containers/Rcs/index.scss.rej +0 -74
  119. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +0 -225
  120. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap.rej +0 -128
  121. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +0 -318
  122. package/v2Containers/Sms/smsFormDataHelpers.js +0 -67
  123. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +0 -253
  124. package/v2Containers/SmsTrai/Edit/index.scss +0 -121
  125. package/v2Containers/Templates/TemplatesActionBar.js +0 -101
  126. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +0 -120
  127. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +0 -180
  128. package/v2Containers/Templates/utils/smsTemplatesListApi.js +0 -79
  129. 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
  };