@capillarytech/creatives-library 9.0.54-alpha.4 → 9.0.54
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 -20
- package/utils/common.js +4 -0
- package/v2Components/FormBuilder/Classic.js +2 -2
- package/v2Containers/CommunicationFlow/CommunicationFlow.js +56 -118
- package/v2Containers/CommunicationFlow/CommunicationFlowCard.js +5 -21
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +49 -365
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlowCard.test.js +2 -18
- package/v2Containers/CommunicationFlow/constants.js +1 -81
- 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 -24
- package/v2Containers/MobilePush/Edit/index.js +1 -2
|
@@ -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,241 +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
375
|
initialData: {
|
|
380
|
-
contentItems: [{ channel: 'sms', templateData: {
|
|
376
|
+
contentItems: [{ channel: 'sms', templateData: { smsBody: 'Hello' } }],
|
|
381
377
|
},
|
|
382
378
|
onSave,
|
|
383
379
|
});
|
|
384
380
|
|
|
385
381
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
386
382
|
|
|
387
|
-
await waitFor(() => expect(
|
|
388
|
-
expect(
|
|
383
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalledTimes(1));
|
|
384
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
389
385
|
expect.objectContaining({
|
|
390
|
-
|
|
391
|
-
strategyType: 'SINGLE',
|
|
392
|
-
singleChannelStrategy: expect.objectContaining({
|
|
393
|
-
variant: expect.objectContaining({
|
|
394
|
-
channel: 'SMS',
|
|
395
|
-
smsMessageContent: { channel: 'SMS', message: 'Hello' },
|
|
396
|
-
}),
|
|
397
|
-
}),
|
|
386
|
+
centralCommsPayload: expect.objectContaining({ channel: 'SMS', module: 'CAMPAIGNS' }),
|
|
398
387
|
}),
|
|
399
388
|
);
|
|
400
389
|
expect(onSave).toHaveBeenCalledTimes(1);
|
|
401
390
|
});
|
|
402
391
|
|
|
403
|
-
it('
|
|
404
|
-
const onSave = jest.fn();
|
|
392
|
+
it('calls getCentralCommsMetaIds when metaIds are returned from createCentralCommsMetaId', async () => {
|
|
405
393
|
renderWithFlow({
|
|
406
394
|
features: {},
|
|
407
|
-
|
|
408
|
-
initialData: {
|
|
409
|
-
contentItems: [{
|
|
410
|
-
channel: 'EMAIL',
|
|
411
|
-
templateData: { emailSubject: 'Order Confirmed', emailBody: '<html>Hi</html>' },
|
|
412
|
-
}],
|
|
413
|
-
},
|
|
414
|
-
onSave,
|
|
395
|
+
initialData: { contentItems: [{ channel: 'EMAIL', templateData: {} }] },
|
|
415
396
|
});
|
|
416
397
|
|
|
417
398
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
418
399
|
|
|
419
|
-
await waitFor(() => expect(
|
|
420
|
-
expect(createCommDefinition).toHaveBeenCalledWith(
|
|
421
|
-
expect.objectContaining({
|
|
422
|
-
singleChannelStrategy: expect.objectContaining({
|
|
423
|
-
variant: expect.objectContaining({
|
|
424
|
-
channel: 'EMAIL',
|
|
425
|
-
emailMessageContent: {
|
|
426
|
-
channel: 'EMAIL',
|
|
427
|
-
messageSubject: 'Order Confirmed',
|
|
428
|
-
messageBody: '<html>Hi</html>',
|
|
429
|
-
},
|
|
430
|
-
}),
|
|
431
|
-
}),
|
|
432
|
-
}),
|
|
433
|
-
);
|
|
400
|
+
await waitFor(() => expect(getCentralCommsMetaIds).toHaveBeenCalledWith('meta-123'));
|
|
434
401
|
});
|
|
435
402
|
|
|
436
|
-
it('
|
|
437
|
-
|
|
438
|
-
const cta = { type: 'SITE_URL', actionLink: 'https://example.com' };
|
|
439
|
-
const expandableDetails = { media: [{ url: 'https://example.com/banner.png', type: 'IMAGE' }], ctas: [] };
|
|
403
|
+
it('skips getCentralCommsMetaIds when response contains no id', async () => {
|
|
404
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: {} } });
|
|
440
405
|
renderWithFlow({
|
|
441
406
|
features: {},
|
|
442
|
-
config: ccsConfig,
|
|
443
|
-
initialData: {
|
|
444
|
-
contentItems: [{
|
|
445
|
-
channel: 'WEBPUSH',
|
|
446
|
-
templateData: {
|
|
447
|
-
messageContent: {
|
|
448
|
-
content: {
|
|
449
|
-
channel: 'WEBPUSH',
|
|
450
|
-
accountId: 13792,
|
|
451
|
-
content: { title: 'Hi', message: 'Body', iconImageUrl: 'https://example.com/icon.png', cta, expandableDetails },
|
|
452
|
-
messageSubject: 'Subject',
|
|
453
|
-
offers: [],
|
|
454
|
-
},
|
|
455
|
-
},
|
|
456
|
-
},
|
|
457
|
-
}],
|
|
458
|
-
},
|
|
459
|
-
onSave,
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
463
|
-
|
|
464
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
465
|
-
expect(createCommDefinition).toHaveBeenCalledWith(
|
|
466
|
-
expect.objectContaining({
|
|
467
|
-
singleChannelStrategy: expect.objectContaining({
|
|
468
|
-
variant: expect.objectContaining({
|
|
469
|
-
channel: 'WEBPUSH',
|
|
470
|
-
webPushMessageContent: {
|
|
471
|
-
channel: 'WEBPUSH',
|
|
472
|
-
messageSubject: 'Subject',
|
|
473
|
-
accountId: 13792,
|
|
474
|
-
content: { title: 'Hi', message: 'Body', iconImageUrl: 'https://example.com/icon.png', cta, expandableDetails },
|
|
475
|
-
},
|
|
476
|
-
}),
|
|
477
|
-
}),
|
|
478
|
-
}),
|
|
479
|
-
);
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
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 () => {
|
|
483
|
-
const onSave = jest.fn();
|
|
484
|
-
renderWithFlow({
|
|
485
|
-
features: {},
|
|
486
|
-
config: ccsConfig,
|
|
487
|
-
initialData: {
|
|
488
|
-
// `channel: 'MOBILEPUSH'` inline on templateData reproduces the real
|
|
489
|
-
// production bug: contentItem.templateData carries the UI's own
|
|
490
|
-
// internal channel identifier, which must not win over the
|
|
491
|
-
// normalized 'PUSH' enum once spread into mpushMessageContent.
|
|
492
|
-
contentItems: [{ channel: 'MOBILEPUSH', templateData: { channel: 'MOBILEPUSH', messageSubject: 'Hi' } }],
|
|
493
|
-
// Likewise, deliverySetting.channelSetting.PUSH carrying its own
|
|
494
|
-
// stray `channel` key must not win over the normalized value once
|
|
495
|
-
// spread into mpushDeliverySettings.channelSettings.
|
|
496
|
-
deliverySetting: { channelSetting: { PUSH: { channel: 'MOBILEPUSH', domainId: 2002 } } },
|
|
497
|
-
},
|
|
498
|
-
onSave,
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
502
|
-
|
|
503
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
504
|
-
expect(createCommDefinition).toHaveBeenCalledWith(
|
|
505
|
-
expect.objectContaining({
|
|
506
|
-
singleChannelStrategy: expect.objectContaining({
|
|
507
|
-
variant: expect.objectContaining({
|
|
508
|
-
channel: 'PUSH',
|
|
509
|
-
mpushMessageContent: { channel: 'PUSH', messageSubject: 'Hi' },
|
|
510
|
-
mpushDeliverySettings: {
|
|
511
|
-
channelSettings: { channel: 'PUSH', domainId: 2002 },
|
|
512
|
-
},
|
|
513
|
-
}),
|
|
514
|
-
}),
|
|
515
|
-
}),
|
|
516
|
-
);
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
it('merges ccsCommDefinition into the data passed to onSave when create succeeds', async () => {
|
|
520
|
-
const onSave = jest.fn();
|
|
521
|
-
renderWithFlow({
|
|
522
|
-
features: {},
|
|
523
|
-
config: ccsConfig,
|
|
524
407
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
525
|
-
onSave,
|
|
526
408
|
});
|
|
527
409
|
|
|
528
410
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
529
411
|
|
|
530
|
-
await waitFor(() => expect(
|
|
531
|
-
expect(
|
|
532
|
-
expect.objectContaining({
|
|
533
|
-
ccsCommDefinition: { id: 'cd_123', referenceId: 'ORDER_PLACED_123', version: 1, status: 'DRAFT' },
|
|
534
|
-
}),
|
|
535
|
-
);
|
|
412
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
413
|
+
expect(getCentralCommsMetaIds).not.toHaveBeenCalled();
|
|
536
414
|
});
|
|
537
415
|
|
|
538
|
-
it('
|
|
539
|
-
const onSave = jest.fn();
|
|
540
|
-
createCommDefinition.mockResolvedValueOnce({
|
|
541
|
-
response: { data: { id: 'cd_123', referenceId: 'ORDER_PLACED_123', status: 'DRAFT', version: { version: 0 } } },
|
|
542
|
-
});
|
|
416
|
+
it('uses ouId and module from config.context when provided', async () => {
|
|
543
417
|
renderWithFlow({
|
|
544
418
|
features: {},
|
|
545
|
-
config:
|
|
419
|
+
config: { ...baseConfig, context: { ouId: 42, module: 'LOYALTY' }, features: {} },
|
|
546
420
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
547
|
-
onSave,
|
|
548
421
|
});
|
|
549
422
|
|
|
550
423
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
551
424
|
|
|
552
|
-
await waitFor(() => expect(
|
|
553
|
-
expect(
|
|
425
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
426
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
554
427
|
expect.objectContaining({
|
|
555
|
-
|
|
428
|
+
centralCommsPayload: expect.objectContaining({ ouId: 42, module: 'LOYALTY' }),
|
|
556
429
|
}),
|
|
557
430
|
);
|
|
558
431
|
});
|
|
559
432
|
|
|
560
|
-
it('generates a referenceId from name when config.context.referenceId is absent', async () => {
|
|
561
|
-
// moduleMocks.js spies on Date.now globally, but this config's resetMocks:true
|
|
562
|
-
// clears that return value before every test — set it explicitly here.
|
|
563
|
-
jest.spyOn(Date, 'now').mockReturnValue(1612267539410);
|
|
564
|
-
renderWithFlow({
|
|
565
|
-
features: {},
|
|
566
|
-
config: ccsConfig,
|
|
567
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
571
|
-
|
|
572
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalled());
|
|
573
|
-
const payload = createCommDefinition.mock.calls[0][0];
|
|
574
|
-
expect(payload.referenceId).toBe('ORDER_PLACED_NOTIFICATION_1612267539410');
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
it('uses config.context.referenceId and description when provided', async () => {
|
|
578
|
-
renderWithFlow({
|
|
579
|
-
features: {},
|
|
580
|
-
config: { ...ccsConfig, context: { ...ccsConfig.context, referenceId: 'ORDER_PLACED', description: 'desc' } },
|
|
581
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
585
|
-
|
|
586
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalled());
|
|
587
|
-
expect(createCommDefinition).toHaveBeenCalledWith(
|
|
588
|
-
expect.objectContaining({ referenceId: 'ORDER_PLACED', description: 'desc' }),
|
|
589
|
-
);
|
|
590
|
-
});
|
|
591
|
-
|
|
592
433
|
it('skips CCS entirely when useCCS is false', async () => {
|
|
593
434
|
const onSave = jest.fn();
|
|
594
435
|
renderWithFlow({
|
|
595
436
|
features: {},
|
|
596
|
-
config: { ...
|
|
437
|
+
config: { ...baseConfig, useCCS: false, features: {} },
|
|
597
438
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
598
439
|
onSave,
|
|
599
440
|
});
|
|
@@ -601,15 +442,14 @@ describe('handleSave — CCS flow', () => {
|
|
|
601
442
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
602
443
|
|
|
603
444
|
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
604
|
-
expect(
|
|
605
|
-
expect(onSave).toHaveBeenCalledWith(expect.not.objectContaining({ ccsCommDefinition: expect.anything() }));
|
|
445
|
+
expect(createCentralCommsMetaId).not.toHaveBeenCalled();
|
|
606
446
|
});
|
|
607
447
|
|
|
608
|
-
it('
|
|
448
|
+
it('still calls onSave when createCentralCommsMetaId rejects', async () => {
|
|
449
|
+
createCentralCommsMetaId.mockRejectedValue(new Error('Network error'));
|
|
609
450
|
const onSave = jest.fn();
|
|
610
451
|
renderWithFlow({
|
|
611
452
|
features: {},
|
|
612
|
-
config: { ...baseConfig, features: {} },
|
|
613
453
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
614
454
|
onSave,
|
|
615
455
|
});
|
|
@@ -617,70 +457,12 @@ describe('handleSave — CCS flow', () => {
|
|
|
617
457
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
618
458
|
|
|
619
459
|
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
620
|
-
expect(createCommDefinition).not.toHaveBeenCalled();
|
|
621
|
-
});
|
|
622
|
-
|
|
623
|
-
it('skips createCommDefinition for multi-channel strategies (CHANNEL_PRIORITY/AB_TEST)', async () => {
|
|
624
|
-
const onSave = jest.fn();
|
|
625
|
-
renderWithFlow({
|
|
626
|
-
features: {},
|
|
627
|
-
config: ccsConfig,
|
|
628
|
-
initialData: {
|
|
629
|
-
communicationStrategy: CHANNEL_PRIORITY,
|
|
630
|
-
channels: ['SMS', 'EMAIL'],
|
|
631
|
-
contentItems: [{ channel: 'SMS', templateData: {} }, { channel: 'EMAIL', templateData: {} }],
|
|
632
|
-
},
|
|
633
|
-
onSave,
|
|
634
|
-
});
|
|
635
|
-
|
|
636
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
637
|
-
|
|
638
|
-
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
639
|
-
expect(createCommDefinition).not.toHaveBeenCalled();
|
|
640
460
|
});
|
|
641
461
|
|
|
642
|
-
it('
|
|
643
|
-
createCommDefinition.mockRejectedValue(new Error('Network error'));
|
|
462
|
+
it('skips createCentralCommsMetaId when contentItems is empty', async () => {
|
|
644
463
|
const onSave = jest.fn();
|
|
645
464
|
renderWithFlow({
|
|
646
465
|
features: {},
|
|
647
|
-
config: ccsConfig,
|
|
648
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
649
|
-
onSave,
|
|
650
|
-
});
|
|
651
|
-
|
|
652
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
653
|
-
|
|
654
|
-
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
655
|
-
expect(onSave).toHaveBeenCalledWith(expect.not.objectContaining({ ccsCommDefinition: expect.anything() }));
|
|
656
|
-
});
|
|
657
|
-
|
|
658
|
-
it('blocks save and shows an error when createCommDefinition resolves with a duplicate REFERENCE_ID_EXISTS conflict', async () => {
|
|
659
|
-
createCommDefinition.mockResolvedValue({
|
|
660
|
-
success: false,
|
|
661
|
-
status: { isError: true, code: 409, message: 'REFERENCE_ID_EXISTS' },
|
|
662
|
-
message: 'REFERENCE_ID_EXISTS',
|
|
663
|
-
});
|
|
664
|
-
const onSave = jest.fn();
|
|
665
|
-
renderWithFlow({
|
|
666
|
-
features: {},
|
|
667
|
-
config: ccsConfig,
|
|
668
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
669
|
-
onSave,
|
|
670
|
-
});
|
|
671
|
-
|
|
672
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
673
|
-
|
|
674
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
675
|
-
expect(await screen.findByText(/already in use in your organization/i)).toBeInTheDocument();
|
|
676
|
-
expect(onSave).not.toHaveBeenCalled();
|
|
677
|
-
});
|
|
678
|
-
|
|
679
|
-
it('skips createCommDefinition when contentItems is empty', async () => {
|
|
680
|
-
const onSave = jest.fn();
|
|
681
|
-
renderWithFlow({
|
|
682
|
-
features: {},
|
|
683
|
-
config: ccsConfig,
|
|
684
466
|
initialData: { contentItems: [] },
|
|
685
467
|
onSave,
|
|
686
468
|
});
|
|
@@ -688,13 +470,12 @@ describe('handleSave — CCS flow', () => {
|
|
|
688
470
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
689
471
|
|
|
690
472
|
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
691
|
-
expect(
|
|
473
|
+
expect(createCentralCommsMetaId).not.toHaveBeenCalled();
|
|
692
474
|
});
|
|
693
475
|
|
|
694
|
-
it('
|
|
476
|
+
it('includes additionalSettings derived from dynamicControls in the payload', async () => {
|
|
695
477
|
renderWithFlow({
|
|
696
478
|
features: {},
|
|
697
|
-
config: ccsConfig,
|
|
698
479
|
initialData: {
|
|
699
480
|
contentItems: [{ channel: 'SMS', templateData: {} }],
|
|
700
481
|
dynamicControls: {
|
|
@@ -708,116 +489,14 @@ describe('handleSave — CCS flow', () => {
|
|
|
708
489
|
|
|
709
490
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
710
491
|
|
|
711
|
-
await waitFor(() => expect(
|
|
712
|
-
const payload =
|
|
713
|
-
expect(payload.
|
|
492
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
493
|
+
const payload = createCentralCommsMetaId.mock.calls[0][0];
|
|
494
|
+
expect(payload.centralCommsPayload.smsDeliverySettings.additionalSettings).toEqual({
|
|
714
495
|
useTinyUrl: true,
|
|
715
496
|
encryptUrl: true,
|
|
716
497
|
linkTrackingEnabled: true,
|
|
717
498
|
userSubscriptionDisabled: true,
|
|
718
499
|
});
|
|
719
|
-
expect(payload.singleChannelStrategy.variant.smsDeliverySettings.additionalSettings).toBeUndefined();
|
|
720
|
-
});
|
|
721
|
-
|
|
722
|
-
it('includes channelSettings from deliverySetting.channelSetting in the payload', async () => {
|
|
723
|
-
renderWithFlow({
|
|
724
|
-
features: {},
|
|
725
|
-
config: ccsConfig,
|
|
726
|
-
initialData: {
|
|
727
|
-
contentItems: [{ channel: 'SMS', templateData: {} }],
|
|
728
|
-
deliverySetting: { channelSetting: { SMS: { domainId: 1001, gsmSenderId: 'BRAND1' } } },
|
|
729
|
-
},
|
|
730
|
-
});
|
|
731
|
-
|
|
732
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
733
|
-
|
|
734
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalled());
|
|
735
|
-
const payload = createCommDefinition.mock.calls[0][0];
|
|
736
|
-
expect(payload.singleChannelStrategy.variant.smsDeliverySettings.channelSettings).toEqual({
|
|
737
|
-
channel: 'SMS',
|
|
738
|
-
domainId: 1001,
|
|
739
|
-
gsmSenderId: 'BRAND1',
|
|
740
|
-
});
|
|
741
|
-
});
|
|
742
|
-
|
|
743
|
-
it('does not call editCommDefinition when config.context.existingCommDefinitionId is absent', async () => {
|
|
744
|
-
const onSave = jest.fn();
|
|
745
|
-
renderWithFlow({
|
|
746
|
-
features: {},
|
|
747
|
-
config: ccsConfig,
|
|
748
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
749
|
-
onSave,
|
|
750
|
-
});
|
|
751
|
-
|
|
752
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
753
|
-
|
|
754
|
-
await waitFor(() => expect(createCommDefinition).toHaveBeenCalledTimes(1));
|
|
755
|
-
expect(editCommDefinition).not.toHaveBeenCalled();
|
|
756
|
-
});
|
|
757
|
-
|
|
758
|
-
it('calls editCommDefinition (not createCommDefinition) and merges the existing id into ccsCommDefinition when config.context.existingCommDefinitionId is set', async () => {
|
|
759
|
-
editCommDefinition.mockResolvedValue({
|
|
760
|
-
response: { data: { version: { version: 2 }, status: 'DRAFT' } },
|
|
761
|
-
});
|
|
762
|
-
const onSave = jest.fn();
|
|
763
|
-
renderWithFlow({
|
|
764
|
-
features: {},
|
|
765
|
-
config: {
|
|
766
|
-
...ccsConfig,
|
|
767
|
-
context: { ...ccsConfig.context, referenceId: 'ORDER_PLACED', existingCommDefinitionId: 'cd_existing_1' },
|
|
768
|
-
},
|
|
769
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
770
|
-
onSave,
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
774
|
-
|
|
775
|
-
await waitFor(() => expect(editCommDefinition).toHaveBeenCalledTimes(1));
|
|
776
|
-
expect(editCommDefinition).toHaveBeenCalledWith(
|
|
777
|
-
'cd_existing_1',
|
|
778
|
-
expect.objectContaining({
|
|
779
|
-
strategyType: 'SINGLE',
|
|
780
|
-
settings: expect.anything(),
|
|
781
|
-
singleChannelStrategy: expect.anything(),
|
|
782
|
-
}),
|
|
783
|
-
);
|
|
784
|
-
expect(createCommDefinition).not.toHaveBeenCalled();
|
|
785
|
-
|
|
786
|
-
await waitFor(() => expect(onSave).toHaveBeenCalledTimes(1));
|
|
787
|
-
expect(onSave).toHaveBeenCalledWith(
|
|
788
|
-
expect.objectContaining({
|
|
789
|
-
ccsCommDefinition: {
|
|
790
|
-
id: 'cd_existing_1',
|
|
791
|
-
referenceId: 'ORDER_PLACED',
|
|
792
|
-
version: 2,
|
|
793
|
-
status: 'DRAFT',
|
|
794
|
-
},
|
|
795
|
-
}),
|
|
796
|
-
);
|
|
797
|
-
});
|
|
798
|
-
|
|
799
|
-
it('blocks save and shows an error when editCommDefinition resolves with a duplicate REFERENCE_ID_EXISTS conflict', async () => {
|
|
800
|
-
editCommDefinition.mockResolvedValue({
|
|
801
|
-
success: false,
|
|
802
|
-
status: { isError: true, code: 409, message: 'REFERENCE_ID_EXISTS' },
|
|
803
|
-
message: 'REFERENCE_ID_EXISTS',
|
|
804
|
-
});
|
|
805
|
-
const onSave = jest.fn();
|
|
806
|
-
renderWithFlow({
|
|
807
|
-
features: {},
|
|
808
|
-
config: {
|
|
809
|
-
...ccsConfig,
|
|
810
|
-
context: { ...ccsConfig.context, referenceId: 'ORDER_PLACED', existingCommDefinitionId: 'cd_existing_1' },
|
|
811
|
-
},
|
|
812
|
-
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
813
|
-
onSave,
|
|
814
|
-
});
|
|
815
|
-
|
|
816
|
-
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
817
|
-
|
|
818
|
-
await waitFor(() => expect(editCommDefinition).toHaveBeenCalledTimes(1));
|
|
819
|
-
expect(await screen.findByText(/already in use in your organization/i)).toBeInTheDocument();
|
|
820
|
-
expect(onSave).not.toHaveBeenCalled();
|
|
821
500
|
});
|
|
822
501
|
});
|
|
823
502
|
|
|
@@ -873,34 +552,39 @@ describe('optional chaining safety', () => {
|
|
|
873
552
|
jest.clearAllMocks();
|
|
874
553
|
});
|
|
875
554
|
|
|
876
|
-
it('
|
|
877
|
-
|
|
555
|
+
it('defaults ouId to -1 when config.context is absent', async () => {
|
|
556
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: { id: 'x' } } });
|
|
878
557
|
renderWithFlow({
|
|
879
558
|
features: {},
|
|
880
|
-
config: { ...baseConfig, features: {} },
|
|
881
559
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
882
|
-
onSave,
|
|
883
560
|
});
|
|
884
561
|
|
|
885
562
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
886
563
|
|
|
887
|
-
await waitFor(() => expect(
|
|
888
|
-
expect(
|
|
564
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
565
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
566
|
+
expect.objectContaining({
|
|
567
|
+
centralCommsPayload: expect.objectContaining({ ouId: -1 }),
|
|
568
|
+
}),
|
|
569
|
+
);
|
|
889
570
|
});
|
|
890
571
|
|
|
891
|
-
it('
|
|
892
|
-
|
|
572
|
+
it('defaults module to consumer.toUpperCase() when config.context.module absent', async () => {
|
|
573
|
+
createCentralCommsMetaId.mockResolvedValue({ response: { data: { id: 'x' } } });
|
|
893
574
|
renderWithFlow({
|
|
894
575
|
features: {},
|
|
895
|
-
config: { ...baseConfig,
|
|
576
|
+
config: { ...baseConfig, consumer: 'loyalty', features: {} },
|
|
896
577
|
initialData: { contentItems: [{ channel: 'SMS', templateData: {} }] },
|
|
897
|
-
onSave,
|
|
898
578
|
});
|
|
899
579
|
|
|
900
580
|
await userEvent.click(screen.getByRole('button', { name: /^save$/i }));
|
|
901
581
|
|
|
902
|
-
await waitFor(() => expect(
|
|
903
|
-
expect(
|
|
582
|
+
await waitFor(() => expect(createCentralCommsMetaId).toHaveBeenCalled());
|
|
583
|
+
expect(createCentralCommsMetaId).toHaveBeenCalledWith(
|
|
584
|
+
expect.objectContaining({
|
|
585
|
+
centralCommsPayload: expect.objectContaining({ module: 'LOYALTY' }),
|
|
586
|
+
}),
|
|
587
|
+
);
|
|
904
588
|
});
|
|
905
589
|
|
|
906
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();
|