@ -1,6 +1,7 @@
import { AccountService } from '@ghostfolio/api/app/account/account.service' ;
import { AccountService } from '@ghostfolio/api/app/account/account.service' ;
import { CashDetails } from '@ghostfolio/api/app/account/interfaces/cash-details.interface' ;
import { CashDetails } from '@ghostfolio/api/app/account/interfaces/cash-details.interface' ;
import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service' ;
import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service' ;
import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator' ;
import { userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils' ;
import { userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils' ;
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory' ;
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory' ;
import { UserService } from '@ghostfolio/api/app/user/user.service' ;
import { UserService } from '@ghostfolio/api/app/user/user.service' ;
@ -11,7 +12,10 @@ import { ImpersonationService } from '@ghostfolio/api/services/impersonation/imp
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service' ;
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile/symbol-profile.service' ;
import { UNKNOWN_KEY } from '@ghostfolio/common/config' ;
import { UNKNOWN_KEY } from '@ghostfolio/common/config' ;
import { parseDate } from '@ghostfolio/common/helper' ;
import { parseDate } from '@ghostfolio/common/helper' ;
import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces' ;
import {
AssetProfileIdentifier ,
PortfolioSummary
} from '@ghostfolio/common/interfaces' ;
import { Account , DataSource } from '@prisma/client' ;
import { Account , DataSource } from '@prisma/client' ;
import { Big } from 'big.js' ;
import { Big } from 'big.js' ;
@ -338,6 +342,86 @@ describe('PortfolioService', () => {
} ) ;
} ) ;
} ) ;
} ) ;
describe ( 'getSummary' , ( ) = > {
const getSummary = ( args : object ) = > {
return (
portfolioService as unknown as {
getSummary : ( aArgs : object ) = > Promise < PortfolioSummary > ;
}
) . getSummary ( args ) ;
} ;
function createPortfolioCalculator() {
return {
getDividendInBaseCurrency : jest.fn ( ) . mockResolvedValue ( new Big ( 0 ) ) ,
getFeesInBaseCurrency : jest.fn ( ) . mockResolvedValue ( new Big ( 0 ) ) ,
getInterestInBaseCurrency : jest.fn ( ) . mockResolvedValue ( new Big ( 0 ) ) ,
getLiabilitiesInBaseCurrency : jest.fn ( ) . mockResolvedValue ( new Big ( 0 ) ) ,
getSnapshot : jest.fn ( ) . mockResolvedValue ( {
currentValueInBaseCurrency : new Big ( 3000 ) ,
totalCashInBaseCurrency : new Big ( 1000 ) ,
totalInvestment : new Big ( 2000 ) ,
totalInvestmentWithCurrencyEffect : new Big ( 2000 )
} ) ,
getStartDate : jest.fn ( ) . mockReturnValue ( parseDate ( '2024-01-01' ) )
} as unknown as PortfolioCalculator ;
}
beforeEach ( ( ) = > {
jest
. spyOn ( activitiesService , 'getActivities' )
. mockResolvedValue ( { activities : [ ] , count : 0 } ) ;
jest
. spyOn ( impersonationService , 'validateImpersonationId' )
. mockResolvedValue ( null ) ;
jest . spyOn ( portfolioService , 'getPerformance' ) . mockResolvedValue ( {
performance : {
currentValueInBaseCurrency : 3000 ,
netPerformance : 500 ,
netPerformancePercentage : 0.2 ,
netPerformancePercentageWithCurrencyEffect : 0.2 ,
netPerformanceWithCurrencyEffect : 500
}
} as Awaited < ReturnType < typeof portfolioService.getPerformance > > ) ;
jest . spyOn ( userService , 'user' ) . mockResolvedValue ( {
id : userDummyData.id ,
settings : {
settings : {
baseCurrency : 'CHF'
}
}
} as unknown as Awaited < ReturnType < typeof userService.user > > ) ;
} ) ;
it ( 'should derive the cash and net worth from the account balance when there are no excluded accounts, no emergency fund and no liabilities' , async ( ) = > {
jest . spyOn ( accountService , 'getCashDetails' ) . mockResolvedValue ( {
accounts : [ ] ,
balanceInBaseCurrency : 1000
} ) ;
const portfolioCalculator = createPortfolioCalculator ( ) ;
const summary = await getSummary ( {
portfolioCalculator ,
balanceInBaseCurrency : 1000 ,
emergencyFundHoldingsValueInBaseCurrency : 0 ,
filteredValueInBaseCurrency : new Big ( 3000 ) ,
impersonationId : undefined ,
userCurrency : 'CHF' ,
userId : userDummyData.id
} ) ;
expect ( summary . cash ) . toBe ( 1000 ) ;
expect ( summary . emergencyFund . total ) . toBe ( 0 ) ;
expect ( summary . excludedAccountsAndActivities ) . toBe ( 0 ) ;
expect ( summary . totalAssetsInBaseCurrency ) . toBe ( 3000 ) ;
expect ( summary . totalValueInBaseCurrency ) . toBe ( 3000 ) ;
} ) ;
} ) ;
describe ( 'getValueOfAccountsAndPlatforms' , ( ) = > {
describe ( 'getValueOfAccountsAndPlatforms' , ( ) = > {
const getValueOfAccountsAndPlatforms = ( args : object ) = > {
const getValueOfAccountsAndPlatforms = ( args : object ) = > {
return (
return (