@capillarytech/creatives-library 9.0.50-alpha.0 → 9.0.50-alpha.1
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/constants/unified.js +1 -0
- package/package.json +1 -1
- package/services/api.js +0 -9
- package/utils/common.js +4 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/ViberCarouselPreviewCards.js +127 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/ViberPreviewContent.js +106 -15
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +139 -1
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_viberCarouselPreviewCards.scss +133 -0
- package/v2Components/CommonTestAndPreview/constants.js +2 -0
- package/v2Components/CommonTestAndPreview/index.js +240 -26
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/ViberPreviewContent.test.js +364 -0
- package/v2Components/CommonTestAndPreview/tests/utils.test.js +49 -0
- package/v2Components/CommonTestAndPreview/utils.js +20 -0
- package/v2Containers/CommunicationFlow/CommunicationFlow.js +58 -85
- package/v2Containers/CommunicationFlow/CommunicationFlowCard.js +4 -20
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +51 -146
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlowCard.test.js +0 -16
- package/v2Containers/CommunicationFlow/constants.js +0 -40
- package/v2Containers/CommunicationFlow/index.js +20 -15
- package/v2Containers/CommunicationFlow/messages.js +0 -4
- package/v2Containers/Templates/_templates.scss +179 -1
- package/v2Containers/Templates/index.js +97 -10
- package/v2Containers/Viber/constants.js +21 -0
- package/v2Containers/Viber/index.js +711 -43
- package/v2Containers/Viber/index.scss +175 -0
- package/v2Containers/Viber/messages.js +121 -0
- package/v2Containers/Viber/tests/index.test.js +80 -0
|
@@ -19,7 +19,6 @@ import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
|
|
|
19
19
|
import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
|
|
20
20
|
import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
|
|
21
21
|
import CapSlideBox from '@capillarytech/cap-ui-library/CapSlideBox';
|
|
22
|
-
import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
|
|
23
22
|
import CommunicationFlow from './index';
|
|
24
23
|
import { CHANNELS, DEFAULT_COMMUNICATION_STRATEGY_OPTIONS, DYNAMIC_CONTROLS_CONFIG } from './constants';
|
|
25
24
|
import {
|
|
@@ -75,8 +74,6 @@ const CommunicationFlowCard = ({
|
|
|
75
74
|
onChange,
|
|
76
75
|
cap,
|
|
77
76
|
intl,
|
|
78
|
-
disabled,
|
|
79
|
-
disabledTooltip,
|
|
80
77
|
}) => {
|
|
81
78
|
const { formatMessage } = intl || {};
|
|
82
79
|
const [showSlideBox, setShowSlideBox] = useState(false);
|
|
@@ -94,9 +91,8 @@ const CommunicationFlowCard = ({
|
|
|
94
91
|
}, [onCancel]);
|
|
95
92
|
|
|
96
93
|
const handleOpen = useCallback(() => {
|
|
97
|
-
if (disabled) return;
|
|
98
94
|
setShowSlideBox(true);
|
|
99
|
-
}, [
|
|
95
|
+
}, []);
|
|
100
96
|
|
|
101
97
|
const firstItem = savedData?.contentItems?.[0];
|
|
102
98
|
const channelConfig = firstItem
|
|
@@ -186,17 +182,9 @@ const CommunicationFlowCard = ({
|
|
|
186
182
|
<CapImage src={addCreativesIllustration} />
|
|
187
183
|
</CapColumn>
|
|
188
184
|
<CapColumn span={14} className="empty-card-action-col">
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
{formatMessage(messages.addCreatives)}
|
|
193
|
-
</CapButton>
|
|
194
|
-
</CapTooltip>
|
|
195
|
-
) : (
|
|
196
|
-
<CapButton type="secondary" onClick={handleOpen} disabled={disabled}>
|
|
197
|
-
{formatMessage(messages.addCreatives)}
|
|
198
|
-
</CapButton>
|
|
199
|
-
)}
|
|
185
|
+
<CapButton type="secondary" onClick={handleOpen}>
|
|
186
|
+
{formatMessage(messages.addCreatives)}
|
|
187
|
+
</CapButton>
|
|
200
188
|
</CapColumn>
|
|
201
189
|
</CapRow>
|
|
202
190
|
</CapCard>
|
|
@@ -239,8 +227,6 @@ CommunicationFlowCard.propTypes = {
|
|
|
239
227
|
onChange: PropTypes.func,
|
|
240
228
|
cap: PropTypes.object,
|
|
241
229
|
intl: PropTypes.object.isRequired,
|
|
242
|
-
disabled: PropTypes.bool, // Disables the "Add creatives" trigger (e.g. until a consumer-required field is filled)
|
|
243
|
-
disabledTooltip: PropTypes.node, // Shown on hover when disabled is true
|
|
244
230
|
};
|
|
245
231
|
|
|
246
232
|
CommunicationFlowCard.defaultProps = {
|
|
@@ -249,8 +235,6 @@ CommunicationFlowCard.defaultProps = {
|
|
|
249
235
|
onCancel: null,
|
|
250
236
|
onChange: null,
|
|
251
237
|
cap: null,
|
|
252
|
-
disabled: false,
|
|
253
|
-
disabledTooltip: null,
|
|
254
238
|
};
|
|
255
239
|
|
|
256
240
|
export default injectIntl(CommunicationFlowCard);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
jest.mock('../../../services/api', () => ({
|
|
4
|
-
|
|
4
|
+
createCentralCommsMetaId: jest.fn(),
|
|
5
|
+
getCentralCommsMetaIds: jest.fn(),
|
|
5
6
|
}));
|
|
6
7
|
|
|
7
8
|
jest.mock('../../CreativesContainer', () => function MockCreativesContainer({
|
|
@@ -37,7 +38,7 @@ import { IntlProvider } from 'react-intl';
|
|
|
37
38
|
import history from '../../../utils/history';
|
|
38
39
|
import { initialReducer } from '../../../initialReducer';
|
|
39
40
|
import CommunicationFlow from '../CommunicationFlow';
|
|
40
|
-
import {
|
|
41
|
+
import { createCentralCommsMetaId, getCentralCommsMetaIds } from '../../../services/api';
|
|
41
42
|
import { getEnabledSteps } from '../utils/getEnabledSteps';
|
|
42
43
|
import {
|
|
43
44
|
CHANNELS,
|
|
@@ -358,93 +359,74 @@ describe('isSaveDisabled', () => {
|
|
|
358
359
|
});
|
|
359
360
|
|
|
360
361
|
describe('handleSave — CCS flow', () => {
|
|
361
|
-
const ccsConfig = { ...baseConfig, context: { name: 'Order Placed Notification' }, features: {} };
|
|
362
|
-
|
|
363
362
|
beforeEach(() => {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
});
|
|
363
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: { id: 'meta-123' } } });
|
|
364
|
+
getCentralCommsMetaIds.mockResolvedValue({ response: { data: {} } });
|
|
367
365
|
});
|
|
368
366
|
|
|
369
367
|
afterEach(() => {
|
|
370
368
|
jest.clearAllMocks();
|
|
371
369
|
});
|
|
372
370
|
|
|
373
|
-
it('calls
|
|
371
|
+
it('calls createCentralCommsMetaId for each content item when useCCS is not false', async () => {
|
|
374
372
|
const onSave = jest.fn();
|
|
375
373
|
renderWithFlow({
|
|
376
374
|
features: {},
|
|
377
|
-
config: ccsConfig,
|
|
378
375
|
initialData: {
|
|
379
|
-
contentItems: [{ channel: 'sms', templateData: {
|
|
376
|
+
contentItems: [{ channel: 'sms', templateData: { smsBody: 'Hello' } }],
|
|
380
377
|
},
|
|
381
378
|
onSave,
|
|
382
379
|
});
|
|
383
380
|
|
|
384
381
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
385
382
|
|
|
386
|
-
await waitFor(() => expect(
|
|
387
|
-
expect(
|
|
383
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalledTimes(1));
|
|
384
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
388
385
|
expect.objectContaining({
|
|
389
|
-
|
|
390
|
-
strategyType: 'SINGLE',
|
|
391
|
-
singleChannelStrategy: expect.objectContaining({
|
|
392
|
-
channel: 'SMS',
|
|
393
|
-
smsMessageContent: { message: 'Hello' },
|
|
394
|
-
}),
|
|
386
|
+
centralCommsPayload: expect.objectContaining({ channel: 'SMS', module: 'CAMPAIGNS' }),
|
|
395
387
|
}),
|
|
396
388
|
);
|
|
397
389
|
expect(onSave).toHaveBeenCalledTimes(1);
|
|
398
390
|
});
|
|
399
391
|
|
|
400
|
-
it('
|
|
401
|
-
const onSave = jest.fn();
|
|
392
|
+
it('calls getCentralCommsMetaIds when metaIds are returned from createCentralCommsMetaId', async () => {
|
|
402
393
|
renderWithFlow({
|
|
403
394
|
features: {},
|
|
404
|
-
|
|
405
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
406
|
-
onSave,
|
|
395
|
+
initialData: { contentItems: [{ channel: 'EMAIL', templateData: {} }] },
|
|
407
396
|
});
|
|
408
397
|
|
|
409
398
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
410
399
|
|
|
411
|
-
await waitFor(() => expect(
|
|
412
|
-
expect(onSave).toHaveBeenCalledWith(
|
|
413
|
-
expect.objectContaining({
|
|
414
|
-
ccsCommDefinition: { id: 'cd_123', referenceId: 'ORDER_PLACED_123', version: 1, status: 'DRAFT' },
|
|
415
|
-
}),
|
|
416
|
-
);
|
|
400
|
+
await waitFor(() => expect(getCentralCommsMetaIds).toHaveBeenCalledWith('meta-123'));
|
|
417
401
|
});
|
|
418
402
|
|
|
419
|
-
it('
|
|
420
|
-
|
|
421
|
-
// clears that return value before every test — set it explicitly here.
|
|
422
|
-
jest.spyOn(Date, 'now').mockReturnValue(1612267539410);
|
|
403
|
+
it('skips getCentralCommsMetaIds when response contains no id', async () => {
|
|
404
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: {} } });
|
|
423
405
|
renderWithFlow({
|
|
424
406
|
features: {},
|
|
425
|
-
config: ccsConfig,
|
|
426
407
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
427
408
|
});
|
|
428
409
|
|
|
429
410
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
430
411
|
|
|
431
|
-
await waitFor(() => expect(
|
|
432
|
-
|
|
433
|
-
expect(payload.referenceId).toBe('ORDER_PLACED_NOTIFICATION_1612267539410');
|
|
412
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
413
|
+
expect(getCentralCommsMetaIds).not.toHaveBeenCalled();
|
|
434
414
|
});
|
|
435
415
|
|
|
436
|
-
it('uses config.context
|
|
416
|
+
it('uses ouId and module from config.context when provided', async () => {
|
|
437
417
|
renderWithFlow({
|
|
438
418
|
features: {},
|
|
439
|
-
config: { ...
|
|
419
|
+
config: { ...baseConfig, context: { ouId: 42, module: 'LOYALTY' }, features: {} },
|
|
440
420
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
441
421
|
});
|
|
442
422
|
|
|
443
423
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
444
424
|
|
|
445
|
-
await waitFor(() => expect(
|
|
446
|
-
expect(
|
|
447
|
-
expect.objectContaining({
|
|
425
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
426
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
427
|
+
expect.objectContaining({
|
|
428
|
+
centralCommsPayload: expect.objectContaining({ ouId: 42, module: 'LOYALTY' }),
|
|
429
|
+
}),
|
|
448
430
|
);
|
|
449
431
|
});
|
|
450
432
|
|
|
@@ -452,7 +434,7 @@ describe('handleSave — CCS flow', () => {
|
|
|
452
434
|
const onSave = jest.fn();
|
|
453
435
|
renderWithFlow({
|
|
454
436
|
features: {},
|
|
455
|
-
config: { ...
|
|
437
|
+
config: { ...baseConfig, useCCS: false, features: {} },
|
|
456
438
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
457
439
|
onSave,
|
|
458
440
|
});
|
|
@@ -460,50 +442,14 @@ describe('handleSave — CCS flow', () => {
|
|
|
460
442
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
461
443
|
|
|
462
444
|
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
463
|
-
expect(
|
|
464
|
-
expect(onSave).toHaveBeenCalledWith(expect.not.objectContaining({ ccsCommDefinition: expect.anything() }));
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
it('skips createCommDefinition when config.context.name is absent (mandatory)', async () => {
|
|
468
|
-
const onSave = jest.fn();
|
|
469
|
-
renderWithFlow({
|
|
470
|
-
features: {},
|
|
471
|
-
config: { ...baseConfig, features: {} },
|
|
472
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
473
|
-
onSave,
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
477
|
-
|
|
478
|
-
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
479
|
-
expect(createCommDefinition).not.toHaveBeenCalled();
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
it('skips createCommDefinition for multi-channel strategies (CHANNEL_PRIORITY/AB_TEST)', async () => {
|
|
483
|
-
const onSave = jest.fn();
|
|
484
|
-
renderWithFlow({
|
|
485
|
-
features: {},
|
|
486
|
-
config: ccsConfig,
|
|
487
|
-
initialData: {
|
|
488
|
-
communicationStrategy: CHANNEL_PRIORITY,
|
|
489
|
-
channels: ['SMS', 'EMAIL'],
|
|
490
|
-
contentItems: [{ channel: 'SMS', templateData: {} }, { channel: 'EMAIL', templateData: {} }],
|
|
491
|
-
},
|
|
492
|
-
onSave,
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
496
|
-
|
|
497
|
-
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
498
|
-
expect(createCommDefinition).not.toHaveBeenCalled();
|
|
445
|
+
expect(createCentralCommsMetaId).not.toHaveBeenCalled();
|
|
499
446
|
});
|
|
500
447
|
|
|
501
|
-
it('still calls onSave
|
|
502
|
-
|
|
448
|
+
it('still calls onSave when createCentralCommsMetaId rejects', async () => {
|
|
449
|
+
createCentralCommsMetaId.mockRejectedValue(new Error('Network error'));
|
|
503
450
|
const onSave = jest.fn();
|
|
504
451
|
renderWithFlow({
|
|
505
452
|
features: {},
|
|
506
|
-
config: ccsConfig,
|
|
507
453
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
508
454
|
onSave,
|
|
509
455
|
});
|
|
@@ -511,35 +457,12 @@ describe('handleSave — CCS flow', () => {
|
|
|
511
457
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
512
458
|
|
|
513
459
|
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
514
|
-
expect(onSave).toHaveBeenCalledWith(expect.not.objectContaining({ ccsCommDefinition: expect.anything() }));
|
|
515
460
|
});
|
|
516
461
|
|
|
517
|
-
it('
|
|
518
|
-
createCommDefinition.mockResolvedValue({
|
|
519
|
-
success: false,
|
|
520
|
-
status: { isError: true, code: 409, message: 'REFERENCE_ID_EXISTS' },
|
|
521
|
-
message: 'REFERENCE_ID_EXISTS',
|
|
522
|
-
});
|
|
462
|
+
it('skips createCentralCommsMetaId when contentItems is empty', async () => {
|
|
523
463
|
const onSave = jest.fn();
|
|
524
464
|
renderWithFlow({
|
|
525
465
|
features: {},
|
|
526
|
-
config: ccsConfig,
|
|
527
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
528
|
-
onSave,
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
532
|
-
|
|
533
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
534
|
-
expect(await screen.findByText(/already in use in your organization/i)).toBeInTheDocument();
|
|
535
|
-
expect(onSave).not.toHaveBeenCalled();
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
it('skips createCommDefinition when contentItems is empty', async () => {
|
|
539
|
-
const onSave = jest.fn();
|
|
540
|
-
renderWithFlow({
|
|
541
|
-
features: {},
|
|
542
|
-
config: ccsConfig,
|
|
543
466
|
initialData: { contentItems: [] },
|
|
544
467
|
onSave,
|
|
545
468
|
});
|
|
@@ -547,13 +470,12 @@ describe('handleSave — CCS flow', () => {
|
|
|
547
470
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
548
471
|
|
|
549
472
|
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
550
|
-
expect(
|
|
473
|
+
expect(createCentralCommsMetaId).not.toHaveBeenCalled();
|
|
551
474
|
});
|
|
552
475
|
|
|
553
|
-
it('
|
|
476
|
+
it('includes additionalSettings derived from dynamicControls in the payload', async () => {
|
|
554
477
|
renderWithFlow({
|
|
555
478
|
features: {},
|
|
556
|
-
config: ccsConfig,
|
|
557
479
|
initialData: {
|
|
558
480
|
contentItems: [{ channel: 'SMS', templateData: {} }],
|
|
559
481
|
dynamicControls: {
|
|
@@ -567,36 +489,14 @@ describe('handleSave — CCS flow', () => {
|
|
|
567
489
|
|
|
568
490
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
569
491
|
|
|
570
|
-
await waitFor(() => expect(
|
|
571
|
-
const payload =
|
|
572
|
-
expect(payload.
|
|
492
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
493
|
+
const payload = createCentralCommsMetaId.mock.calls[0][0];
|
|
494
|
+
expect(payload.centralCommsPayload.smsDeliverySettings.additionalSettings).toEqual({
|
|
573
495
|
useTinyUrl: true,
|
|
574
496
|
encryptUrl: true,
|
|
575
497
|
linkTrackingEnabled: true,
|
|
576
498
|
userSubscriptionDisabled: true,
|
|
577
499
|
});
|
|
578
|
-
expect(payload.singleChannelStrategy.smsDeliverySettings.additionalSettings).toBeUndefined();
|
|
579
|
-
});
|
|
580
|
-
|
|
581
|
-
it('includes channelSettings from deliverySetting.channelSetting in the payload', async () => {
|
|
582
|
-
renderWithFlow({
|
|
583
|
-
features: {},
|
|
584
|
-
config: ccsConfig,
|
|
585
|
-
initialData: {
|
|
586
|
-
contentItems: [{ channel: 'SMS', templateData: {} }],
|
|
587
|
-
deliverySetting: { channelSetting: { SMS: { domainId: 1001, gsmSenderId: 'BRAND1' } } },
|
|
588
|
-
},
|
|
589
|
-
});
|
|
590
|
-
|
|
591
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
592
|
-
|
|
593
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalled());
|
|
594
|
-
const payload = createCommDefinition.mock.calls[0][0];
|
|
595
|
-
expect(payload.singleChannelStrategy.smsDeliverySettings.channelSettings).toEqual({
|
|
596
|
-
channel: 'SMS',
|
|
597
|
-
domainId: 1001,
|
|
598
|
-
gsmSenderId: 'BRAND1',
|
|
599
|
-
});
|
|
600
500
|
});
|
|
601
501
|
});
|
|
602
502
|
|
|
@@ -652,34 +552,39 @@ describe('optional chaining safety', () => {
|
|
|
652
552
|
jest.clearAllMocks();
|
|
653
553
|
});
|
|
654
554
|
|
|
655
|
-
it('
|
|
656
|
-
|
|
555
|
+
it('defaults ouId to -1 when config.context is absent', async () => {
|
|
556
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: { id: 'x' } } });
|
|
657
557
|
renderWithFlow({
|
|
658
558
|
features: {},
|
|
659
|
-
config: { ...baseConfig, features: {} },
|
|
660
559
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
661
|
-
onSave,
|
|
662
560
|
});
|
|
663
561
|
|
|
664
562
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
665
563
|
|
|
666
|
-
await waitFor(() => expect(
|
|
667
|
-
expect(
|
|
564
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
565
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
566
|
+
expect.objectContaining({
|
|
567
|
+
centralCommsPayload: expect.objectContaining({ ouId: -1 }),
|
|
568
|
+
}),
|
|
569
|
+
);
|
|
668
570
|
});
|
|
669
571
|
|
|
670
|
-
it('
|
|
671
|
-
|
|
572
|
+
it('defaults module to consumer.toUpperCase() when config.context.module absent', async () => {
|
|
573
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: { id: 'x' } } });
|
|
672
574
|
renderWithFlow({
|
|
673
575
|
features: {},
|
|
674
|
-
config: { ...baseConfig,
|
|
576
|
+
config: { ...baseConfig, consumer: 'loyalty', features: {} },
|
|
675
577
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
676
|
-
onSave,
|
|
677
578
|
});
|
|
678
579
|
|
|
679
580
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
680
581
|
|
|
681
|
-
await waitFor(() => expect(
|
|
682
|
-
expect(
|
|
582
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
583
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
584
|
+
expect.objectContaining({
|
|
585
|
+
centralCommsPayload: expect.objectContaining({ module: 'LOYALTY' }),
|
|
586
|
+
}),
|
|
587
|
+
);
|
|
683
588
|
});
|
|
684
589
|
|
|
685
590
|
it('initializes channel from config.channel when initialData.channel is absent', () => {
|
|
@@ -108,22 +108,6 @@ describe('CommunicationFlowCard', () => {
|
|
|
108
108
|
fireEvent.click(screen.getByText('Add creatives'));
|
|
109
109
|
expect(screen.getByTestId('comm-flow-mock')).toHaveAttribute('data-mode', 'create');
|
|
110
110
|
});
|
|
111
|
-
|
|
112
|
-
it('disables the Add creatives button when disabled prop is true', () => {
|
|
113
|
-
renderCard({ disabled: true, disabledTooltip: 'Enter an Alert name to add content' });
|
|
114
|
-
expect(screen.getByText('Add creatives').closest('button')).toBeDisabled();
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('does not open SlideBox when Add creatives is clicked while disabled', () => {
|
|
118
|
-
renderCard({ disabled: true, disabledTooltip: 'Enter an Alert name to add content' });
|
|
119
|
-
fireEvent.click(screen.getByText('Add creatives'));
|
|
120
|
-
expect(screen.queryByTestId('slide-box')).not.toBeInTheDocument();
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('Add creatives button is enabled by default (disabled prop absent)', () => {
|
|
124
|
-
renderCard();
|
|
125
|
-
expect(screen.getByText('Add creatives').closest('button')).not.toBeDisabled();
|
|
126
|
-
});
|
|
127
111
|
});
|
|
128
112
|
|
|
129
113
|
describe('configured state (initialData provided)', () => {
|
|
@@ -38,46 +38,6 @@ export const CHANNEL_PRIORITY = 'CHANNEL_PRIORITY';
|
|
|
38
38
|
export const AB_TEST = 'AB_TEST';
|
|
39
39
|
export const SINGLE_TEMPLATE = 'SINGLE_TEMPLATE';
|
|
40
40
|
|
|
41
|
-
// CCS CommDefinition strategyType — distinct from SINGLE_TEMPLATE above, which
|
|
42
|
-
// is this UI's own communicationStrategy value. Only SINGLE is supported this
|
|
43
|
-
// phase; CCS create is skipped entirely for CHANNEL_PRIORITY/AB_TEST.
|
|
44
|
-
export const CCS_STRATEGY_TYPE_SINGLE = 'SINGLE';
|
|
45
|
-
|
|
46
|
-
// Mirrors CCS's SingleChannelStrategy field names exactly (Cap Notify API
|
|
47
|
-
// Design doc, "Channel Strategy overview" / class dump). Kept separate from
|
|
48
|
-
// CHANNEL_CONTENT_KEY_MAP/CHANNEL_DELIVERY_KEY_MAP below, which are the legacy
|
|
49
|
-
// messageMeta payload's keys and do not match CCS naming for every channel
|
|
50
|
-
// (e.g. legacy uses lowercase 'mpushMessageContent'; CCS uses 'mPushMessageContent').
|
|
51
|
-
export const CCS_CHANNEL_CONTENT_KEY_MAP = {
|
|
52
|
-
SMS: 'smsMessageContent',
|
|
53
|
-
EMAIL: 'emailMessageContent',
|
|
54
|
-
WHATSAPP: 'whatsappMessageContent',
|
|
55
|
-
MPUSH: 'mPushMessageContent',
|
|
56
|
-
INAPP: 'inAppMessageContent',
|
|
57
|
-
ANDROID: 'androidMessageContent',
|
|
58
|
-
IOS: 'iosMessageContent',
|
|
59
|
-
ZALO: 'zaloMessageContent',
|
|
60
|
-
VIBER: 'viberMessageContent',
|
|
61
|
-
LINE: 'lineMessageContent',
|
|
62
|
-
WEBPUSH: 'webPushMessageContent',
|
|
63
|
-
RCS: 'rcsMessageContent',
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export const CCS_CHANNEL_DELIVERY_KEY_MAP = {
|
|
67
|
-
SMS: 'smsDeliverySettings',
|
|
68
|
-
EMAIL: 'emailDeliverySettings',
|
|
69
|
-
WHATSAPP: 'whatsappDeliverySettings',
|
|
70
|
-
MPUSH: 'mPushDeliverySettings',
|
|
71
|
-
INAPP: 'inAppDeliverySettings',
|
|
72
|
-
ANDROID: 'androidDeliverySettings',
|
|
73
|
-
IOS: 'iosDeliverySettings',
|
|
74
|
-
ZALO: 'zaloDeliverySettings',
|
|
75
|
-
VIBER: 'viberDeliverySettings',
|
|
76
|
-
LINE: 'lineDeliverySettings',
|
|
77
|
-
WEBPUSH: 'webPushDeliverySettings',
|
|
78
|
-
RCS: 'rcsDeliverySettings',
|
|
79
|
-
};
|
|
80
|
-
|
|
81
41
|
// Channel config - single source of truth for CreativesContainer and TemplatesV2
|
|
82
42
|
// paneKey: TemplatesV2 defaultPanes object key (for channelsToHide)
|
|
83
43
|
// channelProp: CreativesContainer channel prop (must match pane.key for tab to be active)
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import React from 'react';
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
11
|
import CommunicationFlow from './CommunicationFlow';
|
|
12
|
+
import { hasSupportEngagementModule } from '../../utils/common';
|
|
12
13
|
|
|
13
14
|
const CommunicationFlowContainer = ({
|
|
14
15
|
config,
|
|
@@ -17,16 +18,22 @@ const CommunicationFlowContainer = ({
|
|
|
17
18
|
onCancel,
|
|
18
19
|
onChange,
|
|
19
20
|
...otherProps
|
|
20
|
-
}) =>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
}) => {
|
|
22
|
+
if (!hasSupportEngagementModule()) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<CommunicationFlow
|
|
28
|
+
config={config}
|
|
29
|
+
initialData={initialData}
|
|
30
|
+
onSave={onSave}
|
|
31
|
+
onCancel={onCancel}
|
|
32
|
+
onChange={onChange}
|
|
33
|
+
{...otherProps}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
30
37
|
|
|
31
38
|
CommunicationFlowContainer.propTypes = {
|
|
32
39
|
config: PropTypes.shape({
|
|
@@ -80,13 +87,11 @@ CommunicationFlowContainer.propTypes = {
|
|
|
80
87
|
controls: PropTypes.array,
|
|
81
88
|
}),
|
|
82
89
|
}),
|
|
83
|
-
context: PropTypes.object, // ouId, campaignId, programId
|
|
84
|
-
//
|
|
85
|
-
useCCS: PropTypes.bool, // If false, skips the CCS createCommDefinition call on save. Defaults to true.
|
|
90
|
+
context: PropTypes.object, // ouId, campaignId, programId, etc.
|
|
91
|
+
useCCS: PropTypes.bool, // If false, skips CCS bulk-claim-approve on save. Defaults to true.
|
|
86
92
|
}).isRequired,
|
|
87
93
|
initialData: PropTypes.object, // for edit/preview mode
|
|
88
|
-
onSave: PropTypes.func.isRequired, // (data) => void - called when user saves
|
|
89
|
-
// ({id, referenceId, version, status}) is present when the CCS create succeeded
|
|
94
|
+
onSave: PropTypes.func.isRequired, // (data) => void - called when user saves
|
|
90
95
|
onCancel: PropTypes.func.isRequired, // () => void - called when user cancels
|
|
91
96
|
onChange: PropTypes.func, // (data) => void - optional, called on data changes
|
|
92
97
|
};
|
|
@@ -363,8 +363,4 @@ export default {
|
|
|
363
363
|
id: `${prefix}.senderNotConfiguredError`,
|
|
364
364
|
defaultMessage: 'Selected domain gateway id is not correct. Please change the domain id or contact the gateway team to register them with Capillary.',
|
|
365
365
|
},
|
|
366
|
-
duplicateReferenceIdError: {
|
|
367
|
-
id: `${prefix}.duplicateReferenceIdError`,
|
|
368
|
-
defaultMessage: 'This reference ID is already in use in your organization. Please use a different reference ID.',
|
|
369
|
-
},
|
|
370
366
|
};
|