@capillarytech/creatives-library 9.0.15-alpha.3 → 9.0.16-beta.0
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/AppRoot.js +80 -0
- package/app.js +5 -3
- package/constants/unified.js +0 -29
- package/entry.js +67 -1
- package/global-styles.js +1 -1
- package/mfe-exposed-components.js +2 -4
- package/package.json +2 -2
- package/services/api.js +1 -1
- package/services/tests/api.test.js +20 -35
- package/styles/containers/layout/_layoutPage.scss +8 -6
- package/utils/commonUtils.js +1 -19
- package/utils/getDataLayer.js +15 -0
- package/utils/gtmTrackers/gtmEvents/creativeDetails.js +2 -1
- package/utils/mfeDetect.js +1 -0
- package/v2Components/CapActionButton/constants.js +1 -8
- package/v2Components/CapActionButton/index.js +144 -202
- package/v2Components/CapActionButton/index.scss +14 -232
- package/v2Components/CapActionButton/messages.js +3 -19
- package/v2Components/CapActionButton/tests/index.test.js +18 -42
- package/v2Components/CapImageUpload/index.js +2 -2
- package/v2Components/CapTagList/index.js +0 -10
- package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +48 -70
- package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +2 -8
- package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +21 -214
- package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +0 -16
- package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +9 -83
- package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +0 -30
- package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +11 -60
- package/v2Components/CommonTestAndPreview/SendTestMessage.js +5 -10
- package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +22 -202
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +80 -381
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +8 -155
- package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +0 -11
- package/v2Components/CommonTestAndPreview/constants.js +2 -38
- package/v2Components/CommonTestAndPreview/index.js +222 -761
- package/v2Components/CommonTestAndPreview/messages.js +3 -45
- package/v2Components/CommonTestAndPreview/sagas.js +6 -25
- package/v2Components/CommonTestAndPreview/tests/CommonTestAndPreview.addTestCustomer.test.js +0 -1
- package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +267 -284
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +65 -231
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +5 -118
- package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +0 -341
- package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +1 -8
- package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +13 -34
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +283 -281
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +1 -199
- package/v2Components/CommonTestAndPreview/tests/index.test.js +4 -133
- package/v2Components/CommonTestAndPreview/tests/sagas.test.js +24 -31
- package/v2Components/NavigationBar/index.js +9 -7
- package/v2Components/NavigationBar/mfeModuleHeader.config.js +16 -0
- package/v2Components/Pagination/_pagination.scss +2 -0
- package/v2Components/TemplatePreview/_templatePreview.scss +25 -45
- package/v2Components/TemplatePreview/index.js +32 -147
- package/v2Components/TemplatePreview/tests/index.test.js +0 -142
- package/v2Components/TestAndPreviewSlidebox/CustomValuesEditor.js +6 -6
- package/v2Components/TestAndPreviewSlidebox/index.js +1 -13
- package/v2Components/TestAndPreviewSlidebox/sagas.js +4 -11
- package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +1 -3
- package/v2Containers/Cap/constants.js +1 -0
- package/v2Containers/Cap/index.js +47 -21
- package/v2Containers/Cap/sagas.js +19 -0
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +1 -4
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +0 -4
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +20 -20
- package/v2Containers/CreativesContainer/SlideBoxContent.js +7 -37
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +5 -14
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +5 -36
- package/v2Containers/CreativesContainer/constants.js +0 -11
- package/v2Containers/CreativesContainer/index.js +104 -323
- package/v2Containers/CreativesContainer/index.scss +1 -83
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +34 -79
- package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +16 -79
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -8
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +90 -333
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +15 -20
- package/v2Containers/CreativesContainer/tests/index.test.js +9 -71
- package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
- package/v2Containers/Rcs/constants.js +11 -131
- package/v2Containers/Rcs/index.js +829 -2682
- package/v2Containers/Rcs/index.scss +8 -443
- package/v2Containers/Rcs/messages.js +6 -45
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +39409 -74176
- package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +74 -10
- package/v2Containers/Rcs/tests/index.test.js +40 -151
- package/v2Containers/Rcs/tests/mockData.js +0 -38
- package/v2Containers/Rcs/tests/utils.test.js +30 -643
- package/v2Containers/Rcs/utils.js +12 -466
- package/v2Containers/Sms/Create/index.js +48 -115
- package/v2Containers/SmsTrai/Create/index.js +4 -9
- package/v2Containers/SmsTrai/Edit/constants.js +0 -2
- package/v2Containers/SmsTrai/Edit/index.js +169 -678
- package/v2Containers/SmsTrai/Edit/messages.js +4 -14
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +2854 -5455
- package/v2Containers/SmsWrapper/index.js +8 -37
- package/v2Containers/TagList/index.js +0 -6
- package/v2Containers/Templates/_templates.scss +11 -196
- package/v2Containers/Templates/actions.js +0 -11
- package/v2Containers/Templates/constants.js +0 -2
- package/v2Containers/Templates/index.js +60 -131
- package/v2Containers/Templates/sagas.js +13 -57
- package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1015 -1060
- package/v2Containers/Templates/tests/sagas.test.js +16 -199
- package/v2Containers/TemplatesV2/TemplatesV2.style.js +10 -75
- package/v2Containers/TemplatesV2/index.js +43 -86
- package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -9
- package/v2Containers/Whatsapp/index.js +25 -4
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -578
- package/utils/rcsPayloadUtils.js +0 -92
- package/utils/templateVarUtils.js +0 -201
- package/utils/tests/rcsPayloadUtils.test.js +0 -226
- package/utils/tests/templateVarUtils.test.js +0 -204
- package/v2Components/CommonTestAndPreview/previewApiUtils.js +0 -59
- package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +0 -67
- package/v2Components/CommonTestAndPreview/utils.js +0 -84
- package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +0 -91
- package/v2Components/SmsFallback/constants.js +0 -94
- package/v2Components/SmsFallback/index.js +0 -958
- package/v2Components/SmsFallback/index.scss +0 -266
- package/v2Components/SmsFallback/messages.js +0 -78
- package/v2Components/SmsFallback/smsFallbackUtils.js +0 -120
- package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +0 -50
- package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +0 -147
- package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +0 -304
- package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +0 -208
- package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +0 -309
- package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +0 -422
- package/v2Components/SmsFallback/useLocalTemplateList.js +0 -92
- package/v2Components/TemplatePreview/constants.js +0 -2
- package/v2Components/VarSegmentMessageEditor/constants.js +0 -2
- package/v2Components/VarSegmentMessageEditor/index.js +0 -125
- package/v2Components/VarSegmentMessageEditor/index.scss +0 -46
- package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +0 -17
- package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +0 -79
- package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +0 -90
- package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +0 -258
- package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +0 -125
- package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +0 -227
- package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +0 -318
- package/v2Containers/Sms/smsFormDataHelpers.js +0 -67
- package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +0 -253
- package/v2Containers/SmsTrai/Edit/index.scss +0 -126
- package/v2Containers/Templates/TemplatesActionBar.js +0 -101
- package/v2Containers/Templates/tests/TemplatesActionBar.test.js +0 -120
- package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +0 -180
- package/v2Containers/Templates/utils/smsTemplatesListApi.js +0 -79
- package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +0 -131
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
import { expectSaga } from 'redux-saga-test-plan';
|
|
2
|
-
import {
|
|
3
|
-
take, call, takeLatest, takeEvery, put,
|
|
4
|
-
} from 'redux-saga/effects';
|
|
5
2
|
import * as matchers from 'redux-saga-test-plan/matchers';
|
|
6
3
|
import { throwError } from 'redux-saga-test-plan/providers';
|
|
4
|
+
import { call, takeLatest, put } from 'redux-saga/effects';
|
|
7
5
|
import * as api from '../../../services/api';
|
|
8
6
|
import * as types from '../constants';
|
|
9
7
|
import * as cdnUtils from '../../../utils/cdnTransformation';
|
|
10
8
|
import {
|
|
11
9
|
getCdnTransformationConfig,
|
|
12
10
|
getAllTemplates,
|
|
13
|
-
getLocalSmsTemplates,
|
|
14
11
|
watchGetCdnTransformationConfig,
|
|
15
12
|
watchGetAllTemplates,
|
|
16
13
|
getSenderDetails,
|
|
17
14
|
fetchWeCrmAccounts,
|
|
18
15
|
sendZippedFile,
|
|
19
16
|
fetchUserList,
|
|
17
|
+
watchGetUserList,
|
|
20
18
|
deleteRcsTemplate,
|
|
21
19
|
watchDeleteRcsTemplate,
|
|
22
20
|
watchForGetTemplateInfoById,
|
|
@@ -41,14 +39,10 @@ import {
|
|
|
41
39
|
watchUnarchiveTemplate,
|
|
42
40
|
watchBulkArchive,
|
|
43
41
|
watchBulkUnarchive,
|
|
44
|
-
watchGetUserList,
|
|
45
42
|
} from '../sagas';
|
|
46
|
-
|
|
47
|
-
import * as mockData from './mockData';
|
|
48
|
-
import { fetchSmsTemplatesFromQuery } from '../utils/smsTemplatesListApi';
|
|
49
|
-
import { ZALO } from '../../CreativesContainer/constants';
|
|
50
|
-
import { VIET_GUYS, ZALO_TEMPLATE_INFO_REQUEST } from '../../Zalo/constants';
|
|
51
43
|
import { getTemplateInfoById } from '../../Zalo/saga';
|
|
44
|
+
import { ZALO_TEMPLATE_INFO_REQUEST } from '../../Zalo/constants';
|
|
45
|
+
import * as mockData from './mockData';
|
|
52
46
|
|
|
53
47
|
jest.mock('@capillarytech/cap-ui-library', () => ({
|
|
54
48
|
CapNotification: {
|
|
@@ -173,8 +167,8 @@ describe('templateList saga', () => {
|
|
|
173
167
|
],
|
|
174
168
|
]).put({
|
|
175
169
|
type: types.GET_ALL_TEMPLATES_SUCCESS,
|
|
176
|
-
data: mockData.getAllTemplatesListSuccess
|
|
177
|
-
weCRMTemplate: mockData.getAllTemplatesListSuccess
|
|
170
|
+
data: mockData.getAllTemplatesListSuccess,
|
|
171
|
+
weCRMTemplate: mockData.getAllTemplatesListSuccess,
|
|
178
172
|
isReset: mockData.getAllTemplatesListSuccess?.queryParams?.page === 1,
|
|
179
173
|
})
|
|
180
174
|
.run();
|
|
@@ -190,8 +184,8 @@ describe('templateList saga', () => {
|
|
|
190
184
|
],
|
|
191
185
|
]).put({
|
|
192
186
|
type: types.GET_ALL_TEMPLATES_SUCCESS,
|
|
193
|
-
data: mockData.getAllTemplatesListSuccess
|
|
194
|
-
weCRMTemplate: mockData.getAllTemplatesListSuccess
|
|
187
|
+
data: mockData.getAllTemplatesListSuccess,
|
|
188
|
+
weCRMTemplate: mockData.getAllTemplatesListSuccess,
|
|
195
189
|
isReset: mockData.getAllTemplatesListSuccess?.queryParams?.page === 1,
|
|
196
190
|
})
|
|
197
191
|
.run();
|
|
@@ -210,163 +204,6 @@ describe('templateList saga', () => {
|
|
|
210
204
|
})
|
|
211
205
|
.run();
|
|
212
206
|
});
|
|
213
|
-
|
|
214
|
-
it('SMS channel uses fetchSmsTemplatesFromQuery', () => {
|
|
215
|
-
const smsAction = {
|
|
216
|
-
type: types.GET_ALL_TEMPLATES_REQUEST,
|
|
217
|
-
channel: 'Sms',
|
|
218
|
-
queryParams: { page: 1, perPage: 25, name: '', sortBy: 'Most Recent' },
|
|
219
|
-
intlCopyOf: 'Kopie',
|
|
220
|
-
};
|
|
221
|
-
const fetched = {
|
|
222
|
-
channelTemplates: { templates: [{ name: 'Kopie Foo' }], totalCount: 1 },
|
|
223
|
-
weCRMTemplate: undefined,
|
|
224
|
-
raw: {},
|
|
225
|
-
};
|
|
226
|
-
return expectSaga(getAllTemplates, smsAction)
|
|
227
|
-
.provide([
|
|
228
|
-
[call(fetchSmsTemplatesFromQuery, smsAction.queryParams, smsAction.intlCopyOf), fetched],
|
|
229
|
-
])
|
|
230
|
-
.put({
|
|
231
|
-
type: types.GET_ALL_TEMPLATES_SUCCESS,
|
|
232
|
-
data: fetched.channelTemplates,
|
|
233
|
-
weCRMTemplate: fetched.weCRMTemplate,
|
|
234
|
-
isReset: true,
|
|
235
|
-
})
|
|
236
|
-
.run();
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
it('SMS channel propagates fetchSmsTemplatesFromQuery errors', () => {
|
|
240
|
-
const smsAction = {
|
|
241
|
-
type: types.GET_ALL_TEMPLATES_REQUEST,
|
|
242
|
-
channel: 'SMS',
|
|
243
|
-
queryParams: { page: 2, perPage: 25 },
|
|
244
|
-
intlCopyOf: '',
|
|
245
|
-
};
|
|
246
|
-
const error = new Error('sms list fail');
|
|
247
|
-
return expectSaga(getAllTemplates, smsAction)
|
|
248
|
-
.provide([
|
|
249
|
-
[call(fetchSmsTemplatesFromQuery, smsAction.queryParams, smsAction.intlCopyOf), throwError(error)],
|
|
250
|
-
])
|
|
251
|
-
.put({
|
|
252
|
-
type: types.GET_ALL_TEMPLATES_FAILURE,
|
|
253
|
-
error,
|
|
254
|
-
})
|
|
255
|
-
.run();
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
it('wechat channel merges mapped and richmedia and applies Most Recent sort', () => {
|
|
259
|
-
const wechatApiResponse = {
|
|
260
|
-
response: {
|
|
261
|
-
mapped: [
|
|
262
|
-
{ name: 'B', updatedAt: '2024-01-02T00:00:00Z' },
|
|
263
|
-
{ name: 'A', updatedAt: '2024-01-01T00:00:00Z' },
|
|
264
|
-
],
|
|
265
|
-
richmedia: [{ name: 'C', updatedAt: '2024-01-03T00:00:00Z' }],
|
|
266
|
-
unMapped: [],
|
|
267
|
-
},
|
|
268
|
-
};
|
|
269
|
-
const action = {
|
|
270
|
-
channel: 'wechat',
|
|
271
|
-
queryParams: { sortBy: 'Most Recent', page: 1 },
|
|
272
|
-
intlCopyOf: '',
|
|
273
|
-
};
|
|
274
|
-
return expectSaga(getAllTemplates, action)
|
|
275
|
-
.provide([[matchers.call.fn(api.getAllTemplates), wechatApiResponse]])
|
|
276
|
-
.put.actionType(types.GET_ALL_TEMPLATES_SUCCESS)
|
|
277
|
-
.run();
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
it('wechat channel applies Alphabetically sort', () => {
|
|
281
|
-
const wechatApiResponse = {
|
|
282
|
-
response: {
|
|
283
|
-
mapped: [{ name: 'Zebra', updatedAt: '2024-01-02T00:00:00Z' }],
|
|
284
|
-
richmedia: [{ name: 'Apple', updatedAt: '2024-01-01T00:00:00Z' }],
|
|
285
|
-
unMapped: [],
|
|
286
|
-
},
|
|
287
|
-
};
|
|
288
|
-
const action = {
|
|
289
|
-
channel: 'wechat',
|
|
290
|
-
queryParams: { sortBy: 'Alphabetically', page: 1 },
|
|
291
|
-
intlCopyOf: '',
|
|
292
|
-
};
|
|
293
|
-
return expectSaga(getAllTemplates, action)
|
|
294
|
-
.provide([[matchers.call.fn(api.getAllTemplates), wechatApiResponse]])
|
|
295
|
-
.put.actionType(types.GET_ALL_TEMPLATES_SUCCESS)
|
|
296
|
-
.run();
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
it('wechat channel replaces Copy-of prefix when intlCopyOf is set', () => {
|
|
300
|
-
const wechatApiResponse = {
|
|
301
|
-
response: {
|
|
302
|
-
mapped: [{ name: 'Copy of Promo', updatedAt: '2024-01-01T00:00:00Z' }],
|
|
303
|
-
richmedia: [],
|
|
304
|
-
unMapped: [],
|
|
305
|
-
},
|
|
306
|
-
};
|
|
307
|
-
const action = {
|
|
308
|
-
channel: 'wechat',
|
|
309
|
-
queryParams: { page: 1 },
|
|
310
|
-
intlCopyOf: 'Kopia av ',
|
|
311
|
-
};
|
|
312
|
-
return expectSaga(getAllTemplates, action)
|
|
313
|
-
.provide([[matchers.call.fn(api.getAllTemplates), wechatApiResponse]])
|
|
314
|
-
.put.actionType(types.GET_ALL_TEMPLATES_SUCCESS)
|
|
315
|
-
.run();
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
describe('getLocalSmsTemplates saga', () => {
|
|
320
|
-
it('invokes onSuccess with fetched data', () => {
|
|
321
|
-
const onSuccess = jest.fn();
|
|
322
|
-
const action = {
|
|
323
|
-
queryParams: { page: 1 },
|
|
324
|
-
intlCopyOf: '',
|
|
325
|
-
onSuccess,
|
|
326
|
-
};
|
|
327
|
-
const fetched = { channelTemplates: { templates: [] }, raw: {} };
|
|
328
|
-
return expectSaga(getLocalSmsTemplates, action)
|
|
329
|
-
.provide([[call(fetchSmsTemplatesFromQuery, action.queryParams, action.intlCopyOf), fetched]])
|
|
330
|
-
.call(onSuccess, fetched)
|
|
331
|
-
.run();
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
it('invokes onFailure when fetch throws', () => {
|
|
335
|
-
const onFailure = jest.fn();
|
|
336
|
-
const error = new Error('local list fail');
|
|
337
|
-
const action = {
|
|
338
|
-
queryParams: { page: 1 },
|
|
339
|
-
intlCopyOf: 'Kopie',
|
|
340
|
-
onFailure,
|
|
341
|
-
};
|
|
342
|
-
return expectSaga(getLocalSmsTemplates, action)
|
|
343
|
-
.provide([
|
|
344
|
-
[call(fetchSmsTemplatesFromQuery, action.queryParams, action.intlCopyOf), throwError(error)],
|
|
345
|
-
])
|
|
346
|
-
.call(onFailure, error)
|
|
347
|
-
.run();
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
it('does not throw when callbacks are omitted', () => {
|
|
351
|
-
const action = { queryParams: { page: 1 }, intlCopyOf: '' };
|
|
352
|
-
return expectSaga(getLocalSmsTemplates, action)
|
|
353
|
-
.provide([
|
|
354
|
-
[call(fetchSmsTemplatesFromQuery, action.queryParams, action.intlCopyOf), throwError(new Error('x'))],
|
|
355
|
-
])
|
|
356
|
-
.run();
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
it('does not call onSuccess when it is not a function', () => {
|
|
360
|
-
const action = {
|
|
361
|
-
queryParams: { page: 1 },
|
|
362
|
-
intlCopyOf: '',
|
|
363
|
-
onSuccess: 'not-a-fn',
|
|
364
|
-
};
|
|
365
|
-
const fetched = { channelTemplates: { templates: [] } };
|
|
366
|
-
return expectSaga(getLocalSmsTemplates, action)
|
|
367
|
-
.provide([[call(fetchSmsTemplatesFromQuery, action.queryParams, action.intlCopyOf), fetched]])
|
|
368
|
-
.run();
|
|
369
|
-
});
|
|
370
207
|
});
|
|
371
208
|
|
|
372
209
|
describe('watchForTemplates saga', () => {
|
|
@@ -560,7 +397,7 @@ describe('getSenderDetails Saga', () => {
|
|
|
560
397
|
|
|
561
398
|
describe('fetchWeCrmAccounts Saga', () => {
|
|
562
399
|
const action = { source: 'CRM' };
|
|
563
|
-
|
|
400
|
+
test.concurrent('handles successful fetching of WeCRM accounts', () => {
|
|
564
401
|
const fakeResponse = {
|
|
565
402
|
response: [{ id: 1, name: 'Account One' }]
|
|
566
403
|
};
|
|
@@ -573,11 +410,14 @@ describe('fetchWeCrmAccounts Saga', () => {
|
|
|
573
410
|
})
|
|
574
411
|
);
|
|
575
412
|
});
|
|
576
|
-
|
|
413
|
+
test.concurrent('handles error thrown from api', () => {
|
|
577
414
|
const error = new Error('Fetch failed');
|
|
578
|
-
expectSaga(fetchWeCrmAccounts, action)
|
|
415
|
+
expectSaga(fetchWeCrmAccounts, action.source)
|
|
579
416
|
.provide([
|
|
580
|
-
[
|
|
417
|
+
[
|
|
418
|
+
call(api.fetchWeCrmAccounts),
|
|
419
|
+
throwError(error)
|
|
420
|
+
],
|
|
581
421
|
])
|
|
582
422
|
.put({
|
|
583
423
|
type: types.GET_WECRM_ACCOUNTS_FAILURE,
|
|
@@ -619,29 +459,6 @@ describe('sendZippedFile Saga', () => {
|
|
|
619
459
|
expect(generator.next().value).toEqual(call(api.sendZippedFile, action.selectedFile));
|
|
620
460
|
});
|
|
621
461
|
|
|
622
|
-
it('calls errorHandler with message and returns early when isError is true', () => {
|
|
623
|
-
const errorHandler = jest.fn();
|
|
624
|
-
const successHandler = jest.fn();
|
|
625
|
-
const errorAction = {
|
|
626
|
-
selectedFile: 'upload.zip',
|
|
627
|
-
errorHandler,
|
|
628
|
-
successHandler,
|
|
629
|
-
};
|
|
630
|
-
const fakeErrorResponse = {
|
|
631
|
-
status: { isError: true },
|
|
632
|
-
message: 'Upload failed',
|
|
633
|
-
};
|
|
634
|
-
const generator = sendZippedFile(errorAction);
|
|
635
|
-
expect(generator.next().value).toEqual(call(api.sendZippedFile, errorAction.selectedFile));
|
|
636
|
-
// Advancing with isError response causes the saga to call errorHandler and yield
|
|
637
|
-
const yieldStep = generator.next(fakeErrorResponse);
|
|
638
|
-
expect(errorHandler).toHaveBeenCalledWith('Upload failed');
|
|
639
|
-
expect(yieldStep.done).toBe(false);
|
|
640
|
-
// After resuming from the yield, the return statement completes the generator
|
|
641
|
-
expect(generator.next().done).toBe(true);
|
|
642
|
-
expect(successHandler).not.toHaveBeenCalled();
|
|
643
|
-
});
|
|
644
|
-
|
|
645
462
|
it('handles error thrown from api', () => {
|
|
646
463
|
const error = new Error('Fetch failed');
|
|
647
464
|
expectSaga(sendZippedFile, action)
|
|
@@ -1407,7 +1224,7 @@ describe('v2TemplateSaga', () => {
|
|
|
1407
1224
|
// all() returns an IO object with an ALL key containing the array of effects
|
|
1408
1225
|
expect(step.value).toHaveProperty('@@redux-saga/IO', true);
|
|
1409
1226
|
expect(step.value).toHaveProperty('ALL');
|
|
1410
|
-
expect(step.value.ALL).toHaveLength(
|
|
1227
|
+
expect(step.value.ALL).toHaveLength(14);
|
|
1411
1228
|
expect(step.done).toBe(false);
|
|
1412
1229
|
});
|
|
1413
1230
|
});
|
|
@@ -10,10 +10,10 @@ export default css`
|
|
|
10
10
|
|
|
11
11
|
.component-wrapper {
|
|
12
12
|
${(props) => props.isFullMode ? `
|
|
13
|
-
max-width:
|
|
14
|
-
margin: 0
|
|
13
|
+
max-width: 100%;
|
|
14
|
+
margin: 0;
|
|
15
15
|
width: 100%;
|
|
16
|
-
padding: 0
|
|
16
|
+
padding: 0;
|
|
17
17
|
/* Only main channel tabs content, not HTML Editor validation panel tabs */
|
|
18
18
|
> .cap-tab-v2 > .ant-tabs-content-holder > .ant-tabs-content,
|
|
19
19
|
> .cap-tab-v2 > .ant-tabs-content {
|
|
@@ -23,80 +23,15 @@ export default css`
|
|
|
23
23
|
height: calc(100vh - 11.25rem);
|
|
24
24
|
} `}
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
/* SMS fallback / local list: single pane skips .cap-tab-v2, so flex-fill the grid instead of viewport-fixed pagination height */
|
|
28
|
-
.creatives-templates-container--local-sms.library-mode {
|
|
29
|
-
display: flex;
|
|
30
|
-
flex-direction: column;
|
|
31
|
-
flex: 1;
|
|
32
|
-
min-height: 0;
|
|
33
|
-
height: 100%;
|
|
34
|
-
|
|
35
|
-
.component-wrapper {
|
|
36
|
-
display: flex;
|
|
37
|
-
flex-direction: column;
|
|
38
|
-
flex: 1;
|
|
39
|
-
min-height: 0;
|
|
40
|
-
height: 100%;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.templates-v2-local-sms-pane {
|
|
44
|
-
display: flex;
|
|
45
|
-
flex-direction: column;
|
|
46
|
-
flex: 1;
|
|
47
|
-
min-height: 0;
|
|
48
|
-
overflow: hidden;
|
|
49
|
-
height: 100%;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.templates-v2-local-sms-pane .creatives-templates-list.library-mode {
|
|
53
|
-
display: flex;
|
|
54
|
-
flex-direction: column;
|
|
55
|
-
flex: 1;
|
|
56
|
-
min-height: 0;
|
|
57
|
-
overflow: hidden;
|
|
58
|
-
height: 100%;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.templates-v2-local-sms-pane .creatives-templates-list.library-mode > .cap-row:first-of-type {
|
|
62
|
-
flex: 1;
|
|
63
|
-
min-height: 0;
|
|
64
|
-
display: flex;
|
|
65
|
-
flex-direction: column;
|
|
66
|
-
overflow: hidden;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.templates-v2-local-sms-pane .creatives-templates-list.library-mode > .cap-row:first-of-type > div {
|
|
70
|
-
flex: 1;
|
|
71
|
-
min-height: 0;
|
|
72
|
-
display: flex;
|
|
73
|
-
flex-direction: column;
|
|
74
|
-
overflow: hidden;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.templates-v2-local-sms-pane .creatives-templates-list.library-mode > .cap-row:first-of-type > div > div:first-child {
|
|
78
|
-
flex: 1;
|
|
79
|
-
min-height: 0;
|
|
80
|
-
display: flex;
|
|
81
|
-
flex-direction: column;
|
|
82
|
-
overflow: hidden;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
.templates-v2-local-sms-pane .v2-pagination-container,
|
|
86
|
-
.templates-v2-local-sms-pane .v2-pagination-container-half {
|
|
87
|
-
/* Match _templates local-SMS: bounded height so overflow-y scroll works (flex+100% alone often doesn’t) */
|
|
88
|
-
flex: 0 1 auto;
|
|
89
|
-
min-height: 0;
|
|
90
|
-
height: calc(100vh - 12rem);
|
|
91
|
-
max-height: calc(100vh - 12rem);
|
|
92
|
-
overflow-y: auto;
|
|
93
|
-
overflow-x: hidden;
|
|
94
|
-
-webkit-overflow-scrolling: touch;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
26
|
`;
|
|
98
27
|
|
|
99
28
|
export const CapTabStyle = css`
|
|
100
|
-
${(props) => props.isFullMode ? `margin-top: ${CAP_SPACE_24}
|
|
29
|
+
${(props) => props.isFullMode ? `margin-top: ${CAP_SPACE_24};` : ``
|
|
30
|
+
}
|
|
31
|
+
.ant-tabs-nav-list {
|
|
32
|
+
gap: 2rem;
|
|
33
|
+
}
|
|
34
|
+
.ant-tabs-tab + .ant-tabs-tab {
|
|
35
|
+
margin: 0 !important;
|
|
101
36
|
}
|
|
102
37
|
`;
|
|
@@ -10,8 +10,8 @@ import { connect } from 'react-redux';
|
|
|
10
10
|
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
|
|
11
11
|
import { createStructuredSelector } from 'reselect';
|
|
12
12
|
import { bindActionCreators, compose } from 'redux';
|
|
13
|
-
import { CapTab, CapCustomCard, CapButton, CapHeader,
|
|
14
|
-
import { find, get
|
|
13
|
+
import { CapTab, CapCustomCard, CapButton, CapHeader, CapSpin, CapIcon, CapTooltip } from '@capillarytech/cap-ui-library';
|
|
14
|
+
import { find, get } from 'lodash';
|
|
15
15
|
import Helmet from 'react-helmet';
|
|
16
16
|
|
|
17
17
|
import { UserIsAuthenticated } from '../../utils/authWrapper';
|
|
@@ -41,19 +41,22 @@ import { makeSelectAuthenticated, selectCurrentOrgDetails } from "../../v2Contai
|
|
|
41
41
|
import {
|
|
42
42
|
CALL_TASK,
|
|
43
43
|
COMMON_CHANNELS,
|
|
44
|
-
LOCAL_TEMPLATE_CONFIG_KEYS_FOR_PICK,
|
|
45
44
|
LOYALTY_SUPPORTED_ACTION,
|
|
46
45
|
MOBILE_PUSH,
|
|
47
46
|
NORMALIZED_CHANNEL_ALIASES,
|
|
48
47
|
SMS,
|
|
49
48
|
} from "../CreativesContainer/constants";
|
|
49
|
+
import { MFEEventBus } from '@capillarytech/cap-ui-utils';
|
|
50
|
+
import { isMFEMode } from '../../utils/mfeDetect';
|
|
51
|
+
import appConfig from '../../../app-config';
|
|
50
52
|
|
|
51
|
-
const {
|
|
53
|
+
const {CapCustomCardList} = CapCustomCard;
|
|
52
54
|
|
|
53
55
|
const StyledCapTab = withStyles(CapTab, CapTabStyle);
|
|
54
56
|
export class TemplatesV2 extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
55
57
|
constructor(props) {
|
|
56
58
|
super(props);
|
|
59
|
+
this.lcpReported = false;
|
|
57
60
|
let defaultChannel = get(this, 'props.channel') || get(this, 'props.params.channel') || 'sms';
|
|
58
61
|
if (defaultChannel === LOYALTY) {
|
|
59
62
|
defaultChannel = 'sms';
|
|
@@ -125,9 +128,9 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
125
128
|
return !normalizedChannelsToHideSet.has(paneKey);
|
|
126
129
|
});
|
|
127
130
|
|
|
128
|
-
if (isFullMode
|
|
129
|
-
filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.gallery), key:
|
|
130
|
-
} else
|
|
131
|
+
if (isFullMode) {
|
|
132
|
+
filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.gallery), key: 'assets' });
|
|
133
|
+
} else {
|
|
131
134
|
// Add special-mode panes only when not hidden (use normalized checks)
|
|
132
135
|
if (!normalizedChannelsToHideSet.has(CALL_TASK.toLowerCase())) {
|
|
133
136
|
filteredPanes.push({ content: <div></div>, tab: intl.formatMessage(messages.callTask), key: CALL_TASK.toLowerCase() });
|
|
@@ -222,14 +225,30 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
222
225
|
}
|
|
223
226
|
}
|
|
224
227
|
|
|
228
|
+
componentDidUpdate(prevProps) {
|
|
229
|
+
if (
|
|
230
|
+
isMFEMode() &&
|
|
231
|
+
!this.lcpReported &&
|
|
232
|
+
!this.props.Templates.getAllTemplatesInProgress &&
|
|
233
|
+
prevProps.Templates.getAllTemplatesInProgress
|
|
234
|
+
) {
|
|
235
|
+
this.lcpReported = true;
|
|
236
|
+
MFEEventBus.emit('mfe:segment', {
|
|
237
|
+
action: 'stop',
|
|
238
|
+
appId: appConfig.appName,
|
|
239
|
+
type: 'lcp',
|
|
240
|
+
timestamp: performance.now(),
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
225
245
|
componentWillReceiveProps(nextProps) {
|
|
226
246
|
if (this.props.channel !== nextProps.channel) {
|
|
227
247
|
const panes = this.setChannelContent(nextProps.channel, this.state.panes);
|
|
228
248
|
this.setState({selectedChannel: nextProps.channel, panes });
|
|
229
249
|
}
|
|
230
250
|
}
|
|
231
|
-
|
|
232
|
-
getTemplateDataForGrid = ({ templates, handlers, filterContent, channel, isLoading, loadingTip }) => {
|
|
251
|
+
getTemplateDataForGrid = ({templates, handlers, filterContent, channel, isLoading, loadingTip}) => {
|
|
233
252
|
const currentChannel = channel.toUpperCase();
|
|
234
253
|
const cardDataList = templates.map((template) => {
|
|
235
254
|
const templateData =
|
|
@@ -255,8 +274,7 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
255
274
|
</CapSpin>
|
|
256
275
|
|
|
257
276
|
</div>);
|
|
258
|
-
}
|
|
259
|
-
|
|
277
|
+
}
|
|
260
278
|
getGalleryComponent = (location) => <Gallery location={location} isFullMode={this.props.isFullMode}/>
|
|
261
279
|
getCallTaskComponent = () => (
|
|
262
280
|
<CallTask
|
|
@@ -320,29 +338,6 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
320
338
|
if (messageStrategy !== "X_ENGAGE" && channel === 'facebook' && !isFullMode) {
|
|
321
339
|
return this.getFacebookComponent();
|
|
322
340
|
}
|
|
323
|
-
const localConfig = this.props.localTemplatesConfig || pick(this.props, LOCAL_TEMPLATE_CONFIG_KEYS_FOR_PICK);
|
|
324
|
-
const useLocalTemplates = localConfig.useLocalTemplates;
|
|
325
|
-
if (useLocalTemplates && channel === (this.props.channel || 'sms')) {
|
|
326
|
-
// Reuse full Templates component (same UI as Redux flow) with local data only
|
|
327
|
-
const location = { pathname: `/${channel}`, search: '', query: !this.props.isFullMode ? { type: 'embedded', module: 'library' } : {} };
|
|
328
|
-
return (
|
|
329
|
-
<Templates
|
|
330
|
-
key={`${channel}-local`}
|
|
331
|
-
location={location}
|
|
332
|
-
route={{ name: channel }}
|
|
333
|
-
router={this.props.router}
|
|
334
|
-
isFullMode={this.props.isFullMode}
|
|
335
|
-
createNew={this.props.createNew}
|
|
336
|
-
onSelectTemplate={this.props.onSelectTemplate}
|
|
337
|
-
handlePeviewTemplate={this.props.handlePeviewTemplate}
|
|
338
|
-
messageStrategy={this.props.messageStrategy}
|
|
339
|
-
smsRegister={this.props.smsRegister}
|
|
340
|
-
hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
|
|
341
|
-
localTemplatesConfig={localConfig}
|
|
342
|
-
/>
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
341
|
const location = {pathname: `/${channel}`, search: '', query};
|
|
347
342
|
switch (channel) {
|
|
348
343
|
case 'call_task':
|
|
@@ -392,55 +387,28 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
392
387
|
}
|
|
393
388
|
render() {
|
|
394
389
|
const { isFullMode, className, cap = {}, Global = {}} = this.props;
|
|
395
|
-
const useLocalTemplates = get(this.props, 'localTemplatesConfig.useLocalTemplates', false);
|
|
396
390
|
const { accessiblePermissions = []} = cap.user || Global.user || {};
|
|
397
391
|
let isCreativeAccessible = true;
|
|
398
392
|
if (!accessiblePermissions.includes(CREATIVES_UI_VIEW)) {
|
|
399
393
|
isCreativeAccessible = false;
|
|
400
394
|
}
|
|
401
|
-
// Recompute active pane content every render so local-list mode updates
|
|
402
|
-
// (templates/loading/search UI) are not stuck with the initial cached pane.
|
|
403
|
-
const panes = this.setChannelContent(this.state.selectedChannel, this.state.panes);
|
|
404
|
-
const hideChannelTabsForLocalSms = useLocalTemplates && panes.length === 1;
|
|
405
|
-
const activeLocalPane = hideChannelTabsForLocalSms
|
|
406
|
-
? (panes.find(
|
|
407
|
-
(p) => String(p.key).toLowerCase() === String(this.state.selectedChannel).toLowerCase(),
|
|
408
|
-
) || panes[0])
|
|
409
|
-
: null;
|
|
410
395
|
return (
|
|
411
396
|
!isCreativeAccessible ? <AccessForbidden /> : (
|
|
412
|
-
<div
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
meta={[
|
|
420
|
-
{ name: 'description', content: this.props.intl.formatMessage(messages.creativesDesc) },
|
|
421
|
-
]}
|
|
422
|
-
/>
|
|
423
|
-
)}
|
|
397
|
+
<div className={`${className} creatives-templates-container ${isFullMode ? 'fullmode' : 'library-mode'}`} data-testid="cap-wrapper">
|
|
398
|
+
{isFullMode && <Helmet
|
|
399
|
+
title={this.props.intl.formatMessage(messages.creatives)}
|
|
400
|
+
meta={[
|
|
401
|
+
{ name: 'description', content: this.props.intl.formatMessage(messages.creativesDesc) },
|
|
402
|
+
]}
|
|
403
|
+
/>}
|
|
424
404
|
<div className="component-wrapper">
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
)}
|
|
433
|
-
{hideChannelTabsForLocalSms ? (
|
|
434
|
-
<div className="templates-v2-local-sms-pane">{activeLocalPane?.content}</div>
|
|
435
|
-
) : (
|
|
436
|
-
<StyledCapTab
|
|
437
|
-
panes={panes}
|
|
438
|
-
onChange={this.channelChange}
|
|
439
|
-
activeKey={this.state.selectedChannel}
|
|
440
|
-
defaultActiveKey={this.state.selectedChannel}
|
|
441
|
-
isFullMode={isFullMode}
|
|
442
|
-
/>
|
|
443
|
-
)}
|
|
405
|
+
<StyledCapTab
|
|
406
|
+
panes={this.state.panes}
|
|
407
|
+
onChange={this.channelChange}
|
|
408
|
+
activeKey={this.state.selectedChannel}
|
|
409
|
+
defaultActiveKey={this.state.selectedChannel}
|
|
410
|
+
isFullMode={isFullMode}
|
|
411
|
+
/>
|
|
444
412
|
</div>
|
|
445
413
|
</div>
|
|
446
414
|
)
|
|
@@ -472,17 +440,6 @@ TemplatesV2.propTypes = {
|
|
|
472
440
|
currentOrgDetails: PropTypes.object,
|
|
473
441
|
restrictPersonalization: PropTypes.bool,
|
|
474
442
|
isAnonymousType: PropTypes.bool,
|
|
475
|
-
// Optional: reuse grid UI with local template list (e.g. SMS fallback). Pass object or same keys as individual props.
|
|
476
|
-
localTemplatesConfig: PropTypes.shape({
|
|
477
|
-
useLocalTemplates: PropTypes.bool,
|
|
478
|
-
localTemplates: PropTypes.arrayOf(PropTypes.object),
|
|
479
|
-
localTemplatesLoading: PropTypes.bool,
|
|
480
|
-
localTemplatesLoadingTip: PropTypes.string,
|
|
481
|
-
localTemplatesFilterContent: PropTypes.node,
|
|
482
|
-
localTemplatesFooterContent: PropTypes.node,
|
|
483
|
-
localTemplatesOnPageChange: PropTypes.func,
|
|
484
|
-
localTemplatesUseSkeleton: PropTypes.bool,
|
|
485
|
-
}),
|
|
486
443
|
};
|
|
487
444
|
|
|
488
445
|
TemplatesV2.defaultProps = {
|
|
@@ -11,7 +11,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
11
11
|
describe('getDefaultWeChatTemplates Saga', () => {
|
|
12
12
|
const params = { channel: 'WeChat', queryParams: { type: 'default' } };
|
|
13
13
|
|
|
14
|
-
it('handles fetching default WeChat templates successfully', () => {
|
|
14
|
+
it.concurrent('handles fetching default WeChat templates successfully', () => {
|
|
15
15
|
const fakeResponse = {
|
|
16
16
|
response: {
|
|
17
17
|
unMapped: [{ id: 1, name: 'Template One' }],
|
|
@@ -31,7 +31,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
31
31
|
.run();
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
it('handles failure in fetching default WeChat templates', () => {
|
|
34
|
+
it.concurrent('handles failure in fetching default WeChat templates', () => {
|
|
35
35
|
const error = new Error('Fetch failed');
|
|
36
36
|
|
|
37
37
|
return expectSaga(sagas.getDefaultWeChatTemplates, params)
|
|
@@ -48,7 +48,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
48
48
|
|
|
49
49
|
describe('createTemplate Saga', () => {
|
|
50
50
|
const template = { name: 'New WeChat Template' };
|
|
51
|
-
test('handles creating a WeChat template successfully', () => {
|
|
51
|
+
test.concurrent('handles creating a WeChat template successfully', () => {
|
|
52
52
|
const fakeResponse = {
|
|
53
53
|
response: template,
|
|
54
54
|
status: { code: 200 }
|
|
@@ -64,7 +64,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
64
64
|
})
|
|
65
65
|
.run();
|
|
66
66
|
});
|
|
67
|
-
test('handles failure when creating a WeChat template', () => {
|
|
67
|
+
test.concurrent('handles failure when creating a WeChat template', () => {
|
|
68
68
|
const error = new Error('Creation failed');
|
|
69
69
|
return expectSaga(sagas.createTemplate, template)
|
|
70
70
|
.provide([
|
|
@@ -79,7 +79,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
describe('fetchWeCrmAccounts Saga', () => {
|
|
82
|
-
it('handles fetching WeCrm accounts successfully', () => {
|
|
82
|
+
it.concurrent('handles fetching WeCrm accounts successfully', () => {
|
|
83
83
|
const fakeResponse = {
|
|
84
84
|
response: [{ id: 1, name: 'Account One' }]
|
|
85
85
|
};
|
|
@@ -95,7 +95,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
95
95
|
.run();
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
it('handles failure in fetching WeCrm accounts', () => {
|
|
98
|
+
it.concurrent('handles failure in fetching WeCrm accounts', () => {
|
|
99
99
|
const error = new Error('Fetch failed');
|
|
100
100
|
|
|
101
101
|
return expectSaga(sagas.fetchWeCrmAccounts)
|
|
@@ -113,7 +113,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
113
113
|
describe('getTemplateDetails Saga', () => {
|
|
114
114
|
const id = '123';
|
|
115
115
|
|
|
116
|
-
it('handles fetching template details successfully', () => {
|
|
116
|
+
it.concurrent('handles fetching template details successfully', () => {
|
|
117
117
|
const fakeResponse = {
|
|
118
118
|
response: { id: 123, name: 'Detailed Template' }
|
|
119
119
|
};
|
|
@@ -129,7 +129,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
129
129
|
.run();
|
|
130
130
|
});
|
|
131
131
|
|
|
132
|
-
it('handles failure in fetching template details', () => {
|
|
132
|
+
it.concurrent('handles failure in fetching template details', () => {
|
|
133
133
|
const error = new Error('Fetch failed');
|
|
134
134
|
|
|
135
135
|
return expectSaga(sagas.getTemplateDetails, id)
|
|
@@ -148,7 +148,7 @@ describe('WeChat Template Management Sagas', () => {
|
|
|
148
148
|
|
|
149
149
|
// Test combined saga
|
|
150
150
|
describe('Combined v2WechatMapTemplatesSagas', () => {
|
|
151
|
-
it('should initialize all WeChat-related watcher sagas without error', () => {
|
|
151
|
+
it.concurrent('should initialize all WeChat-related watcher sagas without error', () => {
|
|
152
152
|
return expectSaga(v2WechatMapTemplatesSagas)
|
|
153
153
|
.run();
|
|
154
154
|
});
|