@capillarytech/creatives-library 8.0.340-beta.0.5 → 8.0.340-beta.0.8

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.
Files changed (62) hide show
  1. package/constants/unified.js +1 -0
  2. package/package.json +1 -1
  3. package/services/api.js +20 -0
  4. package/services/tests/api.test.js +59 -0
  5. package/utils/common.js +6 -0
  6. package/utils/test-utils.js +2 -2
  7. package/utils/tests/v2Common.test.js +46 -1
  8. package/utils/v2common.js +18 -0
  9. package/v2Components/CapTagList/index.js +5 -6
  10. package/v2Components/CommonTestAndPreview/UnifiedPreview/WhatsAppPreviewContent.js +18 -6
  11. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +27 -0
  12. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/WhatsAppPreviewContent.test.js +48 -0
  13. package/v2Components/TemplatePreview/_templatePreview.scss +21 -0
  14. package/v2Components/TemplatePreview/index.js +18 -6
  15. package/v2Components/TemplatePreview/tests/__snapshots__/index.test.js.snap +1 -0
  16. package/v2Containers/Assets/images/archive_Empty_Illustration.svg +9 -0
  17. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +28 -20
  18. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +24 -16
  19. package/v2Containers/CreativesContainer/SlideBoxContent.js +16 -5
  20. package/v2Containers/CreativesContainer/SlideBoxFooter.js +3 -1
  21. package/v2Containers/CreativesContainer/index.js +14 -1
  22. package/v2Containers/CreativesContainer/messages.js +4 -0
  23. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +2 -4
  24. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +3 -0
  25. package/v2Containers/Email/reducer.js +12 -3
  26. package/v2Containers/Email/sagas.js +9 -4
  27. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +4 -0
  28. package/v2Containers/Email/tests/reducer.test.js +47 -0
  29. package/v2Containers/Email/tests/sagas.test.js +146 -6
  30. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +8 -1
  31. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
  32. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +7 -0
  33. package/v2Containers/Sms/Create/index.js +3 -0
  34. package/v2Containers/Templates/ChannelTypeIllustration.js +23 -6
  35. package/v2Containers/Templates/_templates.scss +155 -24
  36. package/v2Containers/Templates/actions.js +44 -0
  37. package/v2Containers/Templates/constants.js +31 -0
  38. package/v2Containers/Templates/index.js +400 -59
  39. package/v2Containers/Templates/messages.js +96 -0
  40. package/v2Containers/Templates/reducer.js +84 -1
  41. package/v2Containers/Templates/sagas.js +64 -0
  42. package/v2Containers/Templates/selectors.js +12 -0
  43. package/v2Containers/Templates/tests/ChannelTypeIllustration.test.js +12 -0
  44. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1166 -1112
  45. package/v2Containers/Templates/tests/index.test.js +6 -0
  46. package/v2Containers/Templates/tests/reducer.test.js +178 -0
  47. package/v2Containers/Templates/tests/sagas.test.js +390 -8
  48. package/v2Containers/Templates/tests/selector.test.js +32 -0
  49. package/v2Containers/TemplatesV2/TemplatesV2.style.js +1 -1
  50. package/v2Containers/Viber/constants.js +8 -0
  51. package/v2Containers/Viber/index.js +5 -0
  52. package/v2Containers/Viber/messages.js +4 -0
  53. package/v2Containers/Viber/reducer.js +26 -3
  54. package/v2Containers/Viber/sagas.js +50 -8
  55. package/v2Containers/Viber/tests/index.test.js +80 -0
  56. package/v2Containers/Viber/tests/reducer.test.js +297 -0
  57. package/v2Containers/Viber/tests/saga.test.js +412 -40
  58. package/v2Containers/WeChat/Wrapper/index.js +0 -1
  59. package/v2Containers/Whatsapp/constants.js +8 -0
  60. package/v2Containers/Whatsapp/index.js +145 -5
  61. package/v2Containers/Whatsapp/index.scss +12 -0
  62. package/v2Containers/Whatsapp/messages.js +16 -0
@@ -1,50 +1,305 @@
1
1
  import { expectSaga } from 'redux-saga-test-plan';
2
- import { call, put } from 'redux-saga/effects';
2
+ import * as matchers from 'redux-saga-test-plan/matchers';
3
+ import { call } from 'redux-saga/effects';
3
4
  import { throwError } from 'redux-saga-test-plan/providers';
4
5
  import * as Api from '../../../services/api';
5
6
  import * as sagas from '../sagas';
6
- import { v2ViberSagas } from '../sagas';
7
7
  import * as types from '../constants';
8
+ import { pollAssetStatus } from '../../../sagas/assetPolling';
9
+ import { ASSET_STATUS } from '../../../utils/assetStatusConstants';
10
+ import messages from '../messages';
8
11
 
9
12
  describe('Viber Sagas', () => {
10
-
11
13
  describe('uploadViberAsset Saga', () => {
12
- const file = new Blob(['file contents'], { type: 'text/plain' });
13
- const assetType = 'image';
14
- const fileParams = { directory: 'profile', templateType: 'viber' };
14
+ const mockAsset = {
15
+ _id: 'asset-123',
16
+ type: 'IMAGE',
17
+ url: 'https://example.com/image.jpg',
18
+ };
15
19
 
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
+ const mockParams = {
21
+ file: new File(['test'], 'test.jpg', { type: 'image/jpeg' }),
22
+ assetType: 'image',
23
+ fileParams: {},
24
+ templateType: 0,
25
+ };
26
+
27
+ it('handles async upload (202) with polling', () => {
28
+ const mockResponse = {
29
+ status: { code: 202 },
30
+ response: {
31
+ assetId: 'asset-123',
32
+ asset: mockAsset,
33
+ processingStatus: ASSET_STATUS.PROCESSING,
34
+ },
35
+ };
36
+
37
+ return expectSaga(sagas.uploadViberAsset, mockParams)
38
+ .provide([
39
+ [matchers.call.fn(Api.uploadFile), mockResponse],
40
+ [matchers.call.fn(pollAssetStatus), undefined],
41
+ ])
42
+ .put({
43
+ type: types.UPLOAD_VIBER_ASSET_PROCESSING,
44
+ payload: {
45
+ assetId: 'asset-123',
46
+ asset: mockAsset,
47
+ processingStatus: ASSET_STATUS.PROCESSING,
48
+ },
49
+ })
50
+ .call.fn(Api.uploadFile)
51
+ .call.fn(pollAssetStatus)
52
+ .run();
53
+ });
54
+
55
+ it('handles async when processingStatus is processing with 200 status', () => {
56
+ const mockResponse = {
57
+ status: { code: 200 },
58
+ response: {
59
+ assetId: 'asset-123',
60
+ asset: mockAsset,
61
+ processingStatus: ASSET_STATUS.PROCESSING,
62
+ },
20
63
  };
21
64
 
22
- return expectSaga(sagas.uploadViberAsset, file, assetType, fileParams)
65
+ return expectSaga(sagas.uploadViberAsset, mockParams)
23
66
  .provide([
24
- [call(Api.uploadFile, file, assetType, fileParams), fakeResponse]
67
+ [matchers.call.fn(Api.uploadFile), mockResponse],
68
+ [matchers.call.fn(pollAssetStatus), undefined],
69
+ ])
70
+ .put({
71
+ type: types.UPLOAD_VIBER_ASSET_PROCESSING,
72
+ payload: {
73
+ assetId: 'asset-123',
74
+ asset: mockAsset,
75
+ processingStatus: ASSET_STATUS.PROCESSING,
76
+ },
77
+ })
78
+ .call.fn(pollAssetStatus)
79
+ .run();
80
+ });
81
+
82
+ it('handles sync upload (201) without polling', () => {
83
+ const mockResponse = {
84
+ status: { code: 201 },
85
+ response: {
86
+ asset: mockAsset,
87
+ },
88
+ };
89
+
90
+ return expectSaga(sagas.uploadViberAsset, mockParams)
91
+ .provide([
92
+ [matchers.call.fn(Api.uploadFile), mockResponse],
25
93
  ])
26
94
  .put({
27
95
  type: types.UPLOAD_VIBER_ASSET_SUCCESS,
28
- data: fakeResponse.response.asset,
29
- statusCode: fakeResponse.status.code,
30
- templateType: undefined
96
+ data: mockAsset,
97
+ statusCode: 201,
98
+ templateType: 0,
31
99
  })
100
+ .not.call(pollAssetStatus)
32
101
  .run();
33
102
  });
34
103
 
35
- it('handles asset upload failure', () => {
36
- const error = new Error('Upload failed');
104
+ it('extracts assetId from asset._id when assetId omitted', () => {
105
+ const mockResponse = {
106
+ status: { code: 202 },
107
+ response: {
108
+ asset: { ...mockAsset, _id: 'asset-456' },
109
+ processingStatus: ASSET_STATUS.PROCESSING,
110
+ },
111
+ };
37
112
 
38
- return expectSaga(sagas.uploadViberAsset, file, assetType, fileParams)
113
+ return expectSaga(sagas.uploadViberAsset, mockParams)
39
114
  .provide([
40
- [call(Api.uploadFile, file, assetType, fileParams), throwError(error)]
115
+ [matchers.call.fn(Api.uploadFile), mockResponse],
116
+ [matchers.call.fn(pollAssetStatus), undefined],
117
+ ])
118
+ .put({
119
+ type: types.UPLOAD_VIBER_ASSET_PROCESSING,
120
+ payload: {
121
+ assetId: 'asset-456',
122
+ asset: { ...mockAsset, _id: 'asset-456' },
123
+ processingStatus: ASSET_STATUS.PROCESSING,
124
+ },
125
+ })
126
+ .run();
127
+ });
128
+
129
+ it('dispatches FAILED when assetId missing on async response', () => {
130
+ const mockResponse = {
131
+ status: { code: 202 },
132
+ response: {
133
+ processingStatus: ASSET_STATUS.PROCESSING,
134
+ },
135
+ };
136
+
137
+ return expectSaga(sagas.uploadViberAsset, mockParams)
138
+ .provide([
139
+ [matchers.call.fn(Api.uploadFile), mockResponse],
140
+ ])
141
+ .put({
142
+ type: types.UPLOAD_VIBER_ASSET_FAILED,
143
+ payload: {
144
+ assetId: undefined,
145
+ error: messages.assetIdMissingError,
146
+ },
147
+ templateType: 0,
148
+ })
149
+ .not.call(pollAssetStatus)
150
+ .run();
151
+ });
152
+
153
+ it('handles upload error', () => {
154
+ const uploadError = new Error('Upload failed');
155
+
156
+ return expectSaga(sagas.uploadViberAsset, mockParams)
157
+ .provide([
158
+ [matchers.call.fn(Api.uploadFile), throwError(uploadError)],
41
159
  ])
42
160
  .put({
43
161
  type: types.UPLOAD_VIBER_ASSET_FAILURE,
44
- error
162
+ error: uploadError,
163
+ })
164
+ .run();
165
+ });
166
+
167
+ it('falls back to statusCode on response when status object missing', () => {
168
+ const mockResponse = {
169
+ statusCode: 201,
170
+ response: { asset: mockAsset },
171
+ };
172
+ return expectSaga(sagas.uploadViberAsset, mockParams)
173
+ .provide([
174
+ [matchers.call.fn(Api.uploadFile), mockResponse],
175
+ ])
176
+ .put({
177
+ type: types.UPLOAD_VIBER_ASSET_SUCCESS,
178
+ data: mockAsset,
179
+ statusCode: 201,
180
+ templateType: 0,
181
+ })
182
+ .run();
183
+ });
184
+
185
+ it('passes undefined statusCode through when no status info present (no default)', () => {
186
+ const mockResponse = { response: { asset: mockAsset } };
187
+ return expectSaga(sagas.uploadViberAsset, mockParams)
188
+ .provide([
189
+ [matchers.call.fn(Api.uploadFile), mockResponse],
190
+ ])
191
+ .put({
192
+ type: types.UPLOAD_VIBER_ASSET_SUCCESS,
193
+ data: mockAsset,
194
+ statusCode: undefined,
195
+ templateType: 0,
45
196
  })
46
197
  .run();
47
198
  });
199
+
200
+ it('handles empty response object', () => {
201
+ const mockResponse = { status: { code: 201 } };
202
+ return expectSaga(sagas.uploadViberAsset, mockParams)
203
+ .provide([
204
+ [matchers.call.fn(Api.uploadFile), mockResponse],
205
+ ])
206
+ .put({
207
+ type: types.UPLOAD_VIBER_ASSET_SUCCESS,
208
+ data: {},
209
+ statusCode: 201,
210
+ templateType: 0,
211
+ })
212
+ .run();
213
+ });
214
+
215
+ it('normalizes a flat async response (asset fields at top level) for polling', () => {
216
+ // API returns a flat asset object instead of { asset: {...} }
217
+ const flatResponse = {
218
+ status: { code: 202 },
219
+ response: {
220
+ _id: 'flat-asset-789',
221
+ type: 'VIDEO',
222
+ processingStatus: ASSET_STATUS.PROCESSING,
223
+ },
224
+ };
225
+ return expectSaga(sagas.uploadViberAsset, { ...mockParams, assetType: undefined })
226
+ .provide([
227
+ [matchers.call.fn(Api.uploadFile), flatResponse],
228
+ [matchers.call.fn(pollAssetStatus), undefined],
229
+ ])
230
+ .put({
231
+ type: types.UPLOAD_VIBER_ASSET_PROCESSING,
232
+ payload: {
233
+ assetId: 'flat-asset-789',
234
+ asset: flatResponse.response,
235
+ processingStatus: ASSET_STATUS.PROCESSING,
236
+ },
237
+ })
238
+ .call.fn(pollAssetStatus)
239
+ .run();
240
+ });
241
+
242
+ it('normalizes a flat sync response (asset fields at top level)', () => {
243
+ const flatAsset = { _id: 'flat-sync-1', url: 'https://cdn/x.jpg' };
244
+ const flatResponse = {
245
+ status: { code: 201 },
246
+ response: flatAsset,
247
+ };
248
+ return expectSaga(sagas.uploadViberAsset, mockParams)
249
+ .provide([
250
+ [matchers.call.fn(Api.uploadFile), flatResponse],
251
+ ])
252
+ .put({
253
+ type: types.UPLOAD_VIBER_ASSET_SUCCESS,
254
+ data: flatAsset,
255
+ statusCode: 201,
256
+ templateType: 0,
257
+ })
258
+ .run();
259
+ });
260
+
261
+ it('derives assetType from asset.type when params.assetType omitted', () => {
262
+ const paramsWithoutType = {
263
+ file: new File(['v'], 'v.mp4', { type: 'video/mp4' }),
264
+ fileParams: {},
265
+ templateType: 1,
266
+ };
267
+ const mockResponse = {
268
+ status: { code: 202 },
269
+ response: {
270
+ assetId: 'asset-vid',
271
+ asset: { _id: 'asset-vid', type: 'VIDEO' },
272
+ },
273
+ };
274
+ return expectSaga(sagas.uploadViberAsset, paramsWithoutType)
275
+ .provide([
276
+ [matchers.call.fn(Api.uploadFile), mockResponse],
277
+ [matchers.call.fn(pollAssetStatus), undefined],
278
+ ])
279
+ .call.fn(pollAssetStatus)
280
+ .run();
281
+ });
282
+
283
+ it('defaults assetType to image when no type info available', () => {
284
+ const paramsWithoutType = {
285
+ file: new File(['x'], 'x', { type: '' }),
286
+ fileParams: {},
287
+ templateType: 0,
288
+ };
289
+ const mockResponse = {
290
+ status: { code: 202 },
291
+ response: {
292
+ assetId: 'asset-noop',
293
+ },
294
+ };
295
+ return expectSaga(sagas.uploadViberAsset, paramsWithoutType)
296
+ .provide([
297
+ [matchers.call.fn(Api.uploadFile), mockResponse],
298
+ [matchers.call.fn(pollAssetStatus), undefined],
299
+ ])
300
+ .call.fn(pollAssetStatus)
301
+ .run();
302
+ });
48
303
  });
49
304
 
50
305
  describe('createViberTemplate Saga', () => {
@@ -54,18 +309,18 @@ describe('Viber Sagas', () => {
54
309
  it('handles creating template successfully', () => {
55
310
  const fakeResponse = {
56
311
  response: { id: 2, content: template.content },
57
- status: { code: 201 }
312
+ status: { code: 201 },
58
313
  };
59
314
 
60
315
  return expectSaga(sagas.createViberTemplate, { template, callback })
61
316
  .provide([
62
- [call(Api.createViberTemplate, { template }), fakeResponse]
317
+ [call(Api.createViberTemplate, { template }), fakeResponse],
63
318
  ])
64
319
  .put({
65
320
  type: types.CREATE_VIBER_TEMPLATE_SUCCESS,
66
321
  data: fakeResponse.response,
67
322
  statusCode: fakeResponse.status.code,
68
- errorMsg: undefined
323
+ errorMsg: undefined,
69
324
  })
70
325
  .run()
71
326
  .then(() => {
@@ -76,21 +331,74 @@ describe('Viber Sagas', () => {
76
331
  it('handles failure in creating template', () => {
77
332
  const error = new Error({ message: 'Creation failed', status: { code: 400 } });
78
333
 
79
- const errorMsg = 'Creation failed';
80
334
  return expectSaga(sagas.createViberTemplate, { template, callback })
81
335
  .provide([
82
- [call(Api.createViberTemplate, { template }), throwError(error)]
336
+ [call(Api.createViberTemplate, { template }), throwError(error)],
83
337
  ])
84
338
  .put({
85
339
  type: types.CREATE_VIBER_TEMPLATE_FAILURE,
86
340
  error,
87
- errorMsg : undefined
341
+ errorMsg: undefined,
88
342
  })
89
343
  .run()
90
344
  .then(() => {
91
345
  expect(callback).toHaveBeenCalledWith(null, undefined);
92
346
  });
93
347
  });
348
+
349
+ it('handles 4xx API response (treated as failure)', () => {
350
+ const cb = jest.fn();
351
+ const fakeResponse = {
352
+ response: {},
353
+ status: { code: 400 },
354
+ message: 'bad request',
355
+ };
356
+ return expectSaga(sagas.createViberTemplate, { template, callback: cb })
357
+ .provide([
358
+ [call(Api.createViberTemplate, { template }), fakeResponse],
359
+ ])
360
+ .put({
361
+ type: types.CREATE_VIBER_TEMPLATE_FAILURE,
362
+ error: 'bad request',
363
+ errorMsg: 'bad request',
364
+ })
365
+ .run()
366
+ .then(() => {
367
+ expect(cb).toHaveBeenCalledWith(null, 'bad request');
368
+ });
369
+ });
370
+
371
+ it('handles success when no callback is supplied', () => {
372
+ const fakeResponse = {
373
+ response: { id: 42 },
374
+ status: { code: 201 },
375
+ };
376
+ return expectSaga(sagas.createViberTemplate, { template })
377
+ .provide([
378
+ [call(Api.createViberTemplate, { template }), fakeResponse],
379
+ ])
380
+ .put({
381
+ type: types.CREATE_VIBER_TEMPLATE_SUCCESS,
382
+ data: fakeResponse.response,
383
+ statusCode: 201,
384
+ errorMsg: undefined,
385
+ })
386
+ .run();
387
+ });
388
+
389
+ it('handles failure when no callback is supplied', () => {
390
+ const error = new Error('Creation failed');
391
+ return expectSaga(sagas.createViberTemplate, { template })
392
+ .provide([
393
+ [call(Api.createViberTemplate, { template }), throwError(error)],
394
+ ])
395
+ .put({
396
+ type: types.CREATE_VIBER_TEMPLATE_FAILURE,
397
+ error,
398
+ errorMsg: undefined,
399
+ })
400
+ .run();
401
+ });
94
402
  });
95
403
 
96
404
  describe('editTemplate Saga', () => {
@@ -100,18 +408,18 @@ describe('Viber Sagas', () => {
100
408
  it('handles editing template successfully', () => {
101
409
  const fakeResponse = {
102
410
  response: { updated: true },
103
- status: { code: 200 }
411
+ status: { code: 200 },
104
412
  };
105
413
 
106
414
  return expectSaga(sagas.editTemplate, { template, callback })
107
415
  .provide([
108
- [call(Api.createViberTemplate, { template }), fakeResponse]
416
+ [call(Api.createViberTemplate, { template }), fakeResponse],
109
417
  ])
110
418
  .put({
111
419
  type: types.EDIT_VIBER_TEMPLATE_SUCCESS,
112
420
  data: fakeResponse.response,
113
421
  statusCode: fakeResponse.status.code,
114
- errorMsg: undefined
422
+ errorMsg: undefined,
115
423
  })
116
424
  .run()
117
425
  .then(() => {
@@ -123,7 +431,7 @@ describe('Viber Sagas', () => {
123
431
  const errorMsg = 'Error in editing template';
124
432
  return expectSaga(sagas.editTemplate, { template, callback })
125
433
  .provide([
126
- [call(Api.createViberTemplate, { template }), throwError({ message: errorMsg, status: { code: 400 } })]
434
+ [call(Api.createViberTemplate, { template }), throwError({ message: errorMsg, status: { code: 400 } })],
127
435
  ])
128
436
  .put({
129
437
  type: types.EDIT_VIBER_TEMPLATE_FAILURE,
@@ -135,6 +443,60 @@ describe('Viber Sagas', () => {
135
443
  expect(callback).toHaveBeenCalledWith(null, undefined);
136
444
  });
137
445
  });
446
+
447
+ it('handles 4xx API response (treated as failure)', () => {
448
+ const cb = jest.fn();
449
+ const fakeResponse = {
450
+ response: {},
451
+ status: { code: 422 },
452
+ message: 'invalid payload',
453
+ };
454
+ return expectSaga(sagas.editTemplate, { template, callback: cb })
455
+ .provide([
456
+ [call(Api.createViberTemplate, { template }), fakeResponse],
457
+ ])
458
+ .put({
459
+ type: types.EDIT_VIBER_TEMPLATE_FAILURE,
460
+ error: 'invalid payload',
461
+ errorMsg: 'invalid payload',
462
+ })
463
+ .run()
464
+ .then(() => {
465
+ expect(cb).toHaveBeenCalledWith(null, 'invalid payload');
466
+ });
467
+ });
468
+
469
+ it('handles success when no callback is supplied', () => {
470
+ const fakeResponse = {
471
+ response: { updated: true },
472
+ status: { code: 200 },
473
+ };
474
+ return expectSaga(sagas.editTemplate, { template })
475
+ .provide([
476
+ [call(Api.createViberTemplate, { template }), fakeResponse],
477
+ ])
478
+ .put({
479
+ type: types.EDIT_VIBER_TEMPLATE_SUCCESS,
480
+ data: fakeResponse.response,
481
+ statusCode: 200,
482
+ errorMsg: undefined,
483
+ })
484
+ .run();
485
+ });
486
+
487
+ it('handles failure when no callback is supplied', () => {
488
+ const error = new Error('Edit failed');
489
+ return expectSaga(sagas.editTemplate, { template })
490
+ .provide([
491
+ [call(Api.createViberTemplate, { template }), throwError(error)],
492
+ ])
493
+ .put({
494
+ type: types.EDIT_VIBER_TEMPLATE_FAILURE,
495
+ error,
496
+ errorMsg: undefined,
497
+ })
498
+ .run();
499
+ });
138
500
  });
139
501
 
140
502
  describe('getTemplateDetails Saga', () => {
@@ -143,16 +505,16 @@ describe('Viber Sagas', () => {
143
505
 
144
506
  it('handles fetching template details successfully', () => {
145
507
  const fakeResponse = {
146
- response: { id: id, name: 'Detailed Template' }
508
+ response: { id, name: 'Detailed Template' },
147
509
  };
148
510
 
149
511
  return expectSaga(sagas.getTemplateDetails, { id, callback })
150
512
  .provide([
151
- [call(Api.getTemplateDetails, { id, channel: 'VIBER' }), fakeResponse]
513
+ [call(Api.getTemplateDetails, { id, channel: 'VIBER' }), fakeResponse],
152
514
  ])
153
515
  .put({
154
516
  type: types.GET_VIBER_TEMPLATE_DETAILS_SUCCESS,
155
- data: fakeResponse.response
517
+ data: fakeResponse.response,
156
518
  })
157
519
  .run()
158
520
  .then(() => {
@@ -165,23 +527,33 @@ describe('Viber Sagas', () => {
165
527
 
166
528
  return expectSaga(sagas.getTemplateDetails, { id, callback })
167
529
  .provide([
168
- [call(Api.getTemplateDetails, { id, channel: 'VIBER' }), throwError(error)]
530
+ [call(Api.getTemplateDetails, { id, channel: 'VIBER' }), throwError(error)],
169
531
  ])
170
532
  .put({
171
533
  type: types.GET_VIBER_TEMPLATE_DETAILS_FAILURE,
172
- error
534
+ error,
173
535
  })
174
536
  .run()
175
537
  .then(() => {
176
538
  expect(callback).not.toHaveBeenCalledWith();
177
539
  });
178
540
  });
179
- });
180
541
 
181
- describe('v2ViberSagas Combined', () => {
182
- it('should initialize all Viber-related watcher sagas without error', () => {
183
- return expectSaga(v2ViberSagas).run();
542
+ it('handles success without a callback', () => {
543
+ const fakeResponse = { response: { id, name: 'No CB' } };
544
+ return expectSaga(sagas.getTemplateDetails, { id })
545
+ .provide([
546
+ [call(Api.getTemplateDetails, { id, channel: 'VIBER' }), fakeResponse],
547
+ ])
548
+ .put({
549
+ type: types.GET_VIBER_TEMPLATE_DETAILS_SUCCESS,
550
+ data: fakeResponse.response,
551
+ })
552
+ .run();
184
553
  });
185
554
  });
186
555
 
187
- });
556
+ describe('v2ViberSagas Combined', () => {
557
+ it('should initialize all Viber-related watcher sagas without error', () => expectSaga(sagas.v2ViberSagas).run());
558
+ });
559
+ });
@@ -40,7 +40,6 @@ const CardContainer = styled.div`
40
40
  .ant-radio-button-wrapper{
41
41
  &:first-child{
42
42
  margin-left: unset;
43
- margin-top: unset;
44
43
  }
45
44
  }
46
45
 
@@ -319,6 +319,14 @@ export const WHATSAPP_MEDIA_TYPES = {
319
319
  DOCUMENT: 'DOCUMENT',
320
320
  CAROUSEL: 'CAROUSEL',
321
321
  };
322
+
323
+ export const WHATSAPP_IMAGE_SOURCE = {
324
+ UPLOAD: 'UPLOAD_IMAGE',
325
+ URL: 'ADD_IMAGE_URL',
326
+ };
327
+
328
+ export const ADD_IMAGE_URL_PREVIEW_MARKER = '__add_image_url__';
329
+ export const TEMPLATE_VARIABLE_REGEX = /\{\{.*?\}\}/;
322
330
  export const NONE = 'NONE';
323
331
  export const CTA = 'CTA';
324
332
  export const QUICK_REPLY = 'QUICK_REPLY';