@capillarytech/creatives-library 9.0.54-alpha.0 → 9.0.54-alpha.2

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "9.0.54-alpha.0",
4
+ "version": "9.0.54-alpha.2",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -40,6 +40,7 @@ import {
40
40
  CCS_CHANNEL_CONTENT_KEY_MAP,
41
41
  CCS_CHANNEL_DELIVERY_KEY_MAP,
42
42
  CCS_CHANNEL_NAME_MAP,
43
+ CCS_CONTENT_TRANSFORMS,
43
44
  } from './constants';
44
45
  import { getEnabledSteps } from './utils/getEnabledSteps';
45
46
  import messages from './messages';
@@ -191,6 +192,8 @@ const CommunicationFlow = ({
191
192
  const channel = CCS_CHANNEL_NAME_MAP[rawChannel] || rawChannel;
192
193
  const contentKey = CCS_CHANNEL_CONTENT_KEY_MAP[channel];
193
194
  const deliveryKey = CCS_CHANNEL_DELIVERY_KEY_MAP[channel];
195
+ const contentTransform = CCS_CONTENT_TRANSFORMS[channel];
196
+ const contentPayload = contentTransform ? contentTransform(contentItem.templateData) : contentItem.templateData;
194
197
  const { dynamicControls = {} } = aggregatedData;
195
198
  const channelSettings = aggregatedData.deliverySetting?.channelSetting?.[channel] || {};
196
199
  const referenceId = config?.context?.referenceId || buildCcsReferenceId(name);
@@ -212,7 +215,7 @@ const CommunicationFlow = ({
212
215
  singleChannelStrategy: {
213
216
  variant: {
214
217
  channel,
215
- ...(contentKey && { [contentKey]: contentItem.templateData }),
218
+ ...(contentKey && { [contentKey]: { channel, ...contentPayload } }),
216
219
  ...(deliveryKey && { [deliveryKey]: { channelSettings: { channel, ...channelSettings } } }),
217
220
  },
218
221
  },
@@ -391,7 +391,7 @@ describe('handleSave — CCS flow', () => {
391
391
  singleChannelStrategy: expect.objectContaining({
392
392
  variant: expect.objectContaining({
393
393
  channel: 'SMS',
394
- smsMessageContent: { message: 'Hello' },
394
+ smsMessageContent: { channel: 'SMS', message: 'Hello' },
395
395
  }),
396
396
  }),
397
397
  }),
@@ -399,7 +399,86 @@ describe('handleSave — CCS flow', () => {
399
399
  expect(onSave).toHaveBeenCalledTimes(1);
400
400
  });
401
401
 
402
- it('normalizes the internal MOBILEPUSH channel to CCS\'s MPUSH enum and key names', async () => {
402
+ it('transforms EMAIL content from the legacy editor shape (emailSubject) to CCS\'s messageSubject', async () => {
403
+ const onSave = jest.fn();
404
+ renderWithFlow({
405
+ features: {},
406
+ config: ccsConfig,
407
+ initialData: {
408
+ contentItems: [{
409
+ channel: 'EMAIL',
410
+ templateData: { emailSubject: 'Order Confirmed', messageBody: '<html>Hi</html>' },
411
+ }],
412
+ },
413
+ onSave,
414
+ });
415
+
416
+ await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
417
+
418
+ await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
419
+ expect(createCommDefinition).toHaveBeenCalledWith(
420
+ expect.objectContaining({
421
+ singleChannelStrategy: expect.objectContaining({
422
+ variant: expect.objectContaining({
423
+ channel: 'EMAIL',
424
+ emailMessageContent: {
425
+ channel: 'EMAIL',
426
+ messageSubject: 'Order Confirmed',
427
+ messageBody: '<html>Hi</html>',
428
+ },
429
+ }),
430
+ }),
431
+ }),
432
+ );
433
+ });
434
+
435
+ it('transforms WEBPUSH content from the legacy editor\'s messageContent.content wrapping to CCS\'s flat shape', async () => {
436
+ const onSave = jest.fn();
437
+ const cta = { type: 'SITE_URL', actionLink: 'https://example.com' };
438
+ const expandableDetails = { media: [{ url: 'https://example.com/banner.png', type: 'IMAGE' }], ctas: [] };
439
+ renderWithFlow({
440
+ features: {},
441
+ config: ccsConfig,
442
+ initialData: {
443
+ contentItems: [{
444
+ channel: 'WEBPUSH',
445
+ templateData: {
446
+ messageContent: {
447
+ content: {
448
+ channel: 'WEBPUSH',
449
+ accountId: 13792,
450
+ content: { title: 'Hi', message: 'Body', iconImageUrl: 'https://example.com/icon.png', cta, expandableDetails },
451
+ messageSubject: 'Subject',
452
+ offers: [],
453
+ },
454
+ },
455
+ },
456
+ }],
457
+ },
458
+ onSave,
459
+ });
460
+
461
+ await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
462
+
463
+ await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
464
+ expect(createCommDefinition).toHaveBeenCalledWith(
465
+ expect.objectContaining({
466
+ singleChannelStrategy: expect.objectContaining({
467
+ variant: expect.objectContaining({
468
+ channel: 'WEBPUSH',
469
+ webPushMessageContent: {
470
+ channel: 'WEBPUSH',
471
+ messageSubject: 'Subject',
472
+ accountId: 13792,
473
+ content: { title: 'Hi', message: 'Body', iconImageUrl: 'https://example.com/icon.png', cta, expandableDetails },
474
+ },
475
+ }),
476
+ }),
477
+ }),
478
+ );
479
+ });
480
+
481
+ it('normalizes the internal MOBILEPUSH channel to CCS\'s PUSH enum (keys stay mpush*)', async () => {
403
482
  const onSave = jest.fn();
404
483
  renderWithFlow({
405
484
  features: {},
@@ -417,8 +496,8 @@ describe('handleSave — CCS flow', () => {
417
496
  expect.objectContaining({
418
497
  singleChannelStrategy: expect.objectContaining({
419
498
  variant: expect.objectContaining({
420
- channel: 'MPUSH',
421
- mpushMessageContent: { messageSubject: 'Hi' },
499
+ channel: 'PUSH',
500
+ mpushMessageContent: { channel: 'PUSH', messageSubject: 'Hi' },
422
501
  }),
423
502
  }),
424
503
  }),
@@ -51,7 +51,9 @@ export const CCS_CHANNEL_CONTENT_KEY_MAP = {
51
51
  SMS: 'smsMessageContent',
52
52
  EMAIL: 'emailMessageContent',
53
53
  WHATSAPP: 'whatsappMessageContent',
54
- MPUSH: 'mpushMessageContent',
54
+ // CCS's channel enum value for mobile push is 'PUSH' (verified against real
55
+ // create responses), even though the content/delivery keys stay 'mpush*'.
56
+ PUSH: 'mpushMessageContent',
55
57
  INAPP: 'inAppMessageContent',
56
58
  ANDROID: 'androidMessageContent',
57
59
  IOS: 'iosMessageContent',
@@ -62,11 +64,39 @@ export const CCS_CHANNEL_CONTENT_KEY_MAP = {
62
64
  RCS: 'rcsMessageContent',
63
65
  };
64
66
 
67
+ // contentItem.templateData is built by the legacy CreativesContainer content
68
+ // editor (messageMeta-oriented field names) — for channels whose legacy field
69
+ // names don't match CCS's own content schema, transform before sending rather
70
+ // than dumping templateData as-is. EMAIL: legacy stores the subject as
71
+ // `emailSubject` (see getContentBody.js), CCS expects `messageSubject`;
72
+ // `messageBody` already matches CCS's name by coincidence. Channels absent
73
+ // here are passed through unchanged (their legacy/CCS field names already
74
+ // align, e.g. SMS's `message`/`messageBody`).
75
+ export const CCS_CONTENT_TRANSFORMS = {
76
+ EMAIL: (templateData = {}) => ({
77
+ messageSubject: templateData.emailSubject,
78
+ messageBody: templateData.messageBody,
79
+ }),
80
+ // WEBPUSH: the legacy editor nests the real data under
81
+ // messageContent.content (see CommunicationFlowCard.js's own comment on
82
+ // this same wrapping, for the edit-mode case) — extracting it flat here
83
+ // matches CCS's shape ({ messageSubject, accountId, content }); `offers`
84
+ // (a legacy-only field) is deliberately dropped, not part of CCS's schema.
85
+ WEBPUSH: (templateData = {}) => {
86
+ const inner = templateData.messageContent?.content || templateData;
87
+ return {
88
+ messageSubject: inner.messageSubject,
89
+ accountId: inner.accountId,
90
+ content: inner.content,
91
+ };
92
+ },
93
+ };
94
+
65
95
  export const CCS_CHANNEL_DELIVERY_KEY_MAP = {
66
96
  SMS: 'smsDeliverySettings',
67
97
  EMAIL: 'emailDeliverySettings',
68
98
  WHATSAPP: 'whatsappDeliverySettings',
69
- MPUSH: 'mpushDeliverySettings',
99
+ PUSH: 'mpushDeliverySettings',
70
100
  INAPP: 'inAppDeliverySettings',
71
101
  ANDROID: 'androidDeliverySettings',
72
102
  IOS: 'iosDeliverySettings',
@@ -79,10 +109,12 @@ export const CCS_CHANNEL_DELIVERY_KEY_MAP = {
79
109
 
80
110
  // The UI's own internal channel identifier for mobile push is 'MOBILEPUSH'
81
111
  // (see CreativesContainer/constants.js MOBILE_PUSH), but CCS's channel enum
82
- // only recognises 'MPUSH' (globals.js CCS_CHANNELS)normalize before
83
- // building the CCS payload. Every other channel identifier matches CCS as-is.
112
+ // value is 'PUSH' (verified against real create responses the content/
113
+ // delivery KEYS still say 'mpush*', only the enum VALUE is 'PUSH') —
114
+ // normalize before building the CCS payload. Every other channel identifier
115
+ // matches CCS as-is.
84
116
  export const CCS_CHANNEL_NAME_MAP = {
85
- MOBILEPUSH: 'MPUSH',
117
+ MOBILEPUSH: 'PUSH',
86
118
  };
87
119
 
88
120
  // Channel config - single source of truth for CreativesContainer and TemplatesV2
@@ -279,4 +311,4 @@ export const INCENTIVE_TYPES = [
279
311
  {
280
312
  value: 'badges', label: <FormattedMessage {...messages.badges} />, isActive: false, disabled: false,
281
313
  },
282
- ];
314
+ ];