@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.
Files changed (55) hide show
  1. package/containers/Login/index.js +1 -2
  2. package/containers/Templates/constants.js +10 -1
  3. package/containers/Templates/index.js +45 -45
  4. package/package.json +1 -1
  5. package/services/api.js +14 -7
  6. package/services/tests/haptic-api.test.js +387 -0
  7. package/utils/createMobilePushPayload.js +322 -0
  8. package/utils/tests/{createPayload.test.js → createMobilePushPayload.test.js} +333 -64
  9. package/utils/tests/vendorDataTransformers.test.js +512 -0
  10. package/utils/vendorDataTransformers.js +108 -0
  11. package/v2Components/CapDeviceContent/index.js +1 -1
  12. package/v2Components/CapDocumentUpload/index.js +2 -2
  13. package/v2Components/CapImageUpload/index.js +2 -2
  14. package/v2Components/CapMpushCTA/index.js +13 -12
  15. package/v2Components/CapTagList/index.js +5 -5
  16. package/v2Components/CapVideoUpload/index.js +17 -7
  17. package/v2Components/MobilePushPreviewV2/index.js +28 -15
  18. package/v2Components/TemplatePreview/_templatePreview.scss +131 -29
  19. package/v2Components/TemplatePreview/index.js +130 -131
  20. package/v2Components/TemplatePreview/tests/__snapshots__/index.test.js.snap +10 -10
  21. package/v2Containers/CreativesContainer/index.js +6 -4
  22. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +4748 -4658
  23. package/v2Containers/Login/index.js +1 -2
  24. package/v2Containers/MobilePush/tests/commonMethods.test.js +401 -0
  25. package/v2Containers/MobilePushNew/components/CtaButtons.js +18 -16
  26. package/v2Containers/MobilePushNew/components/MediaUploaders.js +46 -45
  27. package/v2Containers/MobilePushNew/components/PlatformContentFields.js +12 -11
  28. package/v2Containers/MobilePushNew/components/tests/CtaButtons.test.js +134 -367
  29. package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +1209 -143
  30. package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +314 -3
  31. package/v2Containers/MobilePushNew/constants.js +1 -0
  32. package/v2Containers/MobilePushNew/hooks/tests/usePlatformSync.test.js +163 -0
  33. package/v2Containers/MobilePushNew/hooks/tests/useUpload.test.js +1131 -895
  34. package/v2Containers/MobilePushNew/hooks/usePlatformSync.js +172 -52
  35. package/v2Containers/MobilePushNew/hooks/useUpload.js +88 -74
  36. package/v2Containers/MobilePushNew/index.js +278 -1532
  37. package/v2Containers/MobilePushNew/messages.js +30 -0
  38. package/v2Containers/MobilePushNew/sagas.js +2 -7
  39. package/v2Containers/MobilePushNew/tests/sagas.test.js +41 -40
  40. package/v2Containers/MobilePushNew/tests/selectors.test.js +240 -0
  41. package/v2Containers/MobilePushNew/tests/utils.test.js +118 -19
  42. package/v2Containers/MobilePushNew/utils.js +53 -2
  43. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +1171 -971
  44. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +684 -424
  45. package/v2Containers/Templates/_templates.scss +0 -1
  46. package/v2Containers/Templates/index.js +58 -29
  47. package/v2Containers/Templates/sagas.js +0 -1
  48. package/v2Containers/Whatsapp/constants.js +32 -0
  49. package/v2Containers/Whatsapp/index.js +104 -25
  50. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +3992 -3677
  51. package/v2Containers/Whatsapp/tests/haptic.test.js +405 -0
  52. package/assets/loading_img.gif +0 -0
  53. package/utils/createPayload.js +0 -405
  54. /package/v2Components/TemplatePreview/assets/images/{Android _ With date and time.svg → Android_With_date_and_time.svg} +0 -0
  55. /package/v2Components/TemplatePreview/assets/images/{iOS _ With date and time.svg → iOS_With_date_and_time.svg} +0 -0
@@ -1,1223 +1,1459 @@
1
1
  import { renderHook, act } from '@testing-library/react';
2
- import { getCdnUrl } from '../../../../utils/cdnTransformation';
3
2
  import useUpload from '../useUpload';
4
3
  import {
4
+ ANDROID,
5
+ IOS,
5
6
  MOBILE_PUSH_CHANNEL,
6
7
  MPUSH_IMG_SIZE,
7
8
  MPUSH_VIDEO_SIZE,
8
9
  MPUSH_GIF_SIZE,
9
- ANDROID,
10
10
  IMAGE,
11
11
  VIDEO,
12
12
  GIF,
13
13
  CAROUSEL,
14
14
  } from '../../constants';
15
15
 
16
- // Mock the CDN transformation utility
16
+ // Mock cdnTransformation module
17
17
  jest.mock('../../../../utils/cdnTransformation', () => ({
18
- getCdnUrl: jest.fn(),
18
+ getCdnUrl: ({ url, channelName }) => {
19
+ if (!url) return '';
20
+ return `cdn/${channelName}/${url}`;
21
+ },
22
+ getLocalStorageItem: (key, parse = false) => {
23
+ const mockData = {
24
+ CREATIVES_CDN_BASE_URL: 'https://cdn.example.com',
25
+ CREATIVES_CDN_QUALITY_CONFIG: '{"MOBILEPUSH":75,"DEFAULT":80}',
26
+ CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX: 'cdn-cgi/image',
27
+ CREATIVES_S3_BUCKET_PATH: 'intouch_creative_assets',
28
+ };
29
+ const val = mockData[key];
30
+ if (parse && val) {
31
+ return JSON.parse(val);
32
+ }
33
+ return val;
34
+ },
19
35
  }));
20
36
 
21
37
  describe('useUpload Hook', () => {
22
38
  // Mock data and functions
23
- const mockMobilePushActions = {
39
+ let mockMobilePushActions;
40
+ let androidContent;
41
+ let iosContent;
42
+ let mockSetAndroidContent;
43
+ let mockSetIosContent;
44
+
45
+ // Mock formatMessage function
46
+ const mockFormatMessage = (message, values = {}) => {
47
+ if (message.id === 'app.containers.MobilePushNew.fileSizeError') {
48
+ return `File size should be less than ${values.size}MB`;
49
+ }
50
+ if (message.id === 'app.containers.MobilePushNew.imageFileTypeError') {
51
+ return 'Only JPEG and PNG files are allowed';
52
+ }
53
+ if (message.id === 'app.containers.MobilePushNew.videoFileTypeError') {
54
+ return 'Only 3GP, MP4, MOV, M4V files are allowed';
55
+ }
56
+ if (message.id === 'app.containers.MobilePushNew.gifFileTypeError') {
57
+ return 'Only GIF files are allowed';
58
+ }
59
+ return message.defaultMessage;
60
+ };
61
+
62
+ // Helper function to create hook instance
63
+ const createHook = (props = {}) => renderHook(() => useUpload(
64
+ mockMobilePushActions,
65
+ props.editData || {},
66
+ props.uploadedAssetData0 || {},
67
+ props.uploadedAssetData1 || {},
68
+ props.uploadAssetSuccess || false,
69
+ props.sameContent || false,
70
+ mockSetAndroidContent,
71
+ mockSetIosContent,
72
+ props.activeTab || ANDROID,
73
+ androidContent,
74
+ iosContent,
75
+ mockFormatMessage,
76
+ ));
77
+
78
+ beforeEach(() => {
79
+ mockMobilePushActions = {
24
80
  uploadAsset: jest.fn(),
25
81
  clearAsset: jest.fn(),
26
82
  };
27
83
 
28
- const mockSetAndroidContent = jest.fn();
29
- const mockSetIosContent = jest.fn();
30
-
31
- const defaultProps = {
32
- mobilePushActions: mockMobilePushActions,
33
- editData: {},
34
- uploadedAssetData0: {},
35
- uploadedAssetData1: {},
36
- uploadAssetSuccess: false,
37
- sameContent: false,
38
- setAndroidContent: mockSetAndroidContent,
39
- setIosContent: mockSetIosContent,
40
- activeTab: ANDROID,
41
- androidContent: { title: 'Test Android', message: 'Test message' },
42
- iosContent: { title: 'Test iOS', message: 'Test message' },
43
- };
44
-
45
- beforeEach(() => {
46
- jest.clearAllMocks();
47
- getCdnUrl.mockImplementation(({ url }) => `cdn_${url}`);
48
- });
49
-
50
- describe('Hook Initialization', () => {
51
- it('should initialize with default states', () => {
52
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
53
-
54
- expect(result.current.androidAssetList).toEqual([]);
55
- expect(result.current.iosAssetList).toEqual([]);
56
- expect(result.current.mpushVideoSrcAndPreview).toEqual({
57
- mpushVideoSrc: "",
58
- mpushVideoPreviewImg: "",
59
- duration: 0,
60
- });
61
- expect(result.current.imageSrc).toEqual({
62
- androidImageSrc: "",
63
- iosImageSrc: "",
64
- });
65
- expect(result.current.uploadErrors).toEqual({});
66
- });
67
-
68
- it('should initialize from edit data when provided', () => {
69
- const editData = {
70
- templateDetails: {
71
- versions: {
72
- base: {
73
- content: {
74
- ANDROID: {
75
- expandableDetails: {
76
- image: 'test-android-image.jpg',
77
- video: 'test-video.mp4',
78
- videoPreview: 'test-preview.jpg',
79
- },
80
- },
81
- IOS: {
82
- expandableDetails: {
83
- image: 'test-ios-image.jpg',
84
- },
85
- },
86
- },
87
- },
88
- },
89
- },
90
- };
91
-
92
- const { result } = renderHook(() => useUpload(
93
- mockMobilePushActions,
94
- editData,
95
- {},
96
- {},
97
- false,
98
- false,
99
- mockSetAndroidContent,
100
- mockSetIosContent,
101
- ANDROID,
102
- defaultProps.androidContent,
103
- defaultProps.iosContent
104
- ));
105
-
106
- expect(result.current.imageSrc.androidImageSrc).toBe('test-android-image.jpg');
107
- expect(result.current.imageSrc.iosImageSrc).toBe('test-ios-image.jpg');
108
- expect(result.current.mpushVideoSrcAndPreview.mpushVideoSrc).toBe('test-video.mp4');
109
- expect(result.current.mpushVideoSrcAndPreview.mpushVideoPreviewImg).toBe('test-preview.jpg');
110
- });
111
- });
112
-
113
- describe('File Validation Functions', () => {
114
- describe('validateImageFile', () => {
115
- it('should pass validation for valid image file', () => {
116
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
117
-
118
- const validFile = new File(['test'], 'test.jpg', {
119
- type: 'image/jpeg',
120
- size: MPUSH_IMG_SIZE - 1000, // Under the limit
121
- });
122
-
123
- const errors = result.current.validateImageFile(validFile);
124
- expect(errors).toEqual([]);
125
- });
126
-
127
- it('should fail validation for oversized image file', () => {
128
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
129
-
130
- // Create a file with data that exceeds the limit
131
- const oversizedData = new Array(MPUSH_IMG_SIZE + 1000).fill('a').join('');
132
- const oversizedFile = new File([oversizedData], 'test.jpg', {
133
- type: 'image/jpeg',
134
- });
135
-
136
- const errors = result.current.validateImageFile(oversizedFile);
137
- expect(errors).toContain('File size should be less than 2MB');
138
- });
84
+ androidContent = { title: 'Test Android', message: 'Test message' };
85
+ iosContent = { title: 'Test iOS', message: 'Test message' };
139
86
 
140
- it('should fail validation for invalid file type', () => {
141
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
142
-
143
- const invalidFile = new File(['test'], 'test.pdf', {
144
- type: 'application/pdf',
145
- size: 1000,
146
- });
147
-
148
- const errors = result.current.validateImageFile(invalidFile);
149
- expect(errors).toContain('Only JPEG and PNG files are allowed');
150
- });
151
-
152
- it('should fail validation for both size and type errors', () => {
153
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
154
-
155
- // Create a file with data that exceeds the limit
156
- const oversizedData = new Array(MPUSH_IMG_SIZE + 1000).fill('a').join('');
157
- const invalidFile = new File([oversizedData], 'test.pdf', {
158
- type: 'application/pdf',
159
- });
160
-
161
- const errors = result.current.validateImageFile(invalidFile);
162
- expect(errors).toHaveLength(2);
163
- expect(errors).toContain('File size should be less than 2MB');
164
- expect(errors).toContain('Only JPEG and PNG files are allowed');
165
- });
87
+ mockSetAndroidContent = jest.fn((updater) => {
88
+ if (typeof updater === 'function') {
89
+ androidContent = updater(androidContent);
90
+ } else {
91
+ androidContent = { ...androidContent, ...updater };
92
+ }
166
93
  });
167
94
 
168
- describe('validateVideoFile', () => {
169
- it('should pass validation for valid video file', () => {
170
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
171
-
172
- const validFile = new File(['test'], 'test.mp4', {
173
- type: 'video/mp4',
174
- size: MPUSH_VIDEO_SIZE - 1000,
175
- });
176
-
177
- const errors = result.current.validateVideoFile(validFile);
178
- expect(errors).toEqual([]);
179
- });
180
-
181
- it('should fail validation for oversized video file', () => {
182
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
183
-
184
- // Mock a file with oversized property
185
- const oversizedFile = new File(['test'], 'test.mp4', {
186
- type: 'video/mp4',
187
- });
188
- // Override the size property to simulate an oversized file
189
- Object.defineProperty(oversizedFile, 'size', {
190
- value: MPUSH_VIDEO_SIZE + 1000,
191
- writable: false,
192
- });
193
-
194
- const errors = result.current.validateVideoFile(oversizedFile);
195
- expect(errors).toContain('File size should be less than 209.7152MB');
196
- });
197
-
198
- it('should fail validation for invalid video file type', () => {
199
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
200
-
201
- const invalidFile = new File(['test'], 'test.avi', {
202
- type: 'video/avi',
203
- size: 1000,
204
- });
205
-
206
- const errors = result.current.validateVideoFile(invalidFile);
207
- expect(errors).toContain('Only 3GP, MP4, MOV, M4V files are allowed');
208
- });
95
+ mockSetIosContent = jest.fn((updater) => {
96
+ if (typeof updater === 'function') {
97
+ iosContent = updater(iosContent);
98
+ } else {
99
+ iosContent = { ...iosContent, ...updater };
100
+ }
209
101
  });
210
102
 
211
- describe('validateGifFile', () => {
212
- it('should pass validation for valid GIF file', () => {
213
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
214
-
215
- const validFile = new File(['test'], 'test.gif', {
216
- type: 'image/gif',
217
- size: MPUSH_GIF_SIZE - 1000,
218
- });
219
-
220
- const errors = result.current.validateGifFile(validFile);
221
- expect(errors).toEqual([]);
222
- });
223
-
224
- it('should fail validation for oversized GIF file', () => {
225
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
226
-
227
- // Mock a file with oversized property
228
- const oversizedFile = new File(['test'], 'test.gif', {
229
- type: 'image/gif',
230
- });
231
- // Override the size property to simulate an oversized file
232
- Object.defineProperty(oversizedFile, 'size', {
233
- value: MPUSH_GIF_SIZE + 1000,
234
- writable: false,
235
- });
236
-
237
- const errors = result.current.validateGifFile(oversizedFile);
238
- expect(errors).toContain('File size should be less than 209.7152MB');
239
- });
240
-
241
- it('should fail validation for non-GIF file', () => {
242
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
243
-
244
- const invalidFile = new File(['test'], 'test.jpg', {
245
- type: 'image/jpeg',
246
- size: 1000,
247
- });
248
-
249
- const errors = result.current.validateGifFile(invalidFile);
250
- expect(errors).toContain('Only GIF files are allowed');
251
- });
252
- });
103
+ // Reset all mocks
104
+ jest.clearAllMocks();
253
105
  });
254
106
 
255
- describe('Upload Asset Function', () => {
256
- it('should upload valid image file', () => {
257
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
258
-
259
- const validFile = new File(['test'], 'test.jpg', {
260
- type: 'image/jpeg',
261
- size: 1000,
262
- });
107
+ describe('Asset Upload', () => {
108
+ it('should handle image upload with validation', () => {
109
+ const { result } = createHook();
263
110
 
111
+ // Test valid image upload
112
+ const validFile = new File([''], 'test.jpg', { type: 'image/jpeg' });
113
+ Object.defineProperty(validFile, 'size', { value: MPUSH_IMG_SIZE - 1000 }); // Just under limit
264
114
  act(() => {
265
115
  result.current.uploadMpushAsset(validFile, IMAGE.toLowerCase(), {});
266
116
  });
267
-
268
117
  expect(mockMobilePushActions.uploadAsset).toHaveBeenCalledWith(
269
118
  validFile,
270
119
  IMAGE.toLowerCase(),
271
120
  {},
272
- 0, // Android tab
273
- {
274
- source: MOBILE_PUSH_CHANNEL.toLowerCase(),
275
- channel: MOBILE_PUSH_CHANNEL,
276
- }
121
+ 0,
122
+ { source: MOBILE_PUSH_CHANNEL.toLowerCase(), channel: MOBILE_PUSH_CHANNEL }
277
123
  );
278
- });
279
124
 
280
- it('should upload valid video file', () => {
281
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
282
-
283
- const validFile = new File(['test'], 'test.mp4', {
284
- type: 'video/mp4',
285
- size: 1000,
125
+ // Test invalid image upload
126
+ const invalidFile = new File([''], 'test.txt', { type: 'text/plain' });
127
+ act(() => {
128
+ result.current.uploadMpushAsset(invalidFile, IMAGE.toLowerCase(), {});
286
129
  });
130
+ expect(result.current.uploadErrors[0]).toEqual(['Only JPEG and PNG files are allowed']);
131
+ });
287
132
 
133
+ it('should handle video upload with validation', () => {
134
+ const { result } = createHook();
135
+
136
+ // Test valid video upload
137
+ const validFile = new File([''], 'test.mp4', { type: 'video/mp4' });
138
+ Object.defineProperty(validFile, 'size', { value: MPUSH_VIDEO_SIZE - 1000 }); // Just under limit
288
139
  act(() => {
289
140
  result.current.uploadMpushAsset(validFile, VIDEO.toLowerCase(), {});
290
141
  });
291
-
292
142
  expect(mockMobilePushActions.uploadAsset).toHaveBeenCalledWith(
293
143
  validFile,
294
144
  VIDEO.toLowerCase(),
295
145
  {},
296
146
  0,
297
- {
298
- source: MOBILE_PUSH_CHANNEL.toLowerCase(),
299
- channel: MOBILE_PUSH_CHANNEL,
300
- }
147
+ { source: MOBILE_PUSH_CHANNEL.toLowerCase(), channel: MOBILE_PUSH_CHANNEL }
301
148
  );
302
- });
303
-
304
- it('should upload GIF file as video type', () => {
305
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
306
149
 
307
- const validFile = new File(['test'], 'test.gif', {
308
- type: 'image/gif',
309
- size: 1000,
150
+ // Test invalid video upload
151
+ const invalidFile = new File([''], 'test.txt', { type: 'text/plain' });
152
+ act(() => {
153
+ result.current.uploadMpushAsset(invalidFile, VIDEO.toLowerCase(), {});
310
154
  });
155
+ expect(result.current.uploadErrors[0]).toEqual(['Only 3GP, MP4, MOV, M4V files are allowed']);
156
+ });
157
+
158
+ it('should handle GIF upload with validation', () => {
159
+ const { result } = createHook();
311
160
 
161
+ // Test valid GIF upload
162
+ const validFile = new File([''], 'test.gif', { type: 'image/gif' });
163
+ Object.defineProperty(validFile, 'size', { value: MPUSH_GIF_SIZE - 1000 }); // Just under limit
312
164
  act(() => {
313
165
  result.current.uploadMpushAsset(validFile, GIF.toLowerCase(), {});
314
166
  });
315
-
316
167
  expect(mockMobilePushActions.uploadAsset).toHaveBeenCalledWith(
317
168
  validFile,
318
- VIDEO.toLowerCase(), // GIF uploads use video type
169
+ VIDEO.toLowerCase(), // GIF uses video type internally
319
170
  {},
320
171
  0,
321
- {
322
- source: MOBILE_PUSH_CHANNEL.toLowerCase(),
323
- channel: MOBILE_PUSH_CHANNEL,
324
- }
172
+ { source: MOBILE_PUSH_CHANNEL.toLowerCase(), channel: MOBILE_PUSH_CHANNEL }
325
173
  );
326
- });
327
174
 
328
- it('should not upload invalid file and set upload errors', () => {
329
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
330
-
331
- // Create a file with data that exceeds the limit
332
- const oversizedData = new Array(MPUSH_IMG_SIZE + 1000).fill('a').join('');
333
- const invalidFile = new File([oversizedData], 'test.pdf', {
334
- type: 'application/pdf',
175
+ // Test invalid GIF upload
176
+ const invalidFile = new File([''], 'test.jpg', { type: 'image/jpeg' });
177
+ act(() => {
178
+ result.current.uploadMpushAsset(invalidFile, GIF.toLowerCase(), {});
335
179
  });
180
+ expect(result.current.uploadErrors[0]).toEqual(['Only GIF files are allowed']);
181
+ });
182
+ });
183
+
184
+ describe('Media Payload Generation', () => {
185
+ it('should generate correct payload for IMAGE type', () => {
186
+ const { result } = createHook();
336
187
 
337
188
  act(() => {
338
- result.current.uploadMpushAsset(invalidFile, IMAGE.toLowerCase(), {});
189
+ result.current.setImageSrc({
190
+ androidImageSrc: 'test-image.jpg',
191
+ iosImageSrc: 'test-image-ios.jpg',
192
+ });
339
193
  });
340
194
 
341
- expect(mockMobilePushActions.uploadAsset).not.toHaveBeenCalled();
342
- expect(result.current.uploadErrors[0]).toHaveLength(2);
343
- expect(result.current.uploadErrors[0]).toContain('File size should be less than 2MB');
344
- expect(result.current.uploadErrors[0]).toContain('Only JPEG and PNG files are allowed');
195
+ const androidPayload = result.current.getMediaPayload(IMAGE, ANDROID);
196
+ expect(androidPayload).toHaveProperty('imageUrl');
197
+ expect(androidPayload.imageUrl).toBe('cdn/MOBILEPUSH/test-image.jpg');
198
+
199
+ const iosPayload = result.current.getMediaPayload(IMAGE, IOS);
200
+ expect(iosPayload).toHaveProperty('imageUrl');
201
+ expect(iosPayload.imageUrl).toBe('cdn/MOBILEPUSH/test-image-ios.jpg');
345
202
  });
346
203
 
347
- it('should handle iOS tab correctly', () => {
348
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
349
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
204
+ it('should generate correct payload for VIDEO type', () => {
205
+ const { result } = createHook();
350
206
 
351
- const validFile = new File(['test'], 'test.jpg', {
352
- type: 'image/jpeg',
353
- size: 1000,
354
- });
207
+ act(() => {
208
+ result.current.setVideoState({
209
+ androidVideoSrc: 'test-video.mp4',
210
+ androidVideoPreview: 'test-preview.jpg',
211
+ androidVideoDuration: 30,
212
+ iosVideoSrc: 'test-video-ios.mp4',
213
+ iosVideoPreview: 'test-preview-ios.jpg',
214
+ iosVideoDuration: 30,
215
+ });
216
+ });
217
+
218
+ const androidPayload = result.current.getMediaPayload(VIDEO, ANDROID);
219
+ expect(androidPayload).toHaveProperty('videoUrl');
220
+ expect(androidPayload).toHaveProperty('videoPreviewImg');
221
+ expect(androidPayload).toHaveProperty('duration');
222
+ expect(androidPayload.videoUrl).toBe('cdn/MOBILEPUSH/test-video.mp4');
223
+ expect(androidPayload.videoPreviewImg).toBe('cdn/MOBILEPUSH/test-preview.jpg');
224
+ expect(androidPayload.duration).toBe(30);
225
+
226
+ const iosPayload = result.current.getMediaPayload(VIDEO, IOS);
227
+ expect(iosPayload).toHaveProperty('videoUrl');
228
+ expect(iosPayload).toHaveProperty('videoPreviewImg');
229
+ expect(iosPayload).toHaveProperty('duration');
230
+ expect(iosPayload.videoUrl).toBe('cdn/MOBILEPUSH/test-video-ios.mp4');
231
+ expect(iosPayload.videoPreviewImg).toBe('cdn/MOBILEPUSH/test-preview-ios.jpg');
232
+ expect(iosPayload.duration).toBe(30);
233
+ });
234
+
235
+ it('should generate correct payload for GIF type', () => {
236
+ const { result } = createHook();
355
237
 
356
238
  act(() => {
357
- result.current.uploadMpushAsset(validFile, IMAGE.toLowerCase(), {});
239
+ result.current.setVideoState({
240
+ androidVideoSrc: 'test.gif',
241
+ androidVideoPreview: 'test-preview.jpg',
242
+ iosVideoSrc: 'test-ios.gif',
243
+ iosVideoPreview: 'test-preview-ios.jpg',
244
+ });
358
245
  });
359
246
 
360
- expect(mockMobilePushActions.uploadAsset).toHaveBeenCalledWith(
361
- validFile,
362
- IMAGE.toLowerCase(),
363
- {},
364
- 1, // iOS tab
365
- expect.any(Object)
366
- );
247
+ const androidPayload = result.current.getMediaPayload(GIF, ANDROID);
248
+ expect(androidPayload).toHaveProperty('gifUrl');
249
+ expect(androidPayload).toHaveProperty('gifPreviewImg');
250
+ expect(androidPayload.gifUrl).toBe('cdn/MOBILEPUSH/test.gif');
251
+ expect(androidPayload.gifPreviewImg).toBe('cdn/MOBILEPUSH/test-preview.jpg');
252
+
253
+ const iosPayload = result.current.getMediaPayload(GIF, IOS);
254
+ expect(iosPayload).toHaveProperty('gifUrl');
255
+ expect(iosPayload).toHaveProperty('gifPreviewImg');
256
+ expect(iosPayload.gifUrl).toBe('cdn/MOBILEPUSH/test-ios.gif');
257
+ expect(iosPayload.gifPreviewImg).toBe('cdn/MOBILEPUSH/test-preview-ios.jpg');
258
+ });
259
+
260
+ it('should return empty object for unknown media type', () => {
261
+ const { result } = createHook();
262
+ const payload = result.current.getMediaPayload('UNKNOWN', ANDROID);
263
+ expect(payload).toEqual({});
367
264
  });
368
265
  });
369
266
 
370
- describe('Image Source Management', () => {
371
- describe('setUpdateMpushImageSrc', () => {
372
- it('should update Android image source when sync is disabled', () => {
373
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
267
+ describe('Preview Data Generation', () => {
268
+ it('should generate correct preview data for IMAGE type', () => {
269
+ const { result } = createHook();
374
270
 
375
- act(() => {
376
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0, IMAGE);
271
+ act(() => {
272
+ result.current.setImageSrc({
273
+ androidImageSrc: 'test-image.jpg',
274
+ iosImageSrc: 'test-image-ios.jpg',
377
275
  });
378
-
379
- expect(result.current.imageSrc.androidImageSrc).toBe('test-image.jpg');
380
- expect(result.current.imageSrc.iosImageSrc).toBe('');
381
- expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
382
276
  });
383
277
 
384
- it('should update both platforms when sync is enabled', () => {
385
- const syncProps = { ...defaultProps, sameContent: true };
386
- const { result } = renderHook(() => useUpload(...Object.values(syncProps)));
278
+ const androidPreview = result.current.getPreviewData(IMAGE, ANDROID);
279
+ expect(androidPreview).toHaveProperty('imageSrc', 'test-image.jpg');
387
280
 
388
- act(() => {
389
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0, IMAGE);
390
- });
391
-
392
- expect(result.current.imageSrc.androidImageSrc).toBe('test-image.jpg');
393
- expect(result.current.imageSrc.iosImageSrc).toBe('test-image.jpg');
394
- });
281
+ const iosPreview = result.current.getPreviewData(IMAGE, IOS);
282
+ expect(iosPreview).toHaveProperty('imageSrc', 'test-image-ios.jpg');
283
+ });
395
284
 
396
- it('should update iOS image source when iOS tab is active', () => {
397
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
398
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
285
+ it('should generate correct preview data for VIDEO type', () => {
286
+ const { result } = createHook();
399
287
 
400
- act(() => {
401
- result.current.setUpdateMpushImageSrc('test-ios-image.jpg', 1, IMAGE);
288
+ act(() => {
289
+ result.current.setVideoState({
290
+ androidVideoSrc: 'test-video.mp4',
291
+ androidVideoPreview: 'test-preview.jpg',
292
+ androidVideoDuration: 30,
293
+ iosVideoSrc: 'test-video-ios.mp4',
294
+ iosVideoPreview: 'test-preview-ios.jpg',
295
+ iosVideoDuration: 30,
402
296
  });
403
-
404
- expect(result.current.imageSrc.androidImageSrc).toBe('');
405
- expect(result.current.imageSrc.iosImageSrc).toBe('test-ios-image.jpg');
406
- expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(1);
407
297
  });
408
298
 
409
- it('should not handle carousel media type', () => {
410
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
411
-
412
- act(() => {
413
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0, CAROUSEL);
414
- });
299
+ const androidPreview = result.current.getPreviewData(VIDEO, ANDROID);
300
+ expect(androidPreview).toEqual({
301
+ videoSrc: 'test-video.mp4',
302
+ videoPreviewImg: 'test-preview.jpg',
303
+ duration: 30,
304
+ });
415
305
 
416
- expect(result.current.imageSrc.androidImageSrc).toBe('test-image.jpg');
417
- expect(result.current.imageSrc.iosImageSrc).toBe('');
418
- expect(mockMobilePushActions.clearAsset).not.toHaveBeenCalled();
306
+ const iosPreview = result.current.getPreviewData(VIDEO, IOS);
307
+ expect(iosPreview).toEqual({
308
+ videoSrc: 'test-video-ios.mp4',
309
+ videoPreviewImg: 'test-preview-ios.jpg',
310
+ duration: 30,
419
311
  });
312
+ });
420
313
 
421
- it('should default to IMAGE media type when mediaType parameter is not provided', () => {
422
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
314
+ it('should generate correct preview data for GIF type', () => {
315
+ const { result } = createHook();
423
316
 
424
- act(() => {
425
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0); // No mediaType parameter
317
+ act(() => {
318
+ result.current.setVideoState({
319
+ androidVideoSrc: 'test.gif',
320
+ androidVideoPreview: 'test-preview.jpg',
321
+ iosVideoSrc: 'test-ios.gif',
322
+ iosVideoPreview: 'test-preview-ios.jpg',
426
323
  });
324
+ });
427
325
 
428
- expect(result.current.imageSrc.androidImageSrc).toBe('test-image.jpg');
429
- expect(result.current.imageSrc.iosImageSrc).toBe('');
430
- expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
326
+ const androidPreview = result.current.getPreviewData(GIF, ANDROID);
327
+ expect(androidPreview).toEqual({
328
+ gifSrc: 'test.gif',
329
+ gifPreviewImg: 'test-preview.jpg',
431
330
  });
432
331
 
433
- it('should default to IMAGE media type for iOS platform when mediaType parameter is not provided', () => {
434
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
435
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
332
+ const iosPreview = result.current.getPreviewData(GIF, IOS);
333
+ expect(iosPreview).toEqual({
334
+ gifSrc: 'test-ios.gif',
335
+ gifPreviewImg: 'test-preview-ios.jpg',
336
+ });
337
+ });
436
338
 
437
- act(() => {
438
- result.current.setUpdateMpushImageSrc('test-ios-image.jpg', 1); // No mediaType parameter
439
- });
339
+ it('should return empty object for unknown media type', () => {
340
+ const { result } = createHook();
341
+ const preview = result.current.getPreviewData('UNKNOWN', ANDROID);
342
+ expect(preview).toEqual({});
343
+ });
344
+ });
345
+
346
+ describe('Media Upload Status', () => {
347
+ it('should correctly check if IMAGE is uploaded', () => {
348
+ const { result } = createHook();
440
349
 
441
- expect(result.current.imageSrc.androidImageSrc).toBe('');
442
- expect(result.current.imageSrc.iosImageSrc).toBe('test-ios-image.jpg');
443
- expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(1);
350
+ act(() => {
351
+ result.current.setImageSrc({
352
+ androidImageSrc: 'test-image.jpg',
353
+ iosImageSrc: 'test-image-ios.jpg',
354
+ });
444
355
  });
445
356
 
446
- it('should default to IMAGE media type when sync is enabled and mediaType parameter is not provided', () => {
447
- const syncProps = { ...defaultProps, sameContent: true };
448
- const { result } = renderHook(() => useUpload(...Object.values(syncProps)));
357
+ expect(result.current.isMediaUploaded(IMAGE, ANDROID)).toBe(true);
358
+ expect(result.current.isMediaUploaded(IMAGE, IOS)).toBe(true);
359
+ });
449
360
 
450
- act(() => {
451
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0); // No mediaType parameter
452
- });
361
+ it('should correctly check if VIDEO is uploaded', () => {
362
+ const { result } = createHook();
453
363
 
454
- expect(result.current.imageSrc.androidImageSrc).toBe('test-image.jpg');
455
- expect(result.current.imageSrc.iosImageSrc).toBe('test-image.jpg');
456
- expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
364
+ act(() => {
365
+ result.current.setVideoState({
366
+ androidVideoSrc: 'test-video.mp4',
367
+ iosVideoSrc: 'test-video-ios.mp4',
368
+ });
457
369
  });
370
+
371
+ expect(result.current.isMediaUploaded(VIDEO, ANDROID)).toBe(true);
372
+ expect(result.current.isMediaUploaded(VIDEO, IOS)).toBe(true);
458
373
  });
459
374
 
460
- describe('updateOnMpushImageReUpload', () => {
461
- it('should clear Android platform image when sync is disabled and Android tab is active', () => {
462
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
375
+ it('should correctly check if GIF is uploaded', () => {
376
+ const { result } = createHook();
463
377
 
464
- // Set initial images for both platforms
465
- act(() => {
466
- result.current.setImageSrc({
467
- androidImageSrc: 'test-android-image.jpg',
468
- iosImageSrc: 'test-ios-image.jpg',
469
- });
378
+ act(() => {
379
+ result.current.setVideoState({
380
+ androidVideoSrc: 'test.gif',
381
+ iosVideoSrc: 'test-ios.gif',
470
382
  });
383
+ });
471
384
 
472
- // Clear image (should only clear Android since activeTab is ANDROID)
473
- act(() => {
474
- result.current.updateOnMpushImageReUpload();
475
- });
385
+ expect(result.current.isMediaUploaded(GIF, ANDROID)).toBe(true);
386
+ expect(result.current.isMediaUploaded(GIF, IOS)).toBe(true);
387
+ });
476
388
 
477
- expect(result.current.imageSrc.androidImageSrc).toBe('');
478
- expect(result.current.imageSrc.iosImageSrc).toBe('test-ios-image.jpg'); // iOS should remain
479
- });
389
+ it('should return true for unknown media type', () => {
390
+ const { result } = createHook();
391
+ expect(result.current.isMediaUploaded('UNKNOWN', ANDROID)).toBe(true);
392
+ });
393
+ });
480
394
 
481
- it('should clear iOS platform image when sync is disabled and iOS tab is active', () => {
482
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
483
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
395
+ describe('Edit Mode Initialization', () => {
396
+ it('should initialize from edit data with Android content', () => {
397
+ const editData = {
398
+ templateDetails: {
399
+ versions: {
400
+ base: {
401
+ content: {
402
+ ANDROID: {
403
+ expandableDetails: {
404
+ image: 'android-image.jpg',
405
+ video: 'android-video.mp4',
406
+ videoPreview: 'android-preview.jpg',
407
+ videoDuration: 30,
408
+ },
409
+ },
410
+ },
411
+ },
412
+ },
413
+ },
414
+ };
484
415
 
485
- // Set initial images for both platforms
486
- act(() => {
487
- result.current.setImageSrc({
488
- androidImageSrc: 'test-android-image.jpg',
489
- iosImageSrc: 'test-ios-image.jpg',
490
- });
491
- });
416
+ const { result } = createHook({ editData });
492
417
 
493
- // Clear image (should only clear iOS since activeTab is IOS)
494
- act(() => {
495
- result.current.updateOnMpushImageReUpload();
496
- });
418
+ expect(result.current.imageSrc.androidImageSrc).toBe('android-image.jpg');
419
+ expect(result.current.videoState.androidVideoSrc).toBe('android-video.mp4');
420
+ expect(result.current.videoState.androidVideoPreview).toBe('android-preview.jpg');
421
+ expect(result.current.videoState.androidVideoDuration).toBe(30);
422
+ });
497
423
 
498
- expect(result.current.imageSrc.androidImageSrc).toBe('test-android-image.jpg'); // Android should remain
499
- expect(result.current.imageSrc.iosImageSrc).toBe(''); // iOS should be cleared
500
- });
424
+ it('should initialize from edit data with iOS content', () => {
425
+ const editData = {
426
+ templateDetails: {
427
+ versions: {
428
+ base: {
429
+ content: {
430
+ IOS: {
431
+ expandableDetails: {
432
+ image: 'ios-image.jpg',
433
+ video: 'ios-video.mp4',
434
+ videoPreview: 'ios-preview.jpg',
435
+ videoDuration: 30,
436
+ },
437
+ },
438
+ },
439
+ },
440
+ },
441
+ },
442
+ };
501
443
 
502
- it('should clear both platforms when sync is enabled', () => {
503
- const syncProps = { ...defaultProps, sameContent: true };
504
- const { result } = renderHook(() => useUpload(...Object.values(syncProps)));
444
+ const { result } = createHook({ editData });
505
445
 
506
- // Set initial images
507
- act(() => {
508
- result.current.setUpdateMpushImageSrc('test-image.jpg', IMAGE);
509
- });
446
+ expect(result.current.imageSrc.iosImageSrc).toBe('ios-image.jpg');
447
+ expect(result.current.videoState.iosVideoSrc).toBe('ios-video.mp4');
448
+ expect(result.current.videoState.iosVideoPreview).toBe('ios-preview.jpg');
449
+ expect(result.current.videoState.iosVideoDuration).toBe(30);
450
+ });
510
451
 
511
- // Clear images
512
- act(() => {
513
- result.current.updateOnMpushImageReUpload();
514
- });
452
+ it('should handle missing video preview and duration in edit data', () => {
453
+ const editData = {
454
+ templateDetails: {
455
+ versions: {
456
+ base: {
457
+ content: {
458
+ ANDROID: {
459
+ expandableDetails: {
460
+ video: 'android-video.mp4',
461
+ },
462
+ },
463
+ IOS: {
464
+ expandableDetails: {
465
+ video: 'ios-video.mp4',
466
+ },
467
+ },
468
+ },
469
+ },
470
+ },
471
+ },
472
+ };
515
473
 
516
- expect(result.current.imageSrc.androidImageSrc).toBe('');
517
- expect(result.current.imageSrc.iosImageSrc).toBe('');
518
- });
474
+ const { result } = createHook({ editData });
475
+
476
+ expect(result.current.videoState.androidVideoSrc).toBe('android-video.mp4');
477
+ expect(result.current.videoState.androidVideoPreview).toBe('');
478
+ expect(result.current.videoState.androidVideoDuration).toBe(0);
479
+ expect(result.current.videoState.iosVideoSrc).toBe('ios-video.mp4');
480
+ expect(result.current.videoState.iosVideoPreview).toBe('');
481
+ expect(result.current.videoState.iosVideoDuration).toBe(0);
519
482
  });
520
483
  });
521
484
 
522
- describe('Video Source Management', () => {
523
- describe('setUpdateMpushVideoSrc', () => {
524
- it('should update video source and asset list', () => {
525
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
485
+ describe('CDN URL Generation', () => {
486
+ it('should generate CDN URLs for images and videos', () => {
487
+ const { result } = createHook();
526
488
 
527
- const videoData = {
528
- videoSrc: 'test-video.mp4',
529
- previewUrl: 'test-preview.jpg',
530
- videoDuration: 120,
531
- videoName: 'test-video.mp4',
532
- fileHandle: 'file-handle-123',
533
- };
489
+ // Test image URL generation
490
+ const imageUrl = result.current.getCdnImageUrl('test-image.jpg');
491
+ expect(imageUrl).toBeDefined();
492
+ expect(imageUrl).toBe('cdn/MOBILEPUSH/test-image.jpg');
534
493
 
535
- act(() => {
536
- result.current.setUpdateMpushVideoSrc(0, videoData);
537
- });
494
+ // Test video URL generation
495
+ const videoUrl = result.current.getCdnVideoUrl('test-video.mp4');
496
+ expect(videoUrl).toBeDefined();
497
+ expect(videoUrl).toBe('cdn/MOBILEPUSH/test-video.mp4');
538
498
 
539
- expect(result.current.mpushVideoSrcAndPreview).toEqual({
499
+ // Test empty URL handling
500
+ expect(result.current.getCdnImageUrl('')).toBe('');
501
+ expect(result.current.getCdnVideoUrl('')).toBe('');
502
+ });
503
+ });
504
+
505
+ describe('Reset Upload States', () => {
506
+ it('should reset all upload states', () => {
507
+ const { result } = createHook();
508
+
509
+ // Set some initial state
510
+ act(() => {
511
+ result.current.setImageSrc({
512
+ androidImageSrc: 'test-image.jpg',
513
+ iosImageSrc: 'test-image-ios.jpg',
514
+ });
515
+ result.current.setVideoState({
516
+ androidVideoSrc: 'test-video.mp4',
517
+ androidVideoPreview: 'test-preview.jpg',
518
+ androidVideoDuration: 30,
519
+ iosVideoSrc: 'test-video-ios.mp4',
520
+ iosVideoPreview: 'test-preview-ios.jpg',
521
+ iosVideoDuration: 30,
522
+ });
523
+ result.current.setMpushVideoSrcAndPreview({
540
524
  mpushVideoSrc: 'test-video.mp4',
541
525
  mpushVideoPreviewImg: 'test-preview.jpg',
542
- duration: 120,
526
+ duration: 30,
543
527
  });
528
+ });
544
529
 
545
- expect(result.current.assetList).toEqual(videoData);
546
- expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
530
+ // Reset all states
531
+ act(() => {
532
+ result.current.resetUploadStates();
547
533
  });
548
534
 
549
- it('should handle partial video data', () => {
550
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
535
+ // Verify all states are reset
536
+ expect(result.current.imageSrc).toEqual({
537
+ androidImageSrc: '',
538
+ iosImageSrc: '',
539
+ });
540
+ expect(result.current.videoState).toEqual({
541
+ androidVideoSrc: '',
542
+ iosVideoSrc: '',
543
+ androidVideoPreview: '',
544
+ iosVideoPreview: '',
545
+ androidVideoDuration: 0,
546
+ iosVideoDuration: 0,
547
+ });
548
+ expect(result.current.mpushVideoSrcAndPreview).toEqual({
549
+ mpushVideoSrc: '',
550
+ mpushVideoPreviewImg: '',
551
+ duration: 0,
552
+ });
553
+ expect(result.current.androidAssetList).toEqual([]);
554
+ expect(result.current.iosAssetList).toEqual([]);
555
+ });
556
+ });
551
557
 
552
- const partialVideoData = {
553
- videoSrc: 'test-video.mp4',
554
- };
558
+ describe('Image Re-upload Handlers', () => {
559
+ it('should handle image re-upload with sync enabled', () => {
560
+ const { result } = createHook({ sameContent: true });
555
561
 
556
- act(() => {
557
- result.current.setUpdateMpushVideoSrc(0, partialVideoData);
562
+ // Set initial state
563
+ act(() => {
564
+ result.current.setImageSrc({
565
+ androidImageSrc: 'test-image.jpg',
566
+ iosImageSrc: 'test-image.jpg',
558
567
  });
568
+ });
559
569
 
560
- expect(result.current.mpushVideoSrcAndPreview).toEqual({
561
- mpushVideoSrc: 'test-video.mp4',
562
- mpushVideoPreviewImg: '',
563
- duration: 0,
564
- });
570
+ // Re-upload image
571
+ act(() => {
572
+ result.current.updateOnMpushImageReUpload();
573
+ });
574
+
575
+ // Verify both platforms are cleared
576
+ expect(result.current.imageSrc).toEqual({
577
+ androidImageSrc: '',
578
+ iosImageSrc: '',
565
579
  });
566
580
  });
567
581
 
568
- describe('updateOnMpushVideoReUpload', () => {
569
- it('should clear all video-related state', () => {
570
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
571
-
572
- // Set initial video data
573
- act(() => {
574
- result.current.setUpdateMpushVideoSrc(0, {
575
- videoSrc: 'test-video.mp4',
576
- previewUrl: 'test-preview.jpg',
577
- videoDuration: 120,
578
- });
582
+ it('should handle image re-upload with sync disabled', () => {
583
+ const { result } = createHook({ sameContent: false, activeTab: ANDROID });
584
+
585
+ // Set initial state
586
+ act(() => {
587
+ result.current.setImageSrc({
588
+ androidImageSrc: 'test-image.jpg',
589
+ iosImageSrc: 'test-image-ios.jpg',
579
590
  });
591
+ });
592
+
593
+ // Re-upload image
594
+ act(() => {
595
+ result.current.updateOnMpushImageReUpload();
596
+ });
597
+
598
+ // Verify only Android is cleared
599
+ expect(result.current.imageSrc).toEqual({
600
+ androidImageSrc: '',
601
+ iosImageSrc: 'test-image-ios.jpg',
602
+ });
603
+ });
580
604
 
581
- // Clear video data
582
- act(() => {
583
- result.current.updateOnMpushVideoReUpload();
584
- });
605
+ it('should handle image source update with sync enabled', () => {
606
+ const { result } = createHook({ sameContent: true });
585
607
 
586
- expect(result.current.mpushVideoSrcAndPreview).toEqual({
587
- mpushVideoSrc: '',
588
- mpushVideoPreviewImg: '',
589
- duration: 0,
590
- });
608
+ // Update image source
609
+ act(() => {
610
+ result.current.setUpdateMpushImageSrc('test-image.jpg', 0);
611
+ });
591
612
 
592
- expect(result.current.assetList).toEqual([]);
593
- expect(mockSetAndroidContent).toHaveBeenCalledWith(expect.any(Function));
594
- expect(mockSetIosContent).toHaveBeenCalledWith(expect.any(Function));
595
- expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
613
+ // Verify both platforms are updated
614
+ expect(result.current.imageSrc).toEqual({
615
+ androidImageSrc: 'test-image.jpg',
616
+ iosImageSrc: 'test-image.jpg',
596
617
  });
618
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
597
619
  });
598
- });
599
620
 
600
- describe('Media Payload Generation', () => {
601
- it('should generate correct payload for IMAGE media type', () => {
602
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
621
+ it('should handle image source update with sync disabled', () => {
622
+ const { result } = createHook({ sameContent: false });
603
623
 
604
- // Set image source
624
+ // Update Android image source
605
625
  act(() => {
606
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0, IMAGE);
626
+ result.current.setUpdateMpushImageSrc('test-image.jpg', 0);
607
627
  });
608
628
 
609
- const payload = result.current.getMediaPayload(IMAGE, ANDROID);
629
+ // Verify only Android is updated
630
+ expect(result.current.imageSrc).toEqual({
631
+ androidImageSrc: 'test-image.jpg',
632
+ iosImageSrc: '',
633
+ });
634
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
635
+
636
+ // Update iOS image source
637
+ act(() => {
638
+ result.current.setUpdateMpushImageSrc('test-image-ios.jpg', 1);
639
+ });
610
640
 
611
- expect(payload).toEqual({
612
- imageUrl: 'cdn_test-image.jpg',
641
+ // Verify iOS is updated
642
+ expect(result.current.imageSrc).toEqual({
643
+ androidImageSrc: 'test-image.jpg',
644
+ iosImageSrc: 'test-image-ios.jpg',
613
645
  });
646
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(1);
614
647
  });
615
648
 
616
- it('should generate correct payload for VIDEO media type', () => {
617
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
649
+ it('should handle carousel image source update', () => {
650
+ const { result } = createHook({ sameContent: true });
618
651
 
619
- // Set video source with preview
652
+ // Update carousel image source
620
653
  act(() => {
621
- result.current.setUpdateMpushVideoSrc(0, {
622
- videoSrc: 'test-video.mp4',
623
- previewUrl: 'test-preview.jpg',
624
- videoDuration: 30,
625
- });
654
+ result.current.setUpdateMpushImageSrc('test-image.jpg', 0, CAROUSEL);
626
655
  });
627
656
 
628
- const payload = result.current.getMediaPayload(VIDEO, ANDROID);
629
-
630
- expect(payload).toEqual({
631
- videoUrl: 'cdn_test-video.mp4',
632
- videoPreviewImg: 'cdn_test-preview.jpg',
633
- duration: 30,
657
+ // Verify both platforms are updated but clearAsset is not called
658
+ expect(result.current.imageSrc).toEqual({
659
+ androidImageSrc: 'test-image.jpg',
660
+ iosImageSrc: 'test-image.jpg',
634
661
  });
662
+ expect(mockMobilePushActions.clearAsset).not.toHaveBeenCalled();
635
663
  });
664
+ });
636
665
 
637
- it('should generate correct payload for GIF media type with preview image', () => {
638
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
666
+ describe('Video Re-upload Handlers', () => {
667
+ it('should handle video re-upload with sync enabled', () => {
668
+ const { result } = createHook({ sameContent: true });
639
669
 
640
- // Set GIF source with preview
670
+ // Set initial state
641
671
  act(() => {
642
- result.current.setUpdateMpushVideoSrc(0, {
643
- videoSrc: 'test-gif.gif',
644
- previewUrl: 'test-preview.jpg',
645
- videoDuration: 5,
672
+ result.current.setVideoState({
673
+ androidVideoSrc: 'test-video.mp4',
674
+ androidVideoPreview: 'test-preview.jpg',
675
+ androidVideoDuration: 30,
676
+ iosVideoSrc: 'test-video.mp4',
677
+ iosVideoPreview: 'test-preview.jpg',
678
+ iosVideoDuration: 30,
679
+ });
680
+ result.current.setMpushVideoSrcAndPreview({
681
+ mpushVideoSrc: 'test-video.mp4',
682
+ mpushVideoPreviewImg: 'test-preview.jpg',
683
+ duration: 30,
646
684
  });
647
685
  });
648
686
 
649
- const payload = result.current.getMediaPayload(GIF, ANDROID);
687
+ // Re-upload video
688
+ act(() => {
689
+ result.current.updateOnMpushVideoReUpload();
690
+ });
650
691
 
651
- expect(payload).toEqual({
652
- gifUrl: 'cdn_test-gif.gif',
653
- gifPreviewImg: 'cdn_test-preview.jpg',
692
+ // Verify all states are cleared
693
+ expect(result.current.videoState).toEqual({
694
+ androidVideoSrc: '',
695
+ iosVideoSrc: '',
696
+ androidVideoPreview: '',
697
+ iosVideoPreview: '',
698
+ androidVideoDuration: 0,
699
+ iosVideoDuration: 0,
700
+ });
701
+ expect(result.current.mpushVideoSrcAndPreview).toEqual({
702
+ mpushVideoSrc: '',
703
+ mpushVideoPreviewImg: '',
704
+ duration: 0,
654
705
  });
706
+ expect(result.current.androidAssetList).toEqual([]);
707
+ expect(result.current.iosAssetList).toEqual([]);
708
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
709
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(1);
655
710
  });
656
711
 
657
- it('should generate correct payload for GIF media type without preview image (covers line 328)', () => {
658
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
712
+ it('should handle video re-upload with sync disabled', () => {
713
+ const { result } = createHook({ sameContent: false, activeTab: ANDROID });
659
714
 
660
- // Set GIF source WITHOUT preview to cover the falsy condition on line 328
715
+ // Set initial state
661
716
  act(() => {
662
- result.current.setUpdateMpushVideoSrc(0, {
663
- videoSrc: 'test-gif.gif',
664
- previewUrl: '', // Empty preview URL to trigger the falsy condition
665
- videoDuration: 5,
717
+ result.current.setVideoState({
718
+ androidVideoSrc: 'test-video.mp4',
719
+ androidVideoPreview: 'test-preview.jpg',
720
+ androidVideoDuration: 30,
721
+ iosVideoSrc: 'test-video-ios.mp4',
722
+ iosVideoPreview: 'test-preview-ios.jpg',
723
+ iosVideoDuration: 30,
666
724
  });
667
725
  });
668
726
 
669
- const payload = result.current.getMediaPayload(GIF, ANDROID);
727
+ // Re-upload video
728
+ act(() => {
729
+ result.current.updateOnMpushVideoReUpload();
730
+ });
670
731
 
671
- expect(payload).toEqual({
672
- gifUrl: 'cdn_test-gif.gif',
673
- gifPreviewImg: '', // This should be empty string due to the falsy condition
732
+ // Verify only Android states are cleared
733
+ expect(result.current.videoState).toEqual({
734
+ androidVideoSrc: '',
735
+ androidVideoPreview: '',
736
+ androidVideoDuration: 0,
737
+ iosVideoSrc: 'test-video-ios.mp4',
738
+ iosVideoPreview: 'test-preview-ios.jpg',
739
+ iosVideoDuration: 30,
674
740
  });
741
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
742
+ expect(mockMobilePushActions.clearAsset).not.toHaveBeenCalledWith(1);
675
743
  });
676
744
 
677
- it('should generate correct payload for GIF media type with null preview image (covers line 328)', () => {
678
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
745
+ it('should handle video source update with sync enabled', () => {
746
+ const { result } = createHook({ sameContent: true });
679
747
 
680
- // Set GIF source with null preview to cover the falsy condition on line 328
748
+ // Update video source
681
749
  act(() => {
682
750
  result.current.setUpdateMpushVideoSrc(0, {
683
- videoSrc: 'test-gif.gif',
684
- previewUrl: null, // Null preview URL to trigger the falsy condition
685
- videoDuration: 5,
751
+ videoSrc: 'test-video.mp4',
752
+ previewUrl: 'test-preview.jpg',
753
+ videoDuration: 30,
754
+ videoName: 'test.mp4',
755
+ fileHandle: 'handle',
686
756
  });
687
757
  });
688
758
 
689
- const payload = result.current.getMediaPayload(GIF, ANDROID);
690
-
691
- expect(payload).toEqual({
692
- gifUrl: 'cdn_test-gif.gif',
693
- gifPreviewImg: '', // This should be empty string due to the falsy condition
759
+ // Verify both platforms are updated
760
+ expect(result.current.videoState).toEqual({
761
+ androidVideoSrc: 'test-video.mp4',
762
+ iosVideoSrc: 'test-video.mp4',
763
+ androidVideoPreview: 'test-preview.jpg',
764
+ iosVideoPreview: 'test-preview.jpg',
765
+ androidVideoDuration: 30,
766
+ iosVideoDuration: 30,
767
+ });
768
+ expect(result.current.mpushVideoSrcAndPreview).toEqual({
769
+ mpushVideoSrc: 'test-video.mp4',
770
+ mpushVideoPreviewImg: 'test-preview.jpg',
771
+ duration: 30,
772
+ });
773
+ expect(result.current.androidAssetList).toEqual({
774
+ videoSrc: 'test-video.mp4',
775
+ previewUrl: 'test-preview.jpg',
776
+ videoDuration: 30,
777
+ videoName: 'test.mp4',
778
+ fileHandle: 'handle',
779
+ });
780
+ expect(result.current.iosAssetList).toEqual({
781
+ videoSrc: 'test-video.mp4',
782
+ previewUrl: 'test-preview.jpg',
783
+ videoDuration: 30,
784
+ videoName: 'test.mp4',
785
+ fileHandle: 'handle',
694
786
  });
787
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
695
788
  });
696
789
 
697
- it('should generate correct payload for GIF media type with undefined preview image (covers line 328)', () => {
698
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
790
+ it('should handle video source update with sync disabled', () => {
791
+ const { result } = createHook({ sameContent: false });
699
792
 
700
- // Set GIF source with undefined preview to cover the falsy condition on line 328
793
+ // Update Android video source
701
794
  act(() => {
702
795
  result.current.setUpdateMpushVideoSrc(0, {
703
- videoSrc: 'test-gif.gif',
704
- previewUrl: undefined, // Undefined preview URL to trigger the falsy condition
705
- videoDuration: 5,
796
+ videoSrc: 'test-video.mp4',
797
+ previewUrl: 'test-preview.jpg',
798
+ videoDuration: 30,
799
+ videoName: 'test.mp4',
800
+ fileHandle: 'handle',
706
801
  });
707
802
  });
708
803
 
709
- const payload = result.current.getMediaPayload(GIF, ANDROID);
710
-
711
- expect(payload).toEqual({
712
- gifUrl: 'cdn_test-gif.gif',
713
- gifPreviewImg: '', // This should be empty string due to the falsy condition
804
+ // Verify only Android is updated
805
+ expect(result.current.videoState).toEqual({
806
+ androidVideoSrc: 'test-video.mp4',
807
+ androidVideoPreview: 'test-preview.jpg',
808
+ androidVideoDuration: 30,
809
+ iosVideoSrc: '',
810
+ iosVideoPreview: '',
811
+ iosVideoDuration: 0,
714
812
  });
715
- });
716
-
717
- it('should return empty object for unknown media type', () => {
718
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
813
+ expect(result.current.androidAssetList).toEqual({
814
+ videoSrc: 'test-video.mp4',
815
+ previewUrl: 'test-preview.jpg',
816
+ videoDuration: 30,
817
+ videoName: 'test.mp4',
818
+ fileHandle: 'handle',
819
+ });
820
+ expect(result.current.iosAssetList).toEqual([]);
821
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
719
822
 
720
- const payload = result.current.getMediaPayload('UNKNOWN_TYPE', ANDROID);
823
+ // Update iOS video source
824
+ act(() => {
825
+ result.current.setUpdateMpushVideoSrc(1, {
826
+ videoSrc: 'test-video-ios.mp4',
827
+ previewUrl: 'test-preview-ios.jpg',
828
+ videoDuration: 30,
829
+ videoName: 'test-ios.mp4',
830
+ fileHandle: 'handle-ios',
831
+ });
832
+ });
721
833
 
722
- expect(payload).toEqual({});
834
+ // Verify iOS is updated
835
+ expect(result.current.videoState).toEqual({
836
+ androidVideoSrc: 'test-video.mp4',
837
+ androidVideoPreview: 'test-preview.jpg',
838
+ androidVideoDuration: 30,
839
+ iosVideoSrc: 'test-video-ios.mp4',
840
+ iosVideoPreview: 'test-preview-ios.jpg',
841
+ iosVideoDuration: 30,
842
+ });
843
+ expect(result.current.iosAssetList).toEqual({
844
+ videoSrc: 'test-video-ios.mp4',
845
+ previewUrl: 'test-preview-ios.jpg',
846
+ videoDuration: 30,
847
+ videoName: 'test-ios.mp4',
848
+ fileHandle: 'handle-ios',
849
+ });
850
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(1);
723
851
  });
724
852
 
725
- it('should return empty object when no media is set', () => {
726
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
727
-
728
- // Test with IMAGE but no image source set
729
- const imagePayload = result.current.getMediaPayload(IMAGE, ANDROID);
730
- expect(imagePayload).toEqual({});
853
+ it('should not clear asset during initialization', () => {
854
+ const { result } = createHook({ sameContent: true });
731
855
 
732
- // Test with VIDEO but no video source set
733
- const videoPayload = result.current.getMediaPayload(VIDEO, ANDROID);
734
- expect(videoPayload).toEqual({});
856
+ // Update video source with isInitialization=true
857
+ act(() => {
858
+ result.current.setUpdateMpushVideoSrc(0, {
859
+ videoSrc: 'test-video.mp4',
860
+ previewUrl: 'test-preview.jpg',
861
+ videoDuration: 30,
862
+ videoName: 'test.mp4',
863
+ fileHandle: 'handle',
864
+ }, true);
865
+ });
735
866
 
736
- // Test with GIF but no GIF source set
737
- const gifPayload = result.current.getMediaPayload(GIF, ANDROID);
738
- expect(gifPayload).toEqual({});
867
+ // Verify states are updated but clearAsset is not called
868
+ expect(result.current.videoState.androidVideoSrc).toBe('test-video.mp4');
869
+ expect(mockMobilePushActions.clearAsset).not.toHaveBeenCalled();
739
870
  });
740
871
  });
741
872
 
742
- describe('Preview Data Generation', () => {
743
- describe('getPreviewData', () => {
744
- it('should generate image preview data', () => {
745
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
746
-
747
- act(() => {
748
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0, IMAGE);
749
- });
750
-
751
- const previewData = result.current.getPreviewData(IMAGE, ANDROID);
873
+ describe('Platform-specific Logic', () => {
874
+ it('should get correct video properties for Android', () => {
875
+ const { result } = createHook({ activeTab: ANDROID });
752
876
 
753
- expect(previewData).toEqual({
754
- imageSrc: 'test-image.jpg',
877
+ // Test Android video properties
878
+ act(() => {
879
+ result.current.setVideoState({
880
+ androidVideoSrc: 'test-video.mp4',
881
+ androidVideoPreview: 'test-preview.jpg',
882
+ androidVideoDuration: 30,
883
+ iosVideoSrc: 'test-video-ios.mp4',
884
+ iosVideoPreview: 'test-preview-ios.jpg',
885
+ iosVideoDuration: 25,
755
886
  });
756
887
  });
757
888
 
758
- it('should generate video preview data', () => {
759
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
760
-
761
- act(() => {
762
- result.current.setUpdateMpushVideoSrc(0, {
763
- videoSrc: 'test-video.mp4',
764
- previewUrl: 'test-preview.jpg',
765
- videoDuration: 120,
766
- });
767
- });
889
+ const androidPayload = result.current.getMediaPayload(VIDEO, ANDROID);
890
+ expect(androidPayload.videoUrl).toBe('cdn/MOBILEPUSH/test-video.mp4');
891
+ expect(androidPayload.videoPreviewImg).toBe('cdn/MOBILEPUSH/test-preview.jpg');
892
+ expect(androidPayload.duration).toBe(30);
893
+ });
768
894
 
769
- const previewData = result.current.getPreviewData(VIDEO, ANDROID);
895
+ it('should get correct video properties for iOS', () => {
896
+ const { result } = createHook({ activeTab: IOS });
770
897
 
771
- expect(previewData).toEqual({
772
- videoSrc: 'test-video.mp4',
773
- videoPreviewImg: 'test-preview.jpg',
774
- duration: 120,
898
+ // Test iOS video properties
899
+ act(() => {
900
+ result.current.setVideoState({
901
+ androidVideoSrc: 'test-video.mp4',
902
+ androidVideoPreview: 'test-preview.jpg',
903
+ androidVideoDuration: 30,
904
+ iosVideoSrc: 'test-video-ios.mp4',
905
+ iosVideoPreview: 'test-preview-ios.jpg',
906
+ iosVideoDuration: 25,
775
907
  });
776
908
  });
777
909
 
778
- it('should generate GIF preview data', () => {
779
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
780
-
781
- act(() => {
782
- result.current.setUpdateMpushVideoSrc(0, {
783
- videoSrc: 'test-gif.gif',
784
- previewUrl: 'test-preview.jpg',
785
- });
786
- });
910
+ const iosPayload = result.current.getMediaPayload(VIDEO, IOS);
911
+ expect(iosPayload.videoUrl).toBe('cdn/MOBILEPUSH/test-video-ios.mp4');
912
+ expect(iosPayload.videoPreviewImg).toBe('cdn/MOBILEPUSH/test-preview-ios.jpg');
913
+ expect(iosPayload.duration).toBe(25);
914
+ });
787
915
 
788
- const previewData = result.current.getPreviewData(GIF, ANDROID);
916
+ it('should handle image re-upload for iOS', () => {
917
+ const { result } = createHook({ sameContent: false, activeTab: IOS });
789
918
 
790
- expect(previewData).toEqual({
791
- gifSrc: 'test-gif.gif',
792
- gifPreviewImg: 'test-preview.jpg',
919
+ // Set initial state
920
+ act(() => {
921
+ result.current.setImageSrc({
922
+ androidImageSrc: 'test-image.jpg',
923
+ iosImageSrc: 'test-image-ios.jpg',
793
924
  });
794
925
  });
795
926
 
796
- it('should generate image preview data for iOS platform', () => {
797
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
798
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
799
-
800
- act(() => {
801
- result.current.setUpdateMpushImageSrc('test-ios-image.jpg', 1, IMAGE);
802
- });
803
-
804
- const previewData = result.current.getPreviewData(IMAGE, 'IOS');
805
-
806
- expect(previewData).toEqual({
807
- imageSrc: 'test-ios-image.jpg',
808
- });
927
+ // Re-upload image
928
+ act(() => {
929
+ result.current.updateOnMpushImageReUpload();
809
930
  });
810
931
 
811
- it('should generate video preview data for iOS platform', () => {
812
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
813
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
814
-
815
- act(() => {
816
- result.current.setUpdateMpushVideoSrc(1, {
817
- videoSrc: 'test-ios-video.mp4',
818
- previewUrl: 'test-ios-preview.jpg',
819
- videoDuration: 90,
820
- });
821
- });
822
-
823
- const previewData = result.current.getPreviewData(VIDEO, 'IOS');
824
-
825
- expect(previewData).toEqual({
826
- videoSrc: 'test-ios-video.mp4',
827
- videoPreviewImg: 'test-ios-preview.jpg',
828
- duration: 90,
829
- });
932
+ // Verify only iOS is cleared
933
+ expect(result.current.imageSrc).toEqual({
934
+ androidImageSrc: 'test-image.jpg',
935
+ iosImageSrc: '',
830
936
  });
937
+ });
831
938
 
832
- it('should generate GIF preview data for iOS platform', () => {
833
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
834
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
939
+ it('should handle video re-upload for iOS', () => {
940
+ const { result } = createHook({ sameContent: false, activeTab: IOS });
835
941
 
836
- act(() => {
837
- result.current.setUpdateMpushVideoSrc(1, {
838
- videoSrc: 'test-ios-gif.gif',
839
- previewUrl: 'test-ios-preview.jpg',
840
- });
942
+ // Set initial state
943
+ act(() => {
944
+ result.current.setVideoState({
945
+ androidVideoSrc: 'test-video.mp4',
946
+ androidVideoPreview: 'test-preview.jpg',
947
+ androidVideoDuration: 30,
948
+ iosVideoSrc: 'test-video-ios.mp4',
949
+ iosVideoPreview: 'test-preview-ios.jpg',
950
+ iosVideoDuration: 25,
841
951
  });
952
+ });
842
953
 
843
- const previewData = result.current.getPreviewData(GIF, 'IOS');
954
+ // Re-upload video
955
+ act(() => {
956
+ result.current.updateOnMpushVideoReUpload();
957
+ });
844
958
 
845
- expect(previewData).toEqual({
846
- gifSrc: 'test-ios-gif.gif',
847
- gifPreviewImg: 'test-ios-preview.jpg',
848
- });
959
+ // Verify only iOS states are cleared
960
+ expect(result.current.videoState).toEqual({
961
+ androidVideoSrc: 'test-video.mp4',
962
+ androidVideoPreview: 'test-preview.jpg',
963
+ androidVideoDuration: 30,
964
+ iosVideoSrc: '',
965
+ iosVideoPreview: '',
966
+ iosVideoDuration: 0,
849
967
  });
968
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(1);
969
+ expect(mockMobilePushActions.clearAsset).not.toHaveBeenCalledWith(0);
850
970
  });
851
- });
852
-
853
- describe('Media Upload Validation', () => {
854
- describe('isMediaUploaded', () => {
855
- it('should return true for uploaded image', () => {
856
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
857
971
 
858
- act(() => {
859
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0, IMAGE);
860
- });
972
+ it('should handle carousel image source update for iOS', () => {
973
+ const { result } = createHook({ sameContent: false, activeTab: IOS });
861
974
 
862
- expect(result.current.isMediaUploaded(IMAGE, ANDROID)).toBe(true);
975
+ // Update carousel image source for iOS
976
+ act(() => {
977
+ result.current.setUpdateMpushImageSrc('test-image-ios.jpg', 1, CAROUSEL);
863
978
  });
864
979
 
865
- it('should return false for non-uploaded image', () => {
866
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
867
-
868
- expect(result.current.isMediaUploaded(IMAGE, ANDROID)).toBe(false);
980
+ // Verify only iOS is updated and clearAsset is not called
981
+ expect(result.current.imageSrc).toEqual({
982
+ androidImageSrc: '',
983
+ iosImageSrc: 'test-image-ios.jpg',
869
984
  });
985
+ expect(mockMobilePushActions.clearAsset).not.toHaveBeenCalled();
986
+ });
870
987
 
871
- it('should return true for uploaded video', () => {
872
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
873
-
874
- act(() => {
875
- result.current.setUpdateMpushVideoSrc(0, {
876
- videoSrc: 'test-video.mp4',
877
- });
878
- });
988
+ it('should handle empty file paths', () => {
989
+ const { result } = createHook();
879
990
 
880
- expect(result.current.isMediaUploaded(VIDEO, ANDROID)).toBe(true);
881
- expect(result.current.isMediaUploaded(GIF, ANDROID)).toBe(true);
882
- });
991
+ // Test empty image URL
992
+ expect(result.current.getCdnImageUrl('')).toBe('');
883
993
 
884
- it('should return true for text media types', () => {
885
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
994
+ // Test empty video URL
995
+ expect(result.current.getCdnVideoUrl('')).toBe('');
886
996
 
887
- expect(result.current.isMediaUploaded('TEXT', ANDROID)).toBe(true);
888
- expect(result.current.isMediaUploaded('NONE', ANDROID)).toBe(true);
997
+ // Test empty image source update
998
+ act(() => {
999
+ result.current.setUpdateMpushImageSrc('', 0);
889
1000
  });
1001
+ expect(result.current.imageSrc).toEqual({
1002
+ androidImageSrc: '',
1003
+ iosImageSrc: '',
1004
+ });
1005
+
1006
+ // Test empty video source update
1007
+ act(() => {
1008
+ result.current.setUpdateMpushVideoSrc(0, {
1009
+ videoSrc: '',
1010
+ previewUrl: '',
1011
+ videoDuration: 0,
1012
+ });
1013
+ });
1014
+ expect(result.current.videoState).toEqual({
1015
+ androidVideoSrc: '',
1016
+ androidVideoPreview: '',
1017
+ androidVideoDuration: 0,
1018
+ iosVideoSrc: '',
1019
+ iosVideoPreview: '',
1020
+ iosVideoDuration: 0,
1021
+ });
1022
+ });
890
1023
 
891
- it('should return true for uploaded image on iOS platform', () => {
892
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
893
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
1024
+ it('should handle missing video preview and duration in source update', () => {
1025
+ const { result } = createHook();
894
1026
 
895
- act(() => {
896
- result.current.setUpdateMpushImageSrc('test-ios-image.jpg', IMAGE);
1027
+ // Update video source without preview and duration
1028
+ act(() => {
1029
+ result.current.setUpdateMpushVideoSrc(0, {
1030
+ videoSrc: 'test-video.mp4',
897
1031
  });
898
-
899
- expect(result.current.isMediaUploaded(IMAGE, 'IOS')).toBe(true);
900
1032
  });
901
1033
 
902
- it('should return false for non-uploaded image on iOS platform', () => {
903
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
904
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
905
-
906
- expect(result.current.isMediaUploaded(IMAGE, 'IOS')).toBe(false);
1034
+ // Verify default values are used
1035
+ expect(result.current.videoState).toEqual({
1036
+ androidVideoSrc: 'test-video.mp4',
1037
+ androidVideoPreview: '',
1038
+ androidVideoDuration: 0,
1039
+ iosVideoSrc: '',
1040
+ iosVideoPreview: '',
1041
+ iosVideoDuration: 0,
1042
+ });
1043
+ expect(result.current.mpushVideoSrcAndPreview).toEqual({
1044
+ mpushVideoSrc: 'test-video.mp4',
1045
+ mpushVideoPreviewImg: '',
1046
+ duration: 0,
907
1047
  });
1048
+ });
908
1049
 
909
- it('should return true for uploaded video on iOS platform', () => {
910
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
911
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
1050
+ it('should handle missing file name and handle in source update', () => {
1051
+ const { result } = createHook();
912
1052
 
913
- act(() => {
914
- result.current.setUpdateMpushVideoSrc(1, {
915
- videoSrc: 'test-ios-video.mp4',
916
- });
917
- });
1053
+ const videoData = {
1054
+ videoSrc: 'test-video.mp4',
1055
+ previewUrl: 'test-preview.jpg',
1056
+ videoDuration: 30,
1057
+ videoName: '',
1058
+ fileHandle: '',
1059
+ };
918
1060
 
919
- expect(result.current.isMediaUploaded(VIDEO, 'IOS')).toBe(true);
920
- expect(result.current.isMediaUploaded(GIF, 'IOS')).toBe(true);
1061
+ // Update video source without file name and handle
1062
+ act(() => {
1063
+ result.current.setUpdateMpushVideoSrc(0, videoData);
921
1064
  });
922
1065
 
923
- it('should return true for text media types on iOS platform', () => {
924
- const iosProps = { ...defaultProps, activeTab: 'IOS' };
925
- const { result } = renderHook(() => useUpload(...Object.values(iosProps)));
926
-
927
- expect(result.current.isMediaUploaded('TEXT', 'IOS')).toBe(true);
928
- expect(result.current.isMediaUploaded('NONE', 'IOS')).toBe(true);
1066
+ // Verify asset data is still updated
1067
+ expect(result.current.androidAssetList).toEqual({
1068
+ ...videoData,
929
1069
  });
930
1070
  });
931
1071
  });
932
1072
 
933
- describe('Utility Functions', () => {
934
- describe('clearImageDataByMediaType', () => {
935
- it('should clear image data for IMAGE media type', () => {
936
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
937
-
938
- // Set initial image on both platforms
939
- act(() => {
940
- result.current.setImageSrc({
941
- androidImageSrc: 'test-android.jpg',
942
- iosImageSrc: 'test-ios.jpg',
943
- });
944
- });
1073
+ describe('Clear Media Data', () => {
1074
+ beforeEach(() => {
1075
+ jest.clearAllMocks();
1076
+ });
945
1077
 
946
- // Clear image data (should only clear Android since activeTab is ANDROID and sameContent is false)
947
- act(() => {
948
- result.current.clearImageDataByMediaType(IMAGE);
949
- });
1078
+ it('should clear image data with sync enabled', () => {
1079
+ const { result } = createHook({ sameContent: true });
950
1080
 
951
- expect(result.current.imageSrc).toEqual({
952
- androidImageSrc: '',
953
- iosImageSrc: 'test-ios.jpg', // iOS should remain unchanged
1081
+ // Set initial state
1082
+ act(() => {
1083
+ result.current.setImageSrc({
1084
+ androidImageSrc: 'test-image.jpg',
1085
+ iosImageSrc: 'test-image.jpg',
954
1086
  });
955
1087
  });
956
1088
 
957
- it('should not clear data for non-IMAGE media types', () => {
958
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
959
-
960
- // Set initial image
961
- act(() => {
962
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0, IMAGE);
963
- });
964
-
965
- // Try to clear with different media type
966
- act(() => {
967
- result.current.clearImageDataByMediaType(VIDEO);
968
- });
1089
+ // Clear image data
1090
+ act(() => {
1091
+ result.current.clearImageDataByMediaType(IMAGE);
1092
+ });
969
1093
 
970
- expect(result.current.imageSrc.androidImageSrc).toBe('test-image.jpg');
1094
+ // Verify both platforms are cleared
1095
+ expect(result.current.imageSrc).toEqual({
1096
+ androidImageSrc: '',
1097
+ iosImageSrc: '',
971
1098
  });
972
1099
  });
973
1100
 
974
- describe('resetUploadStates', () => {
975
- it('should reset all upload states', () => {
976
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
977
-
978
- // Set some data
979
- act(() => {
980
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0, IMAGE);
981
- result.current.setUpdateMpushVideoSrc(0, {
982
- videoSrc: 'test-video.mp4',
983
- previewUrl: 'test-preview.jpg',
984
- });
985
- });
986
-
987
- // Reset all states
988
- act(() => {
989
- result.current.resetUploadStates();
990
- });
1101
+ it('should clear image data with sync disabled', () => {
1102
+ const { result } = createHook({ sameContent: false, activeTab: ANDROID });
991
1103
 
992
- expect(result.current.imageSrc).toEqual({
993
- androidImageSrc: '',
994
- iosImageSrc: '',
995
- });
996
- expect(result.current.mpushVideoSrcAndPreview).toEqual({
997
- mpushVideoSrc: '',
998
- mpushVideoPreviewImg: '',
999
- duration: 0,
1104
+ // Set initial state
1105
+ act(() => {
1106
+ result.current.setImageSrc({
1107
+ androidImageSrc: 'test-image.jpg',
1108
+ iosImageSrc: 'test-image-ios.jpg',
1000
1109
  });
1001
- expect(result.current.assetList).toEqual([]);
1002
1110
  });
1003
- });
1004
1111
 
1005
- describe('CDN URL functions', () => {
1006
- it('should generate CDN image URL', () => {
1007
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1008
-
1009
- const cdnUrl = result.current.getCdnImageUrl('test-image.jpg');
1010
-
1011
- expect(cdnUrl).toBe('cdn_test-image.jpg');
1012
- expect(getCdnUrl).toHaveBeenCalledWith({
1013
- url: 'test-image.jpg',
1014
- channelName: MOBILE_PUSH_CHANNEL,
1015
- });
1112
+ // Clear image data
1113
+ act(() => {
1114
+ result.current.clearImageDataByMediaType(IMAGE);
1016
1115
  });
1017
1116
 
1018
- it('should return empty string for empty image URL', () => {
1019
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1117
+ // Verify only Android is cleared
1118
+ expect(result.current.imageSrc).toEqual({
1119
+ androidImageSrc: '',
1120
+ iosImageSrc: 'test-image-ios.jpg',
1121
+ });
1122
+ });
1020
1123
 
1021
- const cdnUrl = result.current.getCdnImageUrl('');
1124
+ it('should clear video data with sync enabled', () => {
1125
+ const { result } = createHook({ sameContent: true });
1022
1126
 
1023
- expect(cdnUrl).toBe('');
1127
+ // Set initial state
1128
+ act(() => {
1129
+ result.current.setVideoState({
1130
+ androidVideoSrc: 'test-video.mp4',
1131
+ androidVideoPreview: 'test-preview.jpg',
1132
+ androidVideoDuration: 30,
1133
+ iosVideoSrc: 'test-video.mp4',
1134
+ iosVideoPreview: 'test-preview.jpg',
1135
+ iosVideoDuration: 30,
1136
+ });
1024
1137
  });
1025
1138
 
1026
- it('should generate CDN video URL', () => {
1027
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1139
+ // Clear video data
1140
+ act(() => {
1141
+ result.current.clearImageDataByMediaType(VIDEO);
1142
+ });
1143
+
1144
+ // Verify both platforms are cleared
1145
+ expect(result.current.videoState).toEqual({
1146
+ androidVideoSrc: '',
1147
+ androidVideoPreview: '',
1148
+ androidVideoDuration: 0,
1149
+ iosVideoSrc: '',
1150
+ iosVideoPreview: '',
1151
+ iosVideoDuration: 0,
1152
+ });
1153
+
1154
+ // Verify content is cleared
1155
+ expect(androidContent).toMatchObject({
1156
+ title: 'Test Android',
1157
+ message: 'Test message',
1158
+ videoSrc: '',
1159
+ videoPreview: '',
1160
+ videoDuration: 0,
1161
+ });
1162
+ expect(iosContent).toMatchObject({
1163
+ title: 'Test iOS',
1164
+ message: 'Test message',
1165
+ videoSrc: '',
1166
+ videoPreview: '',
1167
+ videoDuration: 0,
1168
+ });
1169
+
1170
+ // Verify Redux state is cleared
1171
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
1172
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(1);
1173
+ });
1028
1174
 
1029
- const cdnUrl = result.current.getCdnVideoUrl('test-video.mp4');
1175
+ it('should clear video data with sync disabled', () => {
1176
+ const { result } = createHook({ sameContent: false, activeTab: ANDROID });
1030
1177
 
1031
- expect(cdnUrl).toBe('cdn_test-video.mp4');
1032
- expect(getCdnUrl).toHaveBeenCalledWith({
1033
- url: 'test-video.mp4',
1034
- channelName: MOBILE_PUSH_CHANNEL,
1178
+ // Set initial state
1179
+ act(() => {
1180
+ result.current.setVideoState({
1181
+ androidVideoSrc: 'test-video.mp4',
1182
+ androidVideoPreview: 'test-preview.jpg',
1183
+ androidVideoDuration: 30,
1184
+ iosVideoSrc: 'test-video-ios.mp4',
1185
+ iosVideoPreview: 'test-preview-ios.jpg',
1186
+ iosVideoDuration: 25,
1035
1187
  });
1036
1188
  });
1037
1189
 
1038
- it('should return empty string for empty video URL', () => {
1039
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1190
+ // Clear video data
1191
+ act(() => {
1192
+ result.current.clearImageDataByMediaType(VIDEO);
1193
+ });
1040
1194
 
1041
- const cdnUrl = result.current.getCdnVideoUrl('');
1195
+ // Verify only Android is cleared
1196
+ expect(result.current.videoState).toEqual({
1197
+ androidVideoSrc: '',
1198
+ androidVideoPreview: '',
1199
+ androidVideoDuration: 0,
1200
+ iosVideoSrc: 'test-video-ios.mp4',
1201
+ iosVideoPreview: 'test-preview-ios.jpg',
1202
+ iosVideoDuration: 25,
1203
+ });
1042
1204
 
1043
- expect(cdnUrl).toBe('');
1205
+ // Verify only Android content is cleared
1206
+ expect(androidContent).toMatchObject({
1207
+ title: 'Test Android',
1208
+ message: 'Test message',
1209
+ videoSrc: '',
1210
+ videoPreview: '',
1211
+ videoDuration: 0,
1212
+ });
1213
+ expect(iosContent).toMatchObject({
1214
+ title: 'Test iOS',
1215
+ message: 'Test message',
1044
1216
  });
1217
+
1218
+ // Verify only Android Redux state is cleared
1219
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
1220
+ expect(mockMobilePushActions.clearAsset).not.toHaveBeenCalledWith(1);
1045
1221
  });
1046
- });
1047
1222
 
1048
- describe('useEffect behaviors', () => {
1049
- it('should call setAndroidContent and setIosContent when imageSrc changes', () => {
1050
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1223
+ it('should clear GIF data with sync enabled', () => {
1224
+ const { result } = createHook({ sameContent: true });
1051
1225
 
1226
+ // Set initial state
1052
1227
  act(() => {
1053
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0, IMAGE);
1228
+ result.current.setVideoState({
1229
+ androidVideoSrc: 'test.gif',
1230
+ androidVideoPreview: 'test-preview.jpg',
1231
+ androidVideoDuration: 30,
1232
+ iosVideoSrc: 'test.gif',
1233
+ iosVideoPreview: 'test-preview.jpg',
1234
+ iosVideoDuration: 30,
1235
+ });
1054
1236
  });
1055
1237
 
1056
- expect(mockSetAndroidContent).toHaveBeenCalledWith(expect.any(Function));
1057
- expect(mockSetIosContent).toHaveBeenCalledWith(expect.any(Function));
1238
+ // Clear GIF data
1239
+ act(() => {
1240
+ result.current.clearImageDataByMediaType(GIF);
1241
+ });
1242
+
1243
+ // Verify both platforms are cleared
1244
+ expect(result.current.videoState).toEqual({
1245
+ androidVideoSrc: '',
1246
+ androidVideoPreview: '',
1247
+ androidVideoDuration: 0,
1248
+ iosVideoSrc: '',
1249
+ iosVideoPreview: '',
1250
+ iosVideoDuration: 0,
1251
+ });
1252
+
1253
+ // Verify content is cleared
1254
+ expect(androidContent).toMatchObject({
1255
+ title: 'Test Android',
1256
+ message: 'Test message',
1257
+ videoSrc: '',
1258
+ videoPreview: '',
1259
+ videoDuration: 0,
1260
+ });
1261
+ expect(iosContent).toMatchObject({
1262
+ title: 'Test iOS',
1263
+ message: 'Test message',
1264
+ videoSrc: '',
1265
+ videoPreview: '',
1266
+ videoDuration: 0,
1267
+ });
1268
+
1269
+ // Verify Redux state is cleared
1270
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
1271
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(1);
1058
1272
  });
1059
1273
 
1060
- it('should call setAndroidContent and setIosContent when video src changes', () => {
1061
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1274
+ it('should clear GIF data with sync disabled', () => {
1275
+ const { result } = createHook({ sameContent: false, activeTab: ANDROID });
1062
1276
 
1277
+ // Set initial state
1063
1278
  act(() => {
1064
- result.current.setUpdateMpushVideoSrc(0, {
1065
- videoSrc: 'test-video.mp4',
1066
- previewUrl: 'test-preview.jpg',
1279
+ result.current.setVideoState({
1280
+ androidVideoSrc: 'test.gif',
1281
+ androidVideoPreview: 'test-preview.jpg',
1282
+ androidVideoDuration: 30,
1283
+ iosVideoSrc: 'test-ios.gif',
1284
+ iosVideoPreview: 'test-preview-ios.jpg',
1285
+ iosVideoDuration: 25,
1067
1286
  });
1068
1287
  });
1069
1288
 
1070
- expect(mockSetAndroidContent).toHaveBeenCalledWith(expect.any(Function));
1071
- expect(mockSetIosContent).toHaveBeenCalledWith(expect.any(Function));
1072
- });
1073
- });
1074
-
1075
- describe('Edge Cases', () => {
1076
- it('should handle undefined file in validation functions', () => {
1077
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1078
-
1079
- expect(() => {
1080
- result.current.validateImageFile(undefined);
1081
- }).toThrow();
1082
- });
1289
+ // Clear GIF data
1290
+ act(() => {
1291
+ result.current.clearImageDataByMediaType(GIF);
1292
+ });
1083
1293
 
1084
- it('should handle missing file properties gracefully', () => {
1085
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1294
+ // Verify only Android is cleared
1295
+ expect(result.current.videoState).toEqual({
1296
+ androidVideoSrc: '',
1297
+ androidVideoPreview: '',
1298
+ androidVideoDuration: 0,
1299
+ iosVideoSrc: 'test-ios.gif',
1300
+ iosVideoPreview: 'test-preview-ios.jpg',
1301
+ iosVideoDuration: 25,
1302
+ });
1086
1303
 
1087
- const fileWithoutSize = { name: 'test.jpg' };
1304
+ // Verify only Android content is cleared
1305
+ expect(androidContent).toMatchObject({
1306
+ title: 'Test Android',
1307
+ message: 'Test message',
1308
+ videoSrc: '',
1309
+ videoPreview: '',
1310
+ videoDuration: 0,
1311
+ });
1312
+ expect(iosContent).toMatchObject({
1313
+ title: 'Test iOS',
1314
+ message: 'Test message',
1315
+ });
1088
1316
 
1089
- expect(() => {
1090
- result.current.validateImageFile(fileWithoutSize);
1091
- }).not.toThrow();
1317
+ // Verify only Android Redux state is cleared
1318
+ expect(mockMobilePushActions.clearAsset).toHaveBeenCalledWith(0);
1319
+ expect(mockMobilePushActions.clearAsset).not.toHaveBeenCalledWith(1);
1092
1320
  });
1093
1321
 
1094
- it('should handle empty edit data gracefully', () => {
1095
- const { result } = renderHook(() => useUpload(
1096
- mockMobilePushActions,
1097
- { templateDetails: null },
1098
- {},
1099
- {},
1100
- false,
1101
- false,
1102
- mockSetAndroidContent,
1103
- mockSetIosContent,
1104
- ANDROID,
1105
- defaultProps.androidContent,
1106
- defaultProps.iosContent
1107
- ));
1322
+ it('should do nothing for unknown media type', () => {
1323
+ const { result } = createHook({ sameContent: true });
1108
1324
 
1109
- expect(result.current.imageSrc).toEqual({
1110
- androidImageSrc: '',
1111
- iosImageSrc: '',
1325
+ // Set initial state
1326
+ act(() => {
1327
+ result.current.setImageSrc({
1328
+ androidImageSrc: 'test-image.jpg',
1329
+ iosImageSrc: 'test-image.jpg',
1330
+ });
1331
+ result.current.setVideoState({
1332
+ androidVideoSrc: 'test-video.mp4',
1333
+ androidVideoPreview: 'test-preview.jpg',
1334
+ androidVideoDuration: 30,
1335
+ iosVideoSrc: 'test-video.mp4',
1336
+ iosVideoPreview: 'test-preview.jpg',
1337
+ iosVideoDuration: 30,
1338
+ });
1112
1339
  });
1113
- });
1114
-
1115
- it('should handle malformed edit data structure', () => {
1116
- const malformedEditData = {
1117
- templateDetails: {
1118
- versions: {
1119
- base: {
1120
- content: null,
1121
- },
1122
- },
1123
- },
1124
- };
1125
1340
 
1126
- const { result } = renderHook(() => useUpload(
1127
- mockMobilePushActions,
1128
- malformedEditData,
1129
- {},
1130
- {},
1131
- false,
1132
- false,
1133
- mockSetAndroidContent,
1134
- mockSetIosContent,
1135
- ANDROID,
1136
- defaultProps.androidContent,
1137
- defaultProps.iosContent
1138
- ));
1341
+ // Clear unknown media type
1342
+ act(() => {
1343
+ result.current.clearImageDataByMediaType('UNKNOWN');
1344
+ });
1139
1345
 
1346
+ // Verify nothing is cleared
1140
1347
  expect(result.current.imageSrc).toEqual({
1141
- androidImageSrc: '',
1142
- iosImageSrc: '',
1143
- });
1348
+ androidImageSrc: 'test-image.jpg',
1349
+ iosImageSrc: 'test-image.jpg',
1350
+ });
1351
+ expect(result.current.videoState).toEqual({
1352
+ androidVideoSrc: 'test-video.mp4',
1353
+ androidVideoPreview: 'test-preview.jpg',
1354
+ androidVideoDuration: 30,
1355
+ iosVideoSrc: 'test-video.mp4',
1356
+ iosVideoPreview: 'test-preview.jpg',
1357
+ iosVideoDuration: 30,
1358
+ });
1359
+ expect(androidContent).toMatchObject({
1360
+ title: 'Test Android',
1361
+ message: 'Test message',
1362
+ });
1363
+ expect(iosContent).toMatchObject({
1364
+ title: 'Test iOS',
1365
+ message: 'Test message',
1366
+ });
1367
+ expect(mockMobilePushActions.clearAsset).not.toHaveBeenCalled();
1144
1368
  });
1145
1369
  });
1146
1370
 
1147
- describe('Additional Edge Cases for Complete Coverage', () => {
1148
- it('should handle setUpdateMpushVideoSrc with minimal data', () => {
1149
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1371
+ describe('Image Source Updates', () => {
1372
+ it('should update content when imageSrc changes with sync enabled', () => {
1373
+ const { result } = createHook({ sameContent: true });
1150
1374
 
1151
- // Test with minimal data object
1375
+ // Set image source
1152
1376
  act(() => {
1153
- result.current.setUpdateMpushVideoSrc(0, {
1154
- videoSrc: 'test.mp4',
1377
+ result.current.setImageSrc({
1378
+ androidImageSrc: 'test-image.jpg',
1379
+ iosImageSrc: '',
1155
1380
  });
1156
1381
  });
1157
1382
 
1158
- expect(result.current.mpushVideoSrcAndPreview.mpushVideoSrc).toBe('test.mp4');
1159
- expect(result.current.mpushVideoSrcAndPreview.mpushVideoPreviewImg).toBe('');
1160
- expect(result.current.mpushVideoSrcAndPreview.duration).toBe(0);
1161
- });
1162
-
1163
- it('should handle setUpdateMpushVideoSrc with extra data spread', () => {
1164
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1165
-
1166
- const extraData = {
1167
- videoSrc: 'test.mp4',
1168
- previewUrl: 'preview.jpg',
1169
- videoDuration: 30,
1170
- extraField: 'extra-value',
1171
- anotherField: 123,
1172
- };
1383
+ // Verify both platforms are updated with Android image
1384
+ expect(androidContent).toMatchObject({
1385
+ title: 'Test Android',
1386
+ message: 'Test message',
1387
+ imageSrc: 'test-image.jpg',
1388
+ });
1389
+ expect(iosContent).toMatchObject({
1390
+ title: 'Test iOS',
1391
+ message: 'Test message',
1392
+ imageSrc: 'test-image.jpg',
1393
+ });
1173
1394
 
1395
+ // Set iOS image source
1174
1396
  act(() => {
1175
- result.current.setUpdateMpushVideoSrc(0, extraData);
1397
+ result.current.setImageSrc({
1398
+ androidImageSrc: '',
1399
+ iosImageSrc: 'test-image-ios.jpg',
1400
+ });
1176
1401
  });
1177
1402
 
1178
- expect(result.current.assetList).toEqual(expect.objectContaining({
1179
- videoSrc: 'test.mp4',
1180
- previewUrl: 'preview.jpg',
1181
- videoDuration: 30,
1182
- extraField: 'extra-value',
1183
- anotherField: 123,
1184
- }));
1403
+ // Verify both platforms are updated with iOS image
1404
+ expect(androidContent).toMatchObject({
1405
+ title: 'Test Android',
1406
+ message: 'Test message',
1407
+ imageSrc: 'test-image-ios.jpg',
1408
+ });
1409
+ expect(iosContent).toMatchObject({
1410
+ title: 'Test iOS',
1411
+ message: 'Test message',
1412
+ imageSrc: 'test-image-ios.jpg',
1413
+ });
1185
1414
  });
1186
1415
 
1187
- it('should handle clearImageDataByMediaType for non-IMAGE types', () => {
1188
- const { result } = renderHook(() => useUpload(...Object.values(defaultProps)));
1416
+ it('should update content when imageSrc changes with sync disabled', () => {
1417
+ const { result } = createHook({ sameContent: false });
1189
1418
 
1190
- // Set some image data first
1419
+ // Set Android image source
1191
1420
  act(() => {
1192
- result.current.setUpdateMpushImageSrc('test-image.jpg', 0, IMAGE);
1421
+ result.current.setImageSrc({
1422
+ androidImageSrc: 'test-image.jpg',
1423
+ iosImageSrc: '',
1424
+ });
1193
1425
  });
1194
1426
 
1195
- expect(result.current.imageSrc.androidImageSrc).toBe('test-image.jpg');
1196
-
1197
- // Clear using CAROUSEL type (should not affect image data)
1198
- act(() => {
1199
- result.current.clearImageDataByMediaType(CAROUSEL);
1427
+ // Verify only Android is updated
1428
+ expect(androidContent).toMatchObject({
1429
+ title: 'Test Android',
1430
+ message: 'Test message',
1431
+ imageSrc: 'test-image.jpg',
1432
+ });
1433
+ expect(iosContent).toMatchObject({
1434
+ title: 'Test iOS',
1435
+ message: 'Test message',
1200
1436
  });
1201
1437
 
1202
- // Image data should remain unchanged for CAROUSEL
1203
- expect(result.current.imageSrc.androidImageSrc).toBe('test-image.jpg');
1204
-
1205
- // Set data for both platforms to test clearing behavior
1438
+ // Set iOS image source
1206
1439
  act(() => {
1207
1440
  result.current.setImageSrc({
1208
- androidImageSrc: 'test-android.jpg',
1209
- iosImageSrc: 'test-ios.jpg',
1441
+ androidImageSrc: 'test-image.jpg',
1442
+ iosImageSrc: 'test-image-ios.jpg',
1210
1443
  });
1211
1444
  });
1212
1445
 
1213
- // Clear using IMAGE type (should clear only Android since activeTab is ANDROID and sameContent is false)
1214
- act(() => {
1215
- result.current.clearImageDataByMediaType(IMAGE);
1446
+ // Verify both platforms have their respective images
1447
+ expect(androidContent).toMatchObject({
1448
+ title: 'Test Android',
1449
+ message: 'Test message',
1450
+ imageSrc: 'test-image.jpg',
1451
+ });
1452
+ expect(iosContent).toMatchObject({
1453
+ title: 'Test iOS',
1454
+ message: 'Test message',
1455
+ imageSrc: 'test-image-ios.jpg',
1216
1456
  });
1217
-
1218
- // Only Android should be cleared when sameContent=false
1219
- expect(result.current.imageSrc.androidImageSrc).toBe('');
1220
- expect(result.current.imageSrc.iosImageSrc).toBe('test-ios.jpg');
1221
1457
  });
1222
1458
  });
1223
1459
  });