import type { IconifyJSON } from '@iconify/types' ; import type { StoredItem } from '../../lib/browser-storage' ; import { loadCache , storeCache , count , config , emptyList , } from '../../lib/browser-storage' ; import { getStorage , iconExists } from '../../lib/storage/storage' ; import { nextPrefix , createCache , reset , cachePrefix , cacheVersion , versionKey , countKey , hour , cacheExpiration , } from './fake_cache' ; describe ( 'Testing saving to localStorage' , ( ) => { const provider = '' ; it ( 'One icon set' , ( ) => { const prefix = nextPrefix ( ) ; const cache = createCache ( ) ; const icon = { prefix : prefix , icons : { foo : { body : '<g></g>' , } , } , } ; const item = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon , } ; reset ( { localStorage : cache , } ) ; const icons = getStorage ( provider , prefix ) ; expect ( iconExists ( icons , 'foo' ) ) . toBe ( false ) ; storeCache ( provider , icon ) ; expect ( iconExists ( icons , 'foo' ) ) . toBe ( false ) ; expect ( config ) . toEqual ( { local : true , session : false , } ) ; expect ( count ) . toEqual ( { local : 1 , session : 0 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; expect ( cache . getItem ( cachePrefix + '0' ) ) . toBe ( JSON . stringify ( item ) ) ; expect ( cache . getItem ( countKey ) ) . toBe ( '1' ) ; expect ( cache . getItem ( versionKey ) ) . toBe ( cacheVersion ) ; } ) ; it ( 'Multiple icon sets' , ( ) => { const prefix = nextPrefix ( ) ; const cache = createCache ( ) ; const icon0 = { prefix : prefix , icons : { foo0 : { body : '<g></g>' , } , } , } ; const item0 = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon0 , } ; const icon1 = { prefix : prefix , icons : { foo : { body : '<g></g>' , } , } , } ; const item1 = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon1 , } ; reset ( { localStorage : cache , } ) ; storeCache ( provider , icon0 ) ; storeCache ( provider , icon1 ) ; expect ( config ) . toEqual ( { local : true , session : false , } ) ; expect ( count ) . toEqual ( { local : 2 , session : 0 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; expect ( cache . getItem ( cachePrefix + '0' ) ) . toBe ( JSON . stringify ( item0 ) ) ; expect ( cache . getItem ( cachePrefix + '1' ) ) . toBe ( JSON . stringify ( item1 ) ) ; expect ( cache . getItem ( countKey ) ) . toBe ( '2' ) ; expect ( cache . getItem ( versionKey ) ) . toBe ( cacheVersion ) ; } ) ; it ( 'Adding icon set on unused spot' , ( ) => { const prefix = nextPrefix ( ) ; const cache = createCache ( ) ; const icon0 = { prefix : prefix , icons : { foo0 : { body : '<g></g>' , } , } , } ; const item0 = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon0 , } ; const icon1 = { prefix : prefix , icons : { foo : { body : '<g></g>' , } , } , } ; const item1 = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon1 , } ; cache . setItem ( versionKey , cacheVersion ) ; cache . setItem ( countKey , '2' ) ; cache . setItem ( cachePrefix + '1' , JSON . stringify ( item1 ) ) ; reset ( { localStorage : cache , } ) ; loadCache ( ) ; expect ( config ) . toEqual ( { local : true , session : false , } ) ; expect ( count ) . toEqual ( { local : 2 , session : 0 , } ) ; expect ( emptyList ) . toEqual ( { local : [ 0 ] , session : [ ] , } ) ; storeCache ( provider , icon0 ) ; expect ( count ) . toEqual ( { local : 2 , session : 0 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; expect ( cache . getItem ( cachePrefix + '0' ) ) . toBe ( JSON . stringify ( item0 ) ) ; expect ( cache . getItem ( cachePrefix + '1' ) ) . toBe ( JSON . stringify ( item1 ) ) ; expect ( cache . getItem ( countKey ) ) . toBe ( '2' ) ; expect ( cache . getItem ( versionKey ) ) . toBe ( cacheVersion ) ; } ) ; it ( 'Adding multiple icon sets to existing data' , ( ) => { const prefix = nextPrefix ( ) ; const cache = createCache ( ) ; const icons = [ ] ; const items = [ ] ; for ( let i = 0 ; i < 12 ; i ++ ) { const icon = { prefix : prefix , icons : { [ 'foo' + i ] : { body : '<g></g>' , } , } , } ; const item = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon , } ; if ( i === 2 || i === 4 ) { item . cached -= cacheExpiration + 1 ; } if ( i === 6 || i === 8 ) { item . cached -= cacheExpiration - 1 ; } icons . push ( icon ) ; items . push ( item ) ; if ( i !== 1 && i !== 5 && i < 9 ) { cache . setItem ( cachePrefix + i , JSON . stringify ( item ) ) ; } } cache . setItem ( versionKey , cacheVersion ) ; cache . setItem ( countKey , '10' ) ; reset ( { sessionStorage : cache , } ) ; loadCache ( ) ; expect ( config ) . toEqual ( { local : false , session : true , } ) ; expect ( count ) . toEqual ( { local : 0 , session : 9 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ 5 , 4 , 2 , 1 ] , } ) ; expect ( cache . getItem ( countKey ) ) . toBe ( '9' ) ; [ 0 , 3 , 6 , 7 , 8 ] . forEach ( ( index ) => { expect ( cache . getItem ( cachePrefix + index ) ) . toBe ( JSON . stringify ( items [ index ] ) ) ; } ) ; [ 2 , 4 , 1 , 5 , 9 , 10 , 11 , 12 , 13 ] . forEach ( ( index ) => { expect ( cache . getItem ( cachePrefix + index ) ) . toBeNull ( ) ; } ) ; storeCache ( provider , icons [ 5 ] ) ; expect ( count ) . toEqual ( { local : 0 , session : 9 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ 4 , 2 , 1 ] , } ) ; expect ( cache . getItem ( countKey ) ) . toBe ( '9' ) ; const list = [ 4 , 2 , 1 ] ; list . slice ( 0 ) . forEach ( ( index ) => { expect ( list . shift ( ) ) . toBe ( index ) ; storeCache ( provider , icons [ index ] ) ; expect ( count ) . toEqual ( { local : 0 , session : 9 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : list , } ) ; expect ( cache . getItem ( countKey ) ) . toBe ( '9' ) ; } ) ; storeCache ( provider , icons [ 10 ] ) ; expect ( count ) . toEqual ( { local : 0 , session : 10 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; expect ( cache . getItem ( countKey ) ) . toBe ( '10' ) ; storeCache ( provider , icons [ 11 ] ) ; expect ( count ) . toEqual ( { local : 0 , session : 11 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; expect ( cache . getItem ( countKey ) ) . toBe ( '11' ) ; } ) ; it ( 'Overwrite outdated data' , ( ) => { const prefix = nextPrefix ( ) ; const cache = createCache ( ) ; cache . setItem ( versionKey , '1.0.6' ) ; cache . setItem ( countKey , '3' ) ; for ( let i = 0 ; i < 3 ; i ++ ) { cache . setItem ( cachePrefix + i , JSON . stringify ( { prefix : prefix , icons : { [ 'foo' + i ] : { body : '<g></g>' , } , } , } ) ) ; } reset ( { localStorage : cache , } ) ; const icons = getStorage ( provider , prefix ) ; expect ( iconExists ( icons , 'foo1' ) ) . toBe ( false ) ; loadCache ( ) ; expect ( config ) . toEqual ( { local : true , session : false , } ) ; expect ( count ) . toEqual ( { local : 0 , session : 0 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; const icon = { prefix : prefix , icons : { foo : { body : '<g></g>' , } , } , } ; const item = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon , } ; storeCache ( provider , icon ) ; expect ( iconExists ( icons , 'foo' ) ) . toBe ( false ) ; expect ( config ) . toEqual ( { local : true , session : false , } ) ; expect ( count ) . toEqual ( { local : 1 , session : 0 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; expect ( cache . getItem ( cachePrefix + '0' ) ) . toBe ( JSON . stringify ( item ) ) ; expect ( cache . getItem ( countKey ) ) . toBe ( '1' ) ; expect ( cache . getItem ( versionKey ) ) . toBe ( cacheVersion ) ; } ) ; it ( 'Using both storage options' , ( ) => { const prefix = nextPrefix ( ) ; const cache1 = createCache ( ) ; const cache2 = createCache ( ) ; cache1 . setItem ( versionKey , cacheVersion ) ; cache1 . setItem ( countKey , '3' ) ; [ 0 , 1 , 2 ] . forEach ( ( index ) => { const icon = { prefix : prefix , icons : { [ 'foo' + index ] : { body : '<g></g>' , } , } , } ; const item = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon , } ; cache1 . setItem ( cachePrefix + index , JSON . stringify ( item ) ) ; } ) ; cache2 . setItem ( versionKey , cacheVersion ) ; cache2 . setItem ( countKey , '4' ) ; [ 0 , 1 , 2 , 3 ] . forEach ( ( index ) => { const icon = { prefix : prefix , icons : { [ 'bar' + index ] : { body : '<g></g>' , } , } , } ; const item = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon , } ; cache2 . setItem ( cachePrefix + index , JSON . stringify ( item ) ) ; } ) ; reset ( { localStorage : cache1 , sessionStorage : cache2 , } ) ; loadCache ( ) ; expect ( config ) . toEqual ( { local : true , session : true , } ) ; expect ( count ) . toEqual ( { local : 3 , session : 4 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; const iconsStorage = getStorage ( provider , prefix ) ; for ( let i = 0 ; i < count . local ; i ++ ) { expect ( iconExists ( iconsStorage , 'foo' + i ) ) . toBe ( true ) ; } for ( let i = 0 ; i < count . session ; i ++ ) { expect ( iconExists ( iconsStorage , 'bar' + i ) ) . toBe ( true ) ; } const icon = { prefix : prefix , icons : { 'new-icon' : { body : '<g></g>' , } , } , } ; const item = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon , } ; storeCache ( provider , icon ) ; expect ( count ) . toEqual ( { local : 4 , session : 4 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; expect ( cache1 . getItem ( cachePrefix + '3' ) ) . toBe ( JSON . stringify ( item ) ) ; } ) ; it ( 'Using both storage options, but localStorage is read only' , ( ) => { const prefix = nextPrefix ( ) ; const cache1 = createCache ( ) ; const cache2 = createCache ( ) ; cache1 . setItem ( versionKey , cacheVersion ) ; cache1 . setItem ( countKey , '3' ) ; [ 0 , 1 , 2 ] . forEach ( ( index ) => { const icon = { prefix : prefix , icons : { [ 'foo' + index ] : { body : '<g></g>' , } , } , } ; const item = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon , } ; cache1 . setItem ( cachePrefix + index , JSON . stringify ( item ) ) ; } ) ; cache2 . setItem ( versionKey , cacheVersion ) ; cache2 . setItem ( countKey , '4' ) ; [ 0 , 1 , 2 , 3 ] . forEach ( ( index ) => { const icon = { prefix : prefix , icons : { [ 'bar' + index ] : { body : '<g></g>' , } , } , } ; const item = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon , } ; cache2 . setItem ( cachePrefix + index , JSON . stringify ( item ) ) ; } ) ; reset ( { localStorage : cache1 , sessionStorage : cache2 , } ) ; loadCache ( ) ; expect ( config ) . toEqual ( { local : true , session : true , } ) ; expect ( count ) . toEqual ( { local : 3 , session : 4 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; const iconsStorage = getStorage ( provider , prefix ) ; for ( let i = 0 ; i < count . local ; i ++ ) { expect ( iconExists ( iconsStorage , 'foo' + i ) ) . toBe ( true ) ; } for ( let i = 0 ; i < count . session ; i ++ ) { expect ( iconExists ( iconsStorage , 'bar' + i ) ) . toBe ( true ) ; } cache1 . canWrite = false ; const icon = { prefix : prefix , icons : { 'new-icon' : { body : '<g></g>' , } , } , } ; const item = { cached : Math . floor ( Date . now ( ) / hour ) , provider , data : icon , } ; storeCache ( provider , icon ) ; expect ( count ) . toEqual ( { local : 3 , session : 5 , } ) ; expect ( emptyList ) . toEqual ( { local : [ ] , session : [ ] , } ) ; expect ( cache2 . getItem ( cachePrefix + '4' ) ) . toBe ( JSON . stringify ( item ) ) ; } ) ; } ) ;