@capillarytech/creatives-library 9.0.55-alpha.2 → 9.0.55
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/.vscode/settings.json +3 -0
- package/constants/unified.js +1 -0
- package/package.json +1 -1
- package/services/api.js +0 -12
- package/utils/common.js +4 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +0 -13
- package/v2Components/CommonTestAndPreview/constants.js +0 -2
- package/v2Components/CommonTestAndPreview/index.js +4 -1
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +0 -106
- package/v2Components/CommonTestAndPreview/tests/constants.test.js +1 -9
- package/v2Containers/CommunicationFlow/CommunicationFlow.js +56 -109
- package/v2Containers/CommunicationFlow/CommunicationFlow.scss +1 -1
- package/v2Containers/CommunicationFlow/CommunicationFlowCard.js +6 -22
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +49 -421
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlowCard.test.js +2 -18
- package/v2Containers/CommunicationFlow/constants.js +4 -63
- package/v2Containers/CommunicationFlow/index.js +20 -15
- package/v2Containers/CommunicationFlow/messages.js +0 -4
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +0 -6
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +0 -25
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +4 -11
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +5 -19
- package/v2Containers/CreativesContainer/index.js +7 -1
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +5 -5
- package/v2Containers/Rcs/constants.js +1 -0
- package/v2Containers/Rcs/index.js +10 -1
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +120 -12
- package/v2Containers/Rcs/tests/index.test.js +121 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +3 -3
- package/v2Containers/Templates/index.js +26 -0
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -34
- package/v2Containers/CommunicationFlow/Tests/constants.test.js +0 -85
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
jest.mock('../../../services/api', () => ({
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
createCentralCommsMetaId: jest.fn(),
|
|
5
|
+
getCentralCommsMetaIds: jest.fn(),
|
|
6
6
|
}));
|
|
7
7
|
|
|
8
8
|
jest.mock('../../CreativesContainer', () => function MockCreativesContainer({
|
|
@@ -38,7 +38,7 @@ import { IntlProvider } from 'react-intl';
|
|
|
38
38
|
import history from '../../../utils/history';
|
|
39
39
|
import { initialReducer } from '../../../initialReducer';
|
|
40
40
|
import CommunicationFlow from '../CommunicationFlow';
|
|
41
|
-
import {
|
|
41
|
+
import { createCentralCommsMetaId, getCentralCommsMetaIds } from '../../../services/api';
|
|
42
42
|
import { getEnabledSteps } from '../utils/getEnabledSteps';
|
|
43
43
|
import {
|
|
44
44
|
CHANNELS,
|
|
@@ -359,313 +359,82 @@ describe('isSaveDisabled', () => {
|
|
|
359
359
|
});
|
|
360
360
|
|
|
361
361
|
describe('handleSave — CCS flow', () => {
|
|
362
|
-
const ccsConfig = { ...baseConfig, context: { name: 'Order Placed Notification' }, features: {} };
|
|
363
|
-
|
|
364
362
|
beforeEach(() => {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
});
|
|
363
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: { id: 'meta-123' } } });
|
|
364
|
+
getCentralCommsMetaIds.mockResolvedValue({ response: { data: {} } });
|
|
368
365
|
});
|
|
369
366
|
|
|
370
367
|
afterEach(() => {
|
|
371
368
|
jest.clearAllMocks();
|
|
372
369
|
});
|
|
373
370
|
|
|
374
|
-
it('calls
|
|
371
|
+
it('calls createCentralCommsMetaId for each content item when useCCS is not false', async () => {
|
|
375
372
|
const onSave = jest.fn();
|
|
376
373
|
renderWithFlow({
|
|
377
374
|
features: {},
|
|
378
|
-
config: ccsConfig,
|
|
379
|
-
// messageBody is the legacy editor's field name for the typed SMS text
|
|
380
|
-
// (see CreativesContainer/index.js's getCreativesData SMS case) — the
|
|
381
|
-
// SMS transform maps it to CCS's `message` field.
|
|
382
375
|
initialData: {
|
|
383
|
-
contentItems: [{ channel: 'sms', templateData: {
|
|
376
|
+
contentItems: [{ channel: 'sms', templateData: { smsBody: 'Hello' } }],
|
|
384
377
|
},
|
|
385
378
|
onSave,
|
|
386
379
|
});
|
|
387
380
|
|
|
388
381
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
389
382
|
|
|
390
|
-
await waitFor(() => expect(
|
|
391
|
-
expect(
|
|
383
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalledTimes(1));
|
|
384
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
392
385
|
expect.objectContaining({
|
|
393
|
-
|
|
394
|
-
strategyType: 'SINGLE',
|
|
395
|
-
singleChannelStrategy: expect.objectContaining({
|
|
396
|
-
variant: expect.objectContaining({
|
|
397
|
-
channel: 'SMS',
|
|
398
|
-
smsMessageContent: { channel: 'SMS', message: 'Hello' },
|
|
399
|
-
}),
|
|
400
|
-
}),
|
|
386
|
+
centralCommsPayload: expect.objectContaining({ channel: 'SMS', module: 'CAMPAIGNS' }),
|
|
401
387
|
}),
|
|
402
388
|
);
|
|
403
389
|
expect(onSave).toHaveBeenCalledTimes(1);
|
|
404
390
|
});
|
|
405
391
|
|
|
406
|
-
it('
|
|
407
|
-
const onSave = jest.fn();
|
|
408
|
-
renderWithFlow({
|
|
409
|
-
features: {},
|
|
410
|
-
config: ccsConfig,
|
|
411
|
-
initialData: {
|
|
412
|
-
contentItems: [{
|
|
413
|
-
channel: 'SMS',
|
|
414
|
-
templateData: { messageBody: 'Hello {{name}}', channel: 'SMS' },
|
|
415
|
-
}],
|
|
416
|
-
},
|
|
417
|
-
onSave,
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
421
|
-
|
|
422
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
423
|
-
expect(createCommDefinition).toHaveBeenCalledWith(
|
|
424
|
-
expect.objectContaining({
|
|
425
|
-
singleChannelStrategy: expect.objectContaining({
|
|
426
|
-
variant: expect.objectContaining({
|
|
427
|
-
channel: 'SMS',
|
|
428
|
-
smsMessageContent: {
|
|
429
|
-
channel: 'SMS',
|
|
430
|
-
message: 'Hello {{name}}',
|
|
431
|
-
},
|
|
432
|
-
}),
|
|
433
|
-
}),
|
|
434
|
-
}),
|
|
435
|
-
);
|
|
436
|
-
});
|
|
437
|
-
|
|
438
|
-
it('does not carry the legacy messageBody key into smsMessageContent (regression guard against reverting to pass-through)', async () => {
|
|
439
|
-
const onSave = jest.fn();
|
|
440
|
-
renderWithFlow({
|
|
441
|
-
features: {},
|
|
442
|
-
config: ccsConfig,
|
|
443
|
-
initialData: {
|
|
444
|
-
contentItems: [{
|
|
445
|
-
channel: 'SMS',
|
|
446
|
-
templateData: { messageBody: 'Hello {{name}}', channel: 'SMS' },
|
|
447
|
-
}],
|
|
448
|
-
},
|
|
449
|
-
onSave,
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
453
|
-
|
|
454
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
455
|
-
const payload = createCommDefinition.mock.calls[0][0];
|
|
456
|
-
expect(payload.singleChannelStrategy.variant.smsMessageContent).not.toHaveProperty('messageBody');
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
it('transforms EMAIL content from the legacy editor shape (emailSubject) to CCS\'s messageSubject', async () => {
|
|
460
|
-
const onSave = jest.fn();
|
|
461
|
-
renderWithFlow({
|
|
462
|
-
features: {},
|
|
463
|
-
config: ccsConfig,
|
|
464
|
-
initialData: {
|
|
465
|
-
contentItems: [{
|
|
466
|
-
channel: 'EMAIL',
|
|
467
|
-
templateData: { emailSubject: 'Order Confirmed', emailBody: '<html>Hi</html>' },
|
|
468
|
-
}],
|
|
469
|
-
},
|
|
470
|
-
onSave,
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
474
|
-
|
|
475
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
476
|
-
expect(createCommDefinition).toHaveBeenCalledWith(
|
|
477
|
-
expect.objectContaining({
|
|
478
|
-
singleChannelStrategy: expect.objectContaining({
|
|
479
|
-
variant: expect.objectContaining({
|
|
480
|
-
channel: 'EMAIL',
|
|
481
|
-
emailMessageContent: {
|
|
482
|
-
channel: 'EMAIL',
|
|
483
|
-
messageSubject: 'Order Confirmed',
|
|
484
|
-
messageBody: '<html>Hi</html>',
|
|
485
|
-
},
|
|
486
|
-
}),
|
|
487
|
-
}),
|
|
488
|
-
}),
|
|
489
|
-
);
|
|
490
|
-
});
|
|
491
|
-
|
|
492
|
-
it('transforms WEBPUSH content from the legacy editor\'s messageContent.content wrapping to CCS\'s flat shape', async () => {
|
|
493
|
-
const onSave = jest.fn();
|
|
494
|
-
const cta = { type: 'SITE_URL', actionLink: 'https://example.com' };
|
|
495
|
-
const expandableDetails = { media: [{ url: 'https://example.com/banner.png', type: 'IMAGE' }], ctas: [] };
|
|
496
|
-
renderWithFlow({
|
|
497
|
-
features: {},
|
|
498
|
-
config: ccsConfig,
|
|
499
|
-
initialData: {
|
|
500
|
-
contentItems: [{
|
|
501
|
-
channel: 'WEBPUSH',
|
|
502
|
-
templateData: {
|
|
503
|
-
messageContent: {
|
|
504
|
-
content: {
|
|
505
|
-
channel: 'WEBPUSH',
|
|
506
|
-
accountId: 13792,
|
|
507
|
-
content: { title: 'Hi', message: 'Body', iconImageUrl: 'https://example.com/icon.png', cta, expandableDetails },
|
|
508
|
-
messageSubject: 'Subject',
|
|
509
|
-
offers: [],
|
|
510
|
-
},
|
|
511
|
-
},
|
|
512
|
-
},
|
|
513
|
-
}],
|
|
514
|
-
},
|
|
515
|
-
onSave,
|
|
516
|
-
});
|
|
517
|
-
|
|
518
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
519
|
-
|
|
520
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
521
|
-
expect(createCommDefinition).toHaveBeenCalledWith(
|
|
522
|
-
expect.objectContaining({
|
|
523
|
-
singleChannelStrategy: expect.objectContaining({
|
|
524
|
-
variant: expect.objectContaining({
|
|
525
|
-
channel: 'WEBPUSH',
|
|
526
|
-
webPushMessageContent: {
|
|
527
|
-
channel: 'WEBPUSH',
|
|
528
|
-
messageSubject: 'Subject',
|
|
529
|
-
accountId: 13792,
|
|
530
|
-
content: { title: 'Hi', message: 'Body', iconImageUrl: 'https://example.com/icon.png', cta, expandableDetails },
|
|
531
|
-
},
|
|
532
|
-
}),
|
|
533
|
-
}),
|
|
534
|
-
}),
|
|
535
|
-
);
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
it('normalizes the internal MOBILEPUSH channel to CCS\'s PUSH enum (keys stay mpush*), even when templateData/channelSetting carry their own stray channel field', async () => {
|
|
539
|
-
const onSave = jest.fn();
|
|
392
|
+
it('calls getCentralCommsMetaIds when metaIds are returned from createCentralCommsMetaId', async () => {
|
|
540
393
|
renderWithFlow({
|
|
541
394
|
features: {},
|
|
542
|
-
|
|
543
|
-
initialData: {
|
|
544
|
-
// `channel: 'MOBILEPUSH'` inline on templateData reproduces the real
|
|
545
|
-
// production bug: contentItem.templateData carries the UI's own
|
|
546
|
-
// internal channel identifier, which must not win over the
|
|
547
|
-
// normalized 'PUSH' enum once spread into mpushMessageContent.
|
|
548
|
-
contentItems: [{ channel: 'MOBILEPUSH', templateData: { channel: 'MOBILEPUSH', messageSubject: 'Hi' } }],
|
|
549
|
-
// Likewise, deliverySetting.channelSetting.PUSH carrying its own
|
|
550
|
-
// stray `channel` key must not win over the normalized value once
|
|
551
|
-
// spread into mpushDeliverySettings.channelSettings.
|
|
552
|
-
deliverySetting: { channelSetting: { PUSH: { channel: 'MOBILEPUSH', domainId: 2002 } } },
|
|
553
|
-
},
|
|
554
|
-
onSave,
|
|
395
|
+
initialData: { contentItems: [{ channel: 'EMAIL', templateData: {} }] },
|
|
555
396
|
});
|
|
556
397
|
|
|
557
398
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
558
399
|
|
|
559
|
-
await waitFor(() => expect(
|
|
560
|
-
expect(createCommDefinition).toHaveBeenCalledWith(
|
|
561
|
-
expect.objectContaining({
|
|
562
|
-
singleChannelStrategy: expect.objectContaining({
|
|
563
|
-
variant: expect.objectContaining({
|
|
564
|
-
channel: 'PUSH',
|
|
565
|
-
mpushMessageContent: { channel: 'PUSH', messageSubject: 'Hi' },
|
|
566
|
-
mpushDeliverySettings: {
|
|
567
|
-
channelSettings: { channel: 'PUSH', domainId: 2002 },
|
|
568
|
-
},
|
|
569
|
-
}),
|
|
570
|
-
}),
|
|
571
|
-
}),
|
|
572
|
-
);
|
|
400
|
+
await waitFor(() => expect(getCentralCommsMetaIds).toHaveBeenCalledWith('meta-123'));
|
|
573
401
|
});
|
|
574
402
|
|
|
575
|
-
it('
|
|
576
|
-
|
|
403
|
+
it('skips getCentralCommsMetaIds when response contains no id', async () => {
|
|
404
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: {} } });
|
|
577
405
|
renderWithFlow({
|
|
578
406
|
features: {},
|
|
579
|
-
config: ccsConfig,
|
|
580
407
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
581
|
-
onSave,
|
|
582
408
|
});
|
|
583
409
|
|
|
584
410
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
585
411
|
|
|
586
|
-
await waitFor(() => expect(
|
|
587
|
-
expect(
|
|
588
|
-
expect.objectContaining({
|
|
589
|
-
ccsCommDefinition: { id: 'cd_123', referenceId: 'ORDER_PLACED_123', version: 1, status: 'DRAFT' },
|
|
590
|
-
}),
|
|
591
|
-
);
|
|
412
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
413
|
+
expect(getCentralCommsMetaIds).not.toHaveBeenCalled();
|
|
592
414
|
});
|
|
593
415
|
|
|
594
|
-
it('
|
|
595
|
-
const onSave = jest.fn();
|
|
596
|
-
createCommDefinition.mockResolvedValueOnce({
|
|
597
|
-
response: { data: { id: 'cd_123', referenceId: 'ORDER_PLACED_123', status: 'DRAFT', version: { version: 0 } } },
|
|
598
|
-
});
|
|
416
|
+
it('uses ouId and module from config.context when provided', async () => {
|
|
599
417
|
renderWithFlow({
|
|
600
418
|
features: {},
|
|
601
|
-
config:
|
|
419
|
+
config: { ...baseConfig, context: { ouId: 42, module: 'LOYALTY' }, features: {} },
|
|
602
420
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
603
|
-
onSave,
|
|
604
421
|
});
|
|
605
422
|
|
|
606
423
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
607
424
|
|
|
608
|
-
await waitFor(() => expect(
|
|
609
|
-
expect(
|
|
425
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
426
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
610
427
|
expect.objectContaining({
|
|
611
|
-
|
|
428
|
+
centralCommsPayload: expect.objectContaining({ ouId: 42, module: 'LOYALTY' }),
|
|
612
429
|
}),
|
|
613
430
|
);
|
|
614
431
|
});
|
|
615
432
|
|
|
616
|
-
it('generates a referenceId from name when config.context.referenceId is absent', async () => {
|
|
617
|
-
// moduleMocks.js spies on Date.now globally, but this config's resetMocks:true
|
|
618
|
-
// clears that return value before every test — set it explicitly here.
|
|
619
|
-
jest.spyOn(Date, 'now').mockReturnValue(1612267539410);
|
|
620
|
-
renderWithFlow({
|
|
621
|
-
features: {},
|
|
622
|
-
config: ccsConfig,
|
|
623
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
624
|
-
});
|
|
625
|
-
|
|
626
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
627
|
-
|
|
628
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalled());
|
|
629
|
-
const payload = createCommDefinition.mock.calls[0][0];
|
|
630
|
-
expect(payload.referenceId).toBe('ORDER_PLACED_NOTIFICATION_1612267539410');
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
it('uses config.context.referenceId and description when provided', async () => {
|
|
634
|
-
renderWithFlow({
|
|
635
|
-
features: {},
|
|
636
|
-
config: { ...ccsConfig, context: { ...ccsConfig.context, referenceId: 'ORDER_PLACED', description: 'desc' } },
|
|
637
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
638
|
-
});
|
|
639
|
-
|
|
640
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
641
|
-
|
|
642
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalled());
|
|
643
|
-
expect(createCommDefinition).toHaveBeenCalledWith(
|
|
644
|
-
expect.objectContaining({ referenceId: 'ORDER_PLACED', description: 'desc' }),
|
|
645
|
-
);
|
|
646
|
-
});
|
|
647
|
-
|
|
648
433
|
it('skips CCS entirely when useCCS is false', async () => {
|
|
649
434
|
const onSave = jest.fn();
|
|
650
435
|
renderWithFlow({
|
|
651
436
|
features: {},
|
|
652
|
-
config: { ...
|
|
653
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
654
|
-
onSave,
|
|
655
|
-
});
|
|
656
|
-
|
|
657
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
658
|
-
|
|
659
|
-
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
660
|
-
expect(createCommDefinition).not.toHaveBeenCalled();
|
|
661
|
-
expect(onSave).toHaveBeenCalledWith(expect.not.objectContaining({ ccsCommDefinition: expect.anything() }));
|
|
662
|
-
});
|
|
663
|
-
|
|
664
|
-
it('skips createCommDefinition when config.context.name is absent (mandatory)', async () => {
|
|
665
|
-
const onSave = jest.fn();
|
|
666
|
-
renderWithFlow({
|
|
667
|
-
features: {},
|
|
668
|
-
config: { ...baseConfig, features: {} },
|
|
437
|
+
config: { ...baseConfig, useCCS: false, features: {} },
|
|
669
438
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
670
439
|
onSave,
|
|
671
440
|
});
|
|
@@ -673,34 +442,14 @@ describe('handleSave — CCS flow', () => {
|
|
|
673
442
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
674
443
|
|
|
675
444
|
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
676
|
-
expect(
|
|
677
|
-
});
|
|
678
|
-
|
|
679
|
-
it('skips createCommDefinition for multi-channel strategies (CHANNEL_PRIORITY/AB_TEST)', async () => {
|
|
680
|
-
const onSave = jest.fn();
|
|
681
|
-
renderWithFlow({
|
|
682
|
-
features: {},
|
|
683
|
-
config: ccsConfig,
|
|
684
|
-
initialData: {
|
|
685
|
-
communicationStrategy: CHANNEL_PRIORITY,
|
|
686
|
-
channels: ['SMS', 'EMAIL'],
|
|
687
|
-
contentItems: [{ channel: 'SMS', templateData: {} }, { channel: 'EMAIL', templateData: {} }],
|
|
688
|
-
},
|
|
689
|
-
onSave,
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
693
|
-
|
|
694
|
-
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
695
|
-
expect(createCommDefinition).not.toHaveBeenCalled();
|
|
445
|
+
expect(createCentralCommsMetaId).not.toHaveBeenCalled();
|
|
696
446
|
});
|
|
697
447
|
|
|
698
|
-
it('still calls onSave
|
|
699
|
-
|
|
448
|
+
it('still calls onSave when createCentralCommsMetaId rejects', async () => {
|
|
449
|
+
createCentralCommsMetaId.mockRejectedValue(new Error('Network error'));
|
|
700
450
|
const onSave = jest.fn();
|
|
701
451
|
renderWithFlow({
|
|
702
452
|
features: {},
|
|
703
|
-
config: ccsConfig,
|
|
704
453
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
705
454
|
onSave,
|
|
706
455
|
});
|
|
@@ -708,35 +457,12 @@ describe('handleSave — CCS flow', () => {
|
|
|
708
457
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
709
458
|
|
|
710
459
|
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
711
|
-
expect(onSave).toHaveBeenCalledWith(expect.not.objectContaining({ ccsCommDefinition: expect.anything() }));
|
|
712
460
|
});
|
|
713
461
|
|
|
714
|
-
it('
|
|
715
|
-
createCommDefinition.mockResolvedValue({
|
|
716
|
-
success: false,
|
|
717
|
-
status: { isError: true, code: 409, message: 'REFERENCE_ID_EXISTS' },
|
|
718
|
-
message: 'REFERENCE_ID_EXISTS',
|
|
719
|
-
});
|
|
462
|
+
it('skips createCentralCommsMetaId when contentItems is empty', async () => {
|
|
720
463
|
const onSave = jest.fn();
|
|
721
464
|
renderWithFlow({
|
|
722
465
|
features: {},
|
|
723
|
-
config: ccsConfig,
|
|
724
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
725
|
-
onSave,
|
|
726
|
-
});
|
|
727
|
-
|
|
728
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
729
|
-
|
|
730
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
731
|
-
expect(await screen.findByText(/already in use in your organization/i)).toBeInTheDocument();
|
|
732
|
-
expect(onSave).not.toHaveBeenCalled();
|
|
733
|
-
});
|
|
734
|
-
|
|
735
|
-
it('skips createCommDefinition when contentItems is empty', async () => {
|
|
736
|
-
const onSave = jest.fn();
|
|
737
|
-
renderWithFlow({
|
|
738
|
-
features: {},
|
|
739
|
-
config: ccsConfig,
|
|
740
466
|
initialData: { contentItems: [] },
|
|
741
467
|
onSave,
|
|
742
468
|
});
|
|
@@ -744,13 +470,12 @@ describe('handleSave — CCS flow', () => {
|
|
|
744
470
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
745
471
|
|
|
746
472
|
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
747
|
-
expect(
|
|
473
|
+
expect(createCentralCommsMetaId).not.toHaveBeenCalled();
|
|
748
474
|
});
|
|
749
475
|
|
|
750
|
-
it('
|
|
476
|
+
it('includes additionalSettings derived from dynamicControls in the payload', async () => {
|
|
751
477
|
renderWithFlow({
|
|
752
478
|
features: {},
|
|
753
|
-
config: ccsConfig,
|
|
754
479
|
initialData: {
|
|
755
480
|
contentItems: [{ channel: 'SMS', templateData: {} }],
|
|
756
481
|
dynamicControls: {
|
|
@@ -764,116 +489,14 @@ describe('handleSave — CCS flow', () => {
|
|
|
764
489
|
|
|
765
490
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
766
491
|
|
|
767
|
-
await waitFor(() => expect(
|
|
768
|
-
const payload =
|
|
769
|
-
expect(payload.
|
|
492
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
493
|
+
const payload = createCentralCommsMetaId.mock.calls[0][0];
|
|
494
|
+
expect(payload.centralCommsPayload.smsDeliverySettings.additionalSettings).toEqual({
|
|
770
495
|
useTinyUrl: true,
|
|
771
496
|
encryptUrl: true,
|
|
772
497
|
linkTrackingEnabled: true,
|
|
773
498
|
userSubscriptionDisabled: true,
|
|
774
499
|
});
|
|
775
|
-
expect(payload.singleChannelStrategy.variant.smsDeliverySettings.additionalSettings).toBeUndefined();
|
|
776
|
-
});
|
|
777
|
-
|
|
778
|
-
it('includes channelSettings from deliverySetting.channelSetting in the payload', async () => {
|
|
779
|
-
renderWithFlow({
|
|
780
|
-
features: {},
|
|
781
|
-
config: ccsConfig,
|
|
782
|
-
initialData: {
|
|
783
|
-
contentItems: [{ channel: 'SMS', templateData: {} }],
|
|
784
|
-
deliverySetting: { channelSetting: { SMS: { domainId: 1001, gsmSenderId: 'BRAND1' } } },
|
|
785
|
-
},
|
|
786
|
-
});
|
|
787
|
-
|
|
788
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
789
|
-
|
|
790
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalled());
|
|
791
|
-
const payload = createCommDefinition.mock.calls[0][0];
|
|
792
|
-
expect(payload.singleChannelStrategy.variant.smsDeliverySettings.channelSettings).toEqual({
|
|
793
|
-
channel: 'SMS',
|
|
794
|
-
domainId: 1001,
|
|
795
|
-
gsmSenderId: 'BRAND1',
|
|
796
|
-
});
|
|
797
|
-
});
|
|
798
|
-
|
|
799
|
-
it('does not call editCommDefinition when config.context.existingCommDefinitionId is absent', async () => {
|
|
800
|
-
const onSave = jest.fn();
|
|
801
|
-
renderWithFlow({
|
|
802
|
-
features: {},
|
|
803
|
-
config: ccsConfig,
|
|
804
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
805
|
-
onSave,
|
|
806
|
-
});
|
|
807
|
-
|
|
808
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
809
|
-
|
|
810
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
811
|
-
expect(editCommDefinition).not.toHaveBeenCalled();
|
|
812
|
-
});
|
|
813
|
-
|
|
814
|
-
it('calls editCommDefinition (not createCommDefinition) and merges the existing id into ccsCommDefinition when config.context.existingCommDefinitionId is set', async () => {
|
|
815
|
-
editCommDefinition.mockResolvedValue({
|
|
816
|
-
response: { data: { version: { version: 2 }, status: 'DRAFT' } },
|
|
817
|
-
});
|
|
818
|
-
const onSave = jest.fn();
|
|
819
|
-
renderWithFlow({
|
|
820
|
-
features: {},
|
|
821
|
-
config: {
|
|
822
|
-
...ccsConfig,
|
|
823
|
-
context: { ...ccsConfig.context, referenceId: 'ORDER_PLACED', existingCommDefinitionId: 'cd_existing_1' },
|
|
824
|
-
},
|
|
825
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
826
|
-
onSave,
|
|
827
|
-
});
|
|
828
|
-
|
|
829
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
830
|
-
|
|
831
|
-
await waitFor(() => expect(editCommDefinition).toHaveBeenCalledTimes(1));
|
|
832
|
-
expect(editCommDefinition).toHaveBeenCalledWith(
|
|
833
|
-
'cd_existing_1',
|
|
834
|
-
expect.objectContaining({
|
|
835
|
-
strategyType: 'SINGLE',
|
|
836
|
-
settings: expect.anything(),
|
|
837
|
-
singleChannelStrategy: expect.anything(),
|
|
838
|
-
}),
|
|
839
|
-
);
|
|
840
|
-
expect(createCommDefinition).not.toHaveBeenCalled();
|
|
841
|
-
|
|
842
|
-
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
843
|
-
expect(onSave).toHaveBeenCalledWith(
|
|
844
|
-
expect.objectContaining({
|
|
845
|
-
ccsCommDefinition: {
|
|
846
|
-
id: 'cd_existing_1',
|
|
847
|
-
referenceId: 'ORDER_PLACED',
|
|
848
|
-
version: 2,
|
|
849
|
-
status: 'DRAFT',
|
|
850
|
-
},
|
|
851
|
-
}),
|
|
852
|
-
);
|
|
853
|
-
});
|
|
854
|
-
|
|
855
|
-
it('blocks save and shows an error when editCommDefinition resolves with a duplicate REFERENCE_ID_EXISTS conflict', async () => {
|
|
856
|
-
editCommDefinition.mockResolvedValue({
|
|
857
|
-
success: false,
|
|
858
|
-
status: { isError: true, code: 409, message: 'REFERENCE_ID_EXISTS' },
|
|
859
|
-
message: 'REFERENCE_ID_EXISTS',
|
|
860
|
-
});
|
|
861
|
-
const onSave = jest.fn();
|
|
862
|
-
renderWithFlow({
|
|
863
|
-
features: {},
|
|
864
|
-
config: {
|
|
865
|
-
...ccsConfig,
|
|
866
|
-
context: { ...ccsConfig.context, referenceId: 'ORDER_PLACED', existingCommDefinitionId: 'cd_existing_1' },
|
|
867
|
-
},
|
|
868
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
869
|
-
onSave,
|
|
870
|
-
});
|
|
871
|
-
|
|
872
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
873
|
-
|
|
874
|
-
await waitFor(() => expect(editCommDefinition).toHaveBeenCalledTimes(1));
|
|
875
|
-
expect(await screen.findByText(/already in use in your organization/i)).toBeInTheDocument();
|
|
876
|
-
expect(onSave).not.toHaveBeenCalled();
|
|
877
500
|
});
|
|
878
501
|
});
|
|
879
502
|
|
|
@@ -929,34 +552,39 @@ describe('optional chaining safety', () => {
|
|
|
929
552
|
jest.clearAllMocks();
|
|
930
553
|
});
|
|
931
554
|
|
|
932
|
-
it('
|
|
933
|
-
|
|
555
|
+
it('defaults ouId to -1 when config.context is absent', async () => {
|
|
556
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: { id: 'x' } } });
|
|
934
557
|
renderWithFlow({
|
|
935
558
|
features: {},
|
|
936
|
-
config: { ...baseConfig, features: {} },
|
|
937
559
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
938
|
-
onSave,
|
|
939
560
|
});
|
|
940
561
|
|
|
941
562
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
942
563
|
|
|
943
|
-
await waitFor(() => expect(
|
|
944
|
-
expect(
|
|
564
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
565
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
566
|
+
expect.objectContaining({
|
|
567
|
+
centralCommsPayload: expect.objectContaining({ ouId: -1 }),
|
|
568
|
+
}),
|
|
569
|
+
);
|
|
945
570
|
});
|
|
946
571
|
|
|
947
|
-
it('
|
|
948
|
-
|
|
572
|
+
it('defaults module to consumer.toUpperCase() when config.context.module absent', async () => {
|
|
573
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: { id: 'x' } } });
|
|
949
574
|
renderWithFlow({
|
|
950
575
|
features: {},
|
|
951
|
-
config: { ...baseConfig,
|
|
576
|
+
config: { ...baseConfig, consumer: 'loyalty', features: {} },
|
|
952
577
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
953
|
-
onSave,
|
|
954
578
|
});
|
|
955
579
|
|
|
956
580
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
957
581
|
|
|
958
|
-
await waitFor(() => expect(
|
|
959
|
-
expect(
|
|
582
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
583
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
584
|
+
expect.objectContaining({
|
|
585
|
+
centralCommsPayload: expect.objectContaining({ module: 'LOYALTY' }),
|
|
586
|
+
}),
|
|
587
|
+
);
|
|
960
588
|
});
|
|
961
589
|
|
|
962
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)', () => {
|
|
@@ -247,11 +231,11 @@ describe('CommunicationFlowCard', () => {
|
|
|
247
231
|
expect(screen.getByText(/Sender ID/)).toBeInTheDocument();
|
|
248
232
|
});
|
|
249
233
|
|
|
250
|
-
it('shows
|
|
234
|
+
it('shows senderEmail for EMAIL with Sender ID label', () => {
|
|
251
235
|
renderCard({
|
|
252
236
|
initialData: makeSavedData({
|
|
253
237
|
contentItems: [{ channel: 'EMAIL', templateData: {} }],
|
|
254
|
-
deliverySetting: { channelSetting: { EMAIL: {
|
|
238
|
+
deliverySetting: { channelSetting: { EMAIL: { senderEmail: 'test@example.com' } } },
|
|
255
239
|
}),
|
|
256
240
|
});
|
|
257
241
|
expect(screen.getByText(/test@example.com/)).toBeInTheDocument();
|