@capillarytech/creatives-library 8.0.129 → 8.0.131
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/containers/Login/index.js +1 -2
- package/containers/Templates/constants.js +10 -1
- package/containers/Templates/index.js +45 -45
- package/package.json +1 -1
- package/services/api.js +14 -7
- package/services/tests/haptic-api.test.js +387 -0
- package/utils/createMobilePushPayload.js +322 -0
- package/utils/tests/{createPayload.test.js → createMobilePushPayload.test.js} +333 -64
- package/utils/tests/vendorDataTransformers.test.js +512 -0
- package/utils/vendorDataTransformers.js +108 -0
- package/v2Components/CapDeviceContent/index.js +1 -1
- package/v2Components/CapDocumentUpload/index.js +2 -2
- package/v2Components/CapImageUpload/index.js +2 -2
- package/v2Components/CapMpushCTA/index.js +13 -12
- package/v2Components/CapTagList/index.js +5 -5
- package/v2Components/CapVideoUpload/index.js +17 -7
- package/v2Components/MobilePushPreviewV2/index.js +28 -15
- package/v2Components/TemplatePreview/_templatePreview.scss +131 -29
- package/v2Components/TemplatePreview/index.js +130 -131
- package/v2Components/TemplatePreview/tests/__snapshots__/index.test.js.snap +10 -10
- package/v2Containers/CreativesContainer/index.js +6 -4
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +4748 -4658
- package/v2Containers/Login/index.js +1 -2
- package/v2Containers/MobilePush/tests/commonMethods.test.js +401 -0
- package/v2Containers/MobilePushNew/components/CtaButtons.js +18 -16
- package/v2Containers/MobilePushNew/components/MediaUploaders.js +46 -45
- package/v2Containers/MobilePushNew/components/PlatformContentFields.js +12 -11
- package/v2Containers/MobilePushNew/components/tests/CtaButtons.test.js +134 -367
- package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +1209 -143
- package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +314 -3
- package/v2Containers/MobilePushNew/constants.js +1 -0
- package/v2Containers/MobilePushNew/hooks/tests/usePlatformSync.test.js +163 -0
- package/v2Containers/MobilePushNew/hooks/tests/useUpload.test.js +1131 -895
- package/v2Containers/MobilePushNew/hooks/usePlatformSync.js +172 -52
- package/v2Containers/MobilePushNew/hooks/useUpload.js +88 -74
- package/v2Containers/MobilePushNew/index.js +278 -1532
- package/v2Containers/MobilePushNew/messages.js +30 -0
- package/v2Containers/MobilePushNew/sagas.js +2 -7
- package/v2Containers/MobilePushNew/tests/sagas.test.js +41 -40
- package/v2Containers/MobilePushNew/tests/selectors.test.js +240 -0
- package/v2Containers/MobilePushNew/tests/utils.test.js +118 -19
- package/v2Containers/MobilePushNew/utils.js +53 -2
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +1171 -971
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +684 -424
- package/v2Containers/Templates/_templates.scss +0 -1
- package/v2Containers/Templates/index.js +58 -29
- package/v2Containers/Templates/sagas.js +0 -1
- package/v2Containers/Whatsapp/constants.js +32 -0
- package/v2Containers/Whatsapp/index.js +104 -25
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +3992 -3677
- package/v2Containers/Whatsapp/tests/haptic.test.js +405 -0
- package/assets/loading_img.gif +0 -0
- package/utils/createPayload.js +0 -405
- /package/v2Components/TemplatePreview/assets/images/{Android _ With date and time.svg → Android_With_date_and_time.svg} +0 -0
- /package/v2Components/TemplatePreview/assets/images/{iOS _ With date and time.svg → iOS_With_date_and_time.svg} +0 -0
|
@@ -8,6 +8,8 @@ import { initialReducer } from '../../../../initialReducer';
|
|
|
8
8
|
import history from '../../../../utils/history';
|
|
9
9
|
import MediaUploaders from '../MediaUploaders';
|
|
10
10
|
import { ANDROID, IOS } from '../../constants';
|
|
11
|
+
import { act } from 'react';
|
|
12
|
+
import messages from '../../messages';
|
|
11
13
|
|
|
12
14
|
// Mock the upload components
|
|
13
15
|
jest.mock('../../../../v2Components/CapImageUpload', () =>
|
|
@@ -21,6 +23,16 @@ jest.mock('../../../../v2Components/CapImageUpload', () =>
|
|
|
21
23
|
>
|
|
22
24
|
Upload Image
|
|
23
25
|
</button>
|
|
26
|
+
<button
|
|
27
|
+
type="button"
|
|
28
|
+
onClick={() => {
|
|
29
|
+
props.updateOnReUpload();
|
|
30
|
+
props.updateImageSrc('mock-image-url');
|
|
31
|
+
}}
|
|
32
|
+
data-testid="image-reupload-button"
|
|
33
|
+
>
|
|
34
|
+
Re-upload Image
|
|
35
|
+
</button>
|
|
24
36
|
</div>
|
|
25
37
|
);
|
|
26
38
|
}
|
|
@@ -117,55 +129,63 @@ jest.mock('@capillarytech/cap-ui-library/CapIcon', () =>
|
|
|
117
129
|
}
|
|
118
130
|
);
|
|
119
131
|
|
|
120
|
-
|
|
121
|
-
|
|
132
|
+
// Mock the CapCheckbox component
|
|
133
|
+
jest.mock('@capillarytech/cap-ui-library/CapCheckbox', () => ({
|
|
134
|
+
__esModule: true,
|
|
135
|
+
default: function MockCapCheckbox({ checked, onChange, children, ...props }) {
|
|
122
136
|
return (
|
|
123
|
-
<label
|
|
137
|
+
<label>
|
|
124
138
|
<input
|
|
125
139
|
type="checkbox"
|
|
126
|
-
checked={checked}
|
|
127
|
-
onChange={onChange}
|
|
128
140
|
data-testid="cap-checkbox"
|
|
141
|
+
checked={checked}
|
|
142
|
+
onChange={(e) => onChange && onChange(e)}
|
|
143
|
+
{...props}
|
|
129
144
|
/>
|
|
130
145
|
<span>{children}</span>
|
|
131
146
|
</label>
|
|
132
147
|
);
|
|
133
|
-
}
|
|
134
|
-
);
|
|
148
|
+
},
|
|
149
|
+
}));
|
|
150
|
+
|
|
151
|
+
// Mock the CapInput component
|
|
152
|
+
jest.mock('@capillarytech/cap-ui-library/CapInput', () => ({
|
|
153
|
+
__esModule: true,
|
|
154
|
+
default: function MockCapInput({ value, onChange, id, placeholder, error }) {
|
|
155
|
+
return (
|
|
156
|
+
<div>
|
|
157
|
+
<input
|
|
158
|
+
data-testid={`cap-input-${id || 'mobile-push-external-link-input-ANDROID-0'}`}
|
|
159
|
+
type="text"
|
|
160
|
+
value={value || ''}
|
|
161
|
+
onChange={(e) => onChange && onChange({ target: { value: e.target.value } })}
|
|
162
|
+
placeholder={placeholder}
|
|
163
|
+
/>
|
|
164
|
+
{error && <div data-testid="error-message">{error}</div>}
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
},
|
|
168
|
+
}));
|
|
135
169
|
|
|
170
|
+
// Mock the CapSelect.CapCustomSelect component
|
|
136
171
|
jest.mock('@capillarytech/cap-ui-library/CapSelect', () => ({
|
|
137
|
-
CapCustomSelect: function MockCapCustomSelect({
|
|
172
|
+
CapCustomSelect: function MockCapCustomSelect({ value, onChange, options }) {
|
|
138
173
|
return (
|
|
139
174
|
<select
|
|
140
|
-
value={value}
|
|
141
|
-
onChange={(e) => onChange(e.target.value)}
|
|
142
175
|
data-testid="cap-custom-select"
|
|
176
|
+
value={value}
|
|
177
|
+
onChange={(e) => onChange && onChange(e.target.value)}
|
|
143
178
|
>
|
|
144
|
-
<option value="">{placeholder || selectPlaceholder}</option>
|
|
145
179
|
{options?.map((option) => (
|
|
146
180
|
<option key={option.value} value={option.value}>
|
|
147
|
-
{option.label}
|
|
181
|
+
{option.label || option.value}
|
|
148
182
|
</option>
|
|
149
183
|
))}
|
|
150
184
|
</select>
|
|
151
185
|
);
|
|
152
|
-
}
|
|
186
|
+
},
|
|
153
187
|
}));
|
|
154
188
|
|
|
155
|
-
jest.mock('@capillarytech/cap-ui-library/CapInput', () =>
|
|
156
|
-
function MockCapInput({ value, onChange, placeholder, id }) {
|
|
157
|
-
return (
|
|
158
|
-
<input
|
|
159
|
-
id={id}
|
|
160
|
-
value={value}
|
|
161
|
-
onChange={onChange}
|
|
162
|
-
placeholder={placeholder}
|
|
163
|
-
data-testid="cap-input"
|
|
164
|
-
/>
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
);
|
|
168
|
-
|
|
169
189
|
jest.mock('@capillarytech/cap-ui-library/CapRow', () =>
|
|
170
190
|
function MockCapRow({ children, className, style }) {
|
|
171
191
|
return <div className={className} style={style}>{children}</div>;
|
|
@@ -220,74 +240,115 @@ jest.mock('../../utils', () => ({
|
|
|
220
240
|
|
|
221
241
|
// Mock the messages
|
|
222
242
|
jest.mock('../../messages', () => ({
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
243
|
+
__esModule: true,
|
|
244
|
+
default: {
|
|
245
|
+
imageErrorMessage: {
|
|
246
|
+
id: 'creatives.containersV2.MobilePushNew.imageErrorMessage',
|
|
247
|
+
defaultMessage: 'Please upload the image with allowed file extension, size, dimension and aspect ratio',
|
|
248
|
+
},
|
|
249
|
+
videoErrorMessage: {
|
|
250
|
+
id: 'creatives.containersV2.MobilePushNew.videoErrorMessage',
|
|
251
|
+
defaultMessage: 'Please upload the video with allowed file extension, size, dimension and aspect ratio',
|
|
252
|
+
},
|
|
253
|
+
gifErrorMessage: {
|
|
254
|
+
id: 'creatives.containersV2.MobilePushNew.gifErrorMessage',
|
|
255
|
+
defaultMessage: 'Please upload the gif with allowed file extension, size, dimension and aspect ratio',
|
|
256
|
+
},
|
|
257
|
+
buttonsAndLinks: {
|
|
258
|
+
id: 'creatives.containersV2.MobilePushNew.buttonsAndLinks',
|
|
259
|
+
defaultMessage: 'Buttons and links',
|
|
260
|
+
},
|
|
261
|
+
optionalText: {
|
|
262
|
+
id: 'creatives.containersV2.MobilePushNew.optionalText',
|
|
263
|
+
defaultMessage: '(Optional)',
|
|
264
|
+
},
|
|
265
|
+
actionOnClick: {
|
|
266
|
+
id: 'creatives.containersV2.MobilePushNew.actionOnClick',
|
|
267
|
+
defaultMessage: 'Action on click of notification body',
|
|
268
|
+
},
|
|
269
|
+
actionDescription: {
|
|
270
|
+
id: 'creatives.containersV2.MobilePushNew.actionDescription',
|
|
271
|
+
defaultMessage: 'Define where the users will redirect when they click on the body of the push notification',
|
|
272
|
+
},
|
|
273
|
+
linkType: {
|
|
274
|
+
id: 'app.containers.MobilePushNew.linkType',
|
|
275
|
+
defaultMessage: 'Link Type',
|
|
276
|
+
},
|
|
277
|
+
selectDeepLink: {
|
|
278
|
+
id: 'creatives.containersV2.MobilePushNew.selectDeepLink',
|
|
279
|
+
defaultMessage: 'Select deep link',
|
|
280
|
+
},
|
|
281
|
+
deepLink: {
|
|
282
|
+
id: 'app.containers.MobilePushNew.deepLink',
|
|
283
|
+
defaultMessage: 'Deep Link',
|
|
284
|
+
},
|
|
285
|
+
externalLink: {
|
|
286
|
+
id: 'app.containers.MobilePushNew.externalLink',
|
|
287
|
+
defaultMessage: 'External Link',
|
|
288
|
+
},
|
|
289
|
+
enterExternalLink: {
|
|
290
|
+
id: 'creatives.containersV2.MobilePushNew.enterExternalLink',
|
|
291
|
+
defaultMessage: 'Enter external link',
|
|
292
|
+
},
|
|
293
|
+
deepLinkKeys: {
|
|
294
|
+
id: 'creatives.containersV2.MobilePushNew.deepLinkKeys',
|
|
295
|
+
defaultMessage: 'Deep Link Keys',
|
|
296
|
+
},
|
|
297
|
+
deepLinkKeysPlaceholder: {
|
|
298
|
+
id: 'creatives.containersV2.MobilePushNew.deepLinkKeysPlaceholder',
|
|
299
|
+
defaultMessage: 'Please input {key}',
|
|
300
|
+
},
|
|
301
|
+
deepLinkKeysRequired: {
|
|
302
|
+
id: 'creatives.containersV2.MobilePushNew.deepLinkKeysRequired',
|
|
303
|
+
defaultMessage: 'Value cannot be empty.',
|
|
304
|
+
},
|
|
305
|
+
invalidUrl: {
|
|
306
|
+
id: 'creatives.containersV2.MobilePushNew.invalidUrl',
|
|
307
|
+
defaultMessage: 'Please enter a valid URL',
|
|
308
|
+
},
|
|
309
|
+
carouselMediaType: {
|
|
310
|
+
id: 'creatives.containersV2.MobilePushNew.carouselMediaType',
|
|
311
|
+
defaultMessage: 'Carousel media Type',
|
|
312
|
+
},
|
|
313
|
+
mediaImage: {
|
|
314
|
+
id: 'creatives.containersV2.MobilePushNew.mediaImage',
|
|
315
|
+
defaultMessage: 'Image',
|
|
316
|
+
},
|
|
317
|
+
mediaVideo: {
|
|
318
|
+
id: 'creatives.containersV2.MobilePushNew.mediaVideo',
|
|
319
|
+
defaultMessage: 'Video',
|
|
320
|
+
},
|
|
321
|
+
card: {
|
|
322
|
+
id: 'creatives.containersV2.MobilePushNew.card',
|
|
323
|
+
defaultMessage: 'Card',
|
|
324
|
+
},
|
|
325
|
+
addCard: {
|
|
326
|
+
id: 'creatives.containersV2.MobilePushNew.addCard',
|
|
327
|
+
defaultMessage: 'Add Card',
|
|
328
|
+
},
|
|
329
|
+
actionOnClickBody: {
|
|
330
|
+
id: 'creatives.containersV2.MobilePushNew.actionOnClickBody',
|
|
331
|
+
defaultMessage: 'Action on click of notification body',
|
|
332
|
+
},
|
|
286
333
|
},
|
|
287
334
|
}));
|
|
288
335
|
|
|
289
336
|
const mockStore = configureStore({}, initialReducer, history);
|
|
290
337
|
|
|
338
|
+
// Helper function for formatMessage
|
|
339
|
+
const mockFormatMessage = (message, values = {}) => {
|
|
340
|
+
if (typeof message === 'object' && message.defaultMessage) {
|
|
341
|
+
let result = message.defaultMessage;
|
|
342
|
+
if (values && typeof values === 'object') {
|
|
343
|
+
Object.keys(values).forEach(key => {
|
|
344
|
+
result = result.replace(`{${key}}`, values[key]);
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
return result;
|
|
348
|
+
}
|
|
349
|
+
return message;
|
|
350
|
+
};
|
|
351
|
+
|
|
291
352
|
const defaultProps = {
|
|
292
353
|
mediaType: 'IMAGE',
|
|
293
354
|
activeTab: ANDROID,
|
|
@@ -325,7 +386,7 @@ const renderComponent = (props = {}) => {
|
|
|
325
386
|
const mergedProps = { ...defaultProps, ...props };
|
|
326
387
|
return render(
|
|
327
388
|
<Provider store={mockStore}>
|
|
328
|
-
<IntlProvider locale="en"
|
|
389
|
+
<IntlProvider messages={messages} locale="en">
|
|
329
390
|
<MediaUploaders {...mergedProps} />
|
|
330
391
|
</IntlProvider>
|
|
331
392
|
</Provider>
|
|
@@ -418,25 +479,41 @@ describe('MediaUploaders', () => {
|
|
|
418
479
|
});
|
|
419
480
|
|
|
420
481
|
describe('CAROUSEL Media Type', () => {
|
|
421
|
-
it('should render carousel component for CAROUSEL media type', () => {
|
|
422
|
-
|
|
482
|
+
it('should render carousel component for CAROUSEL media type', async () => {
|
|
483
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
484
|
+
|
|
485
|
+
const { container } = renderComponent({
|
|
423
486
|
mediaType: 'CAROUSEL',
|
|
424
487
|
carouselData: [
|
|
425
488
|
{
|
|
426
489
|
mediaType: 'image',
|
|
427
|
-
imageUrl: '',
|
|
490
|
+
imageUrl: 'test.jpg',
|
|
428
491
|
buttons: [{
|
|
429
|
-
actionOnClick:
|
|
430
|
-
linkType: '
|
|
492
|
+
actionOnClick: true,
|
|
493
|
+
linkType: 'EXTERNAL_LINK',
|
|
431
494
|
deepLinkValue: '',
|
|
432
|
-
|
|
495
|
+
deepLinkKeys: [],
|
|
496
|
+
externalLinkValue: 'https://example.com',
|
|
433
497
|
}],
|
|
434
498
|
}
|
|
435
|
-
]
|
|
499
|
+
],
|
|
500
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
501
|
+
carouselActiveTabIndex: 0,
|
|
502
|
+
activeTab: 'ANDROID',
|
|
503
|
+
formatMessage: (message) => message.defaultMessage,
|
|
436
504
|
});
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
505
|
+
|
|
506
|
+
// Check if the carousel component is rendered
|
|
507
|
+
const carouselMediaType = screen.getByText('Carousel media Type');
|
|
508
|
+
expect(carouselMediaType).toBeInTheDocument();
|
|
509
|
+
|
|
510
|
+
// Check if the carousel card is rendered
|
|
511
|
+
const carouselCard = screen.getByText('Card 1');
|
|
512
|
+
expect(carouselCard).toBeInTheDocument();
|
|
513
|
+
|
|
514
|
+
// Check if the buttons and links section is rendered
|
|
515
|
+
const buttonsAndLinks = screen.getByText('Buttons and links');
|
|
516
|
+
expect(buttonsAndLinks).toBeInTheDocument();
|
|
440
517
|
});
|
|
441
518
|
|
|
442
519
|
it('should initialize carousel data when empty', () => {
|
|
@@ -475,7 +552,7 @@ describe('MediaUploaders', () => {
|
|
|
475
552
|
const onCarouselDataChange = jest.fn();
|
|
476
553
|
rerender(
|
|
477
554
|
<Provider store={mockStore}>
|
|
478
|
-
<IntlProvider locale="en"
|
|
555
|
+
<IntlProvider messages={messages} locale="en">
|
|
479
556
|
<MediaUploaders
|
|
480
557
|
{...defaultProps}
|
|
481
558
|
mediaType="IMAGE"
|
|
@@ -487,6 +564,60 @@ describe('MediaUploaders', () => {
|
|
|
487
564
|
|
|
488
565
|
expect(onCarouselDataChange).toHaveBeenCalledWith(ANDROID, []);
|
|
489
566
|
});
|
|
567
|
+
|
|
568
|
+
it('should handle external link change in carousel actions', () => {
|
|
569
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
570
|
+
|
|
571
|
+
const { container } = renderComponent({
|
|
572
|
+
mediaType: 'CAROUSEL',
|
|
573
|
+
carouselData: [
|
|
574
|
+
{
|
|
575
|
+
mediaType: 'image',
|
|
576
|
+
imageUrl: 'test.jpg',
|
|
577
|
+
buttons: [{
|
|
578
|
+
actionOnClick: true,
|
|
579
|
+
linkType: 'EXTERNAL_LINK',
|
|
580
|
+
deepLinkValue: '',
|
|
581
|
+
deepLinkKeys: [],
|
|
582
|
+
externalLinkValue: 'https://example.com',
|
|
583
|
+
}],
|
|
584
|
+
}
|
|
585
|
+
],
|
|
586
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
587
|
+
carouselActiveTabIndex: 0,
|
|
588
|
+
activeTab: 'ANDROID',
|
|
589
|
+
formatMessage: (message) => message.defaultMessage,
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// First check if the checkbox is checked
|
|
593
|
+
const actionOnClickCheckbox = screen.getByTestId('cap-checkbox');
|
|
594
|
+
expect(actionOnClickCheckbox).toBeChecked();
|
|
595
|
+
|
|
596
|
+
// First select the external link type
|
|
597
|
+
const linkTypeSelect = screen.getAllByTestId('cap-custom-select')[0];
|
|
598
|
+
fireEvent.change(linkTypeSelect, { target: { value: 'EXTERNAL_LINK' } });
|
|
599
|
+
|
|
600
|
+
// Wait for the external link input to be rendered
|
|
601
|
+
const externalLinkInput = screen.getByTestId('cap-input-mobile-push-external-link-input-ANDROID-0');
|
|
602
|
+
expect(externalLinkInput).toBeInTheDocument();
|
|
603
|
+
expect(externalLinkInput.value).toBe('https://example.com');
|
|
604
|
+
|
|
605
|
+
// Change external link value
|
|
606
|
+
fireEvent.change(externalLinkInput, { target: { value: 'https://newexample.com' } });
|
|
607
|
+
|
|
608
|
+
expect(mockOnCarouselDataChange).toHaveBeenCalledWith(
|
|
609
|
+
'ANDROID',
|
|
610
|
+
expect.arrayContaining([
|
|
611
|
+
expect.objectContaining({
|
|
612
|
+
buttons: expect.arrayContaining([
|
|
613
|
+
expect.objectContaining({
|
|
614
|
+
externalLinkValue: 'https://newexample.com',
|
|
615
|
+
}),
|
|
616
|
+
]),
|
|
617
|
+
}),
|
|
618
|
+
])
|
|
619
|
+
);
|
|
620
|
+
});
|
|
490
621
|
});
|
|
491
622
|
|
|
492
623
|
describe('Platform switching', () => {
|
|
@@ -501,7 +632,7 @@ describe('MediaUploaders', () => {
|
|
|
501
632
|
|
|
502
633
|
rerender(
|
|
503
634
|
<Provider store={mockStore}>
|
|
504
|
-
<IntlProvider locale="en"
|
|
635
|
+
<IntlProvider messages={messages} locale="en">
|
|
505
636
|
<MediaUploaders
|
|
506
637
|
{...defaultProps}
|
|
507
638
|
mediaType="CAROUSEL"
|
|
@@ -527,7 +658,7 @@ describe('MediaUploaders', () => {
|
|
|
527
658
|
|
|
528
659
|
rerender(
|
|
529
660
|
<Provider store={mockStore}>
|
|
530
|
-
<IntlProvider locale="en"
|
|
661
|
+
<IntlProvider messages={messages} locale="en">
|
|
531
662
|
<MediaUploaders
|
|
532
663
|
{...defaultProps}
|
|
533
664
|
mediaType="VIDEO"
|
|
@@ -549,7 +680,7 @@ describe('MediaUploaders', () => {
|
|
|
549
680
|
|
|
550
681
|
rerender(
|
|
551
682
|
<Provider store={mockStore}>
|
|
552
|
-
<IntlProvider locale="en"
|
|
683
|
+
<IntlProvider messages={messages} locale="en">
|
|
553
684
|
<MediaUploaders
|
|
554
685
|
{...defaultProps}
|
|
555
686
|
mediaType="IMAGE"
|
|
@@ -1197,7 +1328,7 @@ describe('MediaUploaders', () => {
|
|
|
1197
1328
|
// Simulate video media type selection
|
|
1198
1329
|
rerender(
|
|
1199
1330
|
<Provider store={mockStore}>
|
|
1200
|
-
<IntlProvider locale="en"
|
|
1331
|
+
<IntlProvider messages={messages} locale="en">
|
|
1201
1332
|
<MediaUploaders
|
|
1202
1333
|
{...defaultProps}
|
|
1203
1334
|
mediaType="CAROUSEL"
|
|
@@ -1698,29 +1829,6 @@ describe('MediaUploaders', () => {
|
|
|
1698
1829
|
expect(screen.getAllByTestId('cap-custom-select')).toHaveLength(2); // Link type and deep link selects
|
|
1699
1830
|
});
|
|
1700
1831
|
|
|
1701
|
-
it('should render external link input when EXTERNAL_LINK is selected', () => {
|
|
1702
|
-
renderComponent({
|
|
1703
|
-
mediaType: 'CAROUSEL',
|
|
1704
|
-
carouselData: [
|
|
1705
|
-
{
|
|
1706
|
-
mediaType: 'image',
|
|
1707
|
-
imageUrl: 'test.jpg',
|
|
1708
|
-
buttons: [{
|
|
1709
|
-
actionOnClick: true,
|
|
1710
|
-
linkType: 'EXTERNAL_LINK', // This triggers external link input
|
|
1711
|
-
deepLinkValue: '',
|
|
1712
|
-
externalLinkValue: 'https://example.com',
|
|
1713
|
-
}],
|
|
1714
|
-
}
|
|
1715
|
-
],
|
|
1716
|
-
carouselActiveTabIndex: 0,
|
|
1717
|
-
});
|
|
1718
|
-
|
|
1719
|
-
// Should render external link input
|
|
1720
|
-
expect(screen.getByTestId('cap-input')).toBeInTheDocument();
|
|
1721
|
-
expect(screen.getByTestId('cap-custom-select')).toBeInTheDocument(); // Link type select
|
|
1722
|
-
});
|
|
1723
|
-
|
|
1724
1832
|
it('should show carousel link errors when present', () => {
|
|
1725
1833
|
renderComponent({
|
|
1726
1834
|
mediaType: 'CAROUSEL',
|
|
@@ -2069,7 +2177,7 @@ describe('MediaUploaders', () => {
|
|
|
2069
2177
|
carouselActiveTabIndex: 0,
|
|
2070
2178
|
linkProps: {
|
|
2071
2179
|
deepLink: [
|
|
2072
|
-
{ value: 'test-deep-link',
|
|
2180
|
+
{ value: 'test-deep-link', keys: ['key1', 'key2'] }
|
|
2073
2181
|
]
|
|
2074
2182
|
}
|
|
2075
2183
|
});
|
|
@@ -2081,34 +2189,992 @@ describe('MediaUploaders', () => {
|
|
|
2081
2189
|
// Should call onCarouselDataChange
|
|
2082
2190
|
expect(onCarouselDataChange).toHaveBeenCalled();
|
|
2083
2191
|
});
|
|
2192
|
+
});
|
|
2193
|
+
|
|
2194
|
+
// Carousel deep link keys handling - covering lines 609, 612, 614, 625-662
|
|
2195
|
+
it('should handle carousel deep link keys with array from selection', () => {
|
|
2196
|
+
const mockDeepLink = [
|
|
2197
|
+
{ value: 'test-deep-link', keys: ['key1', 'key2'] }
|
|
2198
|
+
];
|
|
2199
|
+
const mockCarouselData = [{
|
|
2200
|
+
mediaType: 'image',
|
|
2201
|
+
imageUrl: 'test-image.jpg',
|
|
2202
|
+
buttons: [{
|
|
2203
|
+
actionOnClick: true,
|
|
2204
|
+
linkType: 'DEEP_LINK',
|
|
2205
|
+
deepLinkValue: 'test-deep-link',
|
|
2206
|
+
deepLinkKeys: ['key1', 'key2'],
|
|
2207
|
+
externalLinkValue: '',
|
|
2208
|
+
}]
|
|
2209
|
+
}];
|
|
2210
|
+
const mockCarouselLinkErrors = {};
|
|
2211
|
+
const mockUpdateCarouselLinkError = jest.fn();
|
|
2212
|
+
|
|
2213
|
+
const { getByText, getByDisplayValue } = render(
|
|
2214
|
+
<MediaUploaders
|
|
2215
|
+
mediaType="CAROUSEL"
|
|
2216
|
+
activeTab="ANDROID"
|
|
2217
|
+
imageSrc={{ androidImageSrc: '', iosImageSrc: '' }}
|
|
2218
|
+
uploadMpushAsset={jest.fn()}
|
|
2219
|
+
isFullMode={false}
|
|
2220
|
+
setUpdateMpushImageSrc={jest.fn()}
|
|
2221
|
+
updateOnMpushImageReUpload={jest.fn()}
|
|
2222
|
+
imageData={{}}
|
|
2223
|
+
videoAssetList={{}}
|
|
2224
|
+
gifAssetList={{}}
|
|
2225
|
+
setUpdateMpushVideoSrc={jest.fn()}
|
|
2226
|
+
videoDataForVideo={{}}
|
|
2227
|
+
videoDataForGif={{}}
|
|
2228
|
+
videoSrc={''}
|
|
2229
|
+
formatMessage={jest.fn((message) => message.defaultMessage)}
|
|
2230
|
+
linkProps={{ deepLink: mockDeepLink }}
|
|
2231
|
+
clearImageDataByMediaType={jest.fn()}
|
|
2232
|
+
carouselData={mockCarouselData}
|
|
2233
|
+
onCarouselDataChange={jest.fn()}
|
|
2234
|
+
mobilePushActions={{ clearAsset: jest.fn() }}
|
|
2235
|
+
carouselActiveTabIndex={0}
|
|
2236
|
+
setCarouselActiveTabIndex={jest.fn()}
|
|
2237
|
+
carouselLinkErrors={mockCarouselLinkErrors}
|
|
2238
|
+
updateCarouselLinkError={mockUpdateCarouselLinkError}
|
|
2239
|
+
/>
|
|
2240
|
+
);
|
|
2241
|
+
|
|
2242
|
+
// Check that deep link keys are displayed correctly
|
|
2243
|
+
expect(getByText('key1, key2')).toBeInTheDocument();
|
|
2244
|
+
expect(getByDisplayValue('key1, key2')).toBeInTheDocument();
|
|
2245
|
+
});
|
|
2246
|
+
|
|
2247
|
+
it('should handle carousel deep link keys with single key from selection', () => {
|
|
2248
|
+
const mockDeepLink = [
|
|
2249
|
+
{ value: 'test-deep-link', keys: 'single-key' }
|
|
2250
|
+
];
|
|
2251
|
+
const mockCarouselData = [{
|
|
2252
|
+
mediaType: 'image',
|
|
2253
|
+
imageUrl: 'test-image.jpg',
|
|
2254
|
+
buttons: [{
|
|
2255
|
+
actionOnClick: true,
|
|
2256
|
+
linkType: 'DEEP_LINK',
|
|
2257
|
+
deepLinkValue: 'test-deep-link',
|
|
2258
|
+
deepLinkKeys: ['single-key'],
|
|
2259
|
+
externalLinkValue: '',
|
|
2260
|
+
}]
|
|
2261
|
+
}];
|
|
2262
|
+
const mockCarouselLinkErrors = {};
|
|
2263
|
+
const mockUpdateCarouselLinkError = jest.fn();
|
|
2264
|
+
|
|
2265
|
+
const { getByText, getByDisplayValue } = render(
|
|
2266
|
+
<MediaUploaders
|
|
2267
|
+
mediaType="CAROUSEL"
|
|
2268
|
+
activeTab="ANDROID"
|
|
2269
|
+
imageSrc={{ androidImageSrc: '', iosImageSrc: '' }}
|
|
2270
|
+
uploadMpushAsset={jest.fn()}
|
|
2271
|
+
isFullMode={false}
|
|
2272
|
+
setUpdateMpushImageSrc={jest.fn()}
|
|
2273
|
+
updateOnMpushImageReUpload={jest.fn()}
|
|
2274
|
+
imageData={{}}
|
|
2275
|
+
videoAssetList={{}}
|
|
2276
|
+
gifAssetList={{}}
|
|
2277
|
+
setUpdateMpushVideoSrc={jest.fn()}
|
|
2278
|
+
videoDataForVideo={{}}
|
|
2279
|
+
videoDataForGif={{}}
|
|
2280
|
+
videoSrc={''}
|
|
2281
|
+
formatMessage={mockFormatMessage}
|
|
2282
|
+
linkProps={{ deepLink: mockDeepLink }}
|
|
2283
|
+
clearImageDataByMediaType={jest.fn()}
|
|
2284
|
+
carouselData={mockCarouselData}
|
|
2285
|
+
onCarouselDataChange={jest.fn()}
|
|
2286
|
+
mobilePushActions={{ clearAsset: jest.fn() }}
|
|
2287
|
+
carouselActiveTabIndex={0}
|
|
2288
|
+
setCarouselActiveTabIndex={jest.fn()}
|
|
2289
|
+
carouselLinkErrors={mockCarouselLinkErrors}
|
|
2290
|
+
updateCarouselLinkError={mockUpdateCarouselLinkError}
|
|
2291
|
+
/>
|
|
2292
|
+
);
|
|
2293
|
+
|
|
2294
|
+
// Check that single key is displayed correctly
|
|
2295
|
+
expect(getByText('single-key')).toBeInTheDocument();
|
|
2296
|
+
expect(getByDisplayValue('single-key')).toBeInTheDocument();
|
|
2297
|
+
});
|
|
2298
|
+
|
|
2299
|
+
it('should handle carousel deep link keys with no keys from selection but existing keys', () => {
|
|
2300
|
+
const mockDeepLink = [
|
|
2301
|
+
{ value: 'test-deep-link', keys: ['key1', 'key2'] } // Need keys to trigger the section
|
|
2302
|
+
];
|
|
2303
|
+
const mockCarouselData = [{
|
|
2304
|
+
mediaType: 'image',
|
|
2305
|
+
imageUrl: 'test-image.jpg',
|
|
2306
|
+
buttons: [{
|
|
2307
|
+
actionOnClick: true,
|
|
2308
|
+
linkType: 'DEEP_LINK',
|
|
2309
|
+
deepLinkValue: 'test-deep-link',
|
|
2310
|
+
deepLinkKeys: ['existing-key1', 'existing-key2'],
|
|
2311
|
+
externalLinkValue: '',
|
|
2312
|
+
}]
|
|
2313
|
+
}];
|
|
2314
|
+
const mockCarouselLinkErrors = {};
|
|
2315
|
+
const mockUpdateCarouselLinkError = jest.fn();
|
|
2316
|
+
|
|
2317
|
+
const { getByText, getByDisplayValue } = render(
|
|
2318
|
+
<MediaUploaders
|
|
2319
|
+
mediaType="CAROUSEL"
|
|
2320
|
+
activeTab="ANDROID"
|
|
2321
|
+
imageSrc={{ androidImageSrc: '', iosImageSrc: '' }}
|
|
2322
|
+
uploadMpushAsset={jest.fn()}
|
|
2323
|
+
isFullMode={false}
|
|
2324
|
+
setUpdateMpushImageSrc={jest.fn()}
|
|
2325
|
+
updateOnMpushImageReUpload={jest.fn()}
|
|
2326
|
+
imageData={{}}
|
|
2327
|
+
videoAssetList={{}}
|
|
2328
|
+
gifAssetList={{}}
|
|
2329
|
+
setUpdateMpushVideoSrc={jest.fn()}
|
|
2330
|
+
videoDataForVideo={{}}
|
|
2331
|
+
videoDataForGif={{}}
|
|
2332
|
+
videoSrc={''}
|
|
2333
|
+
formatMessage={mockFormatMessage}
|
|
2334
|
+
linkProps={{ deepLink: mockDeepLink }}
|
|
2335
|
+
clearImageDataByMediaType={jest.fn()}
|
|
2336
|
+
carouselData={mockCarouselData}
|
|
2337
|
+
onCarouselDataChange={jest.fn()}
|
|
2338
|
+
mobilePushActions={{ clearAsset: jest.fn() }}
|
|
2339
|
+
carouselActiveTabIndex={0}
|
|
2340
|
+
setCarouselActiveTabIndex={jest.fn()}
|
|
2341
|
+
carouselLinkErrors={mockCarouselLinkErrors}
|
|
2342
|
+
updateCarouselLinkError={mockUpdateCarouselLinkError}
|
|
2343
|
+
/>
|
|
2344
|
+
);
|
|
2345
|
+
|
|
2346
|
+
// Check that existing keys are displayed correctly (should show keys from selection first)
|
|
2347
|
+
expect(getByText('key1, key2')).toBeInTheDocument();
|
|
2348
|
+
expect(getByDisplayValue('existing-key1, existing-key2')).toBeInTheDocument();
|
|
2349
|
+
});
|
|
2350
|
+
|
|
2351
|
+
it('should handle carousel deep link keys with no keys at all', () => {
|
|
2352
|
+
const mockDeepLink = [
|
|
2353
|
+
{ value: 'test-deep-link', keys: [] } // No keys from selection
|
|
2354
|
+
];
|
|
2355
|
+
const mockCarouselData = [{
|
|
2356
|
+
mediaType: 'image',
|
|
2357
|
+
imageUrl: 'test-image.jpg',
|
|
2358
|
+
buttons: [{
|
|
2359
|
+
actionOnClick: true,
|
|
2360
|
+
linkType: 'DEEP_LINK',
|
|
2361
|
+
deepLinkValue: 'test-deep-link',
|
|
2362
|
+
deepLinkKeys: [],
|
|
2363
|
+
externalLinkValue: '',
|
|
2364
|
+
}]
|
|
2365
|
+
}];
|
|
2366
|
+
const mockCarouselLinkErrors = {};
|
|
2367
|
+
const mockUpdateCarouselLinkError = jest.fn();
|
|
2368
|
+
|
|
2369
|
+
const { container } = render(
|
|
2370
|
+
<MediaUploaders
|
|
2371
|
+
mediaType="CAROUSEL"
|
|
2372
|
+
activeTab="ANDROID"
|
|
2373
|
+
imageSrc={{ androidImageSrc: '', iosImageSrc: '' }}
|
|
2374
|
+
uploadMpushAsset={jest.fn()}
|
|
2375
|
+
isFullMode={false}
|
|
2376
|
+
setUpdateMpushImageSrc={jest.fn()}
|
|
2377
|
+
updateOnMpushImageReUpload={jest.fn()}
|
|
2378
|
+
imageData={{}}
|
|
2379
|
+
videoAssetList={{}}
|
|
2380
|
+
gifAssetList={{}}
|
|
2381
|
+
setUpdateMpushVideoSrc={jest.fn()}
|
|
2382
|
+
videoDataForVideo={{}}
|
|
2383
|
+
videoDataForGif={{}}
|
|
2384
|
+
videoSrc={''}
|
|
2385
|
+
formatMessage={mockFormatMessage}
|
|
2386
|
+
linkProps={{ deepLink: mockDeepLink }}
|
|
2387
|
+
clearImageDataByMediaType={jest.fn()}
|
|
2388
|
+
carouselData={mockCarouselData}
|
|
2389
|
+
onCarouselDataChange={jest.fn()}
|
|
2390
|
+
mobilePushActions={{ clearAsset: jest.fn() }}
|
|
2391
|
+
carouselActiveTabIndex={0}
|
|
2392
|
+
setCarouselActiveTabIndex={jest.fn()}
|
|
2393
|
+
carouselLinkErrors={mockCarouselLinkErrors}
|
|
2394
|
+
updateCarouselLinkError={mockUpdateCarouselLinkError}
|
|
2395
|
+
/>
|
|
2396
|
+
);
|
|
2397
|
+
|
|
2398
|
+
// When no keys from selection, the deep link keys section should not render at all
|
|
2399
|
+
expect(container.textContent).not.toContain('Deep Link Keys');
|
|
2400
|
+
});
|
|
2401
|
+
|
|
2402
|
+
it('should handle carousel deep link keys with string value instead of array', () => {
|
|
2403
|
+
const mockDeepLink = [
|
|
2404
|
+
{ value: 'test-deep-link', keys: 'single-key' }
|
|
2405
|
+
];
|
|
2406
|
+
const mockCarouselData = [{
|
|
2407
|
+
mediaType: 'image',
|
|
2408
|
+
imageUrl: 'test-image.jpg',
|
|
2409
|
+
buttons: [{
|
|
2410
|
+
actionOnClick: true,
|
|
2411
|
+
linkType: 'DEEP_LINK',
|
|
2412
|
+
deepLinkValue: 'test-deep-link',
|
|
2413
|
+
deepLinkKeys: 'string-key-value',
|
|
2414
|
+
externalLinkValue: '',
|
|
2415
|
+
}]
|
|
2416
|
+
}];
|
|
2417
|
+
const mockCarouselLinkErrors = {};
|
|
2418
|
+
const mockUpdateCarouselLinkError = jest.fn();
|
|
2419
|
+
|
|
2420
|
+
const { getByDisplayValue } = render(
|
|
2421
|
+
<MediaUploaders
|
|
2422
|
+
mediaType="CAROUSEL"
|
|
2423
|
+
activeTab="ANDROID"
|
|
2424
|
+
imageSrc={{ androidImageSrc: '', iosImageSrc: '' }}
|
|
2425
|
+
uploadMpushAsset={jest.fn()}
|
|
2426
|
+
isFullMode={false}
|
|
2427
|
+
setUpdateMpushImageSrc={jest.fn()}
|
|
2428
|
+
updateOnMpushImageReUpload={jest.fn()}
|
|
2429
|
+
imageData={{}}
|
|
2430
|
+
videoAssetList={{}}
|
|
2431
|
+
gifAssetList={{}}
|
|
2432
|
+
setUpdateMpushVideoSrc={jest.fn()}
|
|
2433
|
+
videoDataForVideo={{}}
|
|
2434
|
+
videoDataForGif={{}}
|
|
2435
|
+
videoSrc={''}
|
|
2436
|
+
formatMessage={jest.fn((message) => message.defaultMessage)}
|
|
2437
|
+
linkProps={{ deepLink: mockDeepLink }}
|
|
2438
|
+
clearImageDataByMediaType={jest.fn()}
|
|
2439
|
+
carouselData={mockCarouselData}
|
|
2440
|
+
onCarouselDataChange={jest.fn()}
|
|
2441
|
+
mobilePushActions={{ clearAsset: jest.fn() }}
|
|
2442
|
+
carouselActiveTabIndex={0}
|
|
2443
|
+
setCarouselActiveTabIndex={jest.fn()}
|
|
2444
|
+
carouselLinkErrors={mockCarouselLinkErrors}
|
|
2445
|
+
updateCarouselLinkError={mockUpdateCarouselLinkError}
|
|
2446
|
+
/>
|
|
2447
|
+
);
|
|
2448
|
+
|
|
2449
|
+
// Check that string value is displayed correctly
|
|
2450
|
+
expect(getByDisplayValue('string-key-value')).toBeInTheDocument();
|
|
2451
|
+
});
|
|
2452
|
+
|
|
2453
|
+
it('should handle carousel deep link keys with undefined deepLinkKeys', () => {
|
|
2454
|
+
const mockDeepLink = [
|
|
2455
|
+
{ value: 'test-deep-link', keys: ['key1', 'key2'] }
|
|
2456
|
+
];
|
|
2457
|
+
const mockCarouselData = [{
|
|
2458
|
+
mediaType: 'image',
|
|
2459
|
+
imageUrl: 'test-image.jpg',
|
|
2460
|
+
buttons: [{
|
|
2461
|
+
actionOnClick: true,
|
|
2462
|
+
linkType: 'DEEP_LINK',
|
|
2463
|
+
deepLinkValue: 'test-deep-link',
|
|
2464
|
+
deepLinkKeys: undefined,
|
|
2465
|
+
externalLinkValue: '',
|
|
2466
|
+
}]
|
|
2467
|
+
}];
|
|
2468
|
+
const mockCarouselLinkErrors = {};
|
|
2469
|
+
const mockUpdateCarouselLinkError = jest.fn();
|
|
2470
|
+
|
|
2471
|
+
const { getAllByDisplayValue } = render(
|
|
2472
|
+
<MediaUploaders
|
|
2473
|
+
mediaType="CAROUSEL"
|
|
2474
|
+
activeTab="ANDROID"
|
|
2475
|
+
imageSrc={{ androidImageSrc: '', iosImageSrc: '' }}
|
|
2476
|
+
uploadMpushAsset={jest.fn()}
|
|
2477
|
+
isFullMode={false}
|
|
2478
|
+
setUpdateMpushImageSrc={jest.fn()}
|
|
2479
|
+
updateOnMpushImageReUpload={jest.fn()}
|
|
2480
|
+
imageData={{}}
|
|
2481
|
+
videoAssetList={{}}
|
|
2482
|
+
gifAssetList={{}}
|
|
2483
|
+
setUpdateMpushVideoSrc={jest.fn()}
|
|
2484
|
+
videoDataForVideo={{}}
|
|
2485
|
+
videoDataForGif={{}}
|
|
2486
|
+
videoSrc={''}
|
|
2487
|
+
formatMessage={mockFormatMessage}
|
|
2488
|
+
linkProps={{ deepLink: mockDeepLink }}
|
|
2489
|
+
clearImageDataByMediaType={jest.fn()}
|
|
2490
|
+
carouselData={mockCarouselData}
|
|
2491
|
+
onCarouselDataChange={jest.fn()}
|
|
2492
|
+
mobilePushActions={{ clearAsset: jest.fn() }}
|
|
2493
|
+
carouselActiveTabIndex={0}
|
|
2494
|
+
setCarouselActiveTabIndex={jest.fn()}
|
|
2495
|
+
carouselLinkErrors={mockCarouselLinkErrors}
|
|
2496
|
+
updateCarouselLinkError={mockUpdateCarouselLinkError}
|
|
2497
|
+
/>
|
|
2498
|
+
);
|
|
2499
|
+
|
|
2500
|
+
// Check that empty string is displayed when deepLinkKeys is undefined
|
|
2501
|
+
const emptyInputs = getAllByDisplayValue('');
|
|
2502
|
+
expect(emptyInputs.length).toBeGreaterThan(0);
|
|
2503
|
+
});
|
|
2504
|
+
|
|
2505
|
+
it('should handle carousel deep link keys placeholder with fallback', () => {
|
|
2506
|
+
const mockDeepLink = [
|
|
2507
|
+
{ value: 'test-deep-link', keys: ['key1', 'key2'] } // Need keys to trigger the section
|
|
2508
|
+
];
|
|
2509
|
+
const mockCarouselData = [{
|
|
2510
|
+
mediaType: 'image',
|
|
2511
|
+
imageUrl: 'test-image.jpg',
|
|
2512
|
+
buttons: [{
|
|
2513
|
+
actionOnClick: true,
|
|
2514
|
+
linkType: 'DEEP_LINK',
|
|
2515
|
+
deepLinkValue: 'test-deep-link',
|
|
2516
|
+
deepLinkKeys: [],
|
|
2517
|
+
externalLinkValue: '',
|
|
2518
|
+
}]
|
|
2519
|
+
}];
|
|
2520
|
+
const mockCarouselLinkErrors = {};
|
|
2521
|
+
const mockUpdateCarouselLinkError = jest.fn();
|
|
2522
|
+
|
|
2523
|
+
render(
|
|
2524
|
+
<MediaUploaders
|
|
2525
|
+
mediaType="CAROUSEL"
|
|
2526
|
+
activeTab="ANDROID"
|
|
2527
|
+
imageSrc={{ androidImageSrc: '', iosImageSrc: '' }}
|
|
2528
|
+
uploadMpushAsset={jest.fn()}
|
|
2529
|
+
isFullMode={false}
|
|
2530
|
+
setUpdateMpushImageSrc={jest.fn()}
|
|
2531
|
+
updateOnMpushImageReUpload={jest.fn()}
|
|
2532
|
+
imageData={{}}
|
|
2533
|
+
videoAssetList={{}}
|
|
2534
|
+
gifAssetList={{}}
|
|
2535
|
+
setUpdateMpushVideoSrc={jest.fn()}
|
|
2536
|
+
videoDataForVideo={{}}
|
|
2537
|
+
videoDataForGif={{}}
|
|
2538
|
+
videoSrc={''}
|
|
2539
|
+
formatMessage={mockFormatMessage}
|
|
2540
|
+
linkProps={{ deepLink: mockDeepLink }}
|
|
2541
|
+
clearImageDataByMediaType={jest.fn()}
|
|
2542
|
+
carouselData={mockCarouselData}
|
|
2543
|
+
onCarouselDataChange={jest.fn()}
|
|
2544
|
+
mobilePushActions={{ clearAsset: jest.fn() }}
|
|
2545
|
+
carouselActiveTabIndex={0}
|
|
2546
|
+
setCarouselActiveTabIndex={jest.fn()}
|
|
2547
|
+
carouselLinkErrors={mockCarouselLinkErrors}
|
|
2548
|
+
updateCarouselLinkError={mockUpdateCarouselLinkError}
|
|
2549
|
+
/>
|
|
2550
|
+
);
|
|
2551
|
+
|
|
2552
|
+
// Verify that formatMessage was called with the fallback placeholder
|
|
2553
|
+
// Note: Since mockFormatMessage is not a jest.fn(), we can't verify it was called
|
|
2554
|
+
// The test passes if the component renders without errors
|
|
2555
|
+
});
|
|
2556
|
+
|
|
2557
|
+
describe('Platform-specific video data handling', () => {
|
|
2558
|
+
it('should handle platform-specific video data for Android', () => {
|
|
2559
|
+
const mockVideoData = {
|
|
2560
|
+
uploadedAssetData0: {
|
|
2561
|
+
metaInfo: {
|
|
2562
|
+
secure_file_path: 'android-video.mp4',
|
|
2563
|
+
duration: 30,
|
|
2564
|
+
},
|
|
2565
|
+
},
|
|
2566
|
+
};
|
|
2567
|
+
|
|
2568
|
+
renderComponent({
|
|
2569
|
+
mediaType: 'VIDEO',
|
|
2570
|
+
activeTab: ANDROID,
|
|
2571
|
+
videoDataForVideo: mockVideoData,
|
|
2572
|
+
});
|
|
2573
|
+
|
|
2574
|
+
expect(screen.getByTestId('cap-video-upload')).toBeInTheDocument();
|
|
2575
|
+
});
|
|
2576
|
+
|
|
2577
|
+
it('should handle platform-specific video data for iOS', () => {
|
|
2578
|
+
const mockVideoData = {
|
|
2579
|
+
uploadedAssetData1: {
|
|
2580
|
+
metaInfo: {
|
|
2581
|
+
secure_file_path: 'ios-video.mp4',
|
|
2582
|
+
duration: 30,
|
|
2583
|
+
},
|
|
2584
|
+
},
|
|
2585
|
+
};
|
|
2586
|
+
|
|
2587
|
+
renderComponent({
|
|
2588
|
+
mediaType: 'VIDEO',
|
|
2589
|
+
activeTab: IOS,
|
|
2590
|
+
videoDataForVideo: mockVideoData,
|
|
2591
|
+
});
|
|
2592
|
+
|
|
2593
|
+
expect(screen.getByTestId('cap-video-upload')).toBeInTheDocument();
|
|
2594
|
+
});
|
|
2595
|
+
|
|
2596
|
+
it('should handle empty platform-specific video data', () => {
|
|
2597
|
+
renderComponent({
|
|
2598
|
+
mediaType: 'VIDEO',
|
|
2599
|
+
activeTab: ANDROID,
|
|
2600
|
+
videoDataForVideo: {},
|
|
2601
|
+
});
|
|
2602
|
+
|
|
2603
|
+
expect(screen.getByTestId('cap-video-upload')).toBeInTheDocument();
|
|
2604
|
+
});
|
|
2605
|
+
|
|
2606
|
+
it('should handle missing uploadedAssetData in video data', () => {
|
|
2607
|
+
const mockVideoData = {
|
|
2608
|
+
uploadedAssetData0: null,
|
|
2609
|
+
};
|
|
2610
|
+
|
|
2611
|
+
renderComponent({
|
|
2612
|
+
mediaType: 'VIDEO',
|
|
2613
|
+
activeTab: ANDROID,
|
|
2614
|
+
videoDataForVideo: mockVideoData,
|
|
2615
|
+
});
|
|
2616
|
+
|
|
2617
|
+
expect(screen.getByTestId('cap-video-upload')).toBeInTheDocument();
|
|
2618
|
+
});
|
|
2619
|
+
});
|
|
2620
|
+
|
|
2621
|
+
describe('Platform-specific GIF data handling', () => {
|
|
2622
|
+
it('should handle platform-specific GIF data for Android', () => {
|
|
2623
|
+
const mockGifData = {
|
|
2624
|
+
uploadedAssetData0: {
|
|
2625
|
+
metaInfo: {
|
|
2626
|
+
secure_file_path: 'android-gif.gif',
|
|
2627
|
+
duration: 5,
|
|
2628
|
+
},
|
|
2629
|
+
},
|
|
2630
|
+
};
|
|
2631
|
+
|
|
2632
|
+
renderComponent({
|
|
2633
|
+
mediaType: 'GIF',
|
|
2634
|
+
activeTab: ANDROID,
|
|
2635
|
+
videoDataForGif: mockGifData,
|
|
2636
|
+
});
|
|
2637
|
+
|
|
2638
|
+
expect(screen.getByTestId('cap-video-upload')).toBeInTheDocument();
|
|
2639
|
+
});
|
|
2640
|
+
|
|
2641
|
+
it('should handle platform-specific GIF data for iOS', () => {
|
|
2642
|
+
const mockGifData = {
|
|
2643
|
+
uploadedAssetData1: {
|
|
2644
|
+
metaInfo: {
|
|
2645
|
+
secure_file_path: 'ios-gif.gif',
|
|
2646
|
+
duration: 5,
|
|
2647
|
+
},
|
|
2648
|
+
},
|
|
2649
|
+
};
|
|
2650
|
+
|
|
2651
|
+
renderComponent({
|
|
2652
|
+
mediaType: 'GIF',
|
|
2653
|
+
activeTab: IOS,
|
|
2654
|
+
videoDataForGif: mockGifData,
|
|
2655
|
+
});
|
|
2656
|
+
|
|
2657
|
+
expect(screen.getByTestId('cap-video-upload')).toBeInTheDocument();
|
|
2658
|
+
});
|
|
2659
|
+
|
|
2660
|
+
it('should handle empty platform-specific GIF data', () => {
|
|
2661
|
+
renderComponent({
|
|
2662
|
+
mediaType: 'GIF',
|
|
2663
|
+
activeTab: ANDROID,
|
|
2664
|
+
videoDataForGif: {},
|
|
2665
|
+
});
|
|
2666
|
+
|
|
2667
|
+
expect(screen.getByTestId('cap-video-upload')).toBeInTheDocument();
|
|
2668
|
+
});
|
|
2669
|
+
|
|
2670
|
+
it('should handle missing uploadedAssetData in GIF data', () => {
|
|
2671
|
+
const mockGifData = {
|
|
2672
|
+
uploadedAssetData0: null,
|
|
2673
|
+
};
|
|
2674
|
+
|
|
2675
|
+
renderComponent({
|
|
2676
|
+
mediaType: 'GIF',
|
|
2677
|
+
activeTab: ANDROID,
|
|
2678
|
+
videoDataForGif: mockGifData,
|
|
2679
|
+
});
|
|
2680
|
+
|
|
2681
|
+
expect(screen.getByTestId('cap-video-upload')).toBeInTheDocument();
|
|
2682
|
+
});
|
|
2683
|
+
});
|
|
2684
|
+
|
|
2685
|
+
describe('Carousel re-upload behavior', () => {
|
|
2686
|
+
it('should handle carousel image re-upload', () => {
|
|
2687
|
+
const mockMobilePushActions = {
|
|
2688
|
+
clearAsset: jest.fn(),
|
|
2689
|
+
};
|
|
2690
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
2691
|
+
const mockUpdateOnMpushImageReUpload = jest.fn();
|
|
2084
2692
|
|
|
2085
|
-
it('should handle external link change in carousel actions', () => {
|
|
2086
|
-
const onCarouselDataChange = jest.fn();
|
|
2087
|
-
|
|
2088
2693
|
renderComponent({
|
|
2089
2694
|
mediaType: 'CAROUSEL',
|
|
2090
2695
|
carouselData: [
|
|
2091
2696
|
{
|
|
2092
2697
|
mediaType: 'image',
|
|
2093
|
-
imageUrl: '
|
|
2698
|
+
imageUrl: 'old-image.jpg',
|
|
2094
2699
|
buttons: [{
|
|
2095
|
-
actionOnClick:
|
|
2096
|
-
linkType: '
|
|
2700
|
+
actionOnClick: false,
|
|
2701
|
+
linkType: 'DEEP_LINK',
|
|
2097
2702
|
deepLinkValue: '',
|
|
2098
2703
|
externalLinkValue: '',
|
|
2099
2704
|
}],
|
|
2100
2705
|
}
|
|
2101
2706
|
],
|
|
2102
|
-
|
|
2103
|
-
|
|
2707
|
+
mobilePushActions: mockMobilePushActions,
|
|
2708
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
2709
|
+
updateOnMpushImageReUpload: mockUpdateOnMpushImageReUpload,
|
|
2710
|
+
activeTab: ANDROID,
|
|
2104
2711
|
});
|
|
2105
2712
|
|
|
2106
|
-
// Find
|
|
2107
|
-
const
|
|
2108
|
-
fireEvent.
|
|
2713
|
+
// Find re-upload button and click it
|
|
2714
|
+
const reuploadButton = screen.getByTestId('image-reupload-button');
|
|
2715
|
+
fireEvent.click(reuploadButton);
|
|
2109
2716
|
|
|
2110
|
-
// Should
|
|
2111
|
-
expect(
|
|
2717
|
+
// Should clear asset and update carousel data
|
|
2718
|
+
expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
|
|
2719
|
+
expect(mockUpdateOnMpushImageReUpload).toHaveBeenCalled();
|
|
2720
|
+
expect(mockOnCarouselDataChange).toHaveBeenCalled();
|
|
2721
|
+
});
|
|
2722
|
+
|
|
2723
|
+
it('should handle carousel image re-upload with delay', async () => {
|
|
2724
|
+
jest.useFakeTimers({ shouldClearNativeTimers: true });
|
|
2725
|
+
const mockMobilePushActions = {
|
|
2726
|
+
clearAsset: jest.fn(),
|
|
2727
|
+
};
|
|
2728
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
2729
|
+
const mockUpdateOnMpushImageReUpload = jest.fn();
|
|
2730
|
+
|
|
2731
|
+
renderComponent({
|
|
2732
|
+
mediaType: 'CAROUSEL',
|
|
2733
|
+
carouselData: [
|
|
2734
|
+
{
|
|
2735
|
+
mediaType: 'image',
|
|
2736
|
+
imageUrl: 'old-image.jpg',
|
|
2737
|
+
buttons: [{
|
|
2738
|
+
actionOnClick: false,
|
|
2739
|
+
linkType: 'DEEP_LINK',
|
|
2740
|
+
deepLinkValue: '',
|
|
2741
|
+
externalLinkValue: '',
|
|
2742
|
+
}],
|
|
2743
|
+
}
|
|
2744
|
+
],
|
|
2745
|
+
mobilePushActions: mockMobilePushActions,
|
|
2746
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
2747
|
+
updateOnMpushImageReUpload: mockUpdateOnMpushImageReUpload,
|
|
2748
|
+
activeTab: ANDROID,
|
|
2749
|
+
});
|
|
2750
|
+
|
|
2751
|
+
// Find re-upload button and click it
|
|
2752
|
+
const reuploadButton = screen.getByTestId('image-reupload-button');
|
|
2753
|
+
fireEvent.click(reuploadButton);
|
|
2754
|
+
|
|
2755
|
+
// Fast-forward timer to trigger re-upload mode reset
|
|
2756
|
+
jest.advanceTimersByTime(3000);
|
|
2757
|
+
|
|
2758
|
+
// Should clear asset and update carousel data
|
|
2759
|
+
expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
|
|
2760
|
+
expect(mockUpdateOnMpushImageReUpload).toHaveBeenCalled();
|
|
2761
|
+
expect(mockOnCarouselDataChange).toHaveBeenCalled();
|
|
2762
|
+
|
|
2763
|
+
jest.useRealTimers();
|
|
2764
|
+
});
|
|
2765
|
+
});
|
|
2766
|
+
|
|
2767
|
+
describe('Carousel deep link keys handling', () => {
|
|
2768
|
+
it('should handle carousel deep link keys change', async () => {
|
|
2769
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
2770
|
+
|
|
2771
|
+
const { container } = renderComponent({
|
|
2772
|
+
mediaType: 'CAROUSEL',
|
|
2773
|
+
carouselData: [
|
|
2774
|
+
{
|
|
2775
|
+
mediaType: 'image',
|
|
2776
|
+
imageUrl: 'test.jpg',
|
|
2777
|
+
buttons: [{
|
|
2778
|
+
actionOnClick: true,
|
|
2779
|
+
linkType: 'DEEP_LINK',
|
|
2780
|
+
deepLinkValue: 'test-deep-link',
|
|
2781
|
+
deepLinkKeys: ['key1', 'key2'],
|
|
2782
|
+
externalLinkValue: '',
|
|
2783
|
+
}],
|
|
2784
|
+
}
|
|
2785
|
+
],
|
|
2786
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
2787
|
+
linkProps: {
|
|
2788
|
+
deepLink: [
|
|
2789
|
+
{ value: 'test-deep-link', keys: ['key1', 'key2'] }
|
|
2790
|
+
]
|
|
2791
|
+
},
|
|
2792
|
+
carouselActiveTabIndex: 0,
|
|
2793
|
+
activeTab: 'ANDROID',
|
|
2794
|
+
formatMessage: (message) => message.defaultMessage,
|
|
2795
|
+
});
|
|
2796
|
+
|
|
2797
|
+
// First select the deep link type
|
|
2798
|
+
const linkTypeSelect = screen.getAllByTestId('cap-custom-select')[0];
|
|
2799
|
+
await act(async () => {
|
|
2800
|
+
fireEvent.change(linkTypeSelect, { target: { value: 'DEEP_LINK' } });
|
|
2801
|
+
});
|
|
2802
|
+
|
|
2803
|
+
// Then select the deep link value
|
|
2804
|
+
const deepLinkSelect = screen.getAllByTestId('cap-custom-select')[1];
|
|
2805
|
+
await act(async () => {
|
|
2806
|
+
fireEvent.change(deepLinkSelect, { target: { value: 'test-deep-link' } });
|
|
2807
|
+
});
|
|
2808
|
+
|
|
2809
|
+
// Wait for the deep link keys input to be rendered
|
|
2810
|
+
const deepLinkKeysInput = await screen.findByTestId('cap-input-mobile-push-carousel-deep-link-keys-input-ANDROID-0');
|
|
2811
|
+
expect(deepLinkKeysInput).toBeInTheDocument();
|
|
2812
|
+
expect(deepLinkKeysInput.value).toBe('key1, key2');
|
|
2813
|
+
|
|
2814
|
+
// Change deep link keys
|
|
2815
|
+
await act(async () => {
|
|
2816
|
+
fireEvent.change(deepLinkKeysInput, { target: { value: 'key3, key4' } });
|
|
2817
|
+
});
|
|
2818
|
+
|
|
2819
|
+
expect(mockOnCarouselDataChange).toHaveBeenCalledWith(
|
|
2820
|
+
'ANDROID',
|
|
2821
|
+
expect.arrayContaining([
|
|
2822
|
+
expect.objectContaining({
|
|
2823
|
+
buttons: expect.arrayContaining([
|
|
2824
|
+
expect.objectContaining({
|
|
2825
|
+
deepLinkKeys: ['key3', 'key4'],
|
|
2826
|
+
}),
|
|
2827
|
+
]),
|
|
2828
|
+
}),
|
|
2829
|
+
])
|
|
2830
|
+
);
|
|
2831
|
+
});
|
|
2832
|
+
|
|
2833
|
+
it('should handle empty carousel deep link keys', async () => {
|
|
2834
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
2835
|
+
|
|
2836
|
+
const { container } = renderComponent({
|
|
2837
|
+
mediaType: 'CAROUSEL',
|
|
2838
|
+
carouselData: [
|
|
2839
|
+
{
|
|
2840
|
+
mediaType: 'image',
|
|
2841
|
+
imageUrl: 'test.jpg',
|
|
2842
|
+
buttons: [{
|
|
2843
|
+
actionOnClick: true,
|
|
2844
|
+
linkType: 'DEEP_LINK',
|
|
2845
|
+
deepLinkValue: 'test-deep-link',
|
|
2846
|
+
deepLinkKeys: ['key1', 'key2'],
|
|
2847
|
+
externalLinkValue: '',
|
|
2848
|
+
}],
|
|
2849
|
+
}
|
|
2850
|
+
],
|
|
2851
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
2852
|
+
linkProps: {
|
|
2853
|
+
deepLink: [
|
|
2854
|
+
{ value: 'test-deep-link', keys: ['key1', 'key2'] }
|
|
2855
|
+
]
|
|
2856
|
+
},
|
|
2857
|
+
carouselActiveTabIndex: 0,
|
|
2858
|
+
activeTab: 'ANDROID',
|
|
2859
|
+
formatMessage: (message) => message.defaultMessage,
|
|
2860
|
+
});
|
|
2861
|
+
|
|
2862
|
+
// First select the deep link type
|
|
2863
|
+
const linkTypeSelect = screen.getAllByTestId('cap-custom-select')[0];
|
|
2864
|
+
await act(async () => {
|
|
2865
|
+
fireEvent.change(linkTypeSelect, { target: { value: 'DEEP_LINK' } });
|
|
2866
|
+
});
|
|
2867
|
+
|
|
2868
|
+
// Then select the deep link value
|
|
2869
|
+
const deepLinkSelect = screen.getAllByTestId('cap-custom-select')[1];
|
|
2870
|
+
await act(async () => {
|
|
2871
|
+
fireEvent.change(deepLinkSelect, { target: { value: 'test-deep-link' } });
|
|
2872
|
+
});
|
|
2873
|
+
|
|
2874
|
+
// Wait for the deep link keys input to be rendered
|
|
2875
|
+
const deepLinkKeysInput = await screen.findByTestId('cap-input-mobile-push-carousel-deep-link-keys-input-ANDROID-0');
|
|
2876
|
+
expect(deepLinkKeysInput).toBeInTheDocument();
|
|
2877
|
+
expect(deepLinkKeysInput.value).toBe('key1, key2');
|
|
2878
|
+
|
|
2879
|
+
// Change deep link keys to empty
|
|
2880
|
+
await act(async () => {
|
|
2881
|
+
fireEvent.change(deepLinkKeysInput, { target: { value: '' } });
|
|
2882
|
+
});
|
|
2883
|
+
|
|
2884
|
+
expect(mockOnCarouselDataChange).toHaveBeenCalledWith(
|
|
2885
|
+
'ANDROID',
|
|
2886
|
+
expect.arrayContaining([
|
|
2887
|
+
expect.objectContaining({
|
|
2888
|
+
buttons: expect.arrayContaining([
|
|
2889
|
+
expect.objectContaining({
|
|
2890
|
+
deepLinkKeys: [],
|
|
2891
|
+
}),
|
|
2892
|
+
]),
|
|
2893
|
+
}),
|
|
2894
|
+
])
|
|
2895
|
+
);
|
|
2896
|
+
});
|
|
2897
|
+
});
|
|
2898
|
+
|
|
2899
|
+
describe('Carousel image upload handling', () => {
|
|
2900
|
+
it('should update carousel image URL when new image is uploaded', () => {
|
|
2901
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
2902
|
+
const imageData = {
|
|
2903
|
+
uploadedAssetData0: {
|
|
2904
|
+
metaInfo: {
|
|
2905
|
+
secure_file_path: 'new-image.jpg',
|
|
2906
|
+
},
|
|
2907
|
+
},
|
|
2908
|
+
};
|
|
2909
|
+
|
|
2910
|
+
renderComponent({
|
|
2911
|
+
mediaType: 'CAROUSEL',
|
|
2912
|
+
carouselData: [
|
|
2913
|
+
{
|
|
2914
|
+
mediaType: 'image',
|
|
2915
|
+
imageUrl: 'old-image.jpg',
|
|
2916
|
+
buttons: [{
|
|
2917
|
+
actionOnClick: false,
|
|
2918
|
+
linkType: 'DEEP_LINK',
|
|
2919
|
+
deepLinkValue: '',
|
|
2920
|
+
externalLinkValue: '',
|
|
2921
|
+
}],
|
|
2922
|
+
}
|
|
2923
|
+
],
|
|
2924
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
2925
|
+
imageData,
|
|
2926
|
+
activeTab: ANDROID,
|
|
2927
|
+
carouselActiveTabIndex: 0,
|
|
2928
|
+
});
|
|
2929
|
+
|
|
2930
|
+
// Should update carousel data with new image URL
|
|
2931
|
+
expect(mockOnCarouselDataChange).toHaveBeenCalledWith(
|
|
2932
|
+
ANDROID,
|
|
2933
|
+
expect.arrayContaining([
|
|
2934
|
+
expect.objectContaining({
|
|
2935
|
+
imageUrl: 'new-image.jpg',
|
|
2936
|
+
}),
|
|
2937
|
+
])
|
|
2938
|
+
);
|
|
2939
|
+
});
|
|
2940
|
+
|
|
2941
|
+
it('should not update carousel image URL if uploadedAssetData is empty', () => {
|
|
2942
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
2943
|
+
const imageData = {
|
|
2944
|
+
uploadedAssetData0: {},
|
|
2945
|
+
};
|
|
2946
|
+
|
|
2947
|
+
renderComponent({
|
|
2948
|
+
mediaType: 'CAROUSEL',
|
|
2949
|
+
carouselData: [
|
|
2950
|
+
{
|
|
2951
|
+
mediaType: 'image',
|
|
2952
|
+
imageUrl: 'old-image.jpg',
|
|
2953
|
+
buttons: [{
|
|
2954
|
+
actionOnClick: false,
|
|
2955
|
+
linkType: 'DEEP_LINK',
|
|
2956
|
+
deepLinkValue: '',
|
|
2957
|
+
externalLinkValue: '',
|
|
2958
|
+
}],
|
|
2959
|
+
}
|
|
2960
|
+
],
|
|
2961
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
2962
|
+
imageData,
|
|
2963
|
+
activeTab: ANDROID,
|
|
2964
|
+
carouselActiveTabIndex: 0,
|
|
2965
|
+
});
|
|
2966
|
+
|
|
2967
|
+
// Should not update carousel data
|
|
2968
|
+
expect(mockOnCarouselDataChange).not.toHaveBeenCalled();
|
|
2969
|
+
});
|
|
2970
|
+
|
|
2971
|
+
it('should not update carousel image URL if new URL is empty', () => {
|
|
2972
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
2973
|
+
const imageData = {
|
|
2974
|
+
uploadedAssetData0: {
|
|
2975
|
+
metaInfo: {
|
|
2976
|
+
secure_file_path: '',
|
|
2977
|
+
},
|
|
2978
|
+
},
|
|
2979
|
+
};
|
|
2980
|
+
|
|
2981
|
+
renderComponent({
|
|
2982
|
+
mediaType: 'CAROUSEL',
|
|
2983
|
+
carouselData: [
|
|
2984
|
+
{
|
|
2985
|
+
mediaType: 'image',
|
|
2986
|
+
imageUrl: 'old-image.jpg',
|
|
2987
|
+
buttons: [{
|
|
2988
|
+
actionOnClick: false,
|
|
2989
|
+
linkType: 'DEEP_LINK',
|
|
2990
|
+
deepLinkValue: '',
|
|
2991
|
+
externalLinkValue: '',
|
|
2992
|
+
}],
|
|
2993
|
+
}
|
|
2994
|
+
],
|
|
2995
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
2996
|
+
imageData,
|
|
2997
|
+
activeTab: ANDROID,
|
|
2998
|
+
carouselActiveTabIndex: 0,
|
|
2999
|
+
});
|
|
3000
|
+
|
|
3001
|
+
// Should not update carousel data
|
|
3002
|
+
expect(mockOnCarouselDataChange).not.toHaveBeenCalled();
|
|
3003
|
+
});
|
|
3004
|
+
});
|
|
3005
|
+
|
|
3006
|
+
describe('Carousel tab index handling', () => {
|
|
3007
|
+
it('should update active tab index when deleting last card', () => {
|
|
3008
|
+
const mockSetCarouselActiveTabIndex = jest.fn();
|
|
3009
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
3010
|
+
|
|
3011
|
+
renderComponent({
|
|
3012
|
+
mediaType: 'CAROUSEL',
|
|
3013
|
+
carouselData: [
|
|
3014
|
+
{
|
|
3015
|
+
mediaType: 'image',
|
|
3016
|
+
imageUrl: 'image1.jpg',
|
|
3017
|
+
buttons: [{
|
|
3018
|
+
actionOnClick: false,
|
|
3019
|
+
linkType: 'DEEP_LINK',
|
|
3020
|
+
deepLinkValue: '',
|
|
3021
|
+
externalLinkValue: '',
|
|
3022
|
+
}],
|
|
3023
|
+
},
|
|
3024
|
+
{
|
|
3025
|
+
mediaType: 'image',
|
|
3026
|
+
imageUrl: 'image2.jpg',
|
|
3027
|
+
buttons: [{
|
|
3028
|
+
actionOnClick: false,
|
|
3029
|
+
linkType: 'DEEP_LINK',
|
|
3030
|
+
deepLinkValue: '',
|
|
3031
|
+
externalLinkValue: '',
|
|
3032
|
+
}],
|
|
3033
|
+
}
|
|
3034
|
+
],
|
|
3035
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
3036
|
+
carouselActiveTabIndex: 1,
|
|
3037
|
+
setCarouselActiveTabIndex: mockSetCarouselActiveTabIndex,
|
|
3038
|
+
});
|
|
3039
|
+
|
|
3040
|
+
// Find delete button for the last card and click it
|
|
3041
|
+
const deleteButtons = screen.getAllByTestId('cap-button');
|
|
3042
|
+
fireEvent.click(deleteButtons[1]);
|
|
3043
|
+
|
|
3044
|
+
// Should update active tab index to previous card
|
|
3045
|
+
expect(mockSetCarouselActiveTabIndex).toHaveBeenCalledWith(0);
|
|
3046
|
+
});
|
|
3047
|
+
});
|
|
3048
|
+
|
|
3049
|
+
describe('Deep link keys handling', () => {
|
|
3050
|
+
it('should handle deep link keys when no keys are available', async () => {
|
|
3051
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
3052
|
+
|
|
3053
|
+
const { container } = renderComponent({
|
|
3054
|
+
mediaType: 'CAROUSEL',
|
|
3055
|
+
carouselData: [
|
|
3056
|
+
{
|
|
3057
|
+
mediaType: 'image',
|
|
3058
|
+
imageUrl: 'test.jpg',
|
|
3059
|
+
buttons: [{
|
|
3060
|
+
actionOnClick: true,
|
|
3061
|
+
linkType: 'DEEP_LINK',
|
|
3062
|
+
deepLinkValue: 'test-deep-link',
|
|
3063
|
+
deepLinkKeys: [],
|
|
3064
|
+
externalLinkValue: '',
|
|
3065
|
+
}],
|
|
3066
|
+
}
|
|
3067
|
+
],
|
|
3068
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
3069
|
+
linkProps: {
|
|
3070
|
+
deepLink: [
|
|
3071
|
+
{ value: 'test-deep-link', keys: ['key1'] }
|
|
3072
|
+
]
|
|
3073
|
+
},
|
|
3074
|
+
carouselActiveTabIndex: 0,
|
|
3075
|
+
activeTab: 'ANDROID',
|
|
3076
|
+
formatMessage: (message) => message.defaultMessage,
|
|
3077
|
+
});
|
|
3078
|
+
|
|
3079
|
+
// First select the deep link type
|
|
3080
|
+
const linkTypeSelect = screen.getAllByTestId('cap-custom-select')[0];
|
|
3081
|
+
await act(async () => {
|
|
3082
|
+
fireEvent.change(linkTypeSelect, { target: { value: 'DEEP_LINK' } });
|
|
3083
|
+
});
|
|
3084
|
+
|
|
3085
|
+
// Then select the deep link value
|
|
3086
|
+
const deepLinkSelect = screen.getAllByTestId('cap-custom-select')[1];
|
|
3087
|
+
await act(async () => {
|
|
3088
|
+
fireEvent.change(deepLinkSelect, { target: { value: 'test-deep-link' } });
|
|
3089
|
+
});
|
|
3090
|
+
|
|
3091
|
+
// Wait for the deep link keys input to be rendered
|
|
3092
|
+
const deepLinkKeysInput = await screen.findByTestId('cap-input-mobile-push-carousel-deep-link-keys-input-ANDROID-0');
|
|
3093
|
+
expect(deepLinkKeysInput).toBeInTheDocument();
|
|
3094
|
+
expect(deepLinkKeysInput.value).toBe('');
|
|
3095
|
+
|
|
3096
|
+
// Change deep link keys
|
|
3097
|
+
await act(async () => {
|
|
3098
|
+
fireEvent.change(deepLinkKeysInput, { target: { value: '' } });
|
|
3099
|
+
});
|
|
3100
|
+
|
|
3101
|
+
expect(mockOnCarouselDataChange).toHaveBeenCalledWith(
|
|
3102
|
+
'ANDROID',
|
|
3103
|
+
expect.arrayContaining([
|
|
3104
|
+
expect.objectContaining({
|
|
3105
|
+
buttons: expect.arrayContaining([
|
|
3106
|
+
expect.objectContaining({
|
|
3107
|
+
deepLinkKeys: [],
|
|
3108
|
+
}),
|
|
3109
|
+
]),
|
|
3110
|
+
}),
|
|
3111
|
+
])
|
|
3112
|
+
);
|
|
3113
|
+
});
|
|
3114
|
+
|
|
3115
|
+
it('should handle empty carousel deep link keys', async () => {
|
|
3116
|
+
const mockOnCarouselDataChange = jest.fn();
|
|
3117
|
+
|
|
3118
|
+
const { container } = renderComponent({
|
|
3119
|
+
mediaType: 'CAROUSEL',
|
|
3120
|
+
carouselData: [
|
|
3121
|
+
{
|
|
3122
|
+
mediaType: 'image',
|
|
3123
|
+
imageUrl: 'test.jpg',
|
|
3124
|
+
buttons: [{
|
|
3125
|
+
actionOnClick: true,
|
|
3126
|
+
linkType: 'DEEP_LINK',
|
|
3127
|
+
deepLinkValue: 'test-deep-link',
|
|
3128
|
+
deepLinkKeys: [],
|
|
3129
|
+
externalLinkValue: '',
|
|
3130
|
+
}],
|
|
3131
|
+
}
|
|
3132
|
+
],
|
|
3133
|
+
onCarouselDataChange: mockOnCarouselDataChange,
|
|
3134
|
+
linkProps: {
|
|
3135
|
+
deepLink: [
|
|
3136
|
+
{ value: 'test-deep-link', keys: ['key1'] }
|
|
3137
|
+
]
|
|
3138
|
+
},
|
|
3139
|
+
carouselActiveTabIndex: 0,
|
|
3140
|
+
activeTab: 'ANDROID',
|
|
3141
|
+
formatMessage: (message) => message.defaultMessage,
|
|
3142
|
+
});
|
|
3143
|
+
|
|
3144
|
+
// First select the deep link type
|
|
3145
|
+
const linkTypeSelect = screen.getAllByTestId('cap-custom-select')[0];
|
|
3146
|
+
await act(async () => {
|
|
3147
|
+
fireEvent.change(linkTypeSelect, { target: { value: 'DEEP_LINK' } });
|
|
3148
|
+
});
|
|
3149
|
+
|
|
3150
|
+
// Then select the deep link value
|
|
3151
|
+
const deepLinkSelect = screen.getAllByTestId('cap-custom-select')[1];
|
|
3152
|
+
await act(async () => {
|
|
3153
|
+
fireEvent.change(deepLinkSelect, { target: { value: 'test-deep-link' } });
|
|
3154
|
+
});
|
|
3155
|
+
|
|
3156
|
+
// Wait for the deep link keys input to be rendered
|
|
3157
|
+
const deepLinkKeysInput = await screen.findByTestId('cap-input-mobile-push-carousel-deep-link-keys-input-ANDROID-0');
|
|
3158
|
+
expect(deepLinkKeysInput).toBeInTheDocument();
|
|
3159
|
+
expect(deepLinkKeysInput.value).toBe('');
|
|
3160
|
+
|
|
3161
|
+
// Change deep link keys to empty
|
|
3162
|
+
await act(async () => {
|
|
3163
|
+
fireEvent.change(deepLinkKeysInput, { target: { value: '' } });
|
|
3164
|
+
});
|
|
3165
|
+
|
|
3166
|
+
expect(mockOnCarouselDataChange).toHaveBeenCalledWith(
|
|
3167
|
+
'ANDROID',
|
|
3168
|
+
expect.arrayContaining([
|
|
3169
|
+
expect.objectContaining({
|
|
3170
|
+
buttons: expect.arrayContaining([
|
|
3171
|
+
expect.objectContaining({
|
|
3172
|
+
deepLinkKeys: [],
|
|
3173
|
+
}),
|
|
3174
|
+
]),
|
|
3175
|
+
}),
|
|
3176
|
+
])
|
|
3177
|
+
);
|
|
2112
3178
|
});
|
|
2113
3179
|
});
|
|
2114
3180
|
});
|