@@ -106,6 +106,22 @@ describe('CacheableImage', function () {
106
106
expect ( MockedRNFS . copyFile ) . toHaveBeenCalled ( )
107
107
} )
108
108
109
+ it ( 'When local file exists but it fails to be copied to the cache.' , async ( ) => {
110
+ MockedRNFS . copyFile . mockRejectedValueOnce ( new Error ( 'Copy failed' ) )
111
+
112
+ const CacheableImage = imageCacheHoc ( Image )
113
+
114
+ const local = '/exists.png'
115
+ const url = 'https://example.com/exists.png'
116
+
117
+ const result = await CacheableImage . cacheLocalFile ( local , url )
118
+
119
+ expect ( result ) . toStrictEqual ( {
120
+ url : 'https://example.com/exists.png' ,
121
+ path : null ,
122
+ } )
123
+ } )
124
+
109
125
it ( 'When local file exists, it should be moved to the cache' , async ( ) => {
110
126
const CacheableImage = imageCacheHoc ( Image )
111
127
@@ -160,6 +176,34 @@ describe('CacheableImage', function () {
160
176
path :
161
177
'file:///base/file/path/react-native-image-cache-hoc/90c1be491d18ff2a7280039e9b65749461a65403.png' ,
162
178
fileName : '90c1be491d18ff2a7280039e9b65749461a65403.png' ,
179
+ md5 : '#md5#' ,
180
+ } )
181
+ done ( )
182
+ } ,
183
+ )
184
+ } )
185
+
186
+ it ( 'When local file and observable exist, it should be notified of changes even if hash fails.' , async ( done ) => {
187
+ MockedRNFS . hash . mockRejectedValueOnce ( new Error ( 'File not found.' ) )
188
+
189
+ FileSystem . cacheObservables [
190
+ '90c1be491d18ff2a7280039e9b65749461a65403.png'
191
+ ] = new ReplaySubject < CacheFileInfo > ( 1 )
192
+
193
+ const CacheableImage = imageCacheHoc ( Image )
194
+
195
+ const local = '/exists.png'
196
+ const url = 'https://example.com/exists.png'
197
+
198
+ await CacheableImage . cacheLocalFile ( local , url )
199
+
200
+ FileSystem . cacheObservables [ '90c1be491d18ff2a7280039e9b65749461a65403.png' ] . subscribe (
201
+ ( value ) => {
202
+ expect ( value ) . toStrictEqual ( {
203
+ path :
204
+ 'file:///base/file/path/react-native-image-cache-hoc/90c1be491d18ff2a7280039e9b65749461a65403.png' ,
205
+ fileName : '90c1be491d18ff2a7280039e9b65749461a65403.png' ,
206
+ md5 : undefined , // Hash failed
163
207
} )
164
208
done ( )
165
209
} ,
@@ -301,22 +345,74 @@ describe('CacheableImage', function () {
301
345
setImmediate ( ( ) => {
302
346
expect ( wrapper . prop ( 'source' ) ) . toStrictEqual ( {
303
347
uri :
304
- 'file:///base/file/path/react-native-image-cache-hoc/d3b74e9fa8248a5805e2dcf17a8577acd28c089b.png' ,
348
+ 'file:///base/file/path/react-native-image-cache-hoc/d3b74e9fa8248a5805e2dcf17a8577acd28c089b.png?#md5# ' ,
305
349
} )
306
350
307
351
wrapper . setProps ( { source : { uri : 'https://example.com/B.jpg' } } )
308
352
309
353
setImmediate ( ( ) => {
310
354
expect ( wrapper . prop ( 'source' ) ) . toStrictEqual ( {
311
355
uri :
312
- 'file:///base/file/path/react-native-image-cache-hoc/a940ee9ea388fcea7628d9a64dfac6a698aa0228.jpg' ,
356
+ 'file:///base/file/path/react-native-image-cache-hoc/a940ee9ea388fcea7628d9a64dfac6a698aa0228.jpg?#md5# ' ,
313
357
} )
314
358
315
359
done ( )
316
360
} )
317
361
} )
318
362
} )
319
363
364
+ it ( 'componentDidUpdate should validate the source prop correctly.' , ( done ) => {
365
+ console . warn = jest . fn ( )
366
+
367
+ const CacheableImage = imageCacheHoc ( Image )
368
+
369
+ const wrapper = shallow ( < CacheableImage { ...mockData . mockCacheableImageProps } /> )
370
+
371
+ setImmediate ( ( ) => {
372
+ expect ( wrapper . prop ( 'source' ) ) . toBeDefined ( )
373
+
374
+ // Update to an invalid uri
375
+ wrapper . setProps ( { source : { uri : './local-file.jpg' } } )
376
+
377
+ setImmediate ( ( ) => {
378
+ expect ( console . warn ) . toHaveBeenNthCalledWith (
379
+ 1 ,
380
+ 'Invalid source prop. <CacheableImage> props.source.uri should be a web accessible url with a valid protocol and host. NOTE: Default valid protocol is https, default valid hosts are *.' ,
381
+ )
382
+
383
+ expect ( wrapper . prop ( 'source' ) ) . toBeUndefined ( )
384
+
385
+ done ( )
386
+ } )
387
+ } )
388
+ } )
389
+
390
+ it ( 'componentDidUpdate should allow file protocol.' , ( done ) => {
391
+ console . warn = jest . fn ( )
392
+
393
+ const CacheableImage = imageCacheHoc ( Image )
394
+
395
+ const wrapper = shallow ( < CacheableImage { ...mockData . mockCacheableImageProps } /> )
396
+
397
+ setImmediate ( ( ) => {
398
+ expect ( wrapper . prop ( 'source' ) ) . toBeDefined ( )
399
+
400
+ // Update to a local file uri
401
+ wrapper . setProps ( { source : { uri : 'file:///local-file.jpg' } } )
402
+
403
+ setImmediate ( ( ) => {
404
+ expect ( console . warn ) . toHaveBeenNthCalledWith (
405
+ 1 ,
406
+ 'Invalid source prop. <CacheableImage> props.source.uri should be a web accessible url with a valid protocol and host. NOTE: Default valid protocol is https, default valid hosts are *.' ,
407
+ )
408
+
409
+ expect ( wrapper . prop ( 'source' ) ) . toHaveProperty ( 'uri' , 'file:///local-file.jpg' )
410
+
411
+ done ( )
412
+ } )
413
+ } )
414
+ } )
415
+
320
416
it ( '#render with valid props does not throw an error.' , ( done ) => {
321
417
const CacheableImage = imageCacheHoc ( Image )
322
418
@@ -325,7 +421,7 @@ describe('CacheableImage', function () {
325
421
setImmediate ( ( ) => {
326
422
expect ( wrapper . prop ( 'source' ) ) . toStrictEqual ( {
327
423
uri :
328
- 'file:///base/file/path/react-native-image-cache-hoc/d3b74e9fa8248a5805e2dcf17a8577acd28c089b.png' ,
424
+ 'file:///base/file/path/react-native-image-cache-hoc/d3b74e9fa8248a5805e2dcf17a8577acd28c089b.png?#md5# ' ,
329
425
} )
330
426
331
427
wrapper . setState ( {
0 commit comments