@@ -10,7 +10,7 @@ import {
1010 createAssetsTracker
1111} from '../../src/services' ;
1212
13- import { Observable , from , lastValueFrom , map , of , take , tap } from 'rxjs' ;
13+ import { Observable , from , lastValueFrom , of , tap } from 'rxjs' ;
1414import { RetryBackoffConfig } from 'backoff-rxjs' ;
1515
1616const createTxWithValues = ( values : Partial < Cardano . Value > [ ] ) : Cardano . HydratedTx =>
@@ -32,6 +32,8 @@ const cip68AssetId = {
3232 )
3333} ;
3434
35+ const ONE_WEEK = 7 * 24 * 60 * 60 * 1000 ;
36+
3537const assetInfo = {
3638 PXL : { assetId : AssetId . PXL , nftMetadata : { name : 'nft' } , tokenMetadata : null } as Asset . AssetInfo ,
3739 TSLA : { assetId : AssetId . TSLA , nftMetadata : null , tokenMetadata : null } as Asset . AssetInfo ,
@@ -406,8 +408,8 @@ describe('createAssetService', () => {
406408 it ( 'returns cached assets if all assets are fresh' , ( ) => {
407409 createTestScheduler ( ) . run ( ( { cold, expectObservable, flush } ) => {
408410 const cachedAssets = new Map ( [
409- [ AssetId . TSLA , { assetId : AssetId . TSLA , staleAt : new Date ( ) } as never ] ,
410- [ AssetId . PXL , { assetId : AssetId . PXL , staleAt : new Date ( ) } as never ]
411+ [ AssetId . TSLA , { assetId : AssetId . TSLA , staleAt : new Date ( Date . now ( ) + ONE_WEEK ) } as never ] ,
412+ [ AssetId . PXL , { assetId : AssetId . PXL , staleAt : new Date ( Date . now ( ) + ONE_WEEK ) } as never ]
411413 ] ) ;
412414
413415 ( assetProvider . getAssets as jest . Mock ) . mockImplementation ( ( ) => of ( [ ] ) ) ;
@@ -447,10 +449,12 @@ describe('createAssetService', () => {
447449
448450 it ( 'fetches uncached assets from the provider' , ( ) => {
449451 createTestScheduler ( ) . run ( ( { cold, expectObservable, flush } ) => {
450- const cachedAssets = new Map ( [ [ AssetId . TSLA , { assetId : AssetId . TSLA , staleAt : new Date ( ) } as never ] ] ) ;
452+ const cachedAssets = new Map ( [
453+ [ AssetId . TSLA , { assetId : AssetId . TSLA , staleAt : new Date ( Date . now ( ) + ONE_WEEK ) } as never ]
454+ ] ) ;
451455 const fetchedAssets = [
452- { assetId : AssetId . PXL , nftMetadata : null } ,
453- { assetId : AssetId . Unit , nftMetadata : null }
456+ { assetId : AssetId . PXL , nftMetadata : null , tokenMetadata : null } ,
457+ { assetId : AssetId . Unit , nftMetadata : null , tokenMetadata : null }
454458 ] ;
455459
456460 ( assetProvider . getAssets as jest . Mock ) . mockImplementation ( ( ) => of ( fetchedAssets ) ) ;
@@ -466,21 +470,13 @@ describe('createAssetService', () => {
466470 onFatalError
467471 ) ;
468472
469- const result$ = assetService ( [ AssetId . TSLA , AssetId . PXL , AssetId . Unit ] ) . pipe (
470- take ( 1 ) ,
471- map ( ( assets ) =>
472- assets . map ( ( asset ) => ( {
473- ...asset ,
474- staleAt : 'normalized'
475- } ) )
476- )
477- ) ;
473+ const result$ = assetService ( [ AssetId . TSLA , AssetId . PXL , AssetId . Unit ] ) ;
478474
479475 expectObservable ( result$ ) . toBe ( '(a|)' , {
480476 a : [
481- { assetId : AssetId . TSLA , staleAt : 'normalized' } ,
482- { assetId : AssetId . PXL , nftMetadata : null , staleAt : 'normalized' } ,
483- { assetId : AssetId . Unit , nftMetadata : null , staleAt : 'normalized' }
477+ { assetId : AssetId . TSLA , staleAt : expect . any ( Date ) } ,
478+ { assetId : AssetId . PXL , nftMetadata : null , staleAt : expect . any ( Date ) , tokenMetadata : null } ,
479+ { assetId : AssetId . Unit , nftMetadata : null , staleAt : expect . any ( Date ) , tokenMetadata : null }
484480 ]
485481 } ) ;
486482
@@ -491,8 +487,8 @@ describe('createAssetService', () => {
491487 it ( 'handles an empty cache and fetches all assets' , ( ) => {
492488 createTestScheduler ( ) . run ( ( { cold, expectObservable, flush } ) => {
493489 const fetchedAssets = [
494- { assetId : AssetId . TSLA , nftMetadata : null } ,
495- { assetId : AssetId . PXL , nftMetadata : null }
490+ { assetId : AssetId . TSLA , nftMetadata : null , tokenMetadata : null } ,
491+ { assetId : AssetId . PXL , nftMetadata : null , tokenMetadata : null }
496492 ] ;
497493
498494 ( assetProvider . getAssets as jest . Mock ) . mockImplementation ( ( ) => of ( fetchedAssets ) ) ;
@@ -508,25 +504,87 @@ describe('createAssetService', () => {
508504 onFatalError
509505 ) ;
510506
511- const result$ = assetService ( [ AssetId . TSLA , AssetId . PXL ] ) . pipe (
512- take ( 1 ) ,
513- // eslint-disable-next-line sonarjs/no-identical-functions
514- map ( ( assets ) =>
515- assets . map ( ( asset ) => ( {
516- ...asset ,
517- staleAt : 'normalized'
518- } ) )
519- )
507+ const result$ = assetService ( [ AssetId . TSLA , AssetId . PXL ] ) ;
508+
509+ expectObservable ( result$ ) . toBe ( '(a|)' , {
510+ a : [
511+ { assetId : AssetId . TSLA , nftMetadata : null , staleAt : expect . any ( Date ) , tokenMetadata : null } ,
512+ { assetId : AssetId . PXL , nftMetadata : null , staleAt : expect . any ( Date ) , tokenMetadata : null }
513+ ]
514+ } ) ;
515+
516+ flush ( ) ;
517+ } ) ;
518+ } ) ;
519+
520+ it ( 'fetches stale assets from the provider' , ( ) => {
521+ createTestScheduler ( ) . run ( ( { cold, expectObservable, flush } ) => {
522+ const cachedAssets = new Map ( [
523+ // Stale
524+ [
525+ AssetId . TSLA ,
526+ {
527+ assetId : AssetId . TSLA ,
528+ nftMetadata : { name : 'tsla_cached_name' } ,
529+ staleAt : new Date ( Date . now ( ) - ONE_WEEK )
530+ } as never
531+ ] ,
532+ // Fresh
533+ [
534+ AssetId . PXL ,
535+ {
536+ assetId : AssetId . PXL ,
537+ nftMetadata : { name : 'pxl_cached_name' } ,
538+ staleAt : new Date ( Date . now ( ) + ONE_WEEK )
539+ } as never
540+ ]
541+ ] ) ;
542+
543+ const fetchedAssets = [
544+ { assetId : AssetId . TSLA , nftMetadata : { name : 'tsla_updated_name' } , tokenMetadata : null }
545+ ] ;
546+
547+ ( assetProvider . getAssets as jest . Mock ) . mockImplementation ( ( args : { assetIds : Cardano . AssetId [ ] } ) => {
548+ expect ( args . assetIds ) . toEqual ( [ AssetId . TSLA ] ) ; // Only stale asset should be requested
549+ return of ( fetchedAssets ) ;
550+ } ) ;
551+
552+ const assetCache$ = cold ( '(a|)' , { a : cachedAssets } ) ;
553+ const totalBalance$ = cold ( '(a|)' , {
554+ a : {
555+ assets : new Map ( [
556+ [ AssetId . TSLA , 1000n ] ,
557+ [ AssetId . PXL , 1000n ]
558+ ] ) ,
559+ coins : 0n
560+ }
561+ } ) ;
562+
563+ const assetService = createAssetService (
564+ assetProvider ,
565+ assetCache$ ,
566+ totalBalance$ ,
567+ retryBackoffConfig ,
568+ onFatalError
520569 ) ;
521570
571+ const result$ = assetService ( [ AssetId . TSLA , AssetId . PXL ] ) ;
572+
522573 expectObservable ( result$ ) . toBe ( '(a|)' , {
523574 a : [
524- { assetId : AssetId . TSLA , nftMetadata : null , staleAt : 'normalized' } ,
525- { assetId : AssetId . PXL , nftMetadata : null , staleAt : 'normalized' }
575+ { assetId : AssetId . PXL , nftMetadata : { name : 'pxl_cached_name' } , staleAt : expect . any ( Date ) } ,
576+ {
577+ assetId : AssetId . TSLA ,
578+ nftMetadata : { name : 'tsla_updated_name' } ,
579+ staleAt : expect . any ( Date ) ,
580+ tokenMetadata : null
581+ }
526582 ]
527583 } ) ;
528584
529585 flush ( ) ;
586+
587+ expect ( assetProvider . getAssets ) . toHaveBeenCalledTimes ( 1 ) ;
530588 } ) ;
531589 } ) ;
532590} ) ;
0 commit comments