import type { PendingQueryItem } from '@iconify/api-redundancy' ; import { addAPIProvider } from '../../lib/api/config' ; import type { IconifyAPIIconsQueryParams , IconifyAPIQueryParams , } from '../../lib/api/modules' ; import { setAPIModule } from '../../lib/api/modules' ; import { loadIcons , isPending } from '../../lib/api/icons' ; describe ( 'Testing API loadIcons' , ( ) => { let prefixCounter = 0 ; function nextPrefix ( ) { prefixCounter ++ ; return ( 'api-load-test-' + ( prefixCounter < 10 ? '0' : '' ) + prefixCounter ) ; } it ( 'Loading few icons' , ( done ) => { const provider = nextPrefix ( ) ; const prefix = nextPrefix ( ) ; let asyncCounter = 0 ; addAPIProvider ( provider , { resources : [ 'https://api1.local' , 'https://api2.local' ] , } ) ; const prepareQuery = ( provider , prefix , icons ) : IconifyAPIIconsQueryParams [ ] => { const item = { type : 'icons' , provider , prefix , icons , } ; expect ( asyncCounter ) . toBe ( 1 ) ; asyncCounter ++ ; const expected = { type : 'icons' , provider , prefix , icons : [ 'icon1' , 'icon2' ] , } ; expect ( item ) . toEqual ( expected ) ; return [ item ] ; } ; const sendQuery = ( host , params , item ) : void => { expect ( asyncCounter ) . toBe ( 2 ) ; asyncCounter ++ ; expect ( params . type ) . toBe ( 'icons' ) ; expect ( host ) . toBe ( 'https://api1.local' ) ; const expected = { type : 'icons' , provider , prefix , icons : [ 'icon1' , 'icon2' ] , } ; expect ( params ) . toEqual ( expected ) ; item . done ( { prefix , icons : { icon1 : { body : '<path d="" />' , } , icon2 : { body : '<path d="" />' , } , } , } ) ; expect ( asyncCounter ) . toBe ( 3 ) ; } ; setAPIModule ( provider , { prepare : prepareQuery , send : sendQuery , } ) ; loadIcons ( [ { provider , prefix , name : 'icon1' , } , provider + ':' + prefix + ':icon2' , ] , ( loaded , missing , pending ) => { expect ( asyncCounter ) . toBe ( 3 ) ; asyncCounter ++ ; expect ( loaded ) . toEqual ( [ { provider , prefix , name : 'icon1' , } , { provider , prefix , name : 'icon2' , } , ] ) ; expect ( missing ) . toEqual ( [ ] ) ; expect ( pending ) . toEqual ( [ ] ) ; expect ( isPending ( { provider , prefix , name : 'icon1' , } ) ) . toBe ( false ) ; expect ( isPending ( { provider , prefix , name : 'icon3' } ) ) . toBe ( false ) ; done ( ) ; } ) ; expect ( isPending ( { provider , prefix , name : 'icon1' } ) ) . toBe ( true ) ; expect ( isPending ( { provider , prefix , name : 'icon3' } ) ) . toBe ( false ) ; expect ( asyncCounter ) . toBe ( 0 ) ; asyncCounter ++ ; } ) ; it ( 'Split results' , ( done ) => { const provider = nextPrefix ( ) ; const prefix = nextPrefix ( ) ; addAPIProvider ( provider , { resources : [ 'https://api1.local' , 'https://api2.local' ] , } ) ; const prepareQuery = ( provider , prefix , icons ) : IconifyAPIIconsQueryParams [ ] => { const results = [ ] ; icons . forEach ( ( icon ) => { const item = { type : 'icons' , provider , prefix , icons : [ icon ] , } ; results . push ( item ) ; } ) ; expect ( results . length ) . toBe ( 2 ) ; return results ; } ; let queryCounter = 0 ; const sendQuery = ( host , params , item ) : void => { expect ( host ) . toBe ( 'https://api1.local' ) ; expect ( params . type ) . toBe ( 'icons' ) ; if ( params . type !== 'icons' ) { return ; } queryCounter ++ ; const expected = { type : 'icons' , provider , prefix , icons : [ 'icon' + queryCounter ] , } ; expect ( params ) . toEqual ( expected ) ; const icons = Object . create ( null ) ; params . icons . forEach ( ( icon ) => { icons [ icon ] = { body : '<path d="" />' , } ; } ) ; item . done ( { prefix , icons , provider : nextPrefix ( ) , } ) ; } ; setAPIModule ( provider , { prepare : prepareQuery , send : sendQuery , } ) ; let callbackCalled = false ; loadIcons ( [ provider + ':' + prefix + ':icon1' , provider + ':' + prefix + ':icon2' , ] , ( loaded , missing , pending ) => { expect ( callbackCalled ) . toBe ( false ) ; callbackCalled = true ; expect ( loaded ) . toEqual ( [ { provider , prefix , name : 'icon1' , } , { provider , prefix , name : 'icon2' , } , ] ) ; expect ( missing ) . toEqual ( [ ] ) ; expect ( pending ) . toEqual ( [ ] ) ; done ( ) ; } ) ; } ) ; it ( 'Fail on default host' , ( done ) => { const provider = nextPrefix ( ) ; const prefix = nextPrefix ( ) ; addAPIProvider ( provider , { resources : [ 'https://api1.local' , 'https://api2.local' ] , rotate : 100 , } ) ; const prepareQuery = ( provider , prefix , icons ) : IconifyAPIIconsQueryParams [ ] => { const item = { type : 'icons' , provider , prefix , icons , } ; return [ item ] ; } ; let queryCounter = 0 ; const sendQuery = ( host , params , item ) : void => { queryCounter ++ ; params ; switch ( queryCounter ) { case 1 : expect ( host ) . toBe ( 'https://api1.local' ) ; break ; case 2 : expect ( host ) . toBe ( 'https://api2.local' ) ; item . done ( { prefix , icons : { icon1 : { body : '<path d="" />' , } , icon2 : { body : '<path d="" />' , } , } , } ) ; break ; default : done ( `Unexpected additional call to sendQuery for host ${ host }.` ) ; } } ; setAPIModule ( provider , { prepare : prepareQuery , send : sendQuery , } ) ; let callbackCalled = false ; loadIcons ( [ provider + ':' + prefix + ':icon1' , provider + ':' + prefix + ':icon2' , ] , ( loaded , missing , pending ) => { expect ( callbackCalled ) . toBe ( false ) ; callbackCalled = true ; expect ( loaded ) . toEqual ( [ { provider , prefix , name : 'icon1' , } , { provider , prefix , name : 'icon2' , } , ] ) ; expect ( missing ) . toEqual ( [ ] ) ; expect ( pending ) . toEqual ( [ ] ) ; done ( ) ; } ) ; } ) ; it ( 'Fail on default host, multiple queries' , ( done ) => { const provider = nextPrefix ( ) ; const prefix = nextPrefix ( ) ; addAPIProvider ( provider , { resources : [ 'https://api1.local' , 'https://api2.local' ] , rotate : 100 , } ) ; const prepareQuery = ( provider , prefix , icons ) : IconifyAPIIconsQueryParams [ ] => { const item = { type : 'icons' , provider , prefix , icons , } ; return [ item ] ; } ; let queryCounter = 0 ; const sendQuery = ( host , params , item ) : void => { queryCounter ++ ; expect ( params . type ) . toBe ( 'icons' ) ; if ( params . type !== 'icons' ) { return ; } switch ( queryCounter ) { case 1 : expect ( params . icons ) . toEqual ( [ 'icon1' , 'icon2' ] ) ; expect ( host ) . toBe ( 'https://api1.local' ) ; break ; case 2 : expect ( params . icons ) . toEqual ( [ 'icon1' , 'icon2' ] ) ; expect ( host ) . toBe ( 'https://api2.local' ) ; item . done ( { prefix , icons : { icon1 : { body : '<path d="" />' , } , icon2 : { body : '<path d="" />' , } , } , } ) ; break ; case 3 : expect ( params . icons ) . toEqual ( [ 'icon3' , 'icon4' ] ) ; expect ( host ) . toBe ( 'https://api2.local' ) ; item . done ( { prefix , icons : { icon3 : { body : '<path d="" />' , } , icon4 : { body : '<path d="" />' , } , } , } ) ; break ; default : done ( `Unexpected additional call to sendQuery for host ${ host }.` ) ; } } ; setAPIModule ( provider , { prepare : prepareQuery , send : sendQuery , } ) ; let callbackCalled = false ; loadIcons ( [ provider + ':' + prefix + ':icon1' , provider + ':' + prefix + ':icon2' , ] , ( loaded , missing , pending ) => { expect ( callbackCalled ) . toBe ( false ) ; callbackCalled = true ; expect ( loaded ) . toEqual ( [ { provider , prefix , name : 'icon1' , } , { provider , prefix , name : 'icon2' , } , ] ) ; expect ( missing ) . toEqual ( [ ] ) ; expect ( pending ) . toEqual ( [ ] ) ; setTimeout ( ( ) => { let callbackCalled = false ; loadIcons ( [ provider + ':' + prefix + ':icon3' , provider + ':' + prefix + ':icon4' , ] , ( loaded , missing , pending ) => { expect ( callbackCalled ) . toBe ( false ) ; callbackCalled = true ; expect ( loaded ) . toEqual ( [ { provider , prefix , name : 'icon3' , } , { provider , prefix , name : 'icon4' , } , ] ) ; expect ( missing ) . toEqual ( [ ] ) ; expect ( pending ) . toEqual ( [ ] ) ; done ( ) ; } ) ; } ) ; } ) ; } ) ; it ( 'Fail on default host, multiple queries with different prefixes' , ( done ) => { const provider = nextPrefix ( ) ; const prefix = nextPrefix ( ) ; const prefix2 = nextPrefix ( ) ; addAPIProvider ( provider , { resources : [ 'https://api1.local' , 'https://api2.local' ] , rotate : 100 , } ) ; const prepareQuery = ( provider , prefix , icons ) : IconifyAPIIconsQueryParams [ ] => { const item = { type : 'icons' , provider , prefix , icons , } ; return [ item ] ; } ; let queryCounter = 0 ; const sendQuery = ( host , params , item ) : void => { queryCounter ++ ; expect ( params . type ) . toBe ( 'icons' ) ; if ( params . type !== 'icons' ) { return ; } switch ( queryCounter ) { case 1 : expect ( params . prefix ) . toBe ( prefix ) ; expect ( params . icons ) . toEqual ( [ 'icon1' , 'icon2' ] ) ; expect ( host ) . toBe ( 'https://api1.local' ) ; break ; case 2 : expect ( params . prefix ) . toBe ( prefix ) ; expect ( params . icons ) . toEqual ( [ 'icon1' , 'icon2' ] ) ; expect ( host ) . toBe ( 'https://api2.local' ) ; item . done ( { prefix : params . prefix , icons : { icon1 : { body : '<path d="" />' , } , icon2 : { body : '<path d="" />' , } , } , } ) ; break ; case 3 : expect ( params . prefix ) . toBe ( prefix2 ) ; expect ( params . icons ) . toEqual ( [ 'icon2' , 'icon4' ] ) ; expect ( host ) . toBe ( 'https://api2.local' ) ; item . done ( { prefix : params . prefix , icons : { icon2 : { body : '<path d="" />' , } , icon4 : { body : '<path d="" />' , } , } , } ) ; break ; default : done ( `Unexpected additional call to sendQuery for host ${ host }.` ) ; } } ; setAPIModule ( provider , { prepare : prepareQuery , send : sendQuery , } ) ; let callbackCalled = false ; loadIcons ( [ provider + ':' + prefix + ':icon1' , provider + ':' + prefix + ':icon2' , ] , ( loaded , missing , pending ) => { expect ( callbackCalled ) . toBe ( false ) ; callbackCalled = true ; expect ( loaded ) . toEqual ( [ { provider , prefix , name : 'icon1' , } , { provider , prefix , name : 'icon2' , } , ] ) ; expect ( missing ) . toEqual ( [ ] ) ; expect ( pending ) . toEqual ( [ ] ) ; setTimeout ( ( ) => { let callbackCalled = false ; loadIcons ( [ provider + ':' + prefix2 + ':icon2' , provider + ':' + prefix2 + ':icon4' , ] , ( loaded , missing , pending ) => { expect ( callbackCalled ) . toBe ( false ) ; callbackCalled = true ; expect ( loaded ) . toEqual ( [ { provider , prefix : prefix2 , name : 'icon2' , } , { provider , prefix : prefix2 , name : 'icon4' , } , ] ) ; expect ( missing ) . toEqual ( [ ] ) ; expect ( pending ) . toEqual ( [ ] ) ; done ( ) ; } ) ; } ) ; } ) ; } ) ; } ) ;