@@ -5,9 +5,9 @@ import type { ImageViewerInput } from './useImageViewerStore';
55// real (native-backed) package out of the test.
66jest . mock ( '@polycentric/react-native' , ( ) => ( { v2 : { } } ) ) ;
77
8- type BlobUrl = Parameters < typeof resolveImageSources > [ 1 ] ;
8+ type BlobUrls = Parameters < typeof resolveImageSources > [ 1 ] ;
99
10- // Fake ImageSet variants use string digests so blobUrl results are easy
10+ // Fake ImageSet variants use string digests so blobUrls results are easy
1111// to assert against.
1212const variant = ( width : number , height : number , digest ?: string ) => ( {
1313 width,
@@ -19,17 +19,21 @@ const imageSet = (
1919 ...variants : ReturnType < typeof variant > [ ]
2020) : ImageViewerInput => ( { images : variants } ) as unknown as ImageViewerInput ;
2121
22- const blobUrl : BlobUrl = ( digest ) => `blob://${ digest } ` ;
22+ const blobUrls : BlobUrls = ( digest ) => [ `blob://${ digest } ` ] ;
2323
2424describe ( 'resolveImageSources' , ( ) => {
25- it ( 'passes plain-uri sources through unchanged ' , ( ) => {
25+ it ( 'wraps plain-uri sources in a single-candidate list ' , ( ) => {
2626 const plain = { uri : 'https://example.com/identicon.png' } ;
27- expect ( resolveImageSources ( [ plain ] , blobUrl ) ) . toEqual ( [ plain ] ) ;
27+ expect ( resolveImageSources ( [ plain ] , blobUrls ) ) . toEqual ( [
28+ { uris : [ 'https://example.com/identicon.png' ] , aspectRatio : undefined } ,
29+ ] ) ;
2830 } ) ;
2931
3032 it ( 'keeps an explicit aspect ratio on plain sources' , ( ) => {
3133 const plain = { uri : 'https://example.com/banner.png' , aspectRatio : 3 } ;
32- expect ( resolveImageSources ( [ plain ] , blobUrl ) ) . toEqual ( [ plain ] ) ;
34+ expect ( resolveImageSources ( [ plain ] , blobUrls ) ) . toEqual ( [
35+ { uris : [ 'https://example.com/banner.png' ] , aspectRatio : 3 } ,
36+ ] ) ;
3337 } ) ;
3438
3539 it ( 'resolves an ImageSet to the smallest variant at or above the target' , ( ) => {
@@ -38,38 +42,46 @@ describe('resolveImageSources', () => {
3842 variant ( VIEWER_TARGET , 1024 , 'fit' ) ,
3943 variant ( 4096 , 2048 , 'huge' ) ,
4044 ) ;
41- expect ( resolveImageSources ( [ set ] , blobUrl ) ) . toEqual ( [
42- { uri : 'blob://fit' , aspectRatio : 2 } ,
45+ expect ( resolveImageSources ( [ set ] , blobUrls ) ) . toEqual ( [
46+ { uris : [ 'blob://fit' ] , aspectRatio : 2 } ,
4347 ] ) ;
4448 } ) ;
4549
4650 it ( 'falls back to the largest variant when none reach the target' , ( ) => {
4751 const set = imageSet ( variant ( 512 , 512 , 'small' ) , variant ( 1024 , 512 , 'big' ) ) ;
48- expect ( resolveImageSources ( [ set ] , blobUrl ) ) . toEqual ( [
49- { uri : 'blob://big' , aspectRatio : 2 } ,
52+ expect ( resolveImageSources ( [ set ] , blobUrls ) ) . toEqual ( [
53+ { uris : [ 'blob://big' ] , aspectRatio : 2 } ,
54+ ] ) ;
55+ } ) ;
56+
57+ it ( 'keeps one candidate uri per server' , ( ) => {
58+ const set = imageSet ( variant ( 2048 , 1024 , 'x' ) ) ;
59+ const multi : BlobUrls = ( digest ) => [ `a://${ digest } ` , `b://${ digest } ` ] ;
60+ expect ( resolveImageSources ( [ set ] , multi ) ) . toEqual ( [
61+ { uris : [ 'a://x' , 'b://x' ] , aspectRatio : 2 } ,
5062 ] ) ;
5163 } ) ;
5264
5365 it ( 'defaults zero dimensions instead of dividing by zero' , ( ) => {
5466 const set = imageSet ( variant ( 0 , 0 , 'broken' ) ) ;
55- expect ( resolveImageSources ( [ set ] , blobUrl ) ) . toEqual ( [
56- { uri : 'blob://broken' , aspectRatio : 1 } ,
67+ expect ( resolveImageSources ( [ set ] , blobUrls ) ) . toEqual ( [
68+ { uris : [ 'blob://broken' ] , aspectRatio : 1 } ,
5769 ] ) ;
5870 } ) ;
5971
6072 it ( 'drops a set whose chosen variant has no digest' , ( ) => {
6173 expect (
62- resolveImageSources ( [ imageSet ( variant ( 2048 , 1024 ) ) ] , blobUrl ) ,
74+ resolveImageSources ( [ imageSet ( variant ( 2048 , 1024 ) ) ] , blobUrls ) ,
6375 ) . toEqual ( [ ] ) ;
6476 } ) ;
6577
66- it ( 'drops a set when the blob CDN is not known yet ' , ( ) => {
78+ it ( 'drops a set when no server can serve it ' , ( ) => {
6779 const set = imageSet ( variant ( 2048 , 1024 , 'x' ) ) ;
68- expect ( resolveImageSources ( [ set ] , ( ) => null ) ) . toEqual ( [ ] ) ;
80+ expect ( resolveImageSources ( [ set ] , ( ) => [ ] ) ) . toEqual ( [ ] ) ;
6981 } ) ;
7082
7183 it ( 'drops empty image sets' , ( ) => {
72- expect ( resolveImageSources ( [ imageSet ( ) ] , blobUrl ) ) . toEqual ( [ ] ) ;
84+ expect ( resolveImageSources ( [ imageSet ( ) ] , blobUrls ) ) . toEqual ( [ ] ) ;
7385 } ) ;
7486
7587 it ( 'preserves order across mixed inputs and skips unresolvable ones' , ( ) => {
@@ -80,9 +92,9 @@ describe('resolveImageSources', () => {
8092 imageSet ( ) , // unresolvable
8193 { uri : 'plain://third' , aspectRatio : 0.5 } ,
8294 ] ,
83- blobUrl ,
95+ blobUrls ,
8496 ) ;
85- expect ( sources . map ( ( s ) => s . uri ) ) . toEqual ( [
97+ expect ( sources . map ( ( s ) => s . uris [ 0 ] ) ) . toEqual ( [
8698 'plain://first' ,
8799 'blob://second' ,
88100 'plain://third' ,
0 commit comments