@capillarytech/creatives-library 8.0.34-alpha.1 → 8.0.36
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/app.js +0 -1
- package/containers/App/test/saga.test.js +11 -0
- package/containers/Assets/Gallery/sagas.js +2 -1
- package/containers/Assets/Gallery/tests/saga.test.js +161 -0
- package/containers/Cap/tests/saga.test.js +8 -1
- package/containers/Dashboard/test/saga.test.js +9 -0
- package/containers/Ebill/test/saga.test.js +11 -0
- package/containers/Email/sagas.js +1 -1
- package/containers/Email/test/saga.test.js +278 -0
- package/containers/Line/Create/tests/saga.test.js +209 -0
- package/containers/Line/Edit/sagas.js +4 -4
- package/containers/Line/Edit/test/saga.test.js +164 -0
- package/containers/MobilePush/Create/index.js +1 -1
- package/containers/MobilePush/Create/test/saga.test.js +19 -0
- package/containers/MobilePush/Edit/index.js +1 -1
- package/containers/MobilePush/Edit/tests/saga.test.js +255 -0
- package/containers/Sms/Create/test/saga.test.js +12 -0
- package/containers/Sms/Edit/test/saga.test.js +13 -0
- package/containers/Templates/test/saga.test.js +244 -0
- package/containers/WeChat/MapTemplates/test/saga.test.js +159 -0
- package/containers/WeChat/RichmediaTemplates/Create/test/saga.test.js +13 -0
- package/containers/WeChat/RichmediaTemplates/Edit/test/saga.test.js +12 -0
- package/hoc/test/WithReactRouterV3Compatibility.test.js +135 -0
- package/hoc/withReactRouterV3Compatibility.js +4 -4
- package/package.json +3 -3
- package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +4 -2
- package/tests/integration/TemplateCreation/api-response.js +10 -1
- package/tests/integration/TemplateCreation/msw-handler.js +3 -0
- package/utils/authWrapper.js +0 -6
- package/utils/tests/authWrapper.test.js +142 -0
- package/utils/tests/checkStore.test.js +72 -0
- package/utils/tests/customAuth.test.js +30 -0
- package/v2Components/NavigationBar/tests/saga.test.js +35 -0
- package/v2Containers/Assets/Gallery/sagas.js +1 -1
- package/v2Containers/Assets/Gallery/tests/saga.test.js +41 -0
- package/v2Containers/BeeEditor/test/saga.test.js +13 -0
- package/v2Containers/CallTask/test/saga.test.js +13 -0
- package/v2Containers/Cap/sagas.js +3 -3
- package/v2Containers/Cap/tests/Cap.test.js +2 -18
- package/v2Containers/Cap/tests/saga.test.js +73 -1
- package/v2Containers/CapFacebookPreview/tests/saga.test.js +13 -0
- package/v2Containers/Ebill/test/saga.test.js +13 -0
- package/v2Containers/Email/sagas.js +3 -2
- package/v2Containers/Email/tests/sagas.test.js +216 -0
- package/v2Containers/FTP/test/saga.test.js +12 -0
- package/v2Containers/Facebook/test/saga.test.js +171 -0
- package/v2Containers/InApp/tests/sagas.test.js +13 -0
- package/v2Containers/LanguageProvider/sagas.js +1 -1
- package/v2Containers/LanguageProvider/tests/saga.test.js +40 -0
- package/v2Containers/Line/Container/test/saga.test.js +228 -0
- package/v2Containers/MobilePush/Create/index.js +1 -1
- package/v2Containers/MobilePush/Create/test/saga.test.js +19 -0
- package/v2Containers/MobilePush/Edit/index.js +1 -1
- package/v2Containers/MobilePush/Edit/test/saga.test.js +255 -0
- package/v2Containers/Rcs/tests/saga.test.js +13 -0
- package/v2Containers/Sms/Create/test/saga.test.js +8 -0
- package/v2Containers/Sms/Edit/test/saga.test.js +12 -0
- package/v2Containers/SmsTrai/Create/tests/saga.test.js +13 -0
- package/v2Containers/TagList/index.js +20 -8
- package/v2Containers/TagList/tests/TagList.test.js +11 -4
- package/v2Containers/TagList/tests/mockdata.js +4 -20
- package/v2Containers/Templates/sagas.js +7 -7
- package/v2Containers/Templates/tests/sagas.test.js +138 -0
- package/v2Containers/TemplatesV2/index.js +25 -51
- package/v2Containers/Viber/tests/saga.test.js +187 -0
- package/v2Containers/WeChat/MapTemplates/test/saga.test.js +160 -0
- package/v2Containers/WeChat/RichmediaTemplates/Create/test/saga.test.js +12 -0
- package/v2Containers/WeChat/RichmediaTemplates/Edit/test/saga.test.js +13 -0
- package/v2Containers/Whatsapp/tests/saga.test.js +9 -1
- package/v2Containers/Zalo/tests/saga.test.js +8 -1
|
@@ -110,25 +110,8 @@ export const TagListData = {
|
|
|
110
110
|
export const eventContextTags = [
|
|
111
111
|
{
|
|
112
112
|
"profileId": "BEHAVIOURAL_EVENT_PROFILE",
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"params": null,
|
|
116
|
-
"returnType": {
|
|
117
|
-
"isList": false,
|
|
118
|
-
"typeInfo": {
|
|
119
|
-
"type": "DOUBLE",
|
|
120
|
-
"typeId": null
|
|
121
|
-
},
|
|
122
|
-
"list": false
|
|
123
|
-
},
|
|
124
|
-
"factId": "getEventData_butterfly",
|
|
125
|
-
"tagName": "(butterfly)",
|
|
126
|
-
"isTaggable": true,
|
|
127
|
-
"uniqueId": "yW_DH7vjKk__BEHAVIOURAL__monsoon",
|
|
128
|
-
"isDynamicFact": true
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
"profileId": "BEHAVIOURAL_EVENT_PROFILE",
|
|
113
|
+
// "profileName": "Behavioural event",
|
|
114
|
+
// "label": 'raindrops',
|
|
132
115
|
"method": "getEventData",
|
|
133
116
|
"field": "raindrops",
|
|
134
117
|
"params": null,
|
|
@@ -149,6 +132,7 @@ export const eventContextTags = [
|
|
|
149
132
|
{
|
|
150
133
|
"factId": "5LFP9e",
|
|
151
134
|
"profileId": "CUSTOMER_PROFILE",
|
|
135
|
+
"profileName": "Current Customer",
|
|
152
136
|
"params": [],
|
|
153
137
|
"returnType": {
|
|
154
138
|
"isList": false,
|
|
@@ -159,7 +143,7 @@ export const eventContextTags = [
|
|
|
159
143
|
"list": false
|
|
160
144
|
},
|
|
161
145
|
"tagName": "entryTrigger.lifetimePurchases",
|
|
162
|
-
label: 'lifetimePurchases',
|
|
146
|
+
"label": 'lifetimePurchases',
|
|
163
147
|
"isTaggable": true,
|
|
164
148
|
"uniqueId": "yW_DH7vjKk__BEHAVIOURAL__monsoon",
|
|
165
149
|
"isDynamicFact": false
|
|
@@ -185,43 +185,43 @@ export function* watchGetAllTemplates() {
|
|
|
185
185
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
function* watchDeleteTemplate() {
|
|
188
|
+
export function* watchDeleteTemplate() {
|
|
189
189
|
yield takeLatest(types.DELETE_TEMPLATE_REQUEST, deleteTemplate);
|
|
190
190
|
|
|
191
191
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
function* watchGetUserList() {
|
|
194
|
+
export function* watchGetUserList() {
|
|
195
195
|
yield takeLatest(types.GET_USER_LIST_REQUEST, fetchUserList);
|
|
196
196
|
|
|
197
197
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
function* watchFetchWeCrmAccounts() {
|
|
200
|
+
export function* watchFetchWeCrmAccounts() {
|
|
201
201
|
yield takeLatest(types.GET_WECRM_ACCOUNTS_REQUEST, fetchWeCrmAccounts);
|
|
202
202
|
|
|
203
203
|
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
function* watchSendingFile() {
|
|
206
|
+
export function* watchSendingFile() {
|
|
207
207
|
yield takeLatest(types.SEND_ZIPPED_FILE_REQUEST, sendZippedFile);
|
|
208
208
|
|
|
209
209
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
function* watchGetDefaultBeeTemplates() {
|
|
212
|
+
export function* watchGetDefaultBeeTemplates() {
|
|
213
213
|
yield takeLatest(types.GET_DEAFULT_BEE_TEMPLATES_REQUEST, getDefaultBeeTemplates);
|
|
214
214
|
|
|
215
215
|
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
function* watchGetTemplateDetails() {
|
|
218
|
+
export function* watchGetTemplateDetails() {
|
|
219
219
|
yield takeLatest(types.GET_TEMPLATE_DETAILS_REQUEST, getTemplateDetails);
|
|
220
220
|
|
|
221
221
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
function* watchGetSenderDetails() {
|
|
224
|
+
export function* watchGetSenderDetails() {
|
|
225
225
|
yield takeLatest(types.GET_SENDER_DETAILS_REQUEST, getSenderDetails);
|
|
226
226
|
|
|
227
227
|
|
|
@@ -11,11 +11,15 @@ import {
|
|
|
11
11
|
watchGetCdnTransformationConfig,
|
|
12
12
|
watchGetAllTemplates,
|
|
13
13
|
getSenderDetails,
|
|
14
|
+
fetchWeCrmAccounts,
|
|
15
|
+
sendZippedFile,
|
|
16
|
+
fetchUserList
|
|
14
17
|
} from '../sagas';
|
|
15
18
|
|
|
16
19
|
import * as mockData from './mockData';
|
|
17
20
|
import { ZALO } from '../../CreativesContainer/constants';
|
|
18
21
|
import { VIET_GUYS } from '../../Zalo/constants';
|
|
22
|
+
import { throwError } from 'redux-saga-test-plan/providers';
|
|
19
23
|
|
|
20
24
|
describe('getCdnTransformationConfig saga', () => {
|
|
21
25
|
it("handle valid response from api", () => {
|
|
@@ -187,3 +191,137 @@ describe('getSenderDetails Saga', () => {
|
|
|
187
191
|
);
|
|
188
192
|
});
|
|
189
193
|
});
|
|
194
|
+
|
|
195
|
+
describe('fetchWeCrmAccounts Saga', () => {
|
|
196
|
+
const action = { source: 'CRM' };
|
|
197
|
+
|
|
198
|
+
it('handles successful fetching of WeCRM accounts', () => {
|
|
199
|
+
const fakeResponse = {
|
|
200
|
+
response: [{ id: 1, name: 'Account One' }]
|
|
201
|
+
};
|
|
202
|
+
const generator = fetchWeCrmAccounts(action);
|
|
203
|
+
expect(generator.next().value).toEqual(call(api.fetchWeCrmAccounts, action.source));
|
|
204
|
+
expect(generator.next(fakeResponse).value).toEqual(
|
|
205
|
+
put({
|
|
206
|
+
type: types.GET_WECRM_ACCOUNTS_SUCCESS,
|
|
207
|
+
data: fakeResponse.response
|
|
208
|
+
})
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('handles error thrown from api', () => {
|
|
213
|
+
const error = new Error('Fetch failed');
|
|
214
|
+
expectSaga(fetchWeCrmAccounts, action.source)
|
|
215
|
+
.provide([
|
|
216
|
+
[
|
|
217
|
+
call(api.fetchWeCrmAccounts),
|
|
218
|
+
throwError(error)
|
|
219
|
+
],
|
|
220
|
+
])
|
|
221
|
+
.put({
|
|
222
|
+
type: types.GET_WECRM_ACCOUNTS_FAILURE,
|
|
223
|
+
data: error
|
|
224
|
+
})
|
|
225
|
+
.run();
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
describe('sendZippedFile Saga', () => {
|
|
231
|
+
const action = {
|
|
232
|
+
selectedFile: 'dummyFile.zip',
|
|
233
|
+
errorHandler: jest.fn(),
|
|
234
|
+
successHandler: jest.fn()
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
it('handles successful sending of zipped file', () => {
|
|
238
|
+
const fakeResponse = {
|
|
239
|
+
status: { isError: false },
|
|
240
|
+
response: { metaEntity: { htmlContent: encodeURIComponent('<html></html>') } }
|
|
241
|
+
};
|
|
242
|
+
const generator = sendZippedFile(action);
|
|
243
|
+
expect(generator.next().value).toEqual(call(api.sendZippedFile, action.selectedFile));
|
|
244
|
+
expect(generator.next(fakeResponse).value).toEqual(
|
|
245
|
+
put({
|
|
246
|
+
type: types.SEND_ZIPPED_FILE_SUCCESS,
|
|
247
|
+
selectedTemplate: decodeURIComponent(fakeResponse.response.metaEntity.htmlContent)
|
|
248
|
+
})
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('handles scenario when API result indicates an error', () => {
|
|
253
|
+
const fakeErrorResponse = {
|
|
254
|
+
status: { isError: true },
|
|
255
|
+
message: 'Error processing file'
|
|
256
|
+
};
|
|
257
|
+
const generator = sendZippedFile(action);
|
|
258
|
+
expect(generator.next().value).toEqual(call(api.sendZippedFile, action.selectedFile));
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it('handles error thrown from api', () => {
|
|
262
|
+
const error = new Error('Fetch failed');
|
|
263
|
+
expectSaga(sendZippedFile, action)
|
|
264
|
+
.provide([
|
|
265
|
+
[
|
|
266
|
+
call(api.sendZippedFile),
|
|
267
|
+
throwError(error)
|
|
268
|
+
],
|
|
269
|
+
])
|
|
270
|
+
.put({
|
|
271
|
+
type: types.SEND_ZIPPED_FILE_FAILURE,
|
|
272
|
+
data: error
|
|
273
|
+
})
|
|
274
|
+
.run();
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
describe('fetchUserList Saga', () => {
|
|
279
|
+
|
|
280
|
+
it('handles successful fetching of user list', () => {
|
|
281
|
+
const fakeResponse = {
|
|
282
|
+
data: {
|
|
283
|
+
result: [
|
|
284
|
+
{ id: 1, name: 'User One' },
|
|
285
|
+
{ id: 2, name: 'User Two' }
|
|
286
|
+
]
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
const generator = fetchUserList();
|
|
290
|
+
expect(generator.next().value).toEqual(call(api.getUserList));
|
|
291
|
+
expect(generator.next(fakeResponse).value).toEqual(
|
|
292
|
+
put({
|
|
293
|
+
type: types.GET_USER_LIST_SUCCESS,
|
|
294
|
+
data: fakeResponse.data.result
|
|
295
|
+
})
|
|
296
|
+
);
|
|
297
|
+
expect(generator.next().done).toBe(true);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('handles error thrown from API when fetching user list', () => {
|
|
301
|
+
const error = new Error('Fetch failed');
|
|
302
|
+
const generator = fetchUserList();
|
|
303
|
+
expect(generator.next().value).toEqual(call(api.getUserList));
|
|
304
|
+
expect(generator.throw(error).value).toEqual(
|
|
305
|
+
put({
|
|
306
|
+
type: types.GET_USER_LIST_FAILURE,
|
|
307
|
+
data: error
|
|
308
|
+
})
|
|
309
|
+
);
|
|
310
|
+
expect(generator.next().done).toBe(true);
|
|
311
|
+
});
|
|
312
|
+
it('handles error thrown from api', () => {
|
|
313
|
+
const error = new Error('Fetch failed');
|
|
314
|
+
expectSaga(fetchUserList)
|
|
315
|
+
.provide([
|
|
316
|
+
[
|
|
317
|
+
call(api.getUserList),
|
|
318
|
+
throwError(error)
|
|
319
|
+
],
|
|
320
|
+
])
|
|
321
|
+
.put({
|
|
322
|
+
type: types.GET_USER_LIST_FAILURE,
|
|
323
|
+
data: error
|
|
324
|
+
})
|
|
325
|
+
.run();
|
|
326
|
+
});
|
|
327
|
+
});
|
|
@@ -6,14 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import React from 'react';
|
|
9
|
-
import { all } from 'redux-saga/effects';
|
|
10
9
|
import { connect } from 'react-redux';
|
|
11
10
|
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
|
|
12
11
|
import { createStructuredSelector } from 'reselect';
|
|
13
12
|
import { bindActionCreators, compose } from 'redux';
|
|
14
|
-
import {
|
|
15
|
-
CapTab, CapCustomCard, CapButton, CapHeader, CapSpin, CapIcon, CapTooltip,
|
|
16
|
-
} from '@capillarytech/cap-ui-library';
|
|
13
|
+
import { CapTab, CapCustomCard, CapButton, CapHeader, CapSpin, CapIcon, CapTooltip } from '@capillarytech/cap-ui-library';
|
|
17
14
|
import { find, get } from 'lodash';
|
|
18
15
|
import isEmpty from 'lodash/isEmpty';
|
|
19
16
|
import Helmet from 'react-helmet';
|
|
@@ -33,9 +30,7 @@ import FTP from '../FTP';
|
|
|
33
30
|
import Gallery from '../Assets/Gallery';
|
|
34
31
|
import withStyles from '../../hoc/withStyles';
|
|
35
32
|
import styles, { CapTabStyle } from './TemplatesV2.style';
|
|
36
|
-
import {
|
|
37
|
-
CREATIVES_UI_VIEW, LOYALTY, WHATSAPP, RCS, LINE, EMAIL, ASSETS, JP_LOCALE_HIDE_FEATURE, ZALO, INAPP,
|
|
38
|
-
} from '../App/constants';
|
|
33
|
+
import { CREATIVES_UI_VIEW, LOYALTY, WHATSAPP, RCS, LINE, EMAIL, ASSETS, JP_LOCALE_HIDE_FEATURE, ZALO, INAPP } from '../App/constants';
|
|
39
34
|
import AccessForbidden from '../../v2Components/AccessForbidden';
|
|
40
35
|
import { getObjFromQueryParams } from '../../utils/v2common';
|
|
41
36
|
import { makeSelectAuthenticated, selectCurrentOrgDetails } from "../Cap/selectors";
|
|
@@ -124,15 +119,13 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
124
119
|
// eslint-disable-next-line no-param-reassign
|
|
125
120
|
pane.disabled = true;
|
|
126
121
|
if (pane.key === 'facebook' && showDisabledFBInfo) {
|
|
127
|
-
pane.tab = (
|
|
128
|
-
<CapTooltip
|
|
122
|
+
pane.tab = (<CapTooltip
|
|
129
123
|
title={
|
|
130
124
|
intl.formatMessage(messages.facebookDisableinfo)
|
|
131
125
|
}
|
|
132
126
|
>
|
|
133
127
|
{intl.formatMessage(messages.facebook)}
|
|
134
|
-
</CapTooltip>
|
|
135
|
-
);
|
|
128
|
+
</CapTooltip>);
|
|
136
129
|
}
|
|
137
130
|
}
|
|
138
131
|
return pane;
|
|
@@ -185,15 +178,13 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
185
178
|
this.setState({selectedChannel: nextProps.channel, panes });
|
|
186
179
|
}
|
|
187
180
|
}
|
|
188
|
-
|
|
189
|
-
getTemplateDataForGrid = ({
|
|
190
|
-
templates, handlers, filterContent, channel, isLoading, loadingTip,
|
|
191
|
-
}) => {
|
|
181
|
+
getTemplateDataForGrid = ({templates, handlers, filterContent, channel, isLoading, loadingTip}) => {
|
|
192
182
|
const currentChannel = channel.toUpperCase();
|
|
193
183
|
const cardDataList = templates.map((template) => {
|
|
194
|
-
const templateData =
|
|
184
|
+
const templateData =
|
|
185
|
+
{
|
|
195
186
|
key: `${currentChannel}-card-${template.name}`,
|
|
196
|
-
title: <span title={template.name}>{template.name}</span>,
|
|
187
|
+
title: <span title={template.name} >{template.name}</span>,
|
|
197
188
|
extra: [<CapIcon type="eye" onClick={() => { if (this.props.isFullMode) { handlers.handlePreviewClick(template); } else { this.props.handlePeviewTemplate(template); } }} />],
|
|
198
189
|
hoverOption: <CapButton onClick={(e) => handlers.handleEditClick(e, template._id)}>{this.props.intl.formatMessage(this.props.isFullMode ? messages.edit : messages.select)}</CapButton>,
|
|
199
190
|
};
|
|
@@ -204,8 +195,7 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
204
195
|
}
|
|
205
196
|
return templateData;
|
|
206
197
|
});
|
|
207
|
-
return (
|
|
208
|
-
<div>
|
|
198
|
+
return (<div>
|
|
209
199
|
{filterContent}
|
|
210
200
|
<CapSpin spinning={isLoading} tip={loadingTip}>
|
|
211
201
|
<div className="pagination-container">
|
|
@@ -213,12 +203,9 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
213
203
|
</div>
|
|
214
204
|
</CapSpin>
|
|
215
205
|
|
|
216
|
-
</div>
|
|
217
|
-
);
|
|
206
|
+
</div>);
|
|
218
207
|
}
|
|
219
|
-
|
|
220
|
-
getGalleryComponent = (location) => <Gallery location={location} isFullMode={this.props.isFullMode} />
|
|
221
|
-
|
|
208
|
+
getGalleryComponent = (location) => <Gallery location={location} isFullMode={this.props.isFullMode}/>
|
|
222
209
|
getCallTaskComponent = () => (
|
|
223
210
|
<CallTask
|
|
224
211
|
onCreateNew={this.props.createNew}
|
|
@@ -228,13 +215,11 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
228
215
|
);
|
|
229
216
|
|
|
230
217
|
getFacebookComponent = () => {
|
|
231
|
-
const {
|
|
232
|
-
messageDetails, cap, onFacebookSubmit,
|
|
218
|
+
const { messageDetails, cap, onFacebookSubmit,
|
|
233
219
|
messageStrategy,
|
|
234
220
|
showDisabledFBInfo,
|
|
235
221
|
orgUnitId,
|
|
236
|
-
onSelectTemplate
|
|
237
|
-
} = this.props;
|
|
222
|
+
onSelectTemplate } = this.props;
|
|
238
223
|
return (
|
|
239
224
|
<Facebook
|
|
240
225
|
{...this.props}
|
|
@@ -248,15 +233,12 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
248
233
|
/>
|
|
249
234
|
);
|
|
250
235
|
}
|
|
251
|
-
|
|
252
236
|
getViberComponent =() => (
|
|
253
237
|
<Viber
|
|
254
238
|
{...this.props}
|
|
255
239
|
isCreateFlow
|
|
256
|
-
>
|
|
257
|
-
</Viber>
|
|
240
|
+
></Viber>
|
|
258
241
|
)
|
|
259
|
-
|
|
260
242
|
getLineComponent = () => (
|
|
261
243
|
<Line
|
|
262
244
|
{...this.props}
|
|
@@ -293,8 +275,7 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
293
275
|
case 'assets':
|
|
294
276
|
return this.getGalleryComponent(location);
|
|
295
277
|
default:
|
|
296
|
-
return (
|
|
297
|
-
<Templates
|
|
278
|
+
return (<Templates
|
|
298
279
|
key={channel}
|
|
299
280
|
location={location}
|
|
300
281
|
route={{name: channel}}
|
|
@@ -307,8 +288,7 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
307
288
|
messageStrategy={this.props.messageStrategy}
|
|
308
289
|
smsRegister={smsRegister}
|
|
309
290
|
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
310
|
-
/>
|
|
311
|
-
);
|
|
291
|
+
/>);
|
|
312
292
|
}
|
|
313
293
|
}
|
|
314
294
|
|
|
@@ -330,17 +310,13 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
330
310
|
const panes = this.setChannelContent(selectedChannel, this.state.panes);
|
|
331
311
|
this.setState({panes, selectedChannel}, () => { if (!this.props.isFullMode) this.props.onChannelChange(selectedChannel); });
|
|
332
312
|
}
|
|
333
|
-
|
|
334
313
|
selectTemplate = (id) => find(this.props.TemplatesList, {_id: id})
|
|
335
314
|
|
|
336
315
|
isLoading() {
|
|
337
316
|
return this.props.Templates.loadingTemplates;
|
|
338
317
|
}
|
|
339
|
-
|
|
340
318
|
render() {
|
|
341
|
-
const {
|
|
342
|
-
isFullMode, className, cap = {}, authData = {},
|
|
343
|
-
} = this.props;
|
|
319
|
+
const { isFullMode, className, cap = {}, authData = {}} = this.props;
|
|
344
320
|
const { accessiblePermissions = []} = cap.user || authData.user || {};
|
|
345
321
|
let isCreativeAccessible = true;
|
|
346
322
|
if (!accessiblePermissions.includes(CREATIVES_UI_VIEW)) {
|
|
@@ -349,16 +325,14 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
349
325
|
return (
|
|
350
326
|
!isCreativeAccessible ? <AccessForbidden /> : (
|
|
351
327
|
<div className={`${className} creatives-templates-container ${isFullMode ? 'fullmode' : 'library-mode'}`} data-testid="cap-wrapper">
|
|
352
|
-
{isFullMode &&
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
/>
|
|
359
|
-
)}
|
|
328
|
+
{isFullMode && <Helmet
|
|
329
|
+
title={this.props.intl.formatMessage(messages.creatives)}
|
|
330
|
+
meta={[
|
|
331
|
+
{ name: 'description', content: this.props.intl.formatMessage(messages.creativesDesc) },
|
|
332
|
+
]}
|
|
333
|
+
/>}
|
|
360
334
|
<div className="component-wrapper">
|
|
361
|
-
{isFullMode && <CapHeader title={<FormattedMessage {...messages.creatives}
|
|
335
|
+
{isFullMode && <CapHeader title={<FormattedMessage {...messages.creatives}/>} description={<FormattedMessage {...messages.creativesDesc}/>}/>}
|
|
362
336
|
<StyledCapTab
|
|
363
337
|
panes={this.state.panes}
|
|
364
338
|
onChange={this.channelChange}
|
|
@@ -403,7 +377,7 @@ TemplatesV2.defaultProps = {
|
|
|
403
377
|
};
|
|
404
378
|
|
|
405
379
|
const mapStateToProps = createStructuredSelector({
|
|
406
|
-
|
|
380
|
+
cap: makeSelectAuthenticated(),
|
|
407
381
|
Templates: makeSelectTemplates(),
|
|
408
382
|
TemplatesList: makeSelectTemplatesResponse(),
|
|
409
383
|
currentOrgDetails: selectCurrentOrgDetails(),
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { expectSaga } from 'redux-saga-test-plan';
|
|
2
|
+
import { call, put } from 'redux-saga/effects';
|
|
3
|
+
import { throwError } from 'redux-saga-test-plan/providers';
|
|
4
|
+
import * as Api from '../../../services/api';
|
|
5
|
+
import * as sagas from '../sagas';
|
|
6
|
+
import { v2ViberSagas } from '../sagas';
|
|
7
|
+
import * as types from '../constants';
|
|
8
|
+
|
|
9
|
+
describe('Viber Sagas', () => {
|
|
10
|
+
|
|
11
|
+
describe('uploadViberAsset Saga', () => {
|
|
12
|
+
const file = new Blob(['file contents'], { type: 'text/plain' });
|
|
13
|
+
const assetType = 'image';
|
|
14
|
+
const fileParams = { directory: 'profile', templateType: 'viber' };
|
|
15
|
+
|
|
16
|
+
it('handles uploading asset successfully', () => {
|
|
17
|
+
const fakeResponse = {
|
|
18
|
+
response: { asset: { id: 1, url: 'http://example.com/image.png' } },
|
|
19
|
+
status: { code: 200 }
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return expectSaga(sagas.uploadViberAsset, file, assetType, fileParams)
|
|
23
|
+
.provide([
|
|
24
|
+
[call(Api.uploadFile, file, assetType, fileParams), fakeResponse]
|
|
25
|
+
])
|
|
26
|
+
.put({
|
|
27
|
+
type: types.UPLOAD_VIBER_ASSET_SUCCESS,
|
|
28
|
+
data: fakeResponse.response.asset,
|
|
29
|
+
statusCode: fakeResponse.status.code,
|
|
30
|
+
templateType: undefined
|
|
31
|
+
})
|
|
32
|
+
.run();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('handles asset upload failure', () => {
|
|
36
|
+
const error = new Error('Upload failed');
|
|
37
|
+
|
|
38
|
+
return expectSaga(sagas.uploadViberAsset, file, assetType, fileParams)
|
|
39
|
+
.provide([
|
|
40
|
+
[call(Api.uploadFile, file, assetType, fileParams), throwError(error)]
|
|
41
|
+
])
|
|
42
|
+
.put({
|
|
43
|
+
type: types.UPLOAD_VIBER_ASSET_FAILURE,
|
|
44
|
+
error
|
|
45
|
+
})
|
|
46
|
+
.run();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('createViberTemplate Saga', () => {
|
|
51
|
+
const template = { content: 'New Viber Template' };
|
|
52
|
+
const callback = jest.fn();
|
|
53
|
+
|
|
54
|
+
it('handles creating template successfully', () => {
|
|
55
|
+
const fakeResponse = {
|
|
56
|
+
response: { id: 2, content: template.content },
|
|
57
|
+
status: { code: 201 }
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return expectSaga(sagas.createViberTemplate, { template, callback })
|
|
61
|
+
.provide([
|
|
62
|
+
[call(Api.createViberTemplate, { template }), fakeResponse]
|
|
63
|
+
])
|
|
64
|
+
.put({
|
|
65
|
+
type: types.CREATE_VIBER_TEMPLATE_SUCCESS,
|
|
66
|
+
data: fakeResponse.response,
|
|
67
|
+
statusCode: fakeResponse.status.code,
|
|
68
|
+
errorMsg: undefined
|
|
69
|
+
})
|
|
70
|
+
.run()
|
|
71
|
+
.then(() => {
|
|
72
|
+
expect(callback).toHaveBeenCalledWith(fakeResponse.response);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('handles failure in creating template', () => {
|
|
77
|
+
const error = new Error({ message: 'Creation failed', status: { code: 400 } });
|
|
78
|
+
|
|
79
|
+
const errorMsg = 'Creation failed';
|
|
80
|
+
return expectSaga(sagas.createViberTemplate, { template, callback })
|
|
81
|
+
.provide([
|
|
82
|
+
[call(Api.createViberTemplate, { template }), throwError(error)]
|
|
83
|
+
])
|
|
84
|
+
.put({
|
|
85
|
+
type: types.CREATE_VIBER_TEMPLATE_FAILURE,
|
|
86
|
+
error,
|
|
87
|
+
errorMsg : undefined
|
|
88
|
+
})
|
|
89
|
+
.run()
|
|
90
|
+
.then(() => {
|
|
91
|
+
expect(callback).toHaveBeenCalledWith(null, undefined);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('editTemplate Saga', () => {
|
|
97
|
+
const template = { id: 1, content: 'Updated Content' };
|
|
98
|
+
const callback = jest.fn();
|
|
99
|
+
|
|
100
|
+
it('handles editing template successfully', () => {
|
|
101
|
+
const fakeResponse = {
|
|
102
|
+
response: { updated: true },
|
|
103
|
+
status: { code: 200 }
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
return expectSaga(sagas.editTemplate, { template, callback })
|
|
107
|
+
.provide([
|
|
108
|
+
[call(Api.createViberTemplate, { template }), fakeResponse]
|
|
109
|
+
])
|
|
110
|
+
.put({
|
|
111
|
+
type: types.EDIT_VIBER_TEMPLATE_SUCCESS,
|
|
112
|
+
data: fakeResponse.response,
|
|
113
|
+
statusCode: fakeResponse.status.code,
|
|
114
|
+
errorMsg: undefined
|
|
115
|
+
})
|
|
116
|
+
.run()
|
|
117
|
+
.then(() => {
|
|
118
|
+
expect(callback).toHaveBeenCalledWith(fakeResponse.response);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('handles failure in editing template', () => {
|
|
123
|
+
const errorMsg = 'Error in editing template';
|
|
124
|
+
return expectSaga(sagas.editTemplate, { template, callback })
|
|
125
|
+
.provide([
|
|
126
|
+
[call(Api.createViberTemplate, { template }), throwError({ message: errorMsg, status: { code: 400 } })]
|
|
127
|
+
])
|
|
128
|
+
.put({
|
|
129
|
+
type: types.EDIT_VIBER_TEMPLATE_FAILURE,
|
|
130
|
+
error: { message: 'Error in editing template', status: { code: 400 } },
|
|
131
|
+
errorMsg: undefined,
|
|
132
|
+
})
|
|
133
|
+
.run()
|
|
134
|
+
.then(() => {
|
|
135
|
+
expect(callback).toHaveBeenCalledWith(null, undefined);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe('getTemplateDetails Saga', () => {
|
|
141
|
+
const id = '123';
|
|
142
|
+
const callback = jest.fn();
|
|
143
|
+
|
|
144
|
+
it('handles fetching template details successfully', () => {
|
|
145
|
+
const fakeResponse = {
|
|
146
|
+
response: { id: id, name: 'Detailed Template' }
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
return expectSaga(sagas.getTemplateDetails, { id, callback })
|
|
150
|
+
.provide([
|
|
151
|
+
[call(Api.getTemplateDetails, { id, channel: 'VIBER' }), fakeResponse]
|
|
152
|
+
])
|
|
153
|
+
.put({
|
|
154
|
+
type: types.GET_VIBER_TEMPLATE_DETAILS_SUCCESS,
|
|
155
|
+
data: fakeResponse.response
|
|
156
|
+
})
|
|
157
|
+
.run()
|
|
158
|
+
.then(() => {
|
|
159
|
+
expect(callback).not.toHaveBeenCalledWith(0);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('handles failure in fetching template details', () => {
|
|
164
|
+
const error = new Error('Fetch failed');
|
|
165
|
+
|
|
166
|
+
return expectSaga(sagas.getTemplateDetails, { id, callback })
|
|
167
|
+
.provide([
|
|
168
|
+
[call(Api.getTemplateDetails, { id, channel: 'VIBER' }), throwError(error)]
|
|
169
|
+
])
|
|
170
|
+
.put({
|
|
171
|
+
type: types.GET_VIBER_TEMPLATE_DETAILS_FAILURE,
|
|
172
|
+
error
|
|
173
|
+
})
|
|
174
|
+
.run()
|
|
175
|
+
.then(() => {
|
|
176
|
+
expect(callback).not.toHaveBeenCalledWith();
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
describe('v2ViberSagas Combined', () => {
|
|
182
|
+
it('should initialize all Viber-related watcher sagas without error', () => {
|
|
183
|
+
return expectSaga(v2ViberSagas).run();
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
});
|