@capillarytech/creatives-library 8.0.236 → 8.0.237
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/config/app.js +1 -1
- package/package.json +1 -1
- package/v2Containers/Rcs/index.js +5 -3
- package/v2Containers/Rcs/sagas.js +4 -4
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +0 -16
- package/v2Containers/Rcs/tests/index.test.js +139 -2
- package/v2Containers/Rcs/tests/mockData.js +6 -3
- package/v2Containers/Rcs/tests/saga.test.js +88 -0
- package/v2Containers/Templates/actions.js +2 -6
- package/v2Containers/Templates/constants.js +1 -0
- package/v2Containers/Templates/index.js +66 -34
- package/v2Containers/Templates/messages.js +8 -0
- package/v2Containers/Templates/reducer.js +3 -3
- package/v2Containers/Templates/sagas.js +1 -1
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +8 -8
- package/v2Containers/Templates/tests/actions.test.js +36 -1
- package/v2Containers/Templates/tests/reducer.test.js +9 -2
- package/v2Containers/Templates/tests/sagas.test.js +262 -9
package/config/app.js
CHANGED
|
@@ -20,7 +20,7 @@ const config = {
|
|
|
20
20
|
accountConfig: (strs, accountId) => `${window.location.origin}/org/config/AccountAdd?q=a&channelId=2&accountId=${accountId}&edit=1`,
|
|
21
21
|
},
|
|
22
22
|
development: {
|
|
23
|
-
api_endpoint: '
|
|
23
|
+
api_endpoint: 'http://localhost:2022/arya/api/v1/creatives',
|
|
24
24
|
campaigns_api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/campaigns',
|
|
25
25
|
campaigns_api_org_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/org/campaign',
|
|
26
26
|
auth_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/auth',
|
package/package.json
CHANGED
|
@@ -201,6 +201,8 @@ export const Rcs = (props) => {
|
|
|
201
201
|
|
|
202
202
|
const [accountId, setAccountId] = useState('');
|
|
203
203
|
const [accessToken, setAccessToken] = useState('');
|
|
204
|
+
const [hostName, setHostName] = useState('');
|
|
205
|
+
const [accountName, setAccountName] = useState('');
|
|
204
206
|
useEffect(() => {
|
|
205
207
|
const accountObj = accountData.selectedRcsAccount || {};
|
|
206
208
|
if (!isEmpty(accountObj)) {
|
|
@@ -211,6 +213,8 @@ export const Rcs = (props) => {
|
|
|
211
213
|
|
|
212
214
|
setAccountId(sourceAccountIdentifier);
|
|
213
215
|
setAccessToken(configs.accessToken || '');
|
|
216
|
+
setHostName(accountObj.hostName || '');
|
|
217
|
+
setAccountName(accountObj.name || '');
|
|
214
218
|
}
|
|
215
219
|
}, [accountData.selectedRcsAccount]);
|
|
216
220
|
|
|
@@ -579,7 +583,6 @@ export const Rcs = (props) => {
|
|
|
579
583
|
|
|
580
584
|
useEffect(() => {
|
|
581
585
|
const details = isFullMode ? rcsData?.templateDetails : templateData;
|
|
582
|
-
|
|
583
586
|
if (details && Object.keys(details).length > 0) {
|
|
584
587
|
if (!isFullMode) {
|
|
585
588
|
const tempCardVarMapped = get(details, 'versions.base.content.RCS.rcsContent.cardContent[0].cardVarMapped', {});
|
|
@@ -2112,8 +2115,7 @@ const splitTemplateVarString = (str) => {
|
|
|
2112
2115
|
}
|
|
2113
2116
|
],
|
|
2114
2117
|
contentType: isFullMode ? templateType : RICHCARD,
|
|
2115
|
-
...(isFullMode && {
|
|
2116
|
-
...(isFullMode && {user: accountId, pass: accessToken}),
|
|
2118
|
+
...(isFullMode && {accountId:accountId, accessToken: accessToken, accountName: accountName, hostName: hostName}),
|
|
2117
2119
|
},
|
|
2118
2120
|
smsFallBackContent: {
|
|
2119
2121
|
message: fallbackMessage,
|
|
@@ -57,7 +57,7 @@ export function* createRCSTemplate({ template, callback }) {
|
|
|
57
57
|
template,
|
|
58
58
|
});
|
|
59
59
|
if (result.status.code >= 400) {
|
|
60
|
-
errorMsg = result.message
|
|
60
|
+
errorMsg = result.message || result.status.message || `Error: ${result.status.code}`;
|
|
61
61
|
throw errorMsg;
|
|
62
62
|
}
|
|
63
63
|
yield put({
|
|
@@ -72,7 +72,7 @@ export function* createRCSTemplate({ template, callback }) {
|
|
|
72
72
|
} catch (error) {
|
|
73
73
|
yield put({ type: CREATE_RCS_TEMPLATE_FAILURE, error, errorMsg });
|
|
74
74
|
if (callback) {
|
|
75
|
-
callback(null, errorMsg);
|
|
75
|
+
callback(null, errorMsg || error);
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -91,7 +91,7 @@ export function* editTemplate({ template, callback }) {
|
|
|
91
91
|
template,
|
|
92
92
|
});
|
|
93
93
|
if (result.status.code >= 400) {
|
|
94
|
-
errorMsg = result.message
|
|
94
|
+
errorMsg = result.message || result.status.message || `Error: ${result.status.code}`;
|
|
95
95
|
throw errorMsg;
|
|
96
96
|
}
|
|
97
97
|
yield put({
|
|
@@ -106,7 +106,7 @@ export function* editTemplate({ template, callback }) {
|
|
|
106
106
|
} catch (error) {
|
|
107
107
|
yield put({ type: EDIT_RCS_TEMPLATE_FAILURE, error, errorMsg });
|
|
108
108
|
if (callback) {
|
|
109
|
-
callback(null, errorMsg);
|
|
109
|
+
callback(null, errorMsg || error);
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
}
|
|
@@ -2750,7 +2750,6 @@ new message content.",
|
|
|
2750
2750
|
},
|
|
2751
2751
|
"cardType": "STANDALONE",
|
|
2752
2752
|
"contentType": "text_message",
|
|
2753
|
-
"isHostIcs": true,
|
|
2754
2753
|
"smsFallBackContent": Object {
|
|
2755
2754
|
"message": "Fallback SMS for text",
|
|
2756
2755
|
},
|
|
@@ -14575,7 +14574,6 @@ new message content.",
|
|
|
14575
14574
|
},
|
|
14576
14575
|
"cardType": "STANDALONE",
|
|
14577
14576
|
"contentType": "text_message",
|
|
14578
|
-
"isHostIcs": true,
|
|
14579
14577
|
"smsFallBackContent": Object {
|
|
14580
14578
|
"message": "Fallback SMS for text",
|
|
14581
14579
|
},
|
|
@@ -26554,7 +26552,6 @@ new message content.",
|
|
|
26554
26552
|
},
|
|
26555
26553
|
"cardType": "STANDALONE",
|
|
26556
26554
|
"contentType": "text_message",
|
|
26557
|
-
"isHostIcs": true,
|
|
26558
26555
|
"smsFallBackContent": Object {
|
|
26559
26556
|
"message": "Fallback SMS for text",
|
|
26560
26557
|
},
|
|
@@ -38697,7 +38694,6 @@ new message content.",
|
|
|
38697
38694
|
},
|
|
38698
38695
|
"cardType": "STANDALONE",
|
|
38699
38696
|
"contentType": "text_message",
|
|
38700
|
-
"isHostIcs": true,
|
|
38701
38697
|
"smsFallBackContent": Object {
|
|
38702
38698
|
"message": "Fallback SMS for text",
|
|
38703
38699
|
},
|
|
@@ -50518,7 +50514,6 @@ new message content.",
|
|
|
50518
50514
|
},
|
|
50519
50515
|
"cardType": "STANDALONE",
|
|
50520
50516
|
"contentType": "text_message",
|
|
50521
|
-
"isHostIcs": true,
|
|
50522
50517
|
"smsFallBackContent": Object {
|
|
50523
50518
|
"message": "Fallback SMS for text",
|
|
50524
50519
|
},
|
|
@@ -63089,7 +63084,6 @@ new message content.",
|
|
|
63089
63084
|
},
|
|
63090
63085
|
"cardType": "STANDALONE",
|
|
63091
63086
|
"contentType": "text_message",
|
|
63092
|
-
"isHostIcs": true,
|
|
63093
63087
|
"smsFallBackContent": Object {
|
|
63094
63088
|
"message": "Fallback SMS for text",
|
|
63095
63089
|
},
|
|
@@ -64611,7 +64605,6 @@ new message content.",
|
|
|
64611
64605
|
},
|
|
64612
64606
|
"cardType": "STANDALONE",
|
|
64613
64607
|
"contentType": "text_message",
|
|
64614
|
-
"isHostIcs": true,
|
|
64615
64608
|
"smsFallBackContent": Object {
|
|
64616
64609
|
"message": "Fallback SMS for text",
|
|
64617
64610
|
},
|
|
@@ -64669,7 +64662,6 @@ new message content.",
|
|
|
64669
64662
|
},
|
|
64670
64663
|
"cardType": "STANDALONE",
|
|
64671
64664
|
"contentType": "text_message",
|
|
64672
|
-
"isHostIcs": true,
|
|
64673
64665
|
"smsFallBackContent": Object {
|
|
64674
64666
|
"message": "Fallback SMS for text",
|
|
64675
64667
|
},
|
|
@@ -76581,7 +76573,6 @@ new message content.",
|
|
|
76581
76573
|
},
|
|
76582
76574
|
"cardType": "STANDALONE",
|
|
76583
76575
|
"contentType": "text_message",
|
|
76584
|
-
"isHostIcs": true,
|
|
76585
76576
|
"smsFallBackContent": Object {
|
|
76586
76577
|
"message": "Fallback SMS for text",
|
|
76587
76578
|
},
|
|
@@ -78103,7 +78094,6 @@ new message content.",
|
|
|
78103
78094
|
},
|
|
78104
78095
|
"cardType": "STANDALONE",
|
|
78105
78096
|
"contentType": "text_message",
|
|
78106
|
-
"isHostIcs": true,
|
|
78107
78097
|
"smsFallBackContent": Object {
|
|
78108
78098
|
"message": "Fallback SMS for text",
|
|
78109
78099
|
},
|
|
@@ -78161,7 +78151,6 @@ new message content.",
|
|
|
78161
78151
|
},
|
|
78162
78152
|
"cardType": "STANDALONE",
|
|
78163
78153
|
"contentType": "text_message",
|
|
78164
|
-
"isHostIcs": true,
|
|
78165
78154
|
"smsFallBackContent": Object {
|
|
78166
78155
|
"message": "Fallback SMS for text",
|
|
78167
78156
|
},
|
|
@@ -90563,7 +90552,6 @@ new message content.",
|
|
|
90563
90552
|
},
|
|
90564
90553
|
"cardType": "STANDALONE",
|
|
90565
90554
|
"contentType": "text_message",
|
|
90566
|
-
"isHostIcs": true,
|
|
90567
90555
|
"smsFallBackContent": Object {
|
|
90568
90556
|
"message": "Fallback SMS for text",
|
|
90569
90557
|
},
|
|
@@ -102388,7 +102376,6 @@ new message content.",
|
|
|
102388
102376
|
},
|
|
102389
102377
|
"cardType": "STANDALONE",
|
|
102390
102378
|
"contentType": "text_message",
|
|
102391
|
-
"isHostIcs": true,
|
|
102392
102379
|
"smsFallBackContent": Object {
|
|
102393
102380
|
"message": "Fallback SMS for text",
|
|
102394
102381
|
},
|
|
@@ -114213,7 +114200,6 @@ new message content.",
|
|
|
114213
114200
|
},
|
|
114214
114201
|
"cardType": "STANDALONE",
|
|
114215
114202
|
"contentType": "text_message",
|
|
114216
|
-
"isHostIcs": true,
|
|
114217
114203
|
"smsFallBackContent": Object {
|
|
114218
114204
|
"message": "Fallback SMS for text",
|
|
114219
114205
|
},
|
|
@@ -126038,7 +126024,6 @@ new message content.",
|
|
|
126038
126024
|
},
|
|
126039
126025
|
"cardType": "STANDALONE",
|
|
126040
126026
|
"contentType": "text_message",
|
|
126041
|
-
"isHostIcs": true,
|
|
126042
126027
|
"smsFallBackContent": Object {
|
|
126043
126028
|
"message": "Fallback SMS for text",
|
|
126044
126029
|
},
|
|
@@ -138526,7 +138511,6 @@ new message content.",
|
|
|
138526
138511
|
},
|
|
138527
138512
|
"cardType": "STANDALONE",
|
|
138528
138513
|
"contentType": "rich_card",
|
|
138529
|
-
"isHostIcs": true,
|
|
138530
138514
|
"smsFallBackContent": Object {
|
|
138531
138515
|
"message": "Fallback SMS for image",
|
|
138532
138516
|
},
|
|
@@ -578,7 +578,12 @@ describe('RCS createPayload', () => {
|
|
|
578
578
|
expect(doneBtn.exists()).toBe(true);
|
|
579
579
|
await act(async () => {
|
|
580
580
|
const onClick = doneBtn.prop('onClick');
|
|
581
|
-
if (typeof onClick === 'function')
|
|
581
|
+
if (typeof onClick === 'function') {
|
|
582
|
+
const result = onClick();
|
|
583
|
+
if (typeof result === 'function') {
|
|
584
|
+
await result();
|
|
585
|
+
}
|
|
586
|
+
}
|
|
582
587
|
await Promise.resolve();
|
|
583
588
|
});
|
|
584
589
|
|
|
@@ -594,7 +599,10 @@ describe('RCS createPayload', () => {
|
|
|
594
599
|
expect(payloadArg.name).toBe('PromoCard');
|
|
595
600
|
expect(payloadArg.type).toBe('RCS');
|
|
596
601
|
expect(payloadArg.versions.base.content.RCS.rcsContent.contentType).toBe('rich_card');
|
|
597
|
-
expect(payloadArg.versions.base.content.RCS.rcsContent.
|
|
602
|
+
expect(payloadArg.versions.base.content.RCS.rcsContent.accountId).toBe('rcs-account-123');
|
|
603
|
+
expect(payloadArg.versions.base.content.RCS.rcsContent.accessToken).toBe('secret-token');
|
|
604
|
+
expect(payloadArg.versions.base.content.RCS.rcsContent.hostName).toBe('rcs.host.example.com');
|
|
605
|
+
expect(payloadArg.versions.base.content.RCS.rcsContent.accountName).toBe('Brand RCS Account');
|
|
598
606
|
expect(payloadArg.versions.base.content.RCS.rcsContent.cardSettings).toEqual(
|
|
599
607
|
expect.objectContaining({ cardOrientation: 'HORIZONTAL', mediaAlignment: 'LEFT', cardWidth: 'SMALL' }),
|
|
600
608
|
);
|
|
@@ -605,6 +613,135 @@ describe('RCS createPayload', () => {
|
|
|
605
613
|
);
|
|
606
614
|
});
|
|
607
615
|
|
|
616
|
+
it('should include empty account metadata when no account is selected', async () => {
|
|
617
|
+
const createRcsTemplate = jest.fn();
|
|
618
|
+
const getTemplateDetails = jest.fn();
|
|
619
|
+
const getFormData = jest.fn();
|
|
620
|
+
const { createPayloadFullMode } = mockData;
|
|
621
|
+
|
|
622
|
+
const wrapper = mountWithIntl(
|
|
623
|
+
<Provider store={store}>
|
|
624
|
+
<Rcs
|
|
625
|
+
actions={{
|
|
626
|
+
createRcsTemplate,
|
|
627
|
+
clearCreateResponse: jest.fn(),
|
|
628
|
+
getTemplateDetails,
|
|
629
|
+
uploadRcsAsset: jest.fn(),
|
|
630
|
+
clearRcsMediaAsset: jest.fn(),
|
|
631
|
+
editTemplate: jest.fn(),
|
|
632
|
+
clearEditResponse: jest.fn(),
|
|
633
|
+
}}
|
|
634
|
+
globalActions={{ fetchSchemaForEntity }}
|
|
635
|
+
onCreateComplete={onCreateComplete}
|
|
636
|
+
handleClose={handleClose}
|
|
637
|
+
intl={{ formatMessage }}
|
|
638
|
+
location={{ pathname: '/rcs/create', query: { type: false, module: 'default' }, search: '' }}
|
|
639
|
+
params={params}
|
|
640
|
+
rcsData={createPayloadFullMode}
|
|
641
|
+
accountData={{}}
|
|
642
|
+
isFullMode
|
|
643
|
+
isEditFlow={false}
|
|
644
|
+
loadingTags={false}
|
|
645
|
+
metaEntities={[]}
|
|
646
|
+
isDltEnabled={false}
|
|
647
|
+
smsRegister={'DLT'}
|
|
648
|
+
getFormData={getFormData}
|
|
649
|
+
/>
|
|
650
|
+
</Provider>,
|
|
651
|
+
);
|
|
652
|
+
|
|
653
|
+
await act(async () => {
|
|
654
|
+
await Promise.resolve();
|
|
655
|
+
});
|
|
656
|
+
wrapper.update();
|
|
657
|
+
|
|
658
|
+
const doneBtn = wrapper.find('CapButton.rcs-done-btn').at(0);
|
|
659
|
+
expect(doneBtn.exists()).toBe(true);
|
|
660
|
+
await act(async () => {
|
|
661
|
+
const onClick = doneBtn.prop('onClick');
|
|
662
|
+
if (typeof onClick === 'function') {
|
|
663
|
+
onClick();
|
|
664
|
+
}
|
|
665
|
+
await Promise.resolve();
|
|
666
|
+
});
|
|
667
|
+
wrapper.update();
|
|
668
|
+
|
|
669
|
+
const payloadArg =
|
|
670
|
+
createRcsTemplate.mock.calls[0]?.[0] ||
|
|
671
|
+
getFormData.mock.calls[0]?.[0]?.value;
|
|
672
|
+
expect(payloadArg).toBeDefined();
|
|
673
|
+
const rcsContent = payloadArg.versions.base.content.RCS.rcsContent;
|
|
674
|
+
expect(rcsContent.accountId).toBe('');
|
|
675
|
+
expect(rcsContent.accessToken).toBe('');
|
|
676
|
+
expect(rcsContent.hostName).toBe('');
|
|
677
|
+
expect(rcsContent.accountName).toBe('');
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
it('should attach DLT template configs when enabled', async () => {
|
|
681
|
+
const createRcsTemplate = jest.fn();
|
|
682
|
+
const getFormData = jest.fn();
|
|
683
|
+
const { createPayloadFullMode } = mockData;
|
|
684
|
+
|
|
685
|
+
const wrapper = mountWithIntl(
|
|
686
|
+
<Provider store={store}>
|
|
687
|
+
<Rcs
|
|
688
|
+
actions={{
|
|
689
|
+
createRcsTemplate,
|
|
690
|
+
clearCreateResponse: jest.fn(),
|
|
691
|
+
getTemplateDetails: jest.fn(),
|
|
692
|
+
uploadRcsAsset: jest.fn(),
|
|
693
|
+
clearRcsMediaAsset: jest.fn(),
|
|
694
|
+
editTemplate: jest.fn(),
|
|
695
|
+
clearEditResponse: jest.fn(),
|
|
696
|
+
}}
|
|
697
|
+
globalActions={{ fetchSchemaForEntity }}
|
|
698
|
+
onCreateComplete={onCreateComplete}
|
|
699
|
+
handleClose={handleClose}
|
|
700
|
+
intl={{ formatMessage }}
|
|
701
|
+
location={{ pathname: '/rcs/create', query: { type: false, module: 'default' }, search: '' }}
|
|
702
|
+
params={params}
|
|
703
|
+
rcsData={createPayloadFullMode}
|
|
704
|
+
accountData={createPayloadFullMode.accountData}
|
|
705
|
+
isFullMode
|
|
706
|
+
isEditFlow={false}
|
|
707
|
+
loadingTags={false}
|
|
708
|
+
metaEntities={[]}
|
|
709
|
+
isDltEnabled
|
|
710
|
+
smsRegister={'DLT'}
|
|
711
|
+
getFormData={getFormData}
|
|
712
|
+
/>
|
|
713
|
+
</Provider>,
|
|
714
|
+
);
|
|
715
|
+
|
|
716
|
+
await act(async () => Promise.resolve());
|
|
717
|
+
wrapper.update();
|
|
718
|
+
|
|
719
|
+
const doneBtn = wrapper.find('CapButton.rcs-done-btn').at(0);
|
|
720
|
+
await act(async () => {
|
|
721
|
+
const onClick = doneBtn.prop('onClick');
|
|
722
|
+
if (typeof onClick === 'function') {
|
|
723
|
+
onClick();
|
|
724
|
+
}
|
|
725
|
+
await Promise.resolve();
|
|
726
|
+
});
|
|
727
|
+
wrapper.update();
|
|
728
|
+
|
|
729
|
+
const payloadArg =
|
|
730
|
+
createRcsTemplate.mock.calls[0]?.[0] ||
|
|
731
|
+
getFormData.mock.calls[0]?.[0]?.value;
|
|
732
|
+
expect(payloadArg).toBeDefined();
|
|
733
|
+
expect(payloadArg.versions.base.content.RCS.smsFallBackContent).toEqual(
|
|
734
|
+
expect.objectContaining({
|
|
735
|
+
templateConfigs: expect.objectContaining({
|
|
736
|
+
templateId: '',
|
|
737
|
+
templateName: '',
|
|
738
|
+
template: '',
|
|
739
|
+
registeredSenderIds: [],
|
|
740
|
+
}),
|
|
741
|
+
}),
|
|
742
|
+
);
|
|
743
|
+
});
|
|
744
|
+
|
|
608
745
|
it('should build expected payload in non-full mode (VIDEO, vertical medium)', () => {
|
|
609
746
|
const getFormData = jest.fn();
|
|
610
747
|
const { createPayloadNonFullMode } = mockData;
|
|
@@ -24,7 +24,6 @@ export const mockData = {
|
|
|
24
24
|
},
|
|
25
25
|
cardType: "STANDALONE",
|
|
26
26
|
contentType: "text_message",
|
|
27
|
-
isHostIcs: true,
|
|
28
27
|
smsFallBackContent: {
|
|
29
28
|
message: "Fallback SMS for text",
|
|
30
29
|
},
|
|
@@ -71,7 +70,6 @@ export const mockData = {
|
|
|
71
70
|
},
|
|
72
71
|
cardType: "STANDALONE",
|
|
73
72
|
contentType: "rich_card",
|
|
74
|
-
isHostIcs: true,
|
|
75
73
|
smsFallBackContent: {
|
|
76
74
|
message: "Fallback SMS for image",
|
|
77
75
|
},
|
|
@@ -106,7 +104,6 @@ export const mockData = {
|
|
|
106
104
|
},
|
|
107
105
|
cardType: "STANDALONE",
|
|
108
106
|
contentType: "rich_card",
|
|
109
|
-
isHostIcs: true,
|
|
110
107
|
smsFallBackContent: {
|
|
111
108
|
message: "Fallback SMS for video",
|
|
112
109
|
},
|
|
@@ -122,6 +119,10 @@ export const mockData = {
|
|
|
122
119
|
name: 'PromoCard',
|
|
123
120
|
versions: {
|
|
124
121
|
base: {
|
|
122
|
+
template_id: 'TPL-001',
|
|
123
|
+
template_name: 'PromoTPL',
|
|
124
|
+
'sms-editor': '<p>SMS body</p>',
|
|
125
|
+
header: ['SENDER1'],
|
|
125
126
|
content: {
|
|
126
127
|
RCS: {
|
|
127
128
|
rcsContent: {
|
|
@@ -149,6 +150,8 @@ export const mockData = {
|
|
|
149
150
|
selectedRcsAccount: {
|
|
150
151
|
sourceAccountIdentifier: 'rcs-account-123',
|
|
151
152
|
configs: { accessToken: 'secret-token' },
|
|
153
|
+
hostName: 'rcs.host.example.com',
|
|
154
|
+
name: 'Brand RCS Account',
|
|
152
155
|
},
|
|
153
156
|
},
|
|
154
157
|
},
|
|
@@ -167,6 +167,50 @@ describe("rcs Sagas", () => {
|
|
|
167
167
|
.run();
|
|
168
168
|
});
|
|
169
169
|
|
|
170
|
+
it("handles failure picking status.message when message is absent", () => {
|
|
171
|
+
const template = {};
|
|
172
|
+
const apiResult = { status: { code: 500, message: "Nested Msg" } };
|
|
173
|
+
return expectSaga(createRCSTemplate, { template })
|
|
174
|
+
.provide([[matchers.call.fn(Api.createRcsTemplate), apiResult]])
|
|
175
|
+
.put({ type: CREATE_RCS_TEMPLATE_FAILURE, error: "Nested Msg", errorMsg: "Nested Msg" })
|
|
176
|
+
.run();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("handles failure picking result.status.code when others are absent", () => {
|
|
180
|
+
const template = {};
|
|
181
|
+
const apiResult = { status: { code: 500 } };
|
|
182
|
+
return expectSaga(createRCSTemplate, { template })
|
|
183
|
+
.provide([[matchers.call.fn(Api.createRcsTemplate), apiResult]])
|
|
184
|
+
.put({ type: CREATE_RCS_TEMPLATE_FAILURE, error: "Error: 500", errorMsg: "Error: 500" })
|
|
185
|
+
.run();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("handles callback with errorMsg", () => {
|
|
189
|
+
const template = {};
|
|
190
|
+
const callback = jest.fn();
|
|
191
|
+
const apiResult = { status: { code: 500, message: "Nested Msg" } };
|
|
192
|
+
return expectSaga(createRCSTemplate, { template, callback })
|
|
193
|
+
.provide([[matchers.call.fn(Api.createRcsTemplate), apiResult]])
|
|
194
|
+
.put({ type: CREATE_RCS_TEMPLATE_FAILURE, error: "Nested Msg", errorMsg: "Nested Msg" })
|
|
195
|
+
.run()
|
|
196
|
+
.then(() => {
|
|
197
|
+
expect(callback).toHaveBeenCalledWith(null, "Nested Msg");
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("handles callback with error object when errorMsg is undefined", () => {
|
|
202
|
+
const template = {};
|
|
203
|
+
const callback = jest.fn();
|
|
204
|
+
const apiError = new Error("Network Error");
|
|
205
|
+
return expectSaga(createRCSTemplate, { template, callback })
|
|
206
|
+
.provide([[matchers.call.fn(Api.createRcsTemplate), Promise.reject(apiError)]])
|
|
207
|
+
.put({ type: CREATE_RCS_TEMPLATE_FAILURE, error: apiError, errorMsg: undefined })
|
|
208
|
+
.run()
|
|
209
|
+
.then(() => {
|
|
210
|
+
expect(callback).toHaveBeenCalledWith(null, apiError);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
170
214
|
it("handles status code exactly 400 (boundary condition)", () => {
|
|
171
215
|
const template = {};
|
|
172
216
|
const callback = jest.fn();
|
|
@@ -226,6 +270,50 @@ describe("rcs Sagas", () => {
|
|
|
226
270
|
.run();
|
|
227
271
|
});
|
|
228
272
|
|
|
273
|
+
it("handles failure picking status.message when message is absent", () => {
|
|
274
|
+
const template = {};
|
|
275
|
+
const apiResult = { status: { code: 500, message: "Nested Msg" } };
|
|
276
|
+
return expectSaga(editTemplate, { template })
|
|
277
|
+
.provide([[matchers.call.fn(Api.createRcsTemplate), apiResult]])
|
|
278
|
+
.put({ type: EDIT_RCS_TEMPLATE_FAILURE, error: "Nested Msg", errorMsg: "Nested Msg" })
|
|
279
|
+
.run();
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("handles failure picking result.status.code when others are absent", () => {
|
|
283
|
+
const template = {};
|
|
284
|
+
const apiResult = { status: { code: 500 } };
|
|
285
|
+
return expectSaga(editTemplate, { template })
|
|
286
|
+
.provide([[matchers.call.fn(Api.createRcsTemplate), apiResult]])
|
|
287
|
+
.put({ type: EDIT_RCS_TEMPLATE_FAILURE, error: "Error: 500", errorMsg: "Error: 500" })
|
|
288
|
+
.run();
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it("handles callback with errorMsg", () => {
|
|
292
|
+
const template = {};
|
|
293
|
+
const callback = jest.fn();
|
|
294
|
+
const apiResult = { status: { code: 500, message: "Nested Msg" } };
|
|
295
|
+
return expectSaga(editTemplate, { template, callback })
|
|
296
|
+
.provide([[matchers.call.fn(Api.createRcsTemplate), apiResult]])
|
|
297
|
+
.put({ type: EDIT_RCS_TEMPLATE_FAILURE, error: "Nested Msg", errorMsg: "Nested Msg" })
|
|
298
|
+
.run()
|
|
299
|
+
.then(() => {
|
|
300
|
+
expect(callback).toHaveBeenCalledWith(null, "Nested Msg");
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it("handles callback with error object when errorMsg is undefined", () => {
|
|
305
|
+
const template = {};
|
|
306
|
+
const callback = jest.fn();
|
|
307
|
+
const apiError = new Error("Network Error");
|
|
308
|
+
return expectSaga(editTemplate, { template, callback })
|
|
309
|
+
.provide([[matchers.call.fn(Api.createRcsTemplate), Promise.reject(apiError)]])
|
|
310
|
+
.put({ type: EDIT_RCS_TEMPLATE_FAILURE, error: apiError, errorMsg: undefined })
|
|
311
|
+
.run()
|
|
312
|
+
.then(() => {
|
|
313
|
+
expect(callback).toHaveBeenCalledWith(null, apiError);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
229
317
|
it("handles status code exactly 400 (boundary condition)", () => {
|
|
230
318
|
const template = {};
|
|
231
319
|
const callback = jest.fn();
|
|
@@ -68,7 +68,9 @@ export function setChannelAccount(channel, account) {
|
|
|
68
68
|
[LINE]: types.SET_LINE_ACCOUNT,
|
|
69
69
|
[WHATSAPP]: types.SET_WHATSAPP_ACCOUNT,
|
|
70
70
|
[ZALO]: types.SET_ZALO_ACCOUNT,
|
|
71
|
+
[RCS]: types.SET_RCS_ACCOUNT,
|
|
71
72
|
};
|
|
73
|
+
|
|
72
74
|
if (channelTypeMapping[channel]) {
|
|
73
75
|
return {
|
|
74
76
|
type: channelTypeMapping[channel],
|
|
@@ -84,12 +86,6 @@ export function setViberAccount(viberAccount) {
|
|
|
84
86
|
viberAccount,
|
|
85
87
|
};
|
|
86
88
|
}
|
|
87
|
-
export function setRcsAccount(rcsAccount) {
|
|
88
|
-
return {
|
|
89
|
-
type: types.SET_RCS_ACCOUNT,
|
|
90
|
-
rcsAccount,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
89
|
|
|
94
90
|
export function setFacebookAccount(faceBookAccount) {
|
|
95
91
|
return {
|
|
@@ -80,6 +80,7 @@ export const GET_CDN_TRANSFORMATION_CONFIG_FAILURE = 'app/v2Containers/Templates
|
|
|
80
80
|
export const ACCOUNT_MAPPING_ON_CHANNEL = {
|
|
81
81
|
whatsapp: 'selectedWhatsappAccount',
|
|
82
82
|
zalo: 'selectedZaloAccount',
|
|
83
|
+
rcs: 'selectedRcsAccount',
|
|
83
84
|
};
|
|
84
85
|
|
|
85
86
|
export const noFilteredWhatsappZaloTemplatesTitle= 'noFilteredWhatsappZaloTemplatesTitle';
|
|
@@ -292,7 +292,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
292
292
|
return '';
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
|
|
295
|
+
let domainHostName = domainPropertiesData?.find(({ domainProperties }) => {
|
|
296
296
|
const {
|
|
297
297
|
connectionProperties: { account_sid, wabaId, userid, sourceAccountIdentifier, oa_id } = {},
|
|
298
298
|
} = domainProperties || {};
|
|
@@ -301,6 +301,11 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
301
301
|
return [account_sid, wabaId, userid, oa_id, sourceAccountIdentifier].includes(selectedSourceAccountIdentifier);
|
|
302
302
|
})?.domainProperties?.hostName || '';
|
|
303
303
|
|
|
304
|
+
// Fallback for RCS: If no match found (empty connectionProperties) and there's exactly one domain property, use that hostName
|
|
305
|
+
if (!domainHostName && domainPropertiesData.length === 1) {
|
|
306
|
+
domainHostName = domainPropertiesData[0]?.domainProperties?.hostName || '';
|
|
307
|
+
}
|
|
308
|
+
|
|
304
309
|
this.setState({ hostName: domainHostName });
|
|
305
310
|
return domainHostName;
|
|
306
311
|
}
|
|
@@ -410,7 +415,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
410
415
|
if (this.props.location.query.type === 'embedded') {
|
|
411
416
|
this.props.actions.resetAccount();
|
|
412
417
|
}
|
|
413
|
-
if (['line', VIBER_CHANNEL, FACEBOOK_CHANNEL, 'sms', 'email', 'ebill'
|
|
418
|
+
if (['line', VIBER_CHANNEL, FACEBOOK_CHANNEL, 'sms', 'email', 'ebill'].includes((this.state.channel || '').toLowerCase())) {
|
|
414
419
|
const queryParams = {
|
|
415
420
|
// name: this.state.searchText,
|
|
416
421
|
// sortBy: this.state.sortBy,
|
|
@@ -483,7 +488,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
483
488
|
}
|
|
484
489
|
|
|
485
490
|
this.setState({ channel }, () => {
|
|
486
|
-
if (['line', VIBER_CHANNEL, FACEBOOK_CHANNEL, 'sms', 'email', 'ebill'
|
|
491
|
+
if (['line', VIBER_CHANNEL, FACEBOOK_CHANNEL, 'sms', 'email', 'ebill'].includes(this.state.channel.toLowerCase()) || (this.state.channel.toLowerCase() === 'wechat' && !isEmpty(nextProps.Templates.selectedWeChatAccount))) {
|
|
487
492
|
if (this.state.channel.toLowerCase() === 'wechat' && !isEmpty(nextProps.Templates.selectedWeChatAccount)) {
|
|
488
493
|
params.wecrmId = (nextProps.Templates.selectedWeChatAccount.configs || {}).wecrm_app_id;
|
|
489
494
|
params.wecrmToken = (nextProps.Templates.selectedWeChatAccount.configs || {}).wecrm_token;
|
|
@@ -521,22 +526,6 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
521
526
|
this.getAllTemplates({params});
|
|
522
527
|
});
|
|
523
528
|
}
|
|
524
|
-
if (selectedChannel === RCS_LOWERCASE && isEmpty(nextProps.Templates.selectedRcsAccount)) {
|
|
525
|
-
let selectedAccount = '';
|
|
526
|
-
if (isEmpty(nextProps.Templates.weCrmAccounts)) {
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
|
-
selectedAccount = nextProps.Templates.weCrmAccounts[0];
|
|
530
|
-
const { configs = {}, name = "" } = selectedAccount;
|
|
531
|
-
const { wecrm_app_id = "", wecrm_token = "", sourceAccountIdentifier = "" } = configs;
|
|
532
|
-
this.setState({selectedAccount: name}, () => {
|
|
533
|
-
params.wecrmId = wecrm_app_id;
|
|
534
|
-
params.wecrmToken = wecrm_token;
|
|
535
|
-
params.originalId = sourceAccountIdentifier;
|
|
536
|
-
this.props.actions.setRcsAccount(nextProps.Templates.weCrmAccounts[0]);
|
|
537
|
-
this.getAllTemplates({params});
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
529
|
if (selectedChannel === FACEBOOK_CHANNEL && isEmpty(nextProps.Templates.selectedFacebookAccount)) {
|
|
541
530
|
if (isEmpty(nextProps.Templates.campaignSettings)) {
|
|
542
531
|
return;
|
|
@@ -751,7 +740,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
751
740
|
this.setState({ previewTemplate: nextProps.Templates.templateDetails });
|
|
752
741
|
}
|
|
753
742
|
const { weCrmAccounts: weCrmAccountsList = [], senderDetails = {} } = get(nextProps, 'Templates', {});
|
|
754
|
-
const weCrmChannels = [WHATSAPP_LOWERCASE, ZALO_LOWERCASE];
|
|
743
|
+
const weCrmChannels = [WHATSAPP_LOWERCASE, ZALO_LOWERCASE, RCS_LOWERCASE];
|
|
755
744
|
|
|
756
745
|
// Keeping the wechat flow separate as it has different logic for setting the account. Currently we don't support wechat but still keeping the flow.
|
|
757
746
|
if (weCrmAccountsList?.length === 1 && this.state?.defaultAccount && selectedChannel === WECHAT_LOWERCASE && !isEmpty(senderDetails?.hostName)) {
|
|
@@ -773,6 +762,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
773
762
|
this.getAllTemplates({params: paramsDefault}, true);
|
|
774
763
|
}
|
|
775
764
|
|
|
765
|
+
// Auto-select single account for multi-account channels (WhatsApp, Zalo, RCS)
|
|
776
766
|
if (weCrmAccountsList?.length && this.state?.defaultAccount && (weCrmChannels.includes(selectedChannel))) {
|
|
777
767
|
const isSingleAccount = weCrmAccountsList?.length === 1;
|
|
778
768
|
const selectedAccount = this.props.Templates[ACCOUNT_MAPPING_ON_CHANNEL[selectedChannel]] || {};
|
|
@@ -799,6 +789,11 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
799
789
|
paramsDefault.name = this.state.searchText;
|
|
800
790
|
paramsDefault.sortBy = this.state.sortBy;
|
|
801
791
|
}
|
|
792
|
+
if (selectedChannel === RCS_LOWERCASE) {
|
|
793
|
+
paramsDefault.accountId = sourceAccountIdentifier;
|
|
794
|
+
paramsDefault.accessToken = configs?.accessToken;
|
|
795
|
+
paramsDefault.host = hostName || this.props.Templates?.selectedRcsAccount?.hostName;
|
|
796
|
+
}
|
|
802
797
|
this.setState({ defaultAccount: false });
|
|
803
798
|
/**
|
|
804
799
|
* Incase of multiple accounts, getAllTemplates is called on selecting the account. It's handled in onAccountSelect function.
|
|
@@ -834,7 +829,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
834
829
|
params.sortBy = this.state.sortBy;
|
|
835
830
|
}
|
|
836
831
|
const selectedChannel = this.state.channel.toLowerCase();
|
|
837
|
-
const
|
|
832
|
+
const isZaloOrWhatsappOrRcs = [ZALO_LOWERCASE, WHATSAPP_LOWERCASE, RCS_LOWERCASE].includes(selectedChannel);
|
|
838
833
|
if (selectedChannel === 'wechat') {
|
|
839
834
|
params.wecrmId = this.props.Templates.weCrmAccounts[findIndex(this.props.Templates.weCrmAccounts, { name: value})].configs.wecrm_app_id;
|
|
840
835
|
params.wecrmToken = this.props.Templates.weCrmAccounts[findIndex(this.props.Templates.weCrmAccounts, { name: value})].configs.wecrm_token;
|
|
@@ -858,7 +853,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
858
853
|
const setAcc = this.props?.Templates?.weCrmAccounts?.find((item) => item?.name === this.state.selectedAccount);
|
|
859
854
|
const { domainProperties = [] } = this.props?.Templates?.senderDetails || {};
|
|
860
855
|
let hostName = '';
|
|
861
|
-
if (
|
|
856
|
+
if (isZaloOrWhatsappOrRcs) {
|
|
862
857
|
hostName = this.getHostName(setAcc?.sourceAccountIdentifier, domainProperties);
|
|
863
858
|
setAcc.hostName = hostName;
|
|
864
859
|
}
|
|
@@ -881,11 +876,19 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
881
876
|
params.accountId = sourceAccountIdentifier;
|
|
882
877
|
params.host = hostName;
|
|
883
878
|
}
|
|
879
|
+
if (selectedChannel === RCS_LOWERCASE && hostName) {
|
|
880
|
+
const { configs: { accessToken = "" } = {} } = setAcc || {};
|
|
881
|
+
params.accountId = sourceAccountIdentifier;
|
|
882
|
+
params.host = hostName;
|
|
883
|
+
if (accessToken) {
|
|
884
|
+
params.accessToken = accessToken;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
884
887
|
}
|
|
885
888
|
|
|
886
889
|
this.setState({ activeMode: TEMPLATES_MODE }, () => {
|
|
887
|
-
// Restrict getAllTemplates call only if selectedChannel is ZALO or
|
|
888
|
-
if (!(
|
|
890
|
+
// Restrict getAllTemplates call only if selectedChannel is ZALO, WHATSAPP or RCS and hostName is empty
|
|
891
|
+
if (!(isZaloOrWhatsappOrRcs && !params?.host)) {
|
|
889
892
|
this.getAllTemplates({ params, resetPage: true });
|
|
890
893
|
}
|
|
891
894
|
});
|
|
@@ -1004,6 +1007,18 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1004
1007
|
if (this.state?.channel?.toLowerCase() === WHATSAPP_LOWERCASE) {
|
|
1005
1008
|
this.setWhatsappQueryParams(queryParams, params);
|
|
1006
1009
|
}
|
|
1010
|
+
if (this.state?.channel?.toLowerCase() === RCS_LOWERCASE && !isEmpty(this.props.Templates?.selectedRcsAccount)) {
|
|
1011
|
+
const { sourceAccountIdentifier = '', configs: { accessToken = '' } = {}, hostName = '' } = this.props.Templates.selectedRcsAccount;
|
|
1012
|
+
if (sourceAccountIdentifier) {
|
|
1013
|
+
queryParams.accountId = sourceAccountIdentifier;
|
|
1014
|
+
}
|
|
1015
|
+
if (accessToken) {
|
|
1016
|
+
queryParams.accessToken = accessToken;
|
|
1017
|
+
}
|
|
1018
|
+
if (hostName) {
|
|
1019
|
+
queryParams.host = hostName;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1007
1022
|
this.props.actions.getAllTemplates(channel, queryParams,`${copyOf}`);
|
|
1008
1023
|
} else if ((resetPage || (page === 1 && this.state.templatesCount === 0) || page <= (this.state.templatesCount / this.state.perPageLimit))) {
|
|
1009
1024
|
if (getNextPage) {
|
|
@@ -1056,6 +1071,18 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1056
1071
|
if (this.state?.channel?.toLowerCase() === WHATSAPP_LOWERCASE) {
|
|
1057
1072
|
this.setWhatsappQueryParams(queryParams, params);
|
|
1058
1073
|
}
|
|
1074
|
+
if (this.state?.channel?.toLowerCase() === RCS_LOWERCASE && !isEmpty(this.props.Templates?.selectedRcsAccount)) {
|
|
1075
|
+
const { sourceAccountIdentifier = '', configs: { accessToken = '' } = {}, hostName = '' } = this.props.Templates.selectedRcsAccount;
|
|
1076
|
+
if (sourceAccountIdentifier) {
|
|
1077
|
+
queryParams.accountId = sourceAccountIdentifier;
|
|
1078
|
+
}
|
|
1079
|
+
if (accessToken) {
|
|
1080
|
+
queryParams.accessToken = accessToken;
|
|
1081
|
+
}
|
|
1082
|
+
if (hostName) {
|
|
1083
|
+
queryParams.host = hostName;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1059
1086
|
this.setState({ page, templatesCount }, () => {
|
|
1060
1087
|
queryParams.page = page;
|
|
1061
1088
|
queryParams.perPage = this.state.perPageLimit;
|
|
@@ -1755,9 +1782,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1755
1782
|
const noLoaderAndSearchText = isEmpty(this.state.searchText) && !isLoading;
|
|
1756
1783
|
|
|
1757
1784
|
return (<div>
|
|
1758
|
-
{[WECHAT, MOBILE_PUSH, INAPP, WHATSAPP, ZALO].includes(currentChannel) && this.showAccountName()}
|
|
1785
|
+
{[WECHAT, MOBILE_PUSH, INAPP, WHATSAPP, ZALO,RCS].includes(currentChannel) && this.showAccountName()}
|
|
1759
1786
|
{filterContent}
|
|
1760
|
-
{[WHATSAPP, ZALO].includes(currentChannel) && this.selectedFilters()}
|
|
1787
|
+
{[WHATSAPP, ZALO,RCS].includes(currentChannel) && this.selectedFilters()}
|
|
1761
1788
|
{<div>
|
|
1762
1789
|
{!isEmpty(filteredTemplates) || !isEmpty(this.state.searchText) || !isEmpty(this.props.Templates.templateError) ? (
|
|
1763
1790
|
<div className={!isEmpty(this.state.searchText) && isEmpty(cardDataList) ? '' : this.isFullMode() ? "v2-pagination-container" : "v2-pagination-container-half"}>
|
|
@@ -2970,9 +2997,9 @@ return (<div>
|
|
|
2970
2997
|
const isMobilePushChannel = channel === MOBILE_PUSH;
|
|
2971
2998
|
const isInAppChannel = channel === INAPP;
|
|
2972
2999
|
const isFacebookChannel = channel === FACEBOOK;
|
|
2973
|
-
if ([WECHAT, MOBILE_PUSH, INAPP, LINE, ZALO, WHATSAPP].includes(channel) && !isEmpty(weCrmAccounts) && !isFacebookChannel) {
|
|
3000
|
+
if ([WECHAT, MOBILE_PUSH, INAPP, LINE, ZALO, WHATSAPP, RCS].includes(channel) && !isEmpty(weCrmAccounts) && !isFacebookChannel) {
|
|
2974
3001
|
forEach(weCrmAccounts, (account) => {
|
|
2975
|
-
if ((isWechatChannel && account.configs && account.configs.is_wecrm_enabled) || [MOBILE_PUSH, INAPP, LINE, ZALO, WHATSAPP].includes(channel)) {
|
|
3002
|
+
if ((isWechatChannel && account.configs && account.configs.is_wecrm_enabled) || [MOBILE_PUSH, INAPP, LINE, ZALO, WHATSAPP, RCS].includes(channel)) {
|
|
2976
3003
|
if (query.type === 'embedded' && (!query.module || (query.module && query.module !== 'library'))) {
|
|
2977
3004
|
if (query.source_account_id && account.sourceAccountIdentifier === query.source_account_id) {
|
|
2978
3005
|
accountOptions.push(
|
|
@@ -3051,12 +3078,17 @@ return (<div>
|
|
|
3051
3078
|
noAccountHeader = messages.noAccountsPresentZalo;
|
|
3052
3079
|
break;
|
|
3053
3080
|
}
|
|
3081
|
+
case RCS: {
|
|
3082
|
+
accountHeader = formatMessage(messages.rcsAccount);
|
|
3083
|
+
noAccountHeader = messages.noAccountsPresentRcs;
|
|
3084
|
+
break;
|
|
3085
|
+
}
|
|
3054
3086
|
default:
|
|
3055
3087
|
break;
|
|
3056
3088
|
}
|
|
3057
3089
|
let showNoAccountHeader = isEmpty(weCrmAccounts) && !fetchingWeCrmAccounts;
|
|
3058
|
-
// Zalo and
|
|
3059
|
-
const isDomainPropertiesLoading = [WHATSAPP, ZALO].includes(channel) && senderDetails?.status === "REQUEST";
|
|
3090
|
+
// Zalo, Whatsapp and RCS have dependencies on domainProperties to get the hostName. Show loader until the domainProperties are fetched.
|
|
3091
|
+
const isDomainPropertiesLoading = [WHATSAPP, ZALO, RCS].includes(channel) && senderDetails?.status === "REQUEST";
|
|
3060
3092
|
if (channel === FACEBOOK && !isEmpty(campaignSettings) ) {
|
|
3061
3093
|
const fbSetting = get(campaignSettings, 'accountSettings.socialAccountSettings.facebookAccountSettings', []);
|
|
3062
3094
|
const { orgUnitFacebookPageSettingsMap } = fbSetting[0] || {};
|
|
@@ -3126,6 +3158,7 @@ return (<div>
|
|
|
3126
3158
|
[WHATSAPP]: 'whatsappAccount',
|
|
3127
3159
|
[INAPP]: 'inappAccount',
|
|
3128
3160
|
[ZALO]: 'zaloAccount',
|
|
3161
|
+
[RCS]: 'rcsAccount',
|
|
3129
3162
|
};
|
|
3130
3163
|
return formatMessage(messages[channelObj[channel?.toUpperCase()]]);
|
|
3131
3164
|
}
|
|
@@ -3247,10 +3280,9 @@ return (<div>
|
|
|
3247
3280
|
}
|
|
3248
3281
|
}
|
|
3249
3282
|
|
|
3250
|
-
const showForChannels = (![VIBER_CHANNEL, FACEBOOK_CHANNEL
|
|
3283
|
+
const showForChannels = (![VIBER_CHANNEL, FACEBOOK_CHANNEL].includes(channel.toLowerCase()) ||
|
|
3251
3284
|
(channel.toLowerCase() === VIBER_CHANNEL && !this.props.isFullMode && isEmpty(get(this.props, 'Templates.selectedViberAccount', {}))) ||
|
|
3252
|
-
(channel.toLowerCase() === FACEBOOK_CHANNEL && showFbAds)
|
|
3253
|
-
(channel.toLowerCase() === RCS_LOWERCASE && isEmpty(get(this.props, 'Templates.selectedRcsAccount', {})))
|
|
3285
|
+
(channel.toLowerCase() === FACEBOOK_CHANNEL && showFbAds)
|
|
3254
3286
|
);
|
|
3255
3287
|
|
|
3256
3288
|
|
|
@@ -3317,7 +3349,7 @@ return (<div>
|
|
|
3317
3349
|
const isWhatsappCountExeeded = templatesCount >= MAX_WHATSAPP_TEMPLATES;
|
|
3318
3350
|
const showWhatsappCountWarning = templatesCount >= WARNING_WHATSAPP_TEMPLATES;
|
|
3319
3351
|
const whatsappCountExceedText = <FormattedMessage {...messages.whatsappMaxTemplates} values={{ maxCount: MAX_WHATSAPP_TEMPLATES }}/>;
|
|
3320
|
-
if (([WHATSAPP_LOWERCASE, ZALO_LOWERCASE].includes(this.state?.channel?.toLocaleLowerCase()) && isEmpty(this.state?.hostName))) {
|
|
3352
|
+
if (([WHATSAPP_LOWERCASE, ZALO_LOWERCASE, RCS_LOWERCASE].includes(this.state?.channel?.toLocaleLowerCase()) && isEmpty(this.state?.hostName))) {
|
|
3321
3353
|
isfilterContentVisisble = false;
|
|
3322
3354
|
}
|
|
3323
3355
|
const filterContent = (( isfilterContentVisisble || [WECHAT, MOBILE_PUSH, INAPP].includes(this.state.channel.toUpperCase())) && <div className="action-container">
|
|
@@ -462,6 +462,10 @@ export default defineMessages({
|
|
|
462
462
|
id: `${scope}.zaloAccount`,
|
|
463
463
|
defaultMessage: 'Zalo account',
|
|
464
464
|
},
|
|
465
|
+
"rcsAccount": {
|
|
466
|
+
id: `${scope}.rcsAccount`,
|
|
467
|
+
defaultMessage: 'RCS account',
|
|
468
|
+
},
|
|
465
469
|
"all": {
|
|
466
470
|
id: `${scope}.all`,
|
|
467
471
|
defaultMessage: 'All',
|
|
@@ -494,6 +498,10 @@ export default defineMessages({
|
|
|
494
498
|
id: `${scope}.noAccountsPresentZalo`,
|
|
495
499
|
defaultMessage: "Zalo accounts are not setup for your brand",
|
|
496
500
|
},
|
|
501
|
+
"noAccountsPresentRcs": {
|
|
502
|
+
id: `${scope}.noAccountsPresentRcs`,
|
|
503
|
+
defaultMessage: "RCS accounts are not setup for your brand",
|
|
504
|
+
},
|
|
497
505
|
"promotional": {
|
|
498
506
|
id: `${scope}.promotional`,
|
|
499
507
|
defaultMessage: 'Promotional',
|
|
@@ -118,7 +118,7 @@ function templatesReducer(state = initialState, action) {
|
|
|
118
118
|
.set('templates', []);
|
|
119
119
|
case types.SET_RCS_ACCOUNT:
|
|
120
120
|
return state
|
|
121
|
-
.set('selectedRcsAccount', fromJS(action.
|
|
121
|
+
.set('selectedRcsAccount', fromJS(action.account))
|
|
122
122
|
.set('templates', []);
|
|
123
123
|
case types.SET_FACEBOOK_ACCOUNT:
|
|
124
124
|
return state
|
|
@@ -212,9 +212,9 @@ function templatesReducer(state = initialState, action) {
|
|
|
212
212
|
return state.set('senderDetails', { status: 'REQUEST' });
|
|
213
213
|
case types.GET_SENDER_DETAILS_SUCCESS: {
|
|
214
214
|
const { channel, domainProperties = {} } = action?.payload || {};
|
|
215
|
-
const isMultiAccountChannel = ['WHATSAPP', 'ZALO'].includes(channel);
|
|
215
|
+
const isMultiAccountChannel = ['WHATSAPP', 'ZALO', 'RCS'].includes(channel);
|
|
216
216
|
const senderDetailsKey = isMultiAccountChannel ? 'domainProperties' : 'hostName';
|
|
217
|
-
// For Whatsapp and
|
|
217
|
+
// For Whatsapp, Zalo and RCS we need to store domainProperties instead of only hostName
|
|
218
218
|
return state.set('senderDetails', {
|
|
219
219
|
status: 'SUCCESS',
|
|
220
220
|
[senderDetailsKey]: isMultiAccountChannel ? domainProperties : action?.payload,
|
|
@@ -180,7 +180,7 @@ export function* getSenderDetails({
|
|
|
180
180
|
if (!apiResponse?.errors?.length) {
|
|
181
181
|
yield put({
|
|
182
182
|
type: types.GET_SENDER_DETAILS_SUCCESS,
|
|
183
|
-
payload: ['WHATSAPP', 'ZALO'].includes(channel) ?
|
|
183
|
+
payload: ['WHATSAPP', 'ZALO', 'RCS'].includes(channel) ?
|
|
184
184
|
{ channel,
|
|
185
185
|
domainProperties: get(apiResponse, `entity.${channel}`, '')
|
|
186
186
|
} :
|
|
@@ -11,8 +11,8 @@ exports[`Test Templates container Should render correct component for RCS channe
|
|
|
11
11
|
}
|
|
12
12
|
>
|
|
13
13
|
<FormattedMessage
|
|
14
|
-
defaultMessage="
|
|
15
|
-
id="creatives.containersV2.Templates.
|
|
14
|
+
defaultMessage="RCS accounts are not setup for your brand"
|
|
15
|
+
id="creatives.containersV2.Templates.noAccountsPresentRcs"
|
|
16
16
|
values={Object {}}
|
|
17
17
|
/>
|
|
18
18
|
</CapSkeleton>
|
|
@@ -145,8 +145,8 @@ exports[`Test Templates container Should render illustration when no RCS templat
|
|
|
145
145
|
}
|
|
146
146
|
>
|
|
147
147
|
<FormattedMessage
|
|
148
|
-
defaultMessage="
|
|
149
|
-
id="creatives.containersV2.Templates.
|
|
148
|
+
defaultMessage="RCS accounts are not setup for your brand"
|
|
149
|
+
id="creatives.containersV2.Templates.noAccountsPresentRcs"
|
|
150
150
|
values={Object {}}
|
|
151
151
|
/>
|
|
152
152
|
</CapSkeleton>
|
|
@@ -1004,8 +1004,8 @@ exports[`Test Templates container Should render templates when RCS templates are
|
|
|
1004
1004
|
}
|
|
1005
1005
|
>
|
|
1006
1006
|
<FormattedMessage
|
|
1007
|
-
defaultMessage="
|
|
1008
|
-
id="creatives.containersV2.Templates.
|
|
1007
|
+
defaultMessage="RCS accounts are not setup for your brand"
|
|
1008
|
+
id="creatives.containersV2.Templates.noAccountsPresentRcs"
|
|
1009
1009
|
values={Object {}}
|
|
1010
1010
|
/>
|
|
1011
1011
|
</CapSkeleton>
|
|
@@ -1022,8 +1022,8 @@ exports[`Test Templates container Should render templates when RCS templates are
|
|
|
1022
1022
|
}
|
|
1023
1023
|
>
|
|
1024
1024
|
<FormattedMessage
|
|
1025
|
-
defaultMessage="
|
|
1026
|
-
id="creatives.containersV2.Templates.
|
|
1025
|
+
defaultMessage="RCS accounts are not setup for your brand"
|
|
1026
|
+
id="creatives.containersV2.Templates.noAccountsPresentRcs"
|
|
1027
1027
|
values={Object {}}
|
|
1028
1028
|
/>
|
|
1029
1029
|
</CapSkeleton>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { getAllTemplates } from "../actions";
|
|
1
|
+
import { getAllTemplates, setChannelAccount } from "../actions";
|
|
2
2
|
import * as types from "../constants";
|
|
3
|
+
import { RCS } from "../../CreativesContainer/constants";
|
|
3
4
|
|
|
4
5
|
describe("Test zalo list actions", () => {
|
|
5
6
|
test.concurrent("has a type of GET_ALL_TEMPLATES_REQUEST action", () => {
|
|
@@ -17,3 +18,37 @@ describe("Test zalo list actions", () => {
|
|
|
17
18
|
expect(getAllTemplates(channel, queryParams, "test")).toEqual(expected);
|
|
18
19
|
});
|
|
19
20
|
});
|
|
21
|
+
|
|
22
|
+
describe("Test RCS list actions", () => {
|
|
23
|
+
test.concurrent("has a type of GET_ALL_TEMPLATES_REQUEST action for RCS", () => {
|
|
24
|
+
const channel = "Rcs";
|
|
25
|
+
const queryParams = {
|
|
26
|
+
page: 1,
|
|
27
|
+
perPage: 25,
|
|
28
|
+
accountId: "capillary_rcs",
|
|
29
|
+
accessToken: "YugrOlhdSPpM",
|
|
30
|
+
host: "rcsicsbulk",
|
|
31
|
+
};
|
|
32
|
+
const expected = {
|
|
33
|
+
type: types.GET_ALL_TEMPLATES_REQUEST,
|
|
34
|
+
channel,
|
|
35
|
+
intlCopyOf: "test",
|
|
36
|
+
queryParams,
|
|
37
|
+
};
|
|
38
|
+
expect(getAllTemplates(channel, queryParams, "test")).toEqual(expected);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test.concurrent("has a type of SET_RCS_ACCOUNT action", () => {
|
|
42
|
+
const account = {
|
|
43
|
+
sourceAccountIdentifier: "capillary_rcs",
|
|
44
|
+
name: "RCS Account",
|
|
45
|
+
configs: { accessToken: "YugrOlhdSPpM" },
|
|
46
|
+
hostName: "rcsicsbulk",
|
|
47
|
+
};
|
|
48
|
+
const expected = {
|
|
49
|
+
type: types.SET_RCS_ACCOUNT,
|
|
50
|
+
account,
|
|
51
|
+
};
|
|
52
|
+
expect(setChannelAccount(RCS, account)).toEqual(expected);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import reducer, { initialState } from "../reducer";
|
|
2
2
|
import * as types from "../constants";
|
|
3
3
|
import * as mockData from "./mockData";
|
|
4
|
+
import { RCS } from "../../CreativesContainer/constants";
|
|
4
5
|
|
|
5
6
|
describe("test reducer", () => {
|
|
6
7
|
afterEach(() => {
|
|
@@ -277,10 +278,16 @@ describe("test reducer - SET account actions clear templates", () => {
|
|
|
277
278
|
|
|
278
279
|
it.concurrent("should clear templates when SET_RCS_ACCOUNT is dispatched", () => {
|
|
279
280
|
const stateWithTemplates = initialState.set('templates', [{ id: 1, name: "Template 1" }]);
|
|
280
|
-
const mockAccount = {
|
|
281
|
+
const mockAccount = {
|
|
282
|
+
id: 1,
|
|
283
|
+
name: "RCS Account",
|
|
284
|
+
sourceAccountIdentifier: "capillary_rcs",
|
|
285
|
+
configs: { accessToken: "YugrOlhdSPpM" },
|
|
286
|
+
hostName: "rcsicsbulk"
|
|
287
|
+
};
|
|
281
288
|
const action = {
|
|
282
289
|
type: types.SET_RCS_ACCOUNT,
|
|
283
|
-
|
|
290
|
+
account: mockAccount,
|
|
284
291
|
};
|
|
285
292
|
const result = reducer(stateWithTemplates, action).toJS();
|
|
286
293
|
expect(result.selectedRcsAccount).toEqual(mockAccount);
|
|
@@ -17,6 +17,16 @@ import {
|
|
|
17
17
|
deleteRcsTemplate,
|
|
18
18
|
watchDeleteRcsTemplate,
|
|
19
19
|
watchForGetTemplateInfoById,
|
|
20
|
+
deleteTemplate,
|
|
21
|
+
watchDeleteTemplate,
|
|
22
|
+
getTemplateDetails,
|
|
23
|
+
watchGetTemplateDetails,
|
|
24
|
+
getDefaultBeeTemplates,
|
|
25
|
+
watchGetDefaultBeeTemplates,
|
|
26
|
+
getOrgLevelCampaignSettings,
|
|
27
|
+
watchGetOrgLevelCampaignSettings,
|
|
28
|
+
watchSendingFile,
|
|
29
|
+
watchFetchWeCrmAccounts,
|
|
20
30
|
} from '../sagas';
|
|
21
31
|
|
|
22
32
|
import * as mockData from './mockData';
|
|
@@ -88,6 +98,30 @@ describe('watchForGetJourneyList saga', () => {
|
|
|
88
98
|
});
|
|
89
99
|
});
|
|
90
100
|
|
|
101
|
+
describe('getOrgLevelCampaignSettings saga', () => {
|
|
102
|
+
it('handles success', () => {
|
|
103
|
+
const apiResult = { ok: true };
|
|
104
|
+
const generator = getOrgLevelCampaignSettings();
|
|
105
|
+
expect(generator.next().value).toEqual(call(api.getOrgLevelCampaignSettings));
|
|
106
|
+
expect(generator.next(apiResult).value).toEqual(put({
|
|
107
|
+
type: types.GET_ORG_LEVEL_CAMPAIGN_SETTINGS_SUCCESS,
|
|
108
|
+
result: apiResult,
|
|
109
|
+
}));
|
|
110
|
+
expect(generator.next().done).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('handles failure', () => {
|
|
114
|
+
const error = new Error('oops');
|
|
115
|
+
const generator = getOrgLevelCampaignSettings();
|
|
116
|
+
expect(generator.next().value).toEqual(call(api.getOrgLevelCampaignSettings));
|
|
117
|
+
expect(generator.throw(error).value).toEqual(put({
|
|
118
|
+
type: types.GET_ORG_LEVEL_CAMPAIGN_SETTINGS_FAILURE,
|
|
119
|
+
error,
|
|
120
|
+
}));
|
|
121
|
+
expect(generator.next().done).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
91
125
|
describe('templateList saga', () => {
|
|
92
126
|
it('handle valid response from api', () => {
|
|
93
127
|
expectSaga(getAllTemplates, mockData.getAllTemplatesListSuccess)
|
|
@@ -122,16 +156,16 @@ describe('templateList saga', () => {
|
|
|
122
156
|
.run();
|
|
123
157
|
});
|
|
124
158
|
it('handles error thrown from api', () => {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
])
|
|
159
|
+
const failurePayload = {
|
|
160
|
+
channel: { channel: 'RCS', queryParams: { page: 1 } },
|
|
161
|
+
queryParams: { page: 1 },
|
|
162
|
+
};
|
|
163
|
+
const error = new Error('fail');
|
|
164
|
+
expectSaga(getAllTemplates, failurePayload)
|
|
165
|
+
.provide([[matchers.call.fn(api.getAllTemplates), throwError(error)]])
|
|
132
166
|
.put({
|
|
133
167
|
type: types.GET_ALL_TEMPLATES_FAILURE,
|
|
134
|
-
|
|
168
|
+
error,
|
|
135
169
|
})
|
|
136
170
|
.run();
|
|
137
171
|
});
|
|
@@ -146,6 +180,39 @@ describe('watchForTemplates saga', () => {
|
|
|
146
180
|
});
|
|
147
181
|
});
|
|
148
182
|
|
|
183
|
+
describe('getDefaultBeeTemplates saga', () => {
|
|
184
|
+
it('handles success', () => {
|
|
185
|
+
const apiResult = { response: [{ id: 1 }] };
|
|
186
|
+
const generator = getDefaultBeeTemplates();
|
|
187
|
+
expect(generator.next().value).toEqual(call(api.getDefaultBeeTemplates));
|
|
188
|
+
expect(generator.next(apiResult).value).toEqual(put({
|
|
189
|
+
type: types.GET_DEAFULT_BEE_TEMPLATES_SUCCESS,
|
|
190
|
+
data: apiResult.response,
|
|
191
|
+
}));
|
|
192
|
+
expect(generator.next().done).toBe(true);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('handles failure', () => {
|
|
196
|
+
const error = new Error('bee');
|
|
197
|
+
const generator = getDefaultBeeTemplates();
|
|
198
|
+
expect(generator.next().value).toEqual(call(api.getDefaultBeeTemplates));
|
|
199
|
+
expect(generator.throw(error).value).toEqual(put({
|
|
200
|
+
type: types.GET_DEAFULT_BEE_TEMPLATES_FAILURE,
|
|
201
|
+
error,
|
|
202
|
+
}));
|
|
203
|
+
expect(generator.next().done).toBe(true);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe('watchGetDefaultBeeTemplates saga', () => {
|
|
208
|
+
const generator = watchGetDefaultBeeTemplates();
|
|
209
|
+
it('should call watchers functions', () => {
|
|
210
|
+
expect(generator.next().value).toEqual(
|
|
211
|
+
takeLatest(types.GET_DEAFULT_BEE_TEMPLATES_REQUEST, getDefaultBeeTemplates),
|
|
212
|
+
);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
149
216
|
describe('getSenderDetails Saga', () => {
|
|
150
217
|
const channel = 'someChannel';
|
|
151
218
|
const orgUnitId = 'someOrgUnitId';
|
|
@@ -194,6 +261,103 @@ describe('getSenderDetails Saga', () => {
|
|
|
194
261
|
})
|
|
195
262
|
);
|
|
196
263
|
});
|
|
264
|
+
|
|
265
|
+
it('should handle WHATSAPP channel with domainProperties format', () => {
|
|
266
|
+
const whatsappChannel = 'WHATSAPP';
|
|
267
|
+
const whatsappOrgUnitId = 'org123';
|
|
268
|
+
const whatsappAction = { channel: whatsappChannel, orgUnitId: whatsappOrgUnitId };
|
|
269
|
+
const apiResponse = {
|
|
270
|
+
entity: {
|
|
271
|
+
WHATSAPP: { accountId: 'wa-123', phoneNumber: '+1234567890' },
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const generator = getSenderDetails(whatsappAction);
|
|
276
|
+
expect(generator.next().value).toEqual(call(api.getSenderDetails, whatsappChannel, whatsappOrgUnitId));
|
|
277
|
+
expect(generator.next(apiResponse).value).toEqual(
|
|
278
|
+
put({
|
|
279
|
+
type: types.GET_SENDER_DETAILS_SUCCESS,
|
|
280
|
+
payload: {
|
|
281
|
+
channel: whatsappChannel,
|
|
282
|
+
domainProperties: apiResponse.entity.WHATSAPP,
|
|
283
|
+
},
|
|
284
|
+
})
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('should handle ZALO channel with domainProperties format', () => {
|
|
289
|
+
const zaloChannel = 'ZALO';
|
|
290
|
+
const zaloOrgUnitId = 'org456';
|
|
291
|
+
const zaloAction = { channel: zaloChannel, orgUnitId: zaloOrgUnitId };
|
|
292
|
+
const apiResponse = {
|
|
293
|
+
entity: {
|
|
294
|
+
ZALO: { oaId: 'zalo-oa-123', token: 'zalo-token' },
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
const generator = getSenderDetails(zaloAction);
|
|
299
|
+
expect(generator.next().value).toEqual(call(api.getSenderDetails, zaloChannel, zaloOrgUnitId));
|
|
300
|
+
expect(generator.next(apiResponse).value).toEqual(
|
|
301
|
+
put({
|
|
302
|
+
type: types.GET_SENDER_DETAILS_SUCCESS,
|
|
303
|
+
payload: {
|
|
304
|
+
channel: zaloChannel,
|
|
305
|
+
domainProperties: apiResponse.entity.ZALO,
|
|
306
|
+
},
|
|
307
|
+
})
|
|
308
|
+
);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('should handle RCS channel with domainProperties format', () => {
|
|
312
|
+
const rcsChannel = 'RCS';
|
|
313
|
+
const rcsOrgUnitId = 'org789';
|
|
314
|
+
const rcsAction = { channel: rcsChannel, orgUnitId: rcsOrgUnitId };
|
|
315
|
+
const apiResponse = {
|
|
316
|
+
entity: {
|
|
317
|
+
RCS: { accountId: 'rcs-account-123', hostName: 'rcs.example.com' },
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const generator = getSenderDetails(rcsAction);
|
|
322
|
+
expect(generator.next().value).toEqual(call(api.getSenderDetails, rcsChannel, rcsOrgUnitId));
|
|
323
|
+
expect(generator.next(apiResponse).value).toEqual(
|
|
324
|
+
put({
|
|
325
|
+
type: types.GET_SENDER_DETAILS_SUCCESS,
|
|
326
|
+
payload: {
|
|
327
|
+
channel: rcsChannel,
|
|
328
|
+
domainProperties: apiResponse.entity.RCS,
|
|
329
|
+
},
|
|
330
|
+
})
|
|
331
|
+
);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('should handle apiResponse with errors', () => {
|
|
335
|
+
const apiResponse = {
|
|
336
|
+
errors: ['Error 1', 'Error 2'],
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const generator = getSenderDetails(action);
|
|
340
|
+
expect(generator.next().value).toEqual(call(api.getSenderDetails, channel, orgUnitId));
|
|
341
|
+
expect(generator.next(apiResponse).value).toEqual(
|
|
342
|
+
put({
|
|
343
|
+
type: types.GET_SENDER_DETAILS_FAILURE,
|
|
344
|
+
payload: apiResponse.errors,
|
|
345
|
+
})
|
|
346
|
+
);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it('should handle exception thrown during API call', () => {
|
|
350
|
+
const error = new Error('Network error');
|
|
351
|
+
|
|
352
|
+
const generator = getSenderDetails(action);
|
|
353
|
+
expect(generator.next().value).toEqual(call(api.getSenderDetails, channel, orgUnitId));
|
|
354
|
+
expect(generator.throw(error).value).toEqual(
|
|
355
|
+
put({
|
|
356
|
+
type: types.GET_SENDER_DETAILS_FAILURE,
|
|
357
|
+
payload: [],
|
|
358
|
+
})
|
|
359
|
+
);
|
|
360
|
+
});
|
|
197
361
|
});
|
|
198
362
|
|
|
199
363
|
describe('fetchWeCrmAccounts Saga', () => {
|
|
@@ -271,7 +435,7 @@ describe('sendZippedFile Saga', () => {
|
|
|
271
435
|
])
|
|
272
436
|
.put({
|
|
273
437
|
type: types.SEND_ZIPPED_FILE_FAILURE,
|
|
274
|
-
data:
|
|
438
|
+
data: ''
|
|
275
439
|
})
|
|
276
440
|
.run();
|
|
277
441
|
});
|
|
@@ -430,6 +594,95 @@ describe('watchDeleteRcsTemplate saga', () => {
|
|
|
430
594
|
});
|
|
431
595
|
});
|
|
432
596
|
|
|
597
|
+
describe('deleteTemplate saga', () => {
|
|
598
|
+
const channel = { channel: 'RCS' };
|
|
599
|
+
const id = 'tpl-1';
|
|
600
|
+
it('handles success', () => {
|
|
601
|
+
const apiResult = { response: { ok: true } };
|
|
602
|
+
const generator = deleteTemplate(channel, id);
|
|
603
|
+
expect(generator.next().value).toEqual(call(api.deleteTemplate, channel, id));
|
|
604
|
+
expect(generator.next(apiResult).value).toEqual(put({
|
|
605
|
+
type: types.DELETE_TEMPLATE_SUCCESS,
|
|
606
|
+
data: apiResult.response,
|
|
607
|
+
}));
|
|
608
|
+
expect(generator.next().done).toBe(true);
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
it('handles failure', () => {
|
|
612
|
+
const error = new Error('fail');
|
|
613
|
+
const generator = deleteTemplate(channel, id);
|
|
614
|
+
expect(generator.next().value).toEqual(call(api.deleteTemplate, channel, id));
|
|
615
|
+
expect(generator.throw(error).value).toEqual(put({
|
|
616
|
+
type: types.DELETE_TEMPLATE_FAILURE,
|
|
617
|
+
error,
|
|
618
|
+
}));
|
|
619
|
+
expect(generator.next().done).toBe(true);
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
describe('watchDeleteTemplate saga', () => {
|
|
624
|
+
const generator = watchDeleteTemplate();
|
|
625
|
+
it('should call watchers functions', () => {
|
|
626
|
+
expect(generator.next().value).toEqual(
|
|
627
|
+
takeLatest(types.DELETE_TEMPLATE_REQUEST, deleteTemplate),
|
|
628
|
+
);
|
|
629
|
+
});
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
describe('getTemplateDetails saga', () => {
|
|
633
|
+
it('handles success', () => {
|
|
634
|
+
const id = '1';
|
|
635
|
+
const channel = { channel: 'RCS' };
|
|
636
|
+
const apiResult = { response: { id: 1 } };
|
|
637
|
+
const generator = getTemplateDetails(id, channel);
|
|
638
|
+
expect(generator.next().value).toEqual(call(api.getTemplateDetails, id, channel));
|
|
639
|
+
expect(generator.next(apiResult).value).toEqual(put({
|
|
640
|
+
type: types.GET_TEMPLATE_DETAILS_SUCCESS,
|
|
641
|
+
data: apiResult.response,
|
|
642
|
+
}));
|
|
643
|
+
expect(generator.next().done).toBe(true);
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
it('handles failure', () => {
|
|
647
|
+
const id = '1';
|
|
648
|
+
const channel = { channel: 'RCS' };
|
|
649
|
+
const error = new Error('oops');
|
|
650
|
+
const generator = getTemplateDetails(id, channel);
|
|
651
|
+
expect(generator.next().value).toEqual(call(api.getTemplateDetails, id, channel));
|
|
652
|
+
expect(generator.throw(error).value).toEqual(put({
|
|
653
|
+
type: types.GET_TEMPLATE_DETAILS_FAILURE,
|
|
654
|
+
error,
|
|
655
|
+
}));
|
|
656
|
+
expect(generator.next().done).toBe(true);
|
|
657
|
+
});
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
describe('watchGetTemplateDetails saga', () => {
|
|
661
|
+
const generator = watchGetTemplateDetails();
|
|
662
|
+
it('should call watchers functions', () => {
|
|
663
|
+
expect(generator.next().value).toEqual(
|
|
664
|
+
takeLatest(types.GET_TEMPLATE_DETAILS_REQUEST, getTemplateDetails),
|
|
665
|
+
);
|
|
666
|
+
});
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
describe('watchFetchWeCrmAccounts saga', () => {
|
|
670
|
+
const generator = watchFetchWeCrmAccounts();
|
|
671
|
+
it('should call watchers functions', () => {
|
|
672
|
+
expect(generator.next().value).toEqual(
|
|
673
|
+
takeLatest(types.GET_WECRM_ACCOUNTS_REQUEST, fetchWeCrmAccounts),
|
|
674
|
+
);
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
describe('watchSendingFile saga', () => {
|
|
679
|
+
const generator = watchSendingFile();
|
|
680
|
+
it('should call watchers functions', () => {
|
|
681
|
+
expect(generator.next().value).toEqual(
|
|
682
|
+
takeLatest(types.SEND_ZIPPED_FILE_REQUEST, sendZippedFile),
|
|
683
|
+
);
|
|
684
|
+
});
|
|
685
|
+
});
|
|
433
686
|
|
|
434
687
|
describe('watchForGetTemplateInfoById saga', () => {
|
|
435
688
|
it('should call getTemplateInfoById when preview flag is true (preview request)', () => {
|