@ -7,6 +7,8 @@ import {
TAG_ID_EXCLUDE_FROM_ANALYSIS
} from '@ghostfolio/common/config' ;
import {
HistoricalDataItem ,
PortfolioPerformanceResponse ,
PortfolioPosition ,
WatchlistResponse
} from '@ghostfolio/common/interfaces' ;
@ -109,6 +111,26 @@ function createHolding({
} as unknown as PortfolioPosition ;
}
function createPerformance ( {
netPerformancePercentage = 0.1 ,
netPerformancePercentageWithCurrencyEffect = 0.15
} : {
netPerformancePercentage? : number ;
netPerformancePercentageWithCurrencyEffect? : number ;
} = { } ) : PortfolioPerformanceResponse [ 'performance' ] {
return {
netPerformancePercentage ,
netPerformancePercentageWithCurrencyEffect ,
currentNetWorth : 3000 ,
currentValueInBaseCurrency : 2000 ,
dividendInBaseCurrency : 50 ,
netPerformance : 200 ,
netPerformanceWithCurrencyEffect : 300 ,
totalInvestment : 1700 ,
totalInvestmentValueWithCurrencyEffect : 1700
} ;
}
function createWatchlistItem ( {
name = 'Name of AAPL' ,
performancePercent = - 0.25 ,
@ -136,11 +158,15 @@ function createWatchlistItem({
function createPortfolioTableService ( {
accounts = [ ] ,
chart = [ { date : '2024-01-01' } ] ,
holdings = [ ] ,
performance = createPerformance ( ) ,
watchlist = [ ]
} : {
accounts? : AccountWithValue [ ] ;
chart? : HistoricalDataItem [ ] ;
holdings? : PortfolioPosition [ ] ;
performance? : PortfolioPerformanceResponse [ 'performance' ] ;
watchlist? : WatchlistResponse [ 'watchlist' ] ;
} = { } ) {
// The mock gives the identifier of the translation, so that a test can tell
@ -153,7 +179,8 @@ function createPortfolioTableService({
const portfolioService = {
getAccountsWithAggregations : jest.fn ( ) . mockResolvedValue ( { accounts } ) ,
getDetails : jest.fn ( ) . mockResolvedValue ( { holdings } )
getDetails : jest.fn ( ) . mockResolvedValue ( { holdings } ) ,
getPerformance : jest.fn ( ) . mockResolvedValue ( { chart , performance } )
} as unknown as PortfolioService ;
const watchlistService = {
@ -215,6 +242,16 @@ describe('PortfolioTableService', () => {
} ) ;
} ) ;
describe ( 'getPerformanceTableColumnNames' , ( ) = > {
it ( 'gives no column with a monetary value' , ( ) = > {
expect ( PortfolioTableService . getPerformanceTableColumnNames ( ) ) . toEqual ( [
'Asset Performance in Percentage' ,
'Currency Performance in Percentage' ,
'Net Performance in Percentage'
] ) ;
} ) ;
} ) ;
describe ( 'getWatchlistTableColumnNames' , ( ) = > {
it ( 'gives no column with a monetary value' , ( ) = > {
expect ( PortfolioTableService . getWatchlistTableColumnNames ( ) ) . toEqual ( [
@ -324,6 +361,61 @@ describe('PortfolioTableService', () => {
} ) ;
} ) ;
describe ( 'getPerformanceTable' , ( ) = > {
function getPerformanceTable (
parameters : Parameters < typeof createPortfolioTableService > [ 0 ] = { }
) {
return createPortfolioTableService ( parameters ) . getPerformanceTable ( {
dateRange : 'ytd' ,
userId : 'user-id'
} ) ;
}
it ( 'gives the currency performance as the difference of the net performance and the asset performance' , async ( ) = > {
const result = await getPerformanceTable ( ) ;
const [ row ] = result . split ( '\n' ) . filter ( ( line ) = > {
return line . startsWith ( '| 10.000%' ) ;
} ) ;
expect ( row ) . toBe ( '| 10.000% | 5.000% | 15.000% |' ) ;
} ) ;
it ( 'gives a currency performance of zero without a sign' , async ( ) = > {
const result = await getPerformanceTable ( {
performance : createPerformance ( {
netPerformancePercentage : 0.10000000000000003 ,
netPerformancePercentageWithCurrencyEffect : 0.1
} )
} ) ;
const [ row ] = result . split ( '\n' ) . filter ( ( line ) = > {
return line . startsWith ( '| 10.000%' ) ;
} ) ;
expect ( row ) . toBe ( '| 10.000% | 0.000% | 10.000% |' ) ;
} ) ;
it ( 'gives no monetary value' , async ( ) = > {
const result = await getPerformanceTable ( ) ;
const [ , , row ] = result . split ( '\n' ) . filter ( ( line ) = > {
return line . startsWith ( '|' ) ;
} ) ;
for ( const cell of row . split ( '|' ) . slice ( 1 , - 1 ) ) {
expect ( cell . trim ( ) ) . toMatch ( /^-?\d+\.\d{3}%$/ ) ;
}
} ) ;
it ( 'tells that no performance is found if the chart is empty' , async ( ) = > {
const result = await getPerformanceTable ( { chart : [ ] } ) ;
expect ( result ) . toContain ( 'No performance found.' ) ;
expect ( result ) . not . toContain ( '%' ) ;
} ) ;
} ) ;
describe ( 'getWatchlistTable' , ( ) = > {
function getWatchlistTable ( watchlist : WatchlistResponse [ 'watchlist' ] ) {
return createPortfolioTableService ( { watchlist } ) . getWatchlistTable ( {