@capillarytech/creatives-library 8.0.288 → 8.0.290-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/constants/unified.js +0 -1
- package/initialState.js +0 -2
- package/package.json +1 -1
- package/utils/common.js +5 -8
- package/utils/commonUtils.js +4 -85
- package/utils/tagValidations.js +84 -222
- package/utils/tests/commonUtil.test.js +461 -118
- package/utils/tests/tagValidations.test.js +280 -358
- package/v2Components/ErrorInfoNote/index.js +2 -5
- package/v2Components/FormBuilder/index.js +78 -161
- package/v2Components/FormBuilder/messages.js +0 -8
- package/v2Components/HtmlEditor/HTMLEditor.js +0 -5
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +0 -1
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +0 -15
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +1 -2
- package/v2Containers/Cap/mockData.js +0 -14
- package/v2Containers/Cap/reducer.js +3 -55
- package/v2Containers/Cap/tests/reducer.test.js +0 -102
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +3 -1
- package/v2Containers/CreativesContainer/index.js +19 -6
- package/v2Containers/Email/index.js +1 -5
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +10 -62
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +12 -115
- package/v2Containers/FTP/index.js +2 -51
- package/v2Containers/FTP/messages.js +0 -4
- package/v2Containers/InApp/index.js +1 -96
- package/v2Containers/InApp/tests/index.test.js +17 -6
- package/v2Containers/InappAdvance/index.js +2 -103
- package/v2Containers/Line/Container/Text/index.js +0 -1
- package/v2Containers/MobilePush/Create/index.js +6 -16
- package/v2Containers/MobilePush/Edit/index.js +6 -16
- package/v2Containers/MobilePushNew/index.js +2 -33
- package/v2Containers/Rcs/index.js +12 -37
- package/v2Containers/Sms/Create/index.js +31 -3
- package/v2Containers/Sms/Create/messages.js +4 -0
- package/v2Containers/Sms/Edit/index.js +29 -3
- package/v2Containers/Sms/commonMethods.js +6 -6
- package/v2Containers/SmsTrai/Edit/index.js +6 -47
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
- package/v2Containers/Templates/reducer.js +3 -1
- package/v2Containers/Templates/tests/reducer.test.js +12 -0
- package/v2Containers/Viber/index.js +0 -1
- package/v2Containers/WebPush/Create/components/BrandIconSection.test.js +264 -0
- package/v2Containers/WebPush/Create/components/__snapshots__/BrandIconSection.test.js.snap +187 -0
- package/v2Containers/WebPush/Create/hooks/useTagManagement.js +1 -3
- package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -7
- package/v2Containers/WebPush/Create/index.js +2 -2
- package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +269 -0
- package/v2Containers/WebPush/Create/utils/validation.js +17 -2
- package/v2Containers/WebPush/Create/utils/validation.test.js +0 -24
- package/v2Containers/Whatsapp/index.js +9 -17
- package/v2Containers/Zalo/index.js +3 -11
|
@@ -39,10 +39,8 @@ import formBuilderMessages from '../../../v2Components/FormBuilder/messages';
|
|
|
39
39
|
import UnifiedPreview from '../../../v2Components/CommonTestAndPreview/UnifiedPreview';
|
|
40
40
|
import TestAndPreviewSlidebox from '../../../v2Components/TestAndPreviewSlidebox';
|
|
41
41
|
import withCreatives from '../../../hoc/withCreatives';
|
|
42
|
-
import { validateTags } from '../../../utils/tagValidations';
|
|
43
42
|
import {
|
|
44
43
|
CHARLIMIT,
|
|
45
|
-
SMS,
|
|
46
44
|
SMS_TRAI_VAR,
|
|
47
45
|
TAG,
|
|
48
46
|
EMBEDDED,
|
|
@@ -51,16 +49,15 @@ import {
|
|
|
51
49
|
ALL,
|
|
52
50
|
LIBRARY,
|
|
53
51
|
} from './constants';
|
|
52
|
+
import { SMS } from '../../CreativesContainer/constants';
|
|
54
53
|
import v2EditSmsReducer from '../../Sms/Edit/reducer';
|
|
55
54
|
import { v2SmsEditSagas } from '../../Sms/Edit/sagas';
|
|
56
55
|
import ErrorInfoNote from '../../../v2Components/ErrorInfoNote';
|
|
57
56
|
import { validateLiquidTemplateContent } from '../../../utils/commonUtils';
|
|
58
|
-
import { hasLiquidSupportFeature } from '../../../utils/common';
|
|
59
57
|
import { ANDROID } from '../../../v2Components/CommonTestAndPreview/constants';
|
|
60
58
|
|
|
61
59
|
let varMap = {};
|
|
62
60
|
let traiData = {};
|
|
63
|
-
let tagValidationResponse = {};
|
|
64
61
|
const { TextArea } = CapInput;
|
|
65
62
|
const { CapLabelInline } = CapLabel;
|
|
66
63
|
|
|
@@ -94,7 +91,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
94
91
|
const [tags, updateTags] = useState([]);
|
|
95
92
|
const [textAreaId, updateTextAreaId] = useState();
|
|
96
93
|
const [isValidationError, updateIsValidationError] = useState(false);
|
|
97
|
-
const [isTagValidationError, updateIsTagValidationError] = useState(false);
|
|
98
94
|
const [totalMessageLength, setTotalMessageLength] = useState(0);
|
|
99
95
|
const [isUnicodeAllowed, updateIsUnicodeAllowed] = useState(true);
|
|
100
96
|
const [showMsgLengthNote, updateshowMsgLengthNote] = useState(false);
|
|
@@ -229,29 +225,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
229
225
|
}
|
|
230
226
|
}, []);
|
|
231
227
|
|
|
232
|
-
//performs tag validation
|
|
233
|
-
useEffect(() => {
|
|
234
|
-
if (
|
|
235
|
-
!isFullMode &&
|
|
236
|
-
updatedSmsEditor?.length > 0 &&
|
|
237
|
-
!updatedSmsEditor.includes(SMS_TRAI_VAR)
|
|
238
|
-
) {
|
|
239
|
-
tagValidationResponse =
|
|
240
|
-
validateTags({
|
|
241
|
-
content: updatedSmsEditor.join(''),
|
|
242
|
-
tagsParam: tags,
|
|
243
|
-
injectedTagsParams: injectedTags,
|
|
244
|
-
location,
|
|
245
|
-
tagModule: getDefaultTags,
|
|
246
|
-
eventContextTags,
|
|
247
|
-
isFullMode,
|
|
248
|
-
}) || {};
|
|
249
|
-
updateIsTagValidationError(
|
|
250
|
-
tagValidationResponse.unsupportedTags.length > 0,
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
}, [updatedSmsEditor, tags]);
|
|
254
|
-
|
|
255
228
|
const computeUpdatedSmsEditor = () => {
|
|
256
229
|
const arr = [...tempMsgArray];
|
|
257
230
|
const varMapKeys = Object.keys(varMap)?.map((key) => Number(key.slice(8)))?.sort((a, b) => a - b) || [];
|
|
@@ -288,6 +261,8 @@ export const SmsTraiEdit = (props) => {
|
|
|
288
261
|
};
|
|
289
262
|
|
|
290
263
|
const onSubmitWrapper = () => {
|
|
264
|
+
setIsLiquidValidationError(false);
|
|
265
|
+
setLiquidErrorMessages({});
|
|
291
266
|
const content = updatedSmsEditor.join('');
|
|
292
267
|
const onError = ({ standardErrors, liquidErrors }) => {
|
|
293
268
|
setLiquidErrorMessages({
|
|
@@ -298,6 +273,8 @@ export const SmsTraiEdit = (props) => {
|
|
|
298
273
|
};
|
|
299
274
|
|
|
300
275
|
const onSuccess = () => {
|
|
276
|
+
setIsLiquidValidationError(false);
|
|
277
|
+
setLiquidErrorMessages({});
|
|
301
278
|
onDoneCallback();
|
|
302
279
|
};
|
|
303
280
|
validateLiquidTemplateContent(content, {
|
|
@@ -306,10 +283,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
306
283
|
messages: formBuilderMessages,
|
|
307
284
|
onError,
|
|
308
285
|
onSuccess,
|
|
309
|
-
tagLookupMap: metaEntities?.tagLookupMap,
|
|
310
|
-
eventContextTags,
|
|
311
|
-
isLiquidFlow: true,
|
|
312
|
-
forwardedTags: {},
|
|
313
286
|
});
|
|
314
287
|
};
|
|
315
288
|
|
|
@@ -548,17 +521,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
548
521
|
return countVarChar;
|
|
549
522
|
};
|
|
550
523
|
|
|
551
|
-
const tagValidationErrorMessage = () => {
|
|
552
|
-
const { unsupportedTags = [] } = tagValidationResponse;
|
|
553
|
-
let tagError = '';
|
|
554
|
-
if (unsupportedTags.length > 0) {
|
|
555
|
-
tagError = formatMessage(messages.unsupportedTagsValidationError, {
|
|
556
|
-
unsupportedTags,
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
return <CapError>{tagError}</CapError>;
|
|
560
|
-
};
|
|
561
|
-
|
|
562
524
|
const disablehandler = () => {
|
|
563
525
|
if (traiData && !isEmpty(traiData)) {
|
|
564
526
|
const msg = get(traiData, `versions.base.sms-editor`, '');
|
|
@@ -604,7 +566,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
604
566
|
setShowTestAndPreviewSlidebox(false);
|
|
605
567
|
};
|
|
606
568
|
|
|
607
|
-
const isLiquidSupportFeatureEnabled = hasLiquidSupportFeature();
|
|
608
569
|
return (
|
|
609
570
|
<>
|
|
610
571
|
<CapSpin spinning={loading || fetchingLiquidTags} tip={fetchingLiquidTags && formatMessage(formBuilderMessages.liquidSpinText)}>
|
|
@@ -662,7 +623,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
662
623
|
<CapRow>
|
|
663
624
|
{smsLengthForVar()}
|
|
664
625
|
</CapRow>
|
|
665
|
-
{isTagValidationError && tagValidationErrorMessage()}
|
|
666
626
|
<CapCheckbox onChange={unicodeHandler} checked={isUnicodeAllowed} disabled={disablehandler()}>
|
|
667
627
|
{formatMessage(messages.unicodeLabel)}
|
|
668
628
|
</CapCheckbox>
|
|
@@ -693,9 +653,8 @@ export const SmsTraiEdit = (props) => {
|
|
|
693
653
|
<FormattedMessage {...messages.testAndPreviewButtonLabel} />
|
|
694
654
|
</CapButton>
|
|
695
655
|
<CapButton
|
|
696
|
-
onClick={
|
|
656
|
+
onClick={onSubmitWrapper}
|
|
697
657
|
className="create-msg"
|
|
698
|
-
disabled={isTagValidationError || (isLiquidSupportFeatureEnabled && !isObject(metaEntities?.tagLookupMap))}
|
|
699
658
|
>
|
|
700
659
|
<FormattedMessage {...messages.saveButtonLabel} />
|
|
701
660
|
</CapButton>
|
|
@@ -4265,7 +4265,7 @@ FREE GIFTS-
|
|
|
4265
4265
|
<CapCheckbox
|
|
4266
4266
|
checked={false}
|
|
4267
4267
|
disabled={false}
|
|
4268
|
-
key=".
|
|
4268
|
+
key=".3"
|
|
4269
4269
|
labelType="h4"
|
|
4270
4270
|
onChange={[Function]}
|
|
4271
4271
|
>
|
|
@@ -4327,7 +4327,7 @@ FREE GIFTS-
|
|
|
4327
4327
|
</div>
|
|
4328
4328
|
</CapCheckbox>
|
|
4329
4329
|
<div
|
|
4330
|
-
key=".
|
|
4330
|
+
key=".5"
|
|
4331
4331
|
style={
|
|
4332
4332
|
Object {
|
|
4333
4333
|
"marginBottom": "100px",
|
|
@@ -15176,7 +15176,7 @@ FREE GIFTS-
|
|
|
15176
15176
|
<CapCheckbox
|
|
15177
15177
|
checked={false}
|
|
15178
15178
|
disabled={false}
|
|
15179
|
-
key=".
|
|
15179
|
+
key=".3"
|
|
15180
15180
|
labelType="h4"
|
|
15181
15181
|
onChange={[Function]}
|
|
15182
15182
|
>
|
|
@@ -15238,7 +15238,7 @@ FREE GIFTS-
|
|
|
15238
15238
|
</div>
|
|
15239
15239
|
</CapCheckbox>
|
|
15240
15240
|
<div
|
|
15241
|
-
key=".
|
|
15241
|
+
key=".5"
|
|
15242
15242
|
style={
|
|
15243
15243
|
Object {
|
|
15244
15244
|
"marginBottom": "100px",
|
|
@@ -26117,7 +26117,7 @@ FREE GIFTS-
|
|
|
26117
26117
|
<CapCheckbox
|
|
26118
26118
|
checked={false}
|
|
26119
26119
|
disabled={false}
|
|
26120
|
-
key=".
|
|
26120
|
+
key=".3"
|
|
26121
26121
|
labelType="h4"
|
|
26122
26122
|
onChange={[Function]}
|
|
26123
26123
|
>
|
|
@@ -26179,7 +26179,7 @@ FREE GIFTS-
|
|
|
26179
26179
|
</div>
|
|
26180
26180
|
</CapCheckbox>
|
|
26181
26181
|
<div
|
|
26182
|
-
key=".
|
|
26182
|
+
key=".5"
|
|
26183
26183
|
style={
|
|
26184
26184
|
Object {
|
|
26185
26185
|
"marginBottom": "100px",
|
|
@@ -125,7 +125,9 @@ function templatesReducer(state = initialState, action) {
|
|
|
125
125
|
.set('selectedFacebookAccount', fromJS(action.faceBookAccount))
|
|
126
126
|
.set('templates', []);
|
|
127
127
|
case types.SET_WEBPUSH_ACCOUNT:
|
|
128
|
-
return state
|
|
128
|
+
return state
|
|
129
|
+
.set('selectedWebPushAccount', fromJS(action.account))
|
|
130
|
+
.set('templates', []);
|
|
129
131
|
case types.RESET_ACCOUNT:
|
|
130
132
|
return state
|
|
131
133
|
.remove('selectedWeChatAccount')
|
|
@@ -306,6 +306,18 @@ describe("test reducer - SET account actions clear templates", () => {
|
|
|
306
306
|
expect(result.templates).toEqual([]);
|
|
307
307
|
});
|
|
308
308
|
|
|
309
|
+
it.concurrent("should clear templates when SET_WEBPUSH_ACCOUNT is dispatched", () => {
|
|
310
|
+
const stateWithTemplates = initialState.set('templates', [{ id: 1, name: "Template 1" }]);
|
|
311
|
+
const mockAccount = { id: 1, name: "WebPush Account", accountName: "webpush123" };
|
|
312
|
+
const action = {
|
|
313
|
+
type: types.SET_WEBPUSH_ACCOUNT,
|
|
314
|
+
account: mockAccount,
|
|
315
|
+
};
|
|
316
|
+
const result = reducer(stateWithTemplates, action).toJS();
|
|
317
|
+
expect(result.selectedWebPushAccount).toEqual(mockAccount);
|
|
318
|
+
expect(result.templates).toEqual([]);
|
|
319
|
+
});
|
|
320
|
+
|
|
309
321
|
it.concurrent("should clear templates even when templates array is empty", () => {
|
|
310
322
|
const emptyTemplatesState = initialState.set('templates', []);
|
|
311
323
|
const mockAccount = { id: 1, name: "WeChat Account" };
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
|
|
3
|
+
import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
|
|
4
|
+
import CapDivider from '@capillarytech/cap-ui-library/CapDivider';
|
|
5
|
+
import { mountWithIntl, shallowWithIntl } from '../../../../helpers/intl-enzym-test-helpers';
|
|
6
|
+
import { BrandIconSection } from './BrandIconSection';
|
|
7
|
+
import CapImageUpload from '../../../../v2Components/CapImageUpload';
|
|
8
|
+
import { BRAND_ICON_OPTIONS } from '../../constants';
|
|
9
|
+
|
|
10
|
+
describe('BrandIconSection', () => {
|
|
11
|
+
const mockFormatMessage = jest.fn((msg) => msg?.defaultMessage || msg?.id || '');
|
|
12
|
+
|
|
13
|
+
const mockMessages = {
|
|
14
|
+
brandIconLogo: { id: 'app.webpush.brandIconLogo', defaultMessage: 'Brand Icon/Logo' },
|
|
15
|
+
dontShow: { id: 'app.webpush.dontShow', defaultMessage: "Don't show" },
|
|
16
|
+
uploadImage: { id: 'app.webpush.uploadImage', defaultMessage: 'Upload image' },
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const mockBrandIconUpload = {
|
|
20
|
+
imageSrc: '',
|
|
21
|
+
uploadAsset: jest.fn(),
|
|
22
|
+
setUpdateImageSrc: jest.fn(),
|
|
23
|
+
updateOnReUpload: jest.fn(),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const defaultProps = {
|
|
27
|
+
brandIconOption: BRAND_ICON_OPTIONS.DONT_SHOW,
|
|
28
|
+
onBrandIconChange: jest.fn(),
|
|
29
|
+
brandIconUpload: mockBrandIconUpload,
|
|
30
|
+
isLocked: false,
|
|
31
|
+
isAnyUploadActive: false,
|
|
32
|
+
formatMessage: mockFormatMessage,
|
|
33
|
+
messages: mockMessages,
|
|
34
|
+
webPush: {},
|
|
35
|
+
isFullMode: true,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
jest.clearAllMocks();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('brandIconOptions array', () => {
|
|
43
|
+
it('builds exactly two options: DONT_SHOW and UPLOAD_IMAGE', () => {
|
|
44
|
+
const wrapper = mountWithIntl(<BrandIconSection {...defaultProps} />);
|
|
45
|
+
const radioGroup = wrapper.find(CapRadioGroup);
|
|
46
|
+
const options = radioGroup.prop('options');
|
|
47
|
+
expect(options).toHaveLength(2);
|
|
48
|
+
expect(options[0].value).toBe(BRAND_ICON_OPTIONS.DONT_SHOW);
|
|
49
|
+
expect(options[1].value).toBe(BRAND_ICON_OPTIONS.UPLOAD_IMAGE);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('does NOT include ADD_IMAGE_URL option (commented-out feature)', () => {
|
|
53
|
+
const wrapper = mountWithIntl(<BrandIconSection {...defaultProps} />);
|
|
54
|
+
const options = wrapper.find(CapRadioGroup).prop('options');
|
|
55
|
+
const hasAddImageUrl = options.some((opt) => opt.value === BRAND_ICON_OPTIONS.ADD_IMAGE_URL);
|
|
56
|
+
expect(hasAddImageUrl).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('calls formatMessage for each option label', () => {
|
|
60
|
+
mountWithIntl(<BrandIconSection {...defaultProps} />);
|
|
61
|
+
expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.dontShow);
|
|
62
|
+
expect(mockFormatMessage).toHaveBeenCalledWith(mockMessages.uploadImage);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('CapRadioGroup rendering', () => {
|
|
67
|
+
it('passes brandIconOption as value to CapRadioGroup', () => {
|
|
68
|
+
const wrapper = mountWithIntl(
|
|
69
|
+
<BrandIconSection {...defaultProps} brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE} />
|
|
70
|
+
);
|
|
71
|
+
expect(wrapper.find(CapRadioGroup).prop('value')).toBe(BRAND_ICON_OPTIONS.UPLOAD_IMAGE);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('passes onBrandIconChange as onChange to CapRadioGroup', () => {
|
|
75
|
+
const onBrandIconChange = jest.fn();
|
|
76
|
+
const wrapper = mountWithIntl(
|
|
77
|
+
<BrandIconSection {...defaultProps} onBrandIconChange={onBrandIconChange} />
|
|
78
|
+
);
|
|
79
|
+
expect(wrapper.find(CapRadioGroup).prop('onChange')).toBe(onBrandIconChange);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('disables CapRadioGroup when isAnyUploadActive is true', () => {
|
|
83
|
+
const wrapper = mountWithIntl(
|
|
84
|
+
<BrandIconSection {...defaultProps} isAnyUploadActive={true} />
|
|
85
|
+
);
|
|
86
|
+
expect(wrapper.find(CapRadioGroup).prop('disabled')).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('does not disable CapRadioGroup when isAnyUploadActive is false', () => {
|
|
90
|
+
const wrapper = mountWithIntl(
|
|
91
|
+
<BrandIconSection {...defaultProps} isAnyUploadActive={false} />
|
|
92
|
+
);
|
|
93
|
+
expect(wrapper.find(CapRadioGroup).prop('disabled')).toBe(false);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('conditional upload section (brandIconOption === UPLOAD_IMAGE)', () => {
|
|
98
|
+
it('does NOT render CapImageUpload when brandIconOption is DONT_SHOW', () => {
|
|
99
|
+
const wrapper = mountWithIntl(
|
|
100
|
+
<BrandIconSection {...defaultProps} brandIconOption={BRAND_ICON_OPTIONS.DONT_SHOW} />
|
|
101
|
+
);
|
|
102
|
+
expect(wrapper.find(CapImageUpload).exists()).toBe(false);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('renders CapImageUpload when brandIconOption is UPLOAD_IMAGE', () => {
|
|
106
|
+
const wrapper = mountWithIntl(
|
|
107
|
+
<BrandIconSection {...defaultProps} brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE} />
|
|
108
|
+
);
|
|
109
|
+
expect(wrapper.find(CapImageUpload).exists()).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('renders the upload section row with correct className', () => {
|
|
113
|
+
const wrapper = mountWithIntl(
|
|
114
|
+
<BrandIconSection {...defaultProps} brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE} />
|
|
115
|
+
);
|
|
116
|
+
expect(wrapper.find('.webpush-brand-icon-upload-section').exists()).toBe(true);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('passes brandIconUpload.imageSrc to CapImageUpload as imageSrc', () => {
|
|
120
|
+
const wrapper = mountWithIntl(
|
|
121
|
+
<BrandIconSection
|
|
122
|
+
{...defaultProps}
|
|
123
|
+
brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE}
|
|
124
|
+
brandIconUpload={{ ...mockBrandIconUpload, imageSrc: 'https://example.com/icon.png' }}
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
expect(wrapper.find(CapImageUpload).prop('imageSrc')).toBe('https://example.com/icon.png');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('passes brandIconUpload.uploadAsset to CapImageUpload as uploadAsset', () => {
|
|
131
|
+
const uploadAsset = jest.fn();
|
|
132
|
+
const wrapper = mountWithIntl(
|
|
133
|
+
<BrandIconSection
|
|
134
|
+
{...defaultProps}
|
|
135
|
+
brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE}
|
|
136
|
+
brandIconUpload={{ ...mockBrandIconUpload, uploadAsset }}
|
|
137
|
+
/>
|
|
138
|
+
);
|
|
139
|
+
expect(wrapper.find(CapImageUpload).prop('uploadAsset')).toBe(uploadAsset);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('passes isFullMode to CapImageUpload', () => {
|
|
143
|
+
const wrapper = mountWithIntl(
|
|
144
|
+
<BrandIconSection
|
|
145
|
+
{...defaultProps}
|
|
146
|
+
brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE}
|
|
147
|
+
isFullMode={false}
|
|
148
|
+
/>
|
|
149
|
+
);
|
|
150
|
+
expect(wrapper.find(CapImageUpload).prop('isFullMode')).toBe(false);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('isLocked behavior', () => {
|
|
155
|
+
it('applies pointer-events: none and opacity: 0.5 to upload row when isLocked is true', () => {
|
|
156
|
+
const wrapper = mountWithIntl(
|
|
157
|
+
<BrandIconSection
|
|
158
|
+
{...defaultProps}
|
|
159
|
+
brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE}
|
|
160
|
+
isLocked={true}
|
|
161
|
+
/>
|
|
162
|
+
);
|
|
163
|
+
const uploadRow = wrapper.find('.webpush-brand-icon-upload-section').first();
|
|
164
|
+
expect(uploadRow.prop('style')).toEqual({ pointerEvents: 'none', opacity: 0.5 });
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('sets aria-disabled on upload row when isLocked is true', () => {
|
|
168
|
+
const wrapper = mountWithIntl(
|
|
169
|
+
<BrandIconSection
|
|
170
|
+
{...defaultProps}
|
|
171
|
+
brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE}
|
|
172
|
+
isLocked={true}
|
|
173
|
+
/>
|
|
174
|
+
);
|
|
175
|
+
const uploadRow = wrapper.find('.webpush-brand-icon-upload-section').first();
|
|
176
|
+
expect(uploadRow.prop('aria-disabled')).toBe(true);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('does NOT apply lock styles to upload row when isLocked is false', () => {
|
|
180
|
+
const wrapper = mountWithIntl(
|
|
181
|
+
<BrandIconSection
|
|
182
|
+
{...defaultProps}
|
|
183
|
+
brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE}
|
|
184
|
+
isLocked={false}
|
|
185
|
+
/>
|
|
186
|
+
);
|
|
187
|
+
const uploadRow = wrapper.find('.webpush-brand-icon-upload-section').first();
|
|
188
|
+
expect(uploadRow.prop('style')).toBeUndefined();
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('passes disabled=true to CapImageUpload when isLocked is true', () => {
|
|
192
|
+
const wrapper = mountWithIntl(
|
|
193
|
+
<BrandIconSection
|
|
194
|
+
{...defaultProps}
|
|
195
|
+
brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE}
|
|
196
|
+
isLocked={true}
|
|
197
|
+
/>
|
|
198
|
+
);
|
|
199
|
+
expect(wrapper.find(CapImageUpload).prop('disabled')).toBe(true);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('passes disabled=false to CapImageUpload when isLocked is false', () => {
|
|
203
|
+
const wrapper = mountWithIntl(
|
|
204
|
+
<BrandIconSection
|
|
205
|
+
{...defaultProps}
|
|
206
|
+
brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE}
|
|
207
|
+
isLocked={false}
|
|
208
|
+
/>
|
|
209
|
+
);
|
|
210
|
+
expect(wrapper.find(CapImageUpload).prop('disabled')).toBe(false);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
describe('structural rendering', () => {
|
|
215
|
+
it('always renders CapDivider regardless of brandIconOption', () => {
|
|
216
|
+
const wrapperDontShow = mountWithIntl(
|
|
217
|
+
<BrandIconSection {...defaultProps} brandIconOption={BRAND_ICON_OPTIONS.DONT_SHOW} />
|
|
218
|
+
);
|
|
219
|
+
expect(wrapperDontShow.find(CapDivider).exists()).toBe(true);
|
|
220
|
+
|
|
221
|
+
const wrapperUpload = mountWithIntl(
|
|
222
|
+
<BrandIconSection {...defaultProps} brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE} />
|
|
223
|
+
);
|
|
224
|
+
expect(wrapperUpload.find(CapDivider).exists()).toBe(true);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('renders the brand icon heading row with className creatives-webpush-brand-icon', () => {
|
|
228
|
+
const wrapper = mountWithIntl(<BrandIconSection {...defaultProps} />);
|
|
229
|
+
expect(wrapper.find('.creatives-webpush-brand-icon').exists()).toBe(true);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('renders CapHeading with type h4', () => {
|
|
233
|
+
const wrapper = mountWithIntl(<BrandIconSection {...defaultProps} />);
|
|
234
|
+
expect(wrapper.find(CapHeading).prop('type')).toBe('h4');
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe('snapshot', () => {
|
|
239
|
+
it('matches snapshot for DONT_SHOW state', () => {
|
|
240
|
+
const wrapper = shallowWithIntl(
|
|
241
|
+
<BrandIconSection {...defaultProps} brandIconOption={BRAND_ICON_OPTIONS.DONT_SHOW} />
|
|
242
|
+
);
|
|
243
|
+
expect(wrapper).toMatchSnapshot();
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('matches snapshot for UPLOAD_IMAGE state', () => {
|
|
247
|
+
const wrapper = shallowWithIntl(
|
|
248
|
+
<BrandIconSection {...defaultProps} brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE} />
|
|
249
|
+
);
|
|
250
|
+
expect(wrapper).toMatchSnapshot();
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('matches snapshot for locked UPLOAD_IMAGE state', () => {
|
|
254
|
+
const wrapper = shallowWithIntl(
|
|
255
|
+
<BrandIconSection
|
|
256
|
+
{...defaultProps}
|
|
257
|
+
brandIconOption={BRAND_ICON_OPTIONS.UPLOAD_IMAGE}
|
|
258
|
+
isLocked={true}
|
|
259
|
+
/>
|
|
260
|
+
);
|
|
261
|
+
expect(wrapper).toMatchSnapshot();
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
});
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`BrandIconSection snapshot matches snapshot for DONT_SHOW state 1`] = `
|
|
4
|
+
<Fragment>
|
|
5
|
+
<CapRow
|
|
6
|
+
className="creatives-webpush-brand-icon"
|
|
7
|
+
>
|
|
8
|
+
<CapHeading
|
|
9
|
+
className="webpush-brand-icon"
|
|
10
|
+
type="h4"
|
|
11
|
+
>
|
|
12
|
+
<FormattedMessage
|
|
13
|
+
defaultMessage="Brand Icon/Logo"
|
|
14
|
+
id="app.webpush.brandIconLogo"
|
|
15
|
+
values={Object {}}
|
|
16
|
+
/>
|
|
17
|
+
</CapHeading>
|
|
18
|
+
<CapRadioGroup
|
|
19
|
+
disabled={false}
|
|
20
|
+
errorMessage=""
|
|
21
|
+
onChange={[MockFunction]}
|
|
22
|
+
options={
|
|
23
|
+
Array [
|
|
24
|
+
Object {
|
|
25
|
+
"label": undefined,
|
|
26
|
+
"value": "DONT_SHOW",
|
|
27
|
+
},
|
|
28
|
+
Object {
|
|
29
|
+
"label": undefined,
|
|
30
|
+
"value": "UPLOAD_IMAGE",
|
|
31
|
+
},
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
value="DONT_SHOW"
|
|
35
|
+
/>
|
|
36
|
+
</CapRow>
|
|
37
|
+
<CapDivider />
|
|
38
|
+
</Fragment>
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
exports[`BrandIconSection snapshot matches snapshot for UPLOAD_IMAGE state 1`] = `
|
|
42
|
+
<Fragment>
|
|
43
|
+
<CapRow
|
|
44
|
+
className="creatives-webpush-brand-icon"
|
|
45
|
+
>
|
|
46
|
+
<CapHeading
|
|
47
|
+
className="webpush-brand-icon"
|
|
48
|
+
type="h4"
|
|
49
|
+
>
|
|
50
|
+
<FormattedMessage
|
|
51
|
+
defaultMessage="Brand Icon/Logo"
|
|
52
|
+
id="app.webpush.brandIconLogo"
|
|
53
|
+
values={Object {}}
|
|
54
|
+
/>
|
|
55
|
+
</CapHeading>
|
|
56
|
+
<CapRadioGroup
|
|
57
|
+
disabled={false}
|
|
58
|
+
errorMessage=""
|
|
59
|
+
onChange={[MockFunction]}
|
|
60
|
+
options={
|
|
61
|
+
Array [
|
|
62
|
+
Object {
|
|
63
|
+
"label": undefined,
|
|
64
|
+
"value": "DONT_SHOW",
|
|
65
|
+
},
|
|
66
|
+
Object {
|
|
67
|
+
"label": undefined,
|
|
68
|
+
"value": "UPLOAD_IMAGE",
|
|
69
|
+
},
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
value="UPLOAD_IMAGE"
|
|
73
|
+
/>
|
|
74
|
+
</CapRow>
|
|
75
|
+
<CapRow
|
|
76
|
+
aria-disabled={false}
|
|
77
|
+
className="webpush-brand-icon-upload-section"
|
|
78
|
+
>
|
|
79
|
+
<InjectIntl(CapImageUpload)
|
|
80
|
+
allowedExtensionsRegex={/\\\\\\.\\(jpe\\?g\\|png\\)\\$/i}
|
|
81
|
+
channel="WEBPUSH_BRAND_ICON"
|
|
82
|
+
className="cap-custom-image-upload"
|
|
83
|
+
disabled={false}
|
|
84
|
+
imageData={Object {}}
|
|
85
|
+
imageSrc=""
|
|
86
|
+
imgSize={1000000}
|
|
87
|
+
index={1}
|
|
88
|
+
isFullMode={true}
|
|
89
|
+
key="webpush-brand-icon-uploaded-image"
|
|
90
|
+
recommendedDimensions={
|
|
91
|
+
Array [
|
|
92
|
+
Object {
|
|
93
|
+
"height": 192,
|
|
94
|
+
"width": 192,
|
|
95
|
+
},
|
|
96
|
+
Object {
|
|
97
|
+
"height": 256,
|
|
98
|
+
"width": 256,
|
|
99
|
+
},
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
showReUploadButton={true}
|
|
103
|
+
updateImageSrc={[MockFunction]}
|
|
104
|
+
updateOnReUpload={[MockFunction]}
|
|
105
|
+
uploadAsset={[MockFunction]}
|
|
106
|
+
/>
|
|
107
|
+
</CapRow>
|
|
108
|
+
<CapDivider />
|
|
109
|
+
</Fragment>
|
|
110
|
+
`;
|
|
111
|
+
|
|
112
|
+
exports[`BrandIconSection snapshot matches snapshot for locked UPLOAD_IMAGE state 1`] = `
|
|
113
|
+
<Fragment>
|
|
114
|
+
<CapRow
|
|
115
|
+
className="creatives-webpush-brand-icon"
|
|
116
|
+
>
|
|
117
|
+
<CapHeading
|
|
118
|
+
className="webpush-brand-icon"
|
|
119
|
+
type="h4"
|
|
120
|
+
>
|
|
121
|
+
<FormattedMessage
|
|
122
|
+
defaultMessage="Brand Icon/Logo"
|
|
123
|
+
id="app.webpush.brandIconLogo"
|
|
124
|
+
values={Object {}}
|
|
125
|
+
/>
|
|
126
|
+
</CapHeading>
|
|
127
|
+
<CapRadioGroup
|
|
128
|
+
disabled={false}
|
|
129
|
+
errorMessage=""
|
|
130
|
+
onChange={[MockFunction]}
|
|
131
|
+
options={
|
|
132
|
+
Array [
|
|
133
|
+
Object {
|
|
134
|
+
"label": undefined,
|
|
135
|
+
"value": "DONT_SHOW",
|
|
136
|
+
},
|
|
137
|
+
Object {
|
|
138
|
+
"label": undefined,
|
|
139
|
+
"value": "UPLOAD_IMAGE",
|
|
140
|
+
},
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
value="UPLOAD_IMAGE"
|
|
144
|
+
/>
|
|
145
|
+
</CapRow>
|
|
146
|
+
<CapRow
|
|
147
|
+
aria-disabled={true}
|
|
148
|
+
className="webpush-brand-icon-upload-section"
|
|
149
|
+
style={
|
|
150
|
+
Object {
|
|
151
|
+
"opacity": 0.5,
|
|
152
|
+
"pointerEvents": "none",
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
>
|
|
156
|
+
<InjectIntl(CapImageUpload)
|
|
157
|
+
allowedExtensionsRegex={/\\\\\\.\\(jpe\\?g\\|png\\)\\$/i}
|
|
158
|
+
channel="WEBPUSH_BRAND_ICON"
|
|
159
|
+
className="cap-custom-image-upload"
|
|
160
|
+
disabled={true}
|
|
161
|
+
imageData={Object {}}
|
|
162
|
+
imageSrc=""
|
|
163
|
+
imgSize={1000000}
|
|
164
|
+
index={1}
|
|
165
|
+
isFullMode={true}
|
|
166
|
+
key="webpush-brand-icon-uploaded-image"
|
|
167
|
+
recommendedDimensions={
|
|
168
|
+
Array [
|
|
169
|
+
Object {
|
|
170
|
+
"height": 192,
|
|
171
|
+
"width": 192,
|
|
172
|
+
},
|
|
173
|
+
Object {
|
|
174
|
+
"height": 256,
|
|
175
|
+
"width": 256,
|
|
176
|
+
},
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
showReUploadButton={true}
|
|
180
|
+
updateImageSrc={[MockFunction]}
|
|
181
|
+
updateOnReUpload={[MockFunction]}
|
|
182
|
+
uploadAsset={[MockFunction]}
|
|
183
|
+
/>
|
|
184
|
+
</CapRow>
|
|
185
|
+
<CapDivider />
|
|
186
|
+
</Fragment>
|
|
187
|
+
`;
|
|
@@ -105,12 +105,10 @@ export const useTagManagement = ({
|
|
|
105
105
|
const validationConfig = useMemo(
|
|
106
106
|
() => ({
|
|
107
107
|
tagsParam: tags,
|
|
108
|
-
injectedTagsParams: injectedTags,
|
|
109
108
|
location,
|
|
110
109
|
tagModule: getDefaultTags,
|
|
111
|
-
eventContextTags,
|
|
112
110
|
}),
|
|
113
|
-
[tags,
|
|
111
|
+
[tags, location, getDefaultTags],
|
|
114
112
|
);
|
|
115
113
|
|
|
116
114
|
return {
|