@capillarytech/creatives-library 8.0.316-alpha.3 → 8.0.316-alpha.4

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 (105) hide show
  1. package/constants/unified.js +14 -0
  2. package/package.json +1 -1
  3. package/utils/templateVarUtils.js +172 -0
  4. package/utils/tests/templateVarUtils.test.js +160 -0
  5. package/v2Components/CapTagList/index.js +10 -0
  6. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
  7. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
  8. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +207 -21
  9. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
  10. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
  11. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
  12. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
  13. package/v2Components/CommonTestAndPreview/SendTestMessage.js +11 -5
  14. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
  15. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
  16. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +12 -0
  17. package/v2Components/CommonTestAndPreview/constants.js +38 -0
  18. package/v2Components/CommonTestAndPreview/index.js +693 -155
  19. package/v2Components/CommonTestAndPreview/messages.js +41 -3
  20. package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  21. package/v2Components/CommonTestAndPreview/sagas.js +15 -6
  22. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +172 -0
  23. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +269 -1
  24. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
  25. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +245 -0
  26. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +25 -4
  27. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +100 -1
  28. package/v2Components/CommonTestAndPreview/tests/index.test.js +19 -1
  29. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  30. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
  31. package/v2Components/FormBuilder/index.js +7 -1
  32. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
  33. package/v2Components/SmsFallback/constants.js +73 -0
  34. package/v2Components/SmsFallback/index.js +956 -0
  35. package/v2Components/SmsFallback/index.scss +265 -0
  36. package/v2Components/SmsFallback/messages.js +78 -0
  37. package/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
  38. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  39. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  40. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  41. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
  42. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
  43. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +327 -0
  44. package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  45. package/v2Components/TestAndPreviewSlidebox/index.js +8 -1
  46. package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  47. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  48. package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  49. package/v2Components/VarSegmentMessageEditor/index.js +125 -0
  50. package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  51. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  52. package/v2Containers/CreativesContainer/SlideBoxContent.js +36 -4
  53. package/v2Containers/CreativesContainer/SlideBoxFooter.js +10 -1
  54. package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  55. package/v2Containers/CreativesContainer/constants.js +9 -0
  56. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
  57. package/v2Containers/CreativesContainer/index.js +286 -93
  58. package/v2Containers/CreativesContainer/index.scss +51 -1
  59. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  60. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
  61. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -10
  62. package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  63. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  64. package/v2Containers/Rcs/constants.js +32 -1
  65. package/v2Containers/Rcs/index.js +950 -873
  66. package/v2Containers/Rcs/index.scss +85 -6
  67. package/v2Containers/Rcs/messages.js +10 -1
  68. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
  69. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +40834 -1963
  70. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  71. package/v2Containers/Rcs/tests/index.test.js +41 -38
  72. package/v2Containers/Rcs/tests/mockData.js +38 -0
  73. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
  74. package/v2Containers/Rcs/tests/utils.test.js +379 -1
  75. package/v2Containers/Rcs/utils.js +358 -10
  76. package/v2Containers/Sms/Create/index.js +81 -36
  77. package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  78. package/v2Containers/SmsTrai/Create/index.js +9 -4
  79. package/v2Containers/SmsTrai/Edit/constants.js +2 -0
  80. package/v2Containers/SmsTrai/Edit/index.js +609 -128
  81. package/v2Containers/SmsTrai/Edit/index.scss +121 -0
  82. package/v2Containers/SmsTrai/Edit/messages.js +9 -4
  83. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4327 -2374
  84. package/v2Containers/SmsWrapper/index.js +37 -8
  85. package/v2Containers/TagList/index.js +6 -0
  86. package/v2Containers/Templates/TemplatesActionBar.js +101 -0
  87. package/v2Containers/Templates/_templates.scss +61 -2
  88. package/v2Containers/Templates/actions.js +11 -0
  89. package/v2Containers/Templates/constants.js +2 -0
  90. package/v2Containers/Templates/index.js +90 -40
  91. package/v2Containers/Templates/sagas.js +57 -12
  92. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  93. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
  94. package/v2Containers/Templates/tests/sagas.test.js +110 -12
  95. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  96. package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  97. package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  98. package/v2Containers/TemplatesV2/index.js +86 -23
  99. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  100. package/v2Containers/WebPush/Create/components/MessageSection.js +54 -18
  101. package/v2Containers/WebPush/Create/components/MessageSection.test.js +28 -0
  102. package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +7 -3
  103. package/v2Containers/Whatsapp/index.js +7 -23
  104. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
  105. package/v2Containers/Whatsapp/tests/index.test.js +172 -0
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Covers `localTemplatesConfig` / `useLocalTemplates` branch in SlideBoxContent → TemplatesV2
3
+ * (embedded SMS template list / RCS SMS fallback).
4
+ */
5
+ import React from 'react';
6
+ import { mountWithIntl, shallowWithIntl } from '../../../helpers/intl-enzym-test-helpers';
7
+ import { SlideBoxContent } from '../SlideBoxContent';
8
+
9
+ const mockTemplatesV2 = jest.fn(() => <div data-testid="templates-v2-mock" />);
10
+ jest.mock('../../TemplatesV2', () => ({
11
+ __esModule: true,
12
+ default: (props) => mockTemplatesV2(props),
13
+ }));
14
+
15
+ const baseProps = {
16
+ slidBoxContent: 'templates',
17
+ currentChannel: 'SMS',
18
+ onSelectTemplate: jest.fn(),
19
+ onPreviewTemplate: jest.fn(),
20
+ onCreateNew: jest.fn(),
21
+ onChannelChange: jest.fn(),
22
+ location: { pathname: '/sms', query: {}, search: '' },
23
+ cap: {},
24
+ channelsToHide: [],
25
+ channelsToDisable: [],
26
+ handleClose: jest.fn(),
27
+ messageDetails: {},
28
+ onCreateComplete: jest.fn(),
29
+ };
30
+
31
+ describe('SlideBoxContent local templates (TemplatesV2)', () => {
32
+ beforeEach(() => {
33
+ mockTemplatesV2.mockClear();
34
+ });
35
+
36
+ // Use mount when asserting TemplatesV2 mock calls: shallow does not invoke children under styled CreativesWrapper.
37
+ it('renders TemplatesV2 in full mode when useLocalTemplates is true', () => {
38
+ mountWithIntl(
39
+ <SlideBoxContent
40
+ {...baseProps}
41
+ isFullMode
42
+ localTemplatesConfig={{
43
+ useLocalTemplates: true,
44
+ localTemplates: [],
45
+ localTemplatesLoading: false,
46
+ }}
47
+ />,
48
+ );
49
+ expect(mockTemplatesV2).toHaveBeenCalled();
50
+ const passed = mockTemplatesV2.mock.calls[mockTemplatesV2.mock.calls.length - 1][0];
51
+ expect(passed.localTemplatesConfig.useLocalTemplates).toBe(true);
52
+ });
53
+
54
+ it('does not render TemplatesV2 in full mode when useLocalTemplates is false', () => {
55
+ shallowWithIntl(
56
+ <SlideBoxContent
57
+ {...baseProps}
58
+ isFullMode
59
+ localTemplatesConfig={{ useLocalTemplates: false }}
60
+ />,
61
+ );
62
+ expect(mockTemplatesV2).not.toHaveBeenCalled();
63
+ });
64
+
65
+ it('renders TemplatesV2 in library mode without localTemplates flag', () => {
66
+ mountWithIntl(
67
+ <SlideBoxContent
68
+ {...baseProps}
69
+ isFullMode={false}
70
+ />,
71
+ );
72
+ expect(mockTemplatesV2).toHaveBeenCalled();
73
+ });
74
+
75
+ it('merges top-level local template props via pick when localTemplatesConfig is omitted', () => {
76
+ mountWithIntl(
77
+ <SlideBoxContent
78
+ {...baseProps}
79
+ isFullMode
80
+ useLocalTemplates
81
+ localTemplates={[{ _id: '1' }]}
82
+ localTemplatesLoading={false}
83
+ />,
84
+ );
85
+ expect(mockTemplatesV2).toHaveBeenCalled();
86
+ const passed = mockTemplatesV2.mock.calls[mockTemplatesV2.mock.calls.length - 1][0];
87
+ expect(passed.localTemplatesConfig.useLocalTemplates).toBe(true);
88
+ expect(passed.localTemplatesConfig.localTemplates).toEqual([{ _id: '1' }]);
89
+ });
90
+ });
@@ -859,6 +859,11 @@ exports[`Test SlideBoxContent container Should render correct component for rcs
859
859
  }
860
860
  }
861
861
  onCreateComplete={[MockFunction]}
862
+ templateData={
863
+ Object {
864
+ "mode": "create",
865
+ }
866
+ }
862
867
  />
863
868
  </SlideBoxContent__CreativesWrapper>
864
869
  `;
@@ -968,6 +973,7 @@ exports[`Test SlideBoxContent container Should render correct component for rcs
968
973
  <Connect(UserIsAuthenticated(Connect(InjectIntl(withStyles__StyledComponent))))
969
974
  FTPMode="create"
970
975
  channel="rcs"
976
+ localTemplatesConfig={Object {}}
971
977
  loyaltyMetaData={Object {}}
972
978
  messageDetails={Object {}}
973
979
  onCreateComplete={[MockFunction]}
@@ -1376,6 +1382,7 @@ exports[`Test SlideBoxContent container Should render correct component for what
1376
1382
  <Connect(UserIsAuthenticated(Connect(InjectIntl(withStyles__StyledComponent))))
1377
1383
  FTPMode="create"
1378
1384
  channel="whatsapp"
1385
+ localTemplatesConfig={Object {}}
1379
1386
  loyaltyMetaData={Object {}}
1380
1387
  messageDetails={Object {}}
1381
1388
  onCreateComplete={[MockFunction]}
@@ -3365,6 +3372,7 @@ exports[`Test SlideBoxContent container getViber utility function Should handle
3365
3372
  "name": "sms",
3366
3373
  }
3367
3374
  }
3375
+ templateData={null}
3368
3376
  />
3369
3377
  </SlideBoxContent__CreativesWrapper>
3370
3378
  `;
@@ -1,7 +1,7 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
3
  exports[`Test SlideBoxContent container campaign message, add creative click rcs 1`] = `
4
- <CreativesContainer__SlideBoxWrapper
4
+ <CreativesSlideBoxWrapper
5
5
  className="add-creatives-section creatives-library-mode "
6
6
  shouldApplyFooterMargin={false}
7
7
  slideBoxWrapperMargin={0}
@@ -23,6 +23,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click rcs
23
23
  inAppEditorType={null}
24
24
  isAnonymousType={false}
25
25
  isTestAndPreviewMode={false}
26
+ localTemplatesConfig={Object {}}
26
27
  loyaltyMetaData={
27
28
  Object {
28
29
  "actionName": "SEND_COMMUNICATION_ACTION",
@@ -85,6 +86,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click rcs
85
86
  }
86
87
  templateNameRenderProp={[Function]}
87
88
  templateStep="modeSelection"
89
+ useLocalTemplates={false}
88
90
  weChatMaptemplateStep={0}
89
91
  weChatTemplateType=""
90
92
  />
@@ -93,11 +95,11 @@ exports[`Test SlideBoxContent container campaign message, add creative click rcs
93
95
  show={true}
94
96
  size="size-xl"
95
97
  />
96
- </CreativesContainer__SlideBoxWrapper>
98
+ </CreativesSlideBoxWrapper>
97
99
  `;
98
100
 
99
101
  exports[`Test SlideBoxContent container campaign message, add creative click whatsapp 1`] = `
100
- <CreativesContainer__SlideBoxWrapper
102
+ <CreativesSlideBoxWrapper
101
103
  className="add-creatives-section creatives-library-mode "
102
104
  shouldApplyFooterMargin={false}
103
105
  slideBoxWrapperMargin={0}
@@ -119,6 +121,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click wha
119
121
  inAppEditorType={null}
120
122
  isAnonymousType={false}
121
123
  isTestAndPreviewMode={false}
124
+ localTemplatesConfig={Object {}}
122
125
  loyaltyMetaData={
123
126
  Object {
124
127
  "actionName": "SEND_COMMUNICATION_ACTION",
@@ -181,6 +184,7 @@ exports[`Test SlideBoxContent container campaign message, add creative click wha
181
184
  }
182
185
  templateNameRenderProp={[Function]}
183
186
  templateStep="modeSelection"
187
+ useLocalTemplates={false}
184
188
  weChatMaptemplateStep={0}
185
189
  weChatTemplateType=""
186
190
  />
@@ -189,11 +193,11 @@ exports[`Test SlideBoxContent container campaign message, add creative click wha
189
193
  show={true}
190
194
  size="size-xl"
191
195
  />
192
- </CreativesContainer__SlideBoxWrapper>
196
+ </CreativesSlideBoxWrapper>
193
197
  `;
194
198
 
195
199
  exports[`Test SlideBoxContent container campaign message, whatsapp edit all data 1`] = `
196
- <CreativesContainer__SlideBoxWrapper
200
+ <CreativesSlideBoxWrapper
197
201
  className="add-creatives-section creatives-library-mode "
198
202
  shouldApplyFooterMargin={false}
199
203
  slideBoxWrapperMargin={0}
@@ -215,6 +219,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
215
219
  inAppEditorType={null}
216
220
  isAnonymousType={false}
217
221
  isTestAndPreviewMode={false}
222
+ localTemplatesConfig={Object {}}
218
223
  loyaltyMetaData={
219
224
  Object {
220
225
  "actionName": "SEND_COMMUNICATION_ACTION",
@@ -319,6 +324,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
319
324
  slidBoxContent="editTemplate"
320
325
  templateNameRenderProp={[Function]}
321
326
  templateStep="modeSelection"
327
+ useLocalTemplates={false}
322
328
  weChatMaptemplateStep={0}
323
329
  weChatTemplateType=""
324
330
  />
@@ -327,11 +333,11 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit all data
327
333
  show={false}
328
334
  size="size-xl"
329
335
  />
330
- </CreativesContainer__SlideBoxWrapper>
336
+ </CreativesSlideBoxWrapper>
331
337
  `;
332
338
 
333
339
  exports[`Test SlideBoxContent container campaign message, whatsapp edit min data 1`] = `
334
- <CreativesContainer__SlideBoxWrapper
340
+ <CreativesSlideBoxWrapper
335
341
  className="add-creatives-section creatives-library-mode "
336
342
  shouldApplyFooterMargin={false}
337
343
  slideBoxWrapperMargin={0}
@@ -353,6 +359,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
353
359
  inAppEditorType={null}
354
360
  isAnonymousType={false}
355
361
  isTestAndPreviewMode={false}
362
+ localTemplatesConfig={Object {}}
356
363
  loyaltyMetaData={
357
364
  Object {
358
365
  "actionName": "SEND_COMMUNICATION_ACTION",
@@ -457,6 +464,7 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
457
464
  slidBoxContent="editTemplate"
458
465
  templateNameRenderProp={[Function]}
459
466
  templateStep="modeSelection"
467
+ useLocalTemplates={false}
460
468
  weChatMaptemplateStep={0}
461
469
  weChatTemplateType=""
462
470
  />
@@ -465,11 +473,11 @@ exports[`Test SlideBoxContent container campaign message, whatsapp edit min data
465
473
  show={false}
466
474
  size="size-xl"
467
475
  />
468
- </CreativesContainer__SlideBoxWrapper>
476
+ </CreativesSlideBoxWrapper>
469
477
  `;
470
478
 
471
479
  exports[`Test SlideBoxContent container it should clear the url, on channel change from new whatsapp to another 1`] = `
472
- <CreativesContainer__SlideBoxWrapper
480
+ <CreativesSlideBoxWrapper
473
481
  className="add-creatives-section creatives-library-mode "
474
482
  shouldApplyFooterMargin={false}
475
483
  slideBoxWrapperMargin={0}
@@ -491,6 +499,7 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
491
499
  inAppEditorType={null}
492
500
  isAnonymousType={false}
493
501
  isTestAndPreviewMode={false}
502
+ localTemplatesConfig={Object {}}
494
503
  loyaltyMetaData={
495
504
  Object {
496
505
  "actionName": "SEND_COMMUNICATION_ACTION",
@@ -595,6 +604,7 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
595
604
  slidBoxContent="editTemplate"
596
605
  templateNameRenderProp={[Function]}
597
606
  templateStep="modeSelection"
607
+ useLocalTemplates={false}
598
608
  weChatMaptemplateStep={0}
599
609
  weChatTemplateType=""
600
610
  />
@@ -603,5 +613,5 @@ exports[`Test SlideBoxContent container it should clear the url, on channel chan
603
613
  show={false}
604
614
  size="size-xl"
605
615
  />
606
- </CreativesContainer__SlideBoxWrapper>
616
+ </CreativesSlideBoxWrapper>
607
617
  `;
@@ -173,19 +173,35 @@ describe('Test SlideBoxContent container', () => {
173
173
  expect(getCreativesData).toHaveBeenCalledWith({ channel: 'RCS' });
174
174
  });
175
175
 
176
- it('RCS getFormData does not attach smsFallBackContent to templateData', async () => {
177
- renderFunction('RCS', 'editTemplate', rcsTemplates, rcsEditTemplateData);
176
+ it('RCS getFormData mirrors smsFallBackContent onto templateData for library round-trip', async () => {
177
+ renderedComponent = shallowWithIntl(
178
+ <Creatives
179
+ loyaltyMetaData={loyaltyMetaData}
180
+ Templates={rcsTemplates}
181
+ channel="RCS"
182
+ slidBoxContent="editTemplate"
183
+ templateData={rcsEditTemplateData}
184
+ handleCloseCreatives={handleCloseCreatives}
185
+ getCreativesData={getCreativesData}
186
+ isFullMode={false}
187
+ templateActions={{
188
+ getCdnTransformationConfig,
189
+ }}
190
+ />,
191
+ );
178
192
  renderedComponent.instance().onEditTemplate();
179
193
 
180
194
  const mockValue = {
195
+ validity: true,
181
196
  value: {
182
197
  name: 'rcs_creative_name',
198
+ type: 'RCS',
183
199
  versions: {
184
200
  base: {
185
201
  content: {
186
202
  RCS: {
187
203
  rcsContent: { contentType: 'RICHCARD', cardType: 'STANDALONE', cardSettings: {}, cardContent: [{}] },
188
- smsFallBackContent: { message: 'should-not-be-copied' },
204
+ smsFallBackContent: { message: 'fallback-body' },
189
205
  },
190
206
  },
191
207
  },
@@ -193,16 +209,62 @@ describe('Test SlideBoxContent container', () => {
193
209
  },
194
210
  };
195
211
 
196
- renderedComponent
197
- .find('CapSlideBox')
198
- .props()
199
- .content.props.getFormData(mockValue);
212
+ // Call getFormData on the container instance — shallow CapSlideBox `content` shape can differ across wrappers
213
+ renderedComponent.instance().getFormData(mockValue);
200
214
  await tick();
201
215
 
202
216
  const instance = renderedComponent.instance();
203
217
  expect(instance.state.templateData).toBeDefined();
204
- // sms fallback content should not be set on templateData per current logic
205
- expect(instance.state.templateData.smsFallBackContent).toBeUndefined();
218
+ expect(instance.state.templateData.smsFallBackContent).toEqual({ message: 'fallback-body' });
219
+ });
220
+
221
+ it('RCS getFormData mirrors rcsCardVarMapped onto templateData for campaign reopen', async () => {
222
+ renderedComponent = shallowWithIntl(
223
+ <Creatives
224
+ loyaltyMetaData={loyaltyMetaData}
225
+ Templates={rcsTemplates}
226
+ channel="RCS"
227
+ slidBoxContent="editTemplate"
228
+ templateData={rcsEditTemplateData}
229
+ handleCloseCreatives={handleCloseCreatives}
230
+ getCreativesData={getCreativesData}
231
+ isFullMode={false}
232
+ templateActions={{
233
+ getCdnTransformationConfig,
234
+ }}
235
+ />,
236
+ );
237
+ renderedComponent.instance().onEditTemplate();
238
+
239
+ const cardVarMapped = { 1: '[Name]', user_name: '[Name]' };
240
+ const mockValue = {
241
+ validity: true,
242
+ value: {
243
+ name: 'rcs_creative_name',
244
+ type: 'RCS',
245
+ versions: {
246
+ base: {
247
+ content: {
248
+ RCS: {
249
+ rcsContent: {
250
+ contentType: 'RICHCARD',
251
+ cardType: 'STANDALONE',
252
+ cardSettings: {},
253
+ cardContent: [{ title: 'Hi {{user_name}}', cardVarMapped }],
254
+ },
255
+ smsFallBackContent: {},
256
+ },
257
+ },
258
+ },
259
+ },
260
+ },
261
+ };
262
+
263
+ renderedComponent.instance().getFormData(mockValue);
264
+ await tick();
265
+
266
+ const instance = renderedComponent.instance();
267
+ expect(instance.state.templateData.rcsCardVarMapped).toEqual(cardVarMapped);
206
268
  });
207
269
 
208
270
  it('Text getCreatives data for rcs, data from creatives done to campaigns', async () => {
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Covers local-templates flag resolution: nested `localTemplatesConfig.useLocalTemplates`
3
+ * vs top-level `useLocalTemplates` (embedded consumers / SlideBoxContent).
4
+ */
5
+ import React from 'react';
6
+ import { shallowWithIntl } from '../../../helpers/intl-enzym-test-helpers';
7
+ import { Creatives } from '../index';
8
+ import mockdata from '../../mockdata';
9
+
10
+ const { smsTemplates, loyaltyMetaData } = mockdata;
11
+
12
+ jest.mock('../../../v2Components/FormBuilder', () => ({
13
+ __esModule: true,
14
+ default: (props) => (
15
+ <div className="FormBuilder-mock" {...props}>
16
+ FormBuilder
17
+ </div>
18
+ ),
19
+ }));
20
+
21
+ const baseProps = {
22
+ loyaltyMetaData,
23
+ Templates: smsTemplates,
24
+ channel: 'SMS',
25
+ creativesMode: 'create',
26
+ templateData: null,
27
+ isFullMode: true,
28
+ handleCloseCreatives: jest.fn(),
29
+ getCreativesData: jest.fn(),
30
+ templateActions: {
31
+ getCdnTransformationConfig: jest.fn(),
32
+ resetTemplateStoreData: jest.fn(),
33
+ },
34
+ globalActions: {
35
+ clearMetaEntities: jest.fn(),
36
+ },
37
+ };
38
+
39
+ describe('CreativesContainer useLocalTemplates prop resolution', () => {
40
+ beforeEach(() => {
41
+ jest.clearAllMocks();
42
+ });
43
+
44
+ it('initial slidebox is templates when only top-level useLocalTemplates is true', () => {
45
+ const wrapper = shallowWithIntl(
46
+ <Creatives
47
+ {...baseProps}
48
+ useLocalTemplates
49
+ />,
50
+ );
51
+ expect(wrapper.instance().state.slidBoxContent).toBe('templates');
52
+ });
53
+
54
+ it('initial slidebox is templates when localTemplatesConfig.useLocalTemplates is true', () => {
55
+ const wrapper = shallowWithIntl(
56
+ <Creatives
57
+ {...baseProps}
58
+ localTemplatesConfig={{ useLocalTemplates: true }}
59
+ />,
60
+ );
61
+ expect(wrapper.instance().state.slidBoxContent).toBe('templates');
62
+ });
63
+
64
+ it('does not reset template store on unmount when embedded and top-level useLocalTemplates is true', () => {
65
+ const wrapper = shallowWithIntl(
66
+ <Creatives
67
+ {...baseProps}
68
+ location={{ query: { type: 'embedded' } }}
69
+ useLocalTemplates
70
+ />,
71
+ );
72
+ wrapper.unmount();
73
+ expect(baseProps.templateActions.resetTemplateStoreData).not.toHaveBeenCalled();
74
+ expect(baseProps.globalActions.clearMetaEntities).toHaveBeenCalled();
75
+ });
76
+
77
+ it('resets template store on unmount when embedded and local templates are not used', () => {
78
+ const wrapper = shallowWithIntl(
79
+ <Creatives
80
+ {...baseProps}
81
+ location={{ query: { type: 'embedded' } }}
82
+ useLocalTemplates={false}
83
+ />,
84
+ );
85
+ wrapper.unmount();
86
+ expect(baseProps.templateActions.resetTemplateStoreData).toHaveBeenCalled();
87
+ expect(baseProps.globalActions.clearMetaEntities).toHaveBeenCalled();
88
+ });
89
+
90
+ it('prefers nested localTemplatesConfig.useLocalTemplates=false over top-level true (not local list mode)', () => {
91
+ const wrapper = shallowWithIntl(
92
+ <Creatives
93
+ {...baseProps}
94
+ localTemplatesConfig={{ useLocalTemplates: false }}
95
+ useLocalTemplates
96
+ />,
97
+ );
98
+ expect(wrapper.instance().state.slidBoxContent).toBe('createTemplate');
99
+ });
100
+
101
+ it('uses top-level useLocalTemplates when localTemplatesConfig omits the flag', () => {
102
+ const wrapper = shallowWithIntl(
103
+ <Creatives
104
+ {...baseProps}
105
+ localTemplatesConfig={{}}
106
+ useLocalTemplates
107
+ />,
108
+ );
109
+ expect(wrapper.instance().state.slidBoxContent).toBe('templates');
110
+ });
111
+
112
+ it('resets template store when nested useLocalTemplates is false even if top-level is true', () => {
113
+ const wrapper = shallowWithIntl(
114
+ <Creatives
115
+ {...baseProps}
116
+ location={{ query: { type: 'embedded' } }}
117
+ localTemplatesConfig={{ useLocalTemplates: false }}
118
+ useLocalTemplates
119
+ />,
120
+ );
121
+ wrapper.unmount();
122
+ expect(baseProps.templateActions.resetTemplateStoreData).toHaveBeenCalled();
123
+ expect(baseProps.globalActions.clearMetaEntities).toHaveBeenCalled();
124
+ });
125
+ });
@@ -40,6 +40,22 @@ export const contentType = {
40
40
  carousel: 'carousel',
41
41
  };
42
42
 
43
+ export const CHANNELS = [
44
+ 'email',
45
+ 'mPush',
46
+ 'viber',
47
+ 'whatsapp',
48
+ 'zalo',
49
+ 'facebook',
50
+ 'rcs',
51
+ 'inApp',
52
+ 'line',
53
+ 'weChat',
54
+ 'callTask',
55
+ 'FTP',
56
+ 'webpush',
57
+ ];
58
+
43
59
  export const STATUS_OPTIONS = [
44
60
  // {
45
61
  // key: 'created',
@@ -76,8 +92,23 @@ export const RCS_MEDIA_TYPES = {
76
92
 
77
93
  export const rcsVarRegex = /\{\{\w+\}\}/g;
78
94
  export const rcsVarTestRegex = /\{\{\w+\}\}/;
95
+
96
+ /** `cardVarMapped` slot keys that are numeric only (legacy ordering). */
97
+ export const RCS_NUMERIC_VAR_NAME_REGEX = /^\d+$/;
98
+ /** Escape `RegExp` metacharacters when building a pattern from user/tag text. */
99
+ export const RCS_REGEX_META_CHARS_PATTERN = /[.*+?^${}()|[\]\\]/g;
100
+ /** Entire string is a single `{{tag}}` token (value still a placeholder). */
101
+ export const RCS_SINGLE_MUSTACHE_PLACEHOLDER_REGEX = /^\{\{[^}]+\}\}$/;
102
+ /** Strip leading `{{` and trailing `}}` from a token. */
103
+ export const RCS_STRIP_MUSTACHE_DELIMITERS_REGEX = /^\{\{|\}\}$/g;
104
+
105
+ /** Tag-popover target: title vs description field (matches `onTagSelect` `field` argument). */
106
+ export const RCS_TAG_AREA_FIELD_TITLE = 'title';
107
+ export const RCS_TAG_AREA_FIELD_DESC = 'desc';
108
+
79
109
  export const TEMPLATE_DESC_MAX_LENGTH = 2500;
80
- export const FALLBACK_MESSAGE_MAX_LENGTH = 160;
110
+ /** Resolved SMS fallback body cap. Must allow multi-segment DLT (>160); aligns with TRAI / `TEMPLATE_MESSAGE_MAX_LENGTH`. */
111
+ export const FALLBACK_MESSAGE_MAX_LENGTH = TEMPLATE_MESSAGE_MAX_LENGTH;
81
112
  export const TEMPLATE_TITLE_MAX_LENGTH = 200;
82
113
  export const TEMPLATE_BUTTON_TEXT_MAX_LENGTH = 25;
83
114
  export const CTA = 'CTA';