@capillarytech/creatives-library 8.0.353-alpha.6 → 8.0.354

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 (127) hide show
  1. package/constants/unified.js +0 -29
  2. package/index.html +1 -0
  3. package/package.json +1 -1
  4. package/services/tests/api.test.js +20 -35
  5. package/utils/cdnTransformation.js +63 -3
  6. package/utils/commonUtils.js +1 -19
  7. package/utils/tests/cdnTransformation.test.js +111 -0
  8. package/v2Components/CapActionButton/constants.js +0 -7
  9. package/v2Components/CapActionButton/index.js +108 -166
  10. package/v2Components/CapActionButton/index.scss +6 -157
  11. package/v2Components/CapActionButton/messages.js +3 -19
  12. package/v2Components/CapActionButton/tests/index.test.js +17 -41
  13. package/v2Components/CapTagList/index.js +0 -10
  14. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +49 -72
  15. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +2 -8
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +21 -213
  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 -157
  23. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +76 -346
  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 -691
  28. package/v2Components/CommonTestAndPreview/messages.js +3 -45
  29. package/v2Components/CommonTestAndPreview/sagas.js +6 -25
  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 +26 -36
  40. package/v2Components/FormBuilder/index.js +6 -11
  41. package/v2Components/TemplatePreview/_templatePreview.scss +23 -38
  42. package/v2Components/TemplatePreview/index.js +31 -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/CreativesContainer/SlideBoxContent.js +4 -36
  48. package/v2Containers/CreativesContainer/SlideBoxFooter.js +1 -10
  49. package/v2Containers/CreativesContainer/SlideBoxHeader.js +4 -29
  50. package/v2Containers/CreativesContainer/constants.js +0 -9
  51. package/v2Containers/CreativesContainer/index.js +103 -322
  52. package/v2Containers/CreativesContainer/index.scss +1 -51
  53. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +34 -78
  54. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +16 -79
  55. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -8
  56. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +98 -357
  57. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +15 -20
  58. package/v2Containers/CreativesContainer/tests/index.test.js +9 -71
  59. package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
  60. package/v2Containers/Rcs/constants.js +10 -119
  61. package/v2Containers/Rcs/index.js +818 -2450
  62. package/v2Containers/Rcs/index.scss +8 -280
  63. package/v2Containers/Rcs/messages.js +3 -34
  64. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +70073 -98018
  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 -106
  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 -640
  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 +9 -166
  79. package/v2Containers/Templates/actions.js +0 -11
  80. package/v2Containers/Templates/constants.js +0 -2
  81. package/v2Containers/Templates/index.js +52 -120
  82. package/v2Containers/Templates/sagas.js +18 -57
  83. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1017 -1062
  84. package/v2Containers/Templates/tests/sagas.test.js +39 -205
  85. package/v2Containers/TemplatesV2/TemplatesV2.style.js +1 -72
  86. package/v2Containers/TemplatesV2/index.js +23 -86
  87. package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -9
  88. package/v2Containers/Whatsapp/index.js +20 -3
  89. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -578
  90. package/utils/rcsPayloadUtils.js +0 -92
  91. package/utils/templateVarUtils.js +0 -201
  92. package/utils/tests/rcsPayloadUtils.test.js +0 -226
  93. package/utils/tests/templateVarUtils.test.js +0 -204
  94. package/v2Components/CommonTestAndPreview/previewApiUtils.js +0 -59
  95. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +0 -67
  96. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +0 -91
  97. package/v2Components/SmsFallback/constants.js +0 -73
  98. package/v2Components/SmsFallback/index.js +0 -956
  99. package/v2Components/SmsFallback/index.scss +0 -265
  100. package/v2Components/SmsFallback/messages.js +0 -78
  101. package/v2Components/SmsFallback/smsFallbackUtils.js +0 -119
  102. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +0 -50
  103. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +0 -147
  104. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +0 -304
  105. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +0 -223
  106. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +0 -309
  107. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +0 -422
  108. package/v2Components/SmsFallback/useLocalTemplateList.js +0 -92
  109. package/v2Components/TemplatePreview/constants.js +0 -2
  110. package/v2Components/VarSegmentMessageEditor/constants.js +0 -2
  111. package/v2Components/VarSegmentMessageEditor/index.js +0 -125
  112. package/v2Components/VarSegmentMessageEditor/index.scss +0 -46
  113. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +0 -43
  114. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +0 -79
  115. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +0 -90
  116. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +0 -258
  117. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +0 -125
  118. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +0 -225
  119. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +0 -318
  120. package/v2Containers/Sms/smsFormDataHelpers.js +0 -67
  121. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +0 -253
  122. package/v2Containers/SmsTrai/Edit/index.scss +0 -121
  123. package/v2Containers/Templates/TemplatesActionBar.js +0 -101
  124. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +0 -120
  125. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +0 -180
  126. package/v2Containers/Templates/utils/smsTemplatesListApi.js +0 -79
  127. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +0 -131
@@ -9,16 +9,7 @@ import { render, screen } from '@testing-library/react';
9
9
  import '@testing-library/jest-dom';
10
10
  import { injectIntl, IntlProvider } from 'react-intl';
11
11
  import UnifiedPreview from '../../UnifiedPreview';
12
- import {
13
- CHANNELS,
14
- DESKTOP,
15
- TABLET,
16
- MOBILE,
17
- ANDROID,
18
- IOS,
19
- PREVIEW_TAB_RCS,
20
- PREVIEW_TAB_SMS_FALLBACK,
21
- } from '../../constants';
12
+ import { CHANNELS, DESKTOP, TABLET, MOBILE, ANDROID, IOS } from '../../constants';
22
13
  import messages from '../../messages';
23
14
 
24
15
  // Convert messages object to format expected by IntlProvider
@@ -556,195 +547,6 @@ describe('UnifiedPreview', () => {
556
547
 
557
548
  expect(screen.getByTestId('rcs-sender-id')).toHaveTextContent('RCS_SENDER');
558
549
  });
559
-
560
- describe('RCS SMS fallback — Test & Preview tabs', () => {
561
- it('without SMS fallback selected, shows only RCS preview (no RCS+SMS tab layout)', () => {
562
- const props = {
563
- ...defaultProps,
564
- channel: CHANNELS.RCS,
565
- content: { rcsTitle: 'Hello RCS' },
566
- smsFallbackContent: undefined,
567
- };
568
-
569
- const { container } = render(
570
- <TestWrapper>
571
- <ComponentToRender {...props} />
572
- </TestWrapper>
573
- );
574
-
575
- expect(container.querySelector('.unified-preview-rcs-tabs')).toBeNull();
576
- expect(screen.getByTestId('rcs-preview')).toBeInTheDocument();
577
- expect(screen.queryByTestId('sms-preview')).not.toBeInTheDocument();
578
- });
579
-
580
- it('with SMS fallback template body, shows RCS and Fallback SMS tabs', () => {
581
- const props = {
582
- ...defaultProps,
583
- channel: CHANNELS.RCS,
584
- content: { rcsTitle: 'Hello RCS' },
585
- smsFallbackContent: {
586
- content: 'SMS fallback body',
587
- templateContent: 'SMS fallback body',
588
- },
589
- };
590
-
591
- const { container } = render(
592
- <TestWrapper>
593
- <ComponentToRender {...props} />
594
- </TestWrapper>
595
- );
596
-
597
- expect(container.querySelector('.unified-preview-rcs-tabs')).toBeInTheDocument();
598
- expect(
599
- screen.getByRole('tab', { name: messages.rcsTab.defaultMessage })
600
- ).toBeInTheDocument();
601
- expect(
602
- screen.getByRole('tab', { name: messages.smsFallbackTab.defaultMessage })
603
- ).toBeInTheDocument();
604
- });
605
-
606
- it('on SMS fallback tab, renders SMS preview with resolved fallback text when smsFallbackResolvedText is set', () => {
607
- const props = {
608
- ...defaultProps,
609
- channel: CHANNELS.RCS,
610
- content: { rcsTitle: 'Hello RCS' },
611
- smsFallbackContent: {
612
- content: '{{var}}',
613
- templateContent: '{{var}}',
614
- },
615
- smsFallbackResolvedText: 'Resolved SMS for preview',
616
- activePreviewTab: PREVIEW_TAB_SMS_FALLBACK,
617
- onPreviewTabChange: jest.fn(),
618
- };
619
-
620
- render(
621
- <TestWrapper>
622
- <ComponentToRender {...props} />
623
- </TestWrapper>
624
- );
625
-
626
- expect(screen.getByTestId('sms-content')).toHaveTextContent('Resolved SMS for preview');
627
- });
628
-
629
- it('on RCS tab (default), renders RCS preview when dual tabs are shown', () => {
630
- const props = {
631
- ...defaultProps,
632
- channel: CHANNELS.RCS,
633
- content: { rcsTitle: 'Only RCS pane' },
634
- smsFallbackContent: { content: 'SMS', templateContent: 'SMS' },
635
- activePreviewTab: PREVIEW_TAB_RCS,
636
- onPreviewTabChange: jest.fn(),
637
- };
638
-
639
- render(
640
- <TestWrapper>
641
- <ComponentToRender {...props} />
642
- </TestWrapper>
643
- );
644
-
645
- expect(screen.getByTestId('rcs-preview')).toBeInTheDocument();
646
- expect(screen.getByTestId('rcs-content')).toHaveTextContent(/Only RCS pane/);
647
- });
648
-
649
- it('on SMS fallback tab, shows raw template when no varmap and no resolved text', () => {
650
- const props = {
651
- ...defaultProps,
652
- channel: CHANNELS.RCS,
653
- content: { rcsTitle: 'Hello RCS' },
654
- smsFallbackContent: {
655
- content: 'Hello {{name}}',
656
- templateContent: 'Hello {{name}}',
657
- // no rcsSmsFallbackVarMapped
658
- },
659
- smsFallbackResolvedText: undefined,
660
- activePreviewTab: PREVIEW_TAB_SMS_FALLBACK,
661
- onPreviewTabChange: jest.fn(),
662
- };
663
-
664
- render(
665
- <TestWrapper>
666
- <ComponentToRender {...props} />
667
- </TestWrapper>
668
- );
669
-
670
- // rawFallbackTemplate is shown directly — {{tags}} remain visible
671
- expect(screen.getByTestId('sms-content')).toHaveTextContent('Hello {{name}}');
672
- });
673
-
674
- it('on SMS fallback tab, treats empty resolved text as absent and shows raw template', () => {
675
- const props = {
676
- ...defaultProps,
677
- channel: CHANNELS.RCS,
678
- content: { rcsTitle: 'Hello RCS' },
679
- smsFallbackContent: {
680
- content: 'Raw {{var}} template',
681
- templateContent: 'Raw {{var}} template',
682
- },
683
- smsFallbackResolvedText: '',
684
- activePreviewTab: PREVIEW_TAB_SMS_FALLBACK,
685
- onPreviewTabChange: jest.fn(),
686
- };
687
-
688
- render(
689
- <TestWrapper>
690
- <ComponentToRender {...props} />
691
- </TestWrapper>
692
- );
693
-
694
- expect(screen.getByTestId('sms-content')).toHaveTextContent('Raw {{var}} template');
695
- });
696
-
697
- it('on SMS fallback tab, applies varmap slot substitution when varmap entries exist and no resolved text', () => {
698
- // getFallbackResolvedContent key format: `${fullToken}_${segmentIndex}`
699
- // 'Hello {{name}}' → segments ['Hello ', '{{name}}'], so {{name}} is at index 1 → key '{{name}}_1'
700
- const props = {
701
- ...defaultProps,
702
- channel: CHANNELS.RCS,
703
- content: { rcsTitle: 'Hello RCS' },
704
- smsFallbackContent: {
705
- content: 'Hello {{name}}',
706
- templateContent: 'Hello {{name}}',
707
- rcsSmsFallbackVarMapped: { '{{name}}_1': 'World' },
708
- },
709
- smsFallbackResolvedText: undefined,
710
- activePreviewTab: PREVIEW_TAB_SMS_FALLBACK,
711
- onPreviewTabChange: jest.fn(),
712
- };
713
-
714
- render(
715
- <TestWrapper>
716
- <ComponentToRender {...props} />
717
- </TestWrapper>
718
- );
719
-
720
- expect(screen.getByTestId('sms-content')).toHaveTextContent('Hello World');
721
- });
722
-
723
- it('on SMS fallback tab, resolved text takes priority over varmap entries', () => {
724
- const props = {
725
- ...defaultProps,
726
- channel: CHANNELS.RCS,
727
- content: { rcsTitle: 'Hello RCS' },
728
- smsFallbackContent: {
729
- content: 'Hello {{name}}',
730
- templateContent: 'Hello {{name}}',
731
- rcsSmsFallbackVarMapped: { '{{name}}_1': 'World' },
732
- },
733
- smsFallbackResolvedText: 'Hello John',
734
- activePreviewTab: PREVIEW_TAB_SMS_FALLBACK,
735
- onPreviewTabChange: jest.fn(),
736
- };
737
-
738
- render(
739
- <TestWrapper>
740
- <ComponentToRender {...props} />
741
- </TestWrapper>
742
- );
743
-
744
- // resolvedText wins over varmap substitution
745
- expect(screen.getByTestId('sms-content')).toHaveTextContent('Hello John');
746
- });
747
- });
748
550
  });
749
551
 
750
552
  describe('Channel Routing - INAPP', () => {
@@ -30,28 +30,23 @@ jest.mock('@capillarytech/cap-ui-library/CapNotification', () => ({
30
30
  }));
31
31
 
32
32
  // Mock child components - must use React.createElement to avoid hoisting issues
33
- let lastLeftPanelContentProps = null;
34
33
  jest.mock('../LeftPanelContent', () => {
35
34
  // eslint-disable-next-line global-require, import/no-extraneous-dependencies
36
35
  const ReactLib = require('react');
37
36
  return {
38
37
  __esModule: true,
39
- default: function MockLeftPanelContent(props) {
40
- lastLeftPanelContentProps = props;
41
- const editorEl = props.renderCustomValuesEditor ? props.renderCustomValuesEditor() : null;
42
- return ReactLib.createElement('div', { 'data-testid': 'left-panel' }, 'Left Panel', editorEl);
38
+ default: function MockLeftPanelContent() {
39
+ return ReactLib.createElement('div', { 'data-testid': 'left-panel' }, 'Left Panel');
43
40
  },
44
41
  };
45
42
  });
46
43
 
47
- let lastCustomValuesEditorProps = null;
48
44
  jest.mock('../CustomValuesEditor', () => {
49
45
  // eslint-disable-next-line global-require, import/no-extraneous-dependencies
50
46
  const ReactLib = require('react');
51
47
  return {
52
48
  __esModule: true,
53
- default: function MockCustomValuesEditor(props) {
54
- lastCustomValuesEditorProps = props;
49
+ default: function MockCustomValuesEditor() {
55
50
  return ReactLib.createElement('div', { 'data-testid': 'custom-values-editor' }, 'Custom Values Editor');
56
51
  },
57
52
  };
@@ -196,8 +191,6 @@ describe('CommonTestAndPreview', () => {
196
191
  beforeEach(() => {
197
192
  jest.clearAllMocks();
198
193
  lastSendTestMessageProps = null;
199
- lastLeftPanelContentProps = null;
200
- lastCustomValuesEditorProps = null;
201
194
  // Reset all mock function implementations
202
195
  Object.values(mockActions).forEach((mockFn) => {
203
196
  if (jest.isMockFunction(mockFn)) {
@@ -252,24 +245,6 @@ describe('CommonTestAndPreview', () => {
252
245
  });
253
246
  });
254
247
 
255
- it('should call getSenderDetailsRequested for RCS and SMS when channel is RCS', async () => {
256
- render(
257
- <TestWrapper>
258
- <CommonTestAndPreview {...defaultProps} channel={CHANNELS.RCS} />
259
- </TestWrapper>
260
- );
261
- await waitFor(() => {
262
- expect(mockActions.getSenderDetailsRequested).toHaveBeenCalledWith({
263
- channel: CHANNELS.RCS,
264
- orgUnitId: -1,
265
- });
266
- expect(mockActions.getSenderDetailsRequested).toHaveBeenCalledWith({
267
- channel: CHANNELS.SMS,
268
- orgUnitId: -1,
269
- });
270
- });
271
- });
272
-
273
248
  it('should not call getSenderDetailsRequested when channel is INAPP', async () => {
274
249
  render(
275
250
  <TestWrapper>
@@ -328,7 +303,7 @@ describe('CommonTestAndPreview', () => {
328
303
  });
329
304
  expect(lastSendTestMessageProps).toBeDefined();
330
305
  expect(lastSendTestMessageProps.deliverySettings).toBeDefined();
331
- expect(lastSendTestMessageProps.senderDetailsByChannel).toEqual(senderDetailsByChannel);
306
+ expect(lastSendTestMessageProps.senderDetailsOptions).toEqual(senderDetailsByChannel[CHANNELS.SMS]);
332
307
  expect(lastSendTestMessageProps.wecrmAccounts).toEqual([]);
333
308
  expect(typeof lastSendTestMessageProps.onSaveDeliverySettings).toBe('function');
334
309
  expect(lastSendTestMessageProps.isLoadingSenderDetails).toBe(false);
@@ -3306,107 +3281,4 @@ describe('CommonTestAndPreview', () => {
3306
3281
  });
3307
3282
  });
3308
3283
  });
3309
-
3310
- describe('SMS DLT and mustache tag discrimination (smsTemplateHasMustacheTags / buildSyntheticSmsMustacheTags)', () => {
3311
- it('should return no tags for SMS content that contains only DLT {#var#} tokens', async () => {
3312
- render(
3313
- <TestWrapper>
3314
- <CommonTestAndPreview
3315
- {...defaultProps}
3316
- channel={CHANNELS.SMS}
3317
- formData={{ 0: { 'sms-editor': 'Order {#orderId#} is confirmed' } }}
3318
- extractedTags={[]}
3319
- />
3320
- </TestWrapper>
3321
- );
3322
-
3323
- await waitFor(() => expect(lastLeftPanelContentProps).not.toBeNull());
3324
-
3325
- // smsTemplateHasMustacheTags returns false for DLT-only → extractedTags is []
3326
- expect(lastLeftPanelContentProps.extractedTags).toEqual([]);
3327
- });
3328
-
3329
- it('should build synthetic tags from {{mustache}} tokens, excluding DLT {#var#} tokens', async () => {
3330
- render(
3331
- <TestWrapper>
3332
- <CommonTestAndPreview
3333
- {...defaultProps}
3334
- channel={CHANNELS.SMS}
3335
- formData={{ 0: { 'sms-editor': 'Hi {{name}}, order {#orderId#} shipped' } }}
3336
- extractedTags={[]}
3337
- />
3338
- </TestWrapper>
3339
- );
3340
-
3341
- await waitFor(() => expect(lastLeftPanelContentProps).not.toBeNull());
3342
-
3343
- const tags = lastLeftPanelContentProps.extractedTags;
3344
- // Only {{name}} should become a tag — {#orderId#} must be excluded
3345
- expect(tags).toHaveLength(1);
3346
- expect(tags[0].name).toBe('name');
3347
- });
3348
-
3349
- it('should use API-extracted tags when present instead of building synthetic ones', async () => {
3350
- const apiTags = [{ name: 'firstName', metaData: { userDriven: true }, children: [] }];
3351
- render(
3352
- <TestWrapper>
3353
- <CommonTestAndPreview
3354
- {...defaultProps}
3355
- channel={CHANNELS.SMS}
3356
- formData={{ 0: { 'sms-editor': 'Hi {{firstName}}' } }}
3357
- extractedTags={apiTags}
3358
- />
3359
- </TestWrapper>
3360
- );
3361
-
3362
- await waitFor(() => expect(lastLeftPanelContentProps).not.toBeNull());
3363
-
3364
- // API tags take priority over buildSyntheticSmsMustacheTags
3365
- expect(lastLeftPanelContentProps.extractedTags).toEqual(apiTags);
3366
- });
3367
- });
3368
-
3369
- describe('handleDiscardCustomValues — preview reset', () => {
3370
- it('should call updatePreviewRequested when handleDiscardCustomValues is invoked', async () => {
3371
- render(
3372
- <TestWrapper>
3373
- <CommonTestAndPreview
3374
- {...defaultProps}
3375
- channel={CHANNELS.SMS}
3376
- formData={{ 0: { 'sms-editor': 'Hi {{name}}' } }}
3377
- />
3378
- </TestWrapper>
3379
- );
3380
-
3381
- await waitFor(() => expect(lastCustomValuesEditorProps).not.toBeNull());
3382
-
3383
- lastCustomValuesEditorProps.handleDiscardCustomValues();
3384
-
3385
- expect(mockActions.updatePreviewRequested).toHaveBeenCalledTimes(1);
3386
- });
3387
-
3388
- it('should call updatePreviewRequested with RCS channel when handleDiscardCustomValues is invoked for RCS with fallback', async () => {
3389
- render(
3390
- <TestWrapper>
3391
- <CommonTestAndPreview
3392
- {...defaultProps}
3393
- channel={CHANNELS.RCS}
3394
- smsFallbackContent={{
3395
- templateContent: 'Fallback {{name}}',
3396
- content: 'Fallback {{name}}',
3397
- }}
3398
- formData={{}}
3399
- />
3400
- </TestWrapper>
3401
- );
3402
-
3403
- await waitFor(() => expect(lastCustomValuesEditorProps).not.toBeNull());
3404
-
3405
- lastCustomValuesEditorProps.handleDiscardCustomValues();
3406
-
3407
- // updatePreviewRequested is called; syncSmsFallbackPreview (which hits Api directly) is NOT called
3408
- expect(mockActions.updatePreviewRequested).toHaveBeenCalledTimes(1);
3409
- });
3410
- });
3411
3284
  });
3412
-
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import {
8
- call, put, takeLatest, takeEvery, all, take, fork, cancel,
8
+ call, put, takeLatest, all,
9
9
  } from 'redux-saga/effects';
10
10
  import {
11
11
  searchCustomersSaga,
@@ -1333,26 +1333,9 @@ describe('CommonTestAndPreview Sagas', () => {
1333
1333
  it('should watch for GET_SENDER_DETAILS_REQUESTED', () => {
1334
1334
  const generator = watchGetSenderDetails();
1335
1335
  expect(generator.next().value).toEqual(
1336
- take('app/CommonTestAndPreview/GET_SENDER_DETAILS_REQUESTED')
1337
- );
1338
- const firstAction = {
1339
- payload: { channel: 'RCS', orgUnitId: 10 },
1340
- };
1341
- expect(generator.next(firstAction).value).toEqual(
1342
- fork(getSenderDetailsSaga, firstAction)
1343
- );
1344
- expect(generator.next({ '@@redux-saga/TASK': true }).value).toEqual(
1345
- take('app/CommonTestAndPreview/GET_SENDER_DETAILS_REQUESTED')
1346
- );
1347
- const secondAction = {
1348
- payload: { channel: 'RCS', orgUnitId: 20 },
1349
- };
1350
- expect(generator.next(secondAction).value).toEqual(
1351
- cancel({ '@@redux-saga/TASK': true })
1352
- );
1353
- expect(generator.next().value).toEqual(
1354
- fork(getSenderDetailsSaga, secondAction)
1336
+ takeLatest('app/CommonTestAndPreview/GET_SENDER_DETAILS_REQUESTED', getSenderDetailsSaga)
1355
1337
  );
1338
+ expect(generator.next().done).toBe(true);
1356
1339
  });
1357
1340
 
1358
1341
  it('should watch for GET_WECRM_ACCOUNTS_REQUESTED', () => {
@@ -1471,27 +1454,34 @@ describe('CommonTestAndPreview Sagas', () => {
1471
1454
  const action = { payload: {} };
1472
1455
  const generator = getWeCrmAccountsSaga(action);
1473
1456
  generator.next();
1474
- try {
1475
- generator.throw(new Error('API failed'));
1476
- } catch (errValue) {
1477
- expect(errValue).toEqual(
1478
- put({ type: GET_WECRM_ACCOUNTS_FAILURE, payload: { error: 'API failed' } })
1479
- );
1480
- }
1457
+ const err = generator.throw(new Error('API failed'));
1458
+ expect(err.value).toEqual(
1459
+ put({ type: GET_WECRM_ACCOUNTS_FAILURE, payload: { error: 'API failed' } })
1460
+ );
1481
1461
  expect(generator.next().done).toBe(true);
1482
1462
  });
1483
1463
  });
1484
1464
 
1485
- it('should initialize all watcher sagas', () => {
1486
- const generator = commonTestAndPreviewSaga();
1465
+ describe('commonTestAndPreviewSaga', () => {
1466
+ it('should fork all watcher sagas', () => {
1467
+ const generator = commonTestAndPreviewSaga();
1487
1468
 
1488
- const effect = generator.next().value;
1469
+ expect(generator.next().value).toEqual(
1470
+ all([
1471
+ watchSearchCustomers(),
1472
+ watchExtractTags(),
1473
+ watchUpdatePreview(),
1474
+ watchSendTestMessage(),
1475
+ watchFetchTestCustomers(),
1476
+ watchFetchTestGroups(),
1477
+ watchCreateMessageMeta(),
1478
+ watchGetPrefilledValues(),
1479
+ watchGetSenderDetails(),
1480
+ watchGetWeCrmAccounts(),
1481
+ ])
1482
+ );
1489
1483
 
1490
- // redux-saga v0.x stores the array under effect[ALL] key; v1.x uses effect.payload
1491
- const effectData = effect?.payload || effect?.ALL;
1492
- const watchers = Array.isArray(effectData) ? effectData : Object.values(effectData || {});
1493
- expect(Array.isArray(watchers)).toBe(true);
1494
- expect(watchers.length).toBeGreaterThan(0);
1495
- expect(generator.next().done).toBe(true);
1484
+ expect(generator.next().done).toBe(true);
1485
+ });
1496
1486
  });
1497
1487
  });
@@ -37,7 +37,6 @@ import { createStructuredSelector } from 'reselect';
37
37
  import { CAP_SPACE_12, CAP_SPACE_08, FONT_COLOR_05, FONT_COLOR_04 } from '@capillarytech/cap-ui-library/styled/variables';
38
38
  import UnifiedPreview from '../CommonTestAndPreview/UnifiedPreview';
39
39
  import { ANDROID } from '../CommonTestAndPreview/constants';
40
- import TemplatePreview from '../TemplatePreview';
41
40
  import TagList from '../../v2Containers/TagList';
42
41
  import CapTagListWithInput from '../CapTagListWithInput';
43
42
  import SlideBox from '../SlideBox';
@@ -2990,8 +2989,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
2990
2989
  userLocale={this.props.userLocale}
2991
2990
  selectedOfferDetails={this.props.selectedOfferDetails}
2992
2991
  eventContextTags={this.props?.eventContextTags}
2993
- waitEventContextTags={this.props?.waitEventContextTags}
2994
2992
  restrictPersonalization={this.props.restrictPersonalization}
2993
+ waitEventContextTags={this.props?.waitEventContextTags}
2995
2994
  />
2996
2995
  </CapColumn>
2997
2996
  );
@@ -3660,11 +3659,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
3660
3659
  selectedOfferDetails={this.props.selectedOfferDetails}
3661
3660
  channel={channel}
3662
3661
  eventContextTags={this.props?.eventContextTags}
3663
- waitEventContextTags={this.props?.waitEventContextTags}
3664
3662
  restrictPersonalization={this.props.restrictPersonalization}
3665
- getPopupContainer={this.props.tagListGetPopupContainer}
3666
- popoverOverlayStyle={this.props.tagListPopoverOverlayStyle}
3667
- popoverOverlayClassName={this.props.tagListPopoverOverlayClassName}
3663
+ waitEventContextTags={this.props?.waitEventContextTags}
3668
3664
  />
3669
3665
  </CapColumn>
3670
3666
  );
@@ -4007,6 +4003,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
4007
4003
  moduleFilterEnabled={isModuleFilterEnabled}
4008
4004
  eventContextTags={this.props?.eventContextTags}
4009
4005
  waitEventContextTags={this.props?.waitEventContextTags}
4006
+ isGetBeeData={this.props?.isGetBeeData}
4007
+ getBEEData={this.props?.getBEEData}
4010
4008
  />
4011
4009
  </CapColumn>
4012
4010
  );
@@ -4309,8 +4307,8 @@ FormBuilder.defaultProps = {
4309
4307
  userLocale: localStorage.getItem('jlocale') || 'en',
4310
4308
  showLiquidErrorInFooter: () => {},
4311
4309
  metaDataStatus: "",
4312
- isTestAndPreviewMode: false, // Default to false to maintain existing behavior
4313
4310
  waitEventContextTags: {},
4311
+ isTestAndPreviewMode: false, // Default to false to maintain existing behavior
4314
4312
  };
4315
4313
 
4316
4314
  FormBuilder.propTypes = {
@@ -4358,16 +4356,13 @@ FormBuilder.propTypes = {
4358
4356
  type: PropTypes.string.isRequired,
4359
4357
  isEmailLoading: PropTypes.bool.isRequired,
4360
4358
  moduleType: PropTypes.string.isRequired,
4361
- showLiquidErrorInFooter: PropTypes.func.isRequired,
4359
+ showLiquidErrorInFooter: PropTypes.bool.isRequired,
4362
4360
  eventContextTags: PropTypes.array.isRequired,
4363
4361
  waitEventContextTags: PropTypes.object,
4364
4362
  forwardedTags: PropTypes.object.isRequired,
4365
4363
  isLoyaltyModule: PropTypes.bool.isRequired,
4366
4364
  isTestAndPreviewMode: PropTypes.bool, // Add new prop type
4367
4365
  restrictPersonalization: PropTypes.bool,
4368
- tagListGetPopupContainer: PropTypes.func,
4369
- tagListPopoverOverlayStyle: PropTypes.object,
4370
- tagListPopoverOverlayClassName: PropTypes.string,
4371
4366
  };
4372
4367
 
4373
4368
  const mapStateToProps = createStructuredSelector({
@@ -537,21 +537,20 @@
537
537
  .unicode-disabled{
538
538
  font-size: 16px;
539
539
  }
540
- position: absolute;
541
- overflow: auto;
542
- top: 0;
543
- left: 17%;
544
- white-space: pre-wrap;
545
- word-break: break-word;
546
- max-height: 100%;
547
- line-height: 14px;
548
- font-size: 10px;
549
- font-family: 'open-sans';
550
-
551
540
  &.sms {
541
+ max-height: 100%;
542
+ position: absolute;
552
543
  // width: initial;
544
+ overflow: auto;
545
+ top: 0;
546
+ left: 17%;
547
+ white-space: pre-wrap;
548
+ word-break: break-word;
549
+ line-height: 14px;
553
550
  padding: 0 8px 8px 8px;
551
+ font-size: 10px;
554
552
  width: 100%;
553
+ font-family: 'open-sans';
555
554
  .rcs-image{
556
555
  width: 100%;
557
556
  height: 123px;
@@ -583,12 +582,22 @@
583
582
  &:not(.sms){
584
583
  padding: 4px;
585
584
  background: #3F51B5;
585
+ position: absolute;
586
586
  // width: initial;
587
+ overflow: auto;
588
+ top: 0;
589
+ left: 17%;
590
+ white-space: pre-wrap;
591
+ word-break: break-word;
587
592
  border-radius: 4px;
593
+ max-height: 100%;
588
594
  color: #FFFFFF;
589
595
  width: 70%;
590
596
  min-height: 26px;
597
+ line-height: 14px;
591
598
  padding: 8px;
599
+ font-size: 10px;
600
+ font-family: 'open-sans';
592
601
  }
593
602
  &.message-pop-carousel {
594
603
  position: relative;
@@ -854,32 +863,6 @@
854
863
  }
855
864
  }
856
865
 
857
- .shell-v2.rcs-preview {
858
- // Collapse the default 8px margin so the divider renders as a clean hairline, not a white gap.
859
- .whatsapp-divider {
860
- margin: 0;
861
- }
862
-
863
- // Override `.message-pop:not(.sms)` (blue background) for RCS carousel cards.
864
- .msg-container.sms {
865
- .message-pop.sms {
866
- .rcs-carousel-card {
867
- background: $CAP_WHITE;
868
- color: $CAP_G01;
869
- width: 10.4rem;
870
- left: 0;
871
- flex-shrink: 0;
872
- padding: $CAP_SPACE_04 0 $CAP_SPACE_08;
873
- border-radius: 0.428rem;
874
-
875
- .carousel-title {
876
- font-weight: 700 !important;
877
- }
878
- }
879
- }
880
- }
881
- }
882
-
883
866
  .align-center {
884
867
  text-align: center;
885
868
  }
@@ -1050,7 +1033,9 @@
1050
1033
  top: 0;
1051
1034
  }
1052
1035
  .video-icon {
1053
- position: sticky;
1036
+ position: absolute;
1037
+ right: -17px;
1038
+ bottom: -17px;
1054
1039
  }
1055
1040
 
1056
1041
  .zalo-preview-container {