@capillarytech/creatives-library 7.17.105 → 7.17.106-alpha.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/package.json +1 -1
- package/services/api.js +12 -1
- package/services/tests/api.test.js +19 -0
- package/utils/common.js +20 -1
- package/utils/tests/common.test.js +55 -5
- package/v2Components/CapVideoUpload/index.js +2 -2
- package/v2Containers/Assets/Gallery/index.js +1 -0
- package/v2Containers/Email/index.js +2 -0
- package/v2Containers/Line/Container/Video/index.js +2 -1
- package/v2Containers/Whatsapp/utils.js +2 -1
package/package.json
CHANGED
package/services/api.js
CHANGED
|
@@ -304,7 +304,18 @@ export const deleteAssetById = ({assetId, assetType}) => {
|
|
|
304
304
|
|
|
305
305
|
export const uploadFile = ({file, assetType, fileParams, mode, wechatParams, whatsappParams}) => {
|
|
306
306
|
const data = new FormData();
|
|
307
|
-
|
|
307
|
+
let fileName = '';
|
|
308
|
+
try {
|
|
309
|
+
fileName = encodeURIComponent(file?.name || '');
|
|
310
|
+
} catch (error) {
|
|
311
|
+
fileName = file?.name || '';
|
|
312
|
+
}
|
|
313
|
+
// Creating a new File object with the modified filename
|
|
314
|
+
const modifiedFile = new File([file], fileName, {
|
|
315
|
+
type: file?.type,
|
|
316
|
+
});
|
|
317
|
+
// Append the modified file to the FormData object
|
|
318
|
+
data.append('file', modifiedFile);
|
|
308
319
|
data.append('fileParam', JSON.stringify(fileParams));
|
|
309
320
|
if (mode) {
|
|
310
321
|
data.append('mode', mode);
|
|
@@ -38,6 +38,25 @@ describe('uploadFile -- whatsapp image upload', () => {
|
|
|
38
38
|
},
|
|
39
39
|
}),
|
|
40
40
|
).toEqual(Promise.resolve()));
|
|
41
|
+
|
|
42
|
+
it('Uploads the file with the original filename when encodeURIComponent fails', async () => {
|
|
43
|
+
// Mocking the encodeURIComponent function to throw an error
|
|
44
|
+
global.encodeURIComponent = jest.fn(() => { throw new Error('encodeURIComponent error'); });
|
|
45
|
+
const blob = new Blob([''], { type: 'image/jpeg' });
|
|
46
|
+
const file = new File([blob], '@%test.jpeg', { type: 'image/jpeg' });
|
|
47
|
+
expect(
|
|
48
|
+
uploadFile({
|
|
49
|
+
file,
|
|
50
|
+
assetType: 'image',
|
|
51
|
+
fileParams: {
|
|
52
|
+
width: 275,
|
|
53
|
+
height: 183,
|
|
54
|
+
error: false,
|
|
55
|
+
},
|
|
56
|
+
whatsappParams: {},
|
|
57
|
+
}),
|
|
58
|
+
).toEqual(Promise.resolve());
|
|
59
|
+
});
|
|
41
60
|
});
|
|
42
61
|
|
|
43
62
|
describe('createWhatsappTemplate -- Test with valid responses', () => {
|
package/utils/common.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
+
import Bugsnag from '@bugsnag/js';
|
|
2
3
|
import { Auth } from '@capillarytech/cap-ui-utils';
|
|
3
4
|
import {
|
|
4
5
|
STORE2DOOR_PLUS_ENABLED,
|
|
@@ -427,4 +428,22 @@ export const handleInjectedData = (data, scope) => {
|
|
|
427
428
|
|
|
428
429
|
export const handlePreviewInNewTab = (previewUrl) => {
|
|
429
430
|
window.open(previewUrl, '_blank');
|
|
430
|
-
}
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
export const getDecodedFileName = (templateName = '') => {
|
|
434
|
+
try {
|
|
435
|
+
return decodeURIComponent(templateName);
|
|
436
|
+
} catch (error) {
|
|
437
|
+
// If decoding fails due to URIError, using the original encoded filename
|
|
438
|
+
if (error instanceof URIError) {
|
|
439
|
+
return templateName;
|
|
440
|
+
} else {
|
|
441
|
+
// For other errors, registering the exception in Bugsnag
|
|
442
|
+
Bugsnag.leaveBreadcrumb("Error decoding the string:", error);
|
|
443
|
+
Bugsnag.notify(error, (event) => {
|
|
444
|
+
event.severity = "error";
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return templateName;
|
|
449
|
+
};
|
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import Bugsnag from '@bugsnag/js';
|
|
2
3
|
import { FormattedMessage } from 'react-intl';
|
|
3
4
|
import "@testing-library/jest-dom";
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
filterTags,
|
|
7
|
+
getTreeStructuredTags,
|
|
8
|
+
handleInjectedData,
|
|
9
|
+
intlKeyGenerator,
|
|
10
|
+
bytes2Size,
|
|
11
|
+
getUserNameById,
|
|
12
|
+
iframePreviewAdjustWidth,
|
|
13
|
+
getDecodedFileName
|
|
14
|
+
} from "../common";
|
|
5
15
|
import * as mockdata from "./common.mockdata";
|
|
6
16
|
|
|
7
17
|
describe("getTreeStructuredTags test", () => {
|
|
8
18
|
it("test for getTreeStructuredTags when tagsList is not empty", () => {
|
|
9
|
-
expect(getTreeStructuredTags({tagsList: mockdata.tagsList})).toEqual(mockdata.output1);
|
|
19
|
+
expect(getTreeStructuredTags({ tagsList: mockdata.tagsList })).toEqual(mockdata.output1);
|
|
10
20
|
});
|
|
11
21
|
it("test for getTreeStructuredTags when tagsList is empty", () => {
|
|
12
|
-
expect(getTreeStructuredTags({tagsList: []})).toEqual([]);
|
|
22
|
+
expect(getTreeStructuredTags({ tagsList: [] })).toEqual([]);
|
|
13
23
|
});
|
|
14
24
|
|
|
15
25
|
it("test for getTreeStructuredTags when incentive attached is BADGES", () => {
|
|
16
|
-
expect(getTreeStructuredTags({tagsList: mockdata.badgesTags, offerDetails: mockdata.offer})).toEqual(mockdata.expectedOffer);
|
|
26
|
+
expect(getTreeStructuredTags({ tagsList: mockdata.badgesTags, offerDetails: mockdata.offer })).toEqual(mockdata.expectedOffer);
|
|
17
27
|
});
|
|
18
28
|
it("test for filterTags", () => {
|
|
19
29
|
expect(filterTags(mockdata.tagsToFilter, mockdata.tagsList)).toEqual([mockdata.tagsList[1]]);
|
|
@@ -22,7 +32,7 @@ describe("getTreeStructuredTags test", () => {
|
|
|
22
32
|
expect(filterTags([], [])).toEqual([]);
|
|
23
33
|
});
|
|
24
34
|
it("test for getTreeStructuredTags when incentive attached is offer", () => {
|
|
25
|
-
expect(getTreeStructuredTags({tagsList: mockdata.OfferTag, offerDetails: [{id: '12', couponName: 'mac'}]})).toEqual(mockdata.offerOutput);
|
|
35
|
+
expect(getTreeStructuredTags({ tagsList: mockdata.OfferTag, offerDetails: [{ id: '12', couponName: 'mac' }] })).toEqual(mockdata.offerOutput);
|
|
26
36
|
});
|
|
27
37
|
});
|
|
28
38
|
|
|
@@ -221,3 +231,43 @@ describe('iframeAdjustWidth', () => {
|
|
|
221
231
|
expect(iframePreviewAdjustWidth(data)).toBe("<html><head></head><body>[object Object]</body></html>");
|
|
222
232
|
});
|
|
223
233
|
});
|
|
234
|
+
|
|
235
|
+
describe('getDecodedFileName function', () => {
|
|
236
|
+
it('Returns an empty string when templateName is undefined', () => {
|
|
237
|
+
expect(getDecodedFileName()).toEqual('');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('Returns the decoded filename from encoded filename', () => {
|
|
241
|
+
expect(getDecodedFileName('%24Test.jpeg')).toEqual('$Test.jpeg');
|
|
242
|
+
expect(getDecodedFileName('cap%24.logo.%23.jpg')).toEqual('cap$.logo.#.jpg');
|
|
243
|
+
expect(getDecodedFileName("%24L_i%40n%26e__%60AL%60L%2BI'ma_g__e%2Bco_pyAI____Copy____Copy_wek1SeS0.jpg")).toEqual("$L_i@n&e__`AL`L+I'ma_g__e+co_pyAI____Copy____Copy_wek1SeS0.jpg");
|
|
244
|
+
expect(getDecodedFileName('test.jpeg')).toEqual('test.jpeg');
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('Returns the original filename when decoding fails due to URIError', () => {
|
|
248
|
+
const fileName = '@Test%ZZ.jpeg';
|
|
249
|
+
expect(getDecodedFileName(fileName)).toEqual(fileName);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('Returns the original filename and notifies Bugsnag for other decoding errors', () => {
|
|
253
|
+
// Mocking Bugsnag methods for testing
|
|
254
|
+
const originalLeaveBreadcrumb = Bugsnag.leaveBreadcrumb;
|
|
255
|
+
const originalNotify = Bugsnag.notify;
|
|
256
|
+
Bugsnag.leaveBreadcrumb = jest.fn();
|
|
257
|
+
Bugsnag.notify = jest.fn((error, callback) => {
|
|
258
|
+
const event = {};
|
|
259
|
+
callback(event);
|
|
260
|
+
expect(event.severity).toEqual("error");
|
|
261
|
+
});
|
|
262
|
+
const fileName = '@Test%20ZZ.jpg';
|
|
263
|
+
const error = new Error('Some other decoding error');
|
|
264
|
+
// Mocking decodeURIComponent to throw the error
|
|
265
|
+
global.decodeURIComponent = jest.fn(() => { throw error; });
|
|
266
|
+
|
|
267
|
+
expect(getDecodedFileName(fileName)).toEqual(fileName);
|
|
268
|
+
expect(Bugsnag.notify).toHaveBeenCalled();
|
|
269
|
+
// Restoring original Bugsnag methods
|
|
270
|
+
Bugsnag.leaveBreadcrumb = originalLeaveBreadcrumb;
|
|
271
|
+
Bugsnag.notify = originalNotify;
|
|
272
|
+
});
|
|
273
|
+
});
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
CapSpin,
|
|
19
19
|
} from '@capillarytech/cap-ui-library';
|
|
20
20
|
import messages from './messages';
|
|
21
|
-
import {bytes2Size} from '../../utils/common';
|
|
21
|
+
import {bytes2Size, getDecodedFileName} from '../../utils/common';
|
|
22
22
|
import { WHATSAPP } from './constants';
|
|
23
23
|
import './index.scss';
|
|
24
24
|
|
|
@@ -265,7 +265,7 @@ function CapVideoUpload(props) {
|
|
|
265
265
|
{showVideoNameAndDuration &&
|
|
266
266
|
<div className="video-info">
|
|
267
267
|
<CapHeading type="h6">
|
|
268
|
-
{videoName}
|
|
268
|
+
{getDecodedFileName(videoName)}
|
|
269
269
|
</CapHeading>
|
|
270
270
|
<CapHeading type="h6">
|
|
271
271
|
{videoDuration}
|
|
@@ -307,6 +307,7 @@ export class Gallery extends React.Component { // eslint-disable-line react/pref
|
|
|
307
307
|
const currentChannel = 'gallery';
|
|
308
308
|
const { searchLoader, searchText } = this.state;
|
|
309
309
|
const cardDataList = templates?.length ? _.map(templates, (template) => {
|
|
310
|
+
template.name = commonUtil.getDecodedFileName(template?.name);
|
|
310
311
|
const templateData =
|
|
311
312
|
{
|
|
312
313
|
key: `${currentChannel}-card-${template.name}`,
|
|
@@ -25,6 +25,7 @@ import messages from './messages';
|
|
|
25
25
|
import './_email.scss';
|
|
26
26
|
import {getMessageObject} from '../../utils/messageUtils';
|
|
27
27
|
import EmailPreview from '../../v2Components/EmailPreview';
|
|
28
|
+
import { getDecodedFileName } from '../../utils/common';
|
|
28
29
|
|
|
29
30
|
import Pagination from '../../v2Components/Pagination';
|
|
30
31
|
import * as creativesContainerActions from '../CreativesContainer/actions';
|
|
@@ -2448,6 +2449,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2448
2449
|
getTemplateDataForGrid = ({templates, handlers, isLoading, loadingTip}) => {
|
|
2449
2450
|
const currentChannel = 'gallery';
|
|
2450
2451
|
const cardDataList = templates.length ? _.map(templates, (template) => {
|
|
2452
|
+
template.name = getDecodedFileName(template?.name);
|
|
2451
2453
|
const templateData =
|
|
2452
2454
|
{
|
|
2453
2455
|
key: `${currentChannel}-card-${template.name}`,
|
|
@@ -11,6 +11,7 @@ import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
|
|
|
11
11
|
import CapError from '@capillarytech/cap-ui-library/CapError';
|
|
12
12
|
import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
|
|
13
13
|
import { isUrl } from '../Wrapper/utils';
|
|
14
|
+
import { getDecodedFileName } from '../../../../utils/common';
|
|
14
15
|
import LineDrawer from '../Drawer';
|
|
15
16
|
import { CAP_SPACE_12, CAP_SPACE_08, FONT_COLOR_05, CAP_SPACE_24, CAP_SPACE_04 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
16
17
|
import style from './style';
|
|
@@ -414,7 +415,7 @@ export const LineVideo = ({
|
|
|
414
415
|
</video>
|
|
415
416
|
<div style={{ marginLeft: CAP_SPACE_24 }}>
|
|
416
417
|
<CapHeading type="h6">
|
|
417
|
-
{videoName}
|
|
418
|
+
{getDecodedFileName(videoName)}
|
|
418
419
|
</CapHeading>
|
|
419
420
|
<CapHeading type="h6">
|
|
420
421
|
{videoDuration}
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
import './styles.scss';
|
|
24
24
|
import pdfIcon from "../../assets/pdfIcon.svg";
|
|
25
25
|
import messages from './messages';
|
|
26
|
+
import { getDecodedFileName } from '../../utils/common';
|
|
26
27
|
|
|
27
28
|
export function bytesConversion(x) {
|
|
28
29
|
// the function accepts bytes and convert in appropriate size following the,
|
|
@@ -47,7 +48,7 @@ export const getWhatsappDocPreview = (whatsappDocParams) => {
|
|
|
47
48
|
<CapImage src={pdfIcon} />
|
|
48
49
|
<div className="pdf-info">
|
|
49
50
|
<div className="pdf-name-div">
|
|
50
|
-
<CapLabel type="label9" className="pdf-name">{whatsappDocName}</CapLabel>
|
|
51
|
+
<CapLabel type="label9" className="pdf-name">{getDecodedFileName(whatsappDocName)}</CapLabel>
|
|
51
52
|
</div>
|
|
52
53
|
<CapLabel className="pdf-info-sec">
|
|
53
54
|
{whatsappDocPages} {whatsappDocPages > 1 ? <FormattedMessage {...messages.pages} /> : <FormattedMessage {...messages.page} />}{` · ${bytesConversion(whatsappDocParams?.whatsappDocSize)} · `}
|