mirror of https://github.com/ghostfolio/ghostfolio
committed by
GitHub
3 changed files with 221 additions and 0 deletions
@ -0,0 +1,210 @@ |
|||||
|
import { ImportService } from './import.service'; |
||||
|
|
||||
|
describe('ImportService', () => { |
||||
|
let importService: ImportService; |
||||
|
|
||||
|
let exchangeRateDataServiceMock: { toCurrencyAtDate: jest.Mock }; |
||||
|
let dataProviderServiceMock: { |
||||
|
getDataSourceForImport: jest.Mock; |
||||
|
getDataSources: jest.Mock; |
||||
|
getAssetProfiles: jest.Mock; |
||||
|
}; |
||||
|
let orderServiceMock: { getOrders: jest.Mock }; |
||||
|
let accountServiceMock: { getAccounts: jest.Mock }; |
||||
|
let tagServiceMock: { getTagsForUser: jest.Mock }; |
||||
|
let configurationServiceMock: { get: jest.Mock }; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
exchangeRateDataServiceMock = { |
||||
|
toCurrencyAtDate: jest.fn() |
||||
|
}; |
||||
|
|
||||
|
dataProviderServiceMock = { |
||||
|
getDataSourceForImport: jest.fn().mockReturnValue('YAHOO'), |
||||
|
getDataSources: jest.fn().mockResolvedValue(['MANUAL', 'YAHOO']), |
||||
|
getAssetProfiles: jest.fn() |
||||
|
}; |
||||
|
|
||||
|
orderServiceMock = { |
||||
|
getOrders: jest.fn().mockResolvedValue({ activities: [], count: 0 }) |
||||
|
}; |
||||
|
|
||||
|
accountServiceMock = { |
||||
|
getAccounts: jest.fn().mockResolvedValue([]) |
||||
|
}; |
||||
|
|
||||
|
tagServiceMock = { |
||||
|
getTagsForUser: jest.fn().mockResolvedValue([]) |
||||
|
}; |
||||
|
|
||||
|
configurationServiceMock = { |
||||
|
get: jest.fn().mockImplementation((key: string) => { |
||||
|
if (key === 'ENABLE_FEATURE_SUBSCRIPTION') { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (key === 'MAX_ACTIVITIES_TO_IMPORT') { |
||||
|
return Number.MAX_SAFE_INTEGER; |
||||
|
} |
||||
|
|
||||
|
return undefined; |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
importService = new ImportService( |
||||
|
accountServiceMock as any, |
||||
|
null, |
||||
|
configurationServiceMock as any, |
||||
|
null, |
||||
|
dataProviderServiceMock as any, |
||||
|
exchangeRateDataServiceMock as any, |
||||
|
null, |
||||
|
orderServiceMock as any, |
||||
|
null, |
||||
|
null, |
||||
|
null, |
||||
|
tagServiceMock as any |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
describe('import', () => { |
||||
|
it('should include valueInBaseCurrency for a dry-run FEE activity', async () => { |
||||
|
const expectedValueInBaseCurrency = 15; |
||||
|
|
||||
|
exchangeRateDataServiceMock.toCurrencyAtDate.mockResolvedValue( |
||||
|
expectedValueInBaseCurrency |
||||
|
); |
||||
|
|
||||
|
const activities = await importService.import({ |
||||
|
isDryRun: true, |
||||
|
maxActivitiesToImport: Number.MAX_SAFE_INTEGER, |
||||
|
accountsWithBalancesDto: [], |
||||
|
activitiesDto: [ |
||||
|
{ |
||||
|
currency: 'USD', |
||||
|
dataSource: 'MANUAL', |
||||
|
date: '2024-01-15T00:00:00.000Z', |
||||
|
fee: 0, |
||||
|
quantity: 1, |
||||
|
symbol: 'Account Opening Fee', |
||||
|
type: 'FEE', |
||||
|
unitPrice: 15 |
||||
|
} as any |
||||
|
], |
||||
|
assetProfilesWithMarketDataDto: [], |
||||
|
tagsDto: [], |
||||
|
user: { |
||||
|
id: 'test-user-id', |
||||
|
settings: { settings: { baseCurrency: 'USD' } } |
||||
|
} as any |
||||
|
}); |
||||
|
|
||||
|
expect(activities).toHaveLength(1); |
||||
|
expect(activities[0].valueInBaseCurrency).toBe( |
||||
|
expectedValueInBaseCurrency |
||||
|
); |
||||
|
expect(activities[0].value).toBe(15); |
||||
|
expect(exchangeRateDataServiceMock.toCurrencyAtDate).toHaveBeenCalledWith( |
||||
|
15, |
||||
|
'USD', |
||||
|
'USD', |
||||
|
expect.any(Date) |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
it('should convert valueInBaseCurrency using the correct currencies', async () => { |
||||
|
exchangeRateDataServiceMock.toCurrencyAtDate.mockResolvedValue(1350.5); |
||||
|
|
||||
|
dataProviderServiceMock.getAssetProfiles.mockResolvedValue({ |
||||
|
MSFT: { |
||||
|
currency: 'USD', |
||||
|
dataSource: 'YAHOO', |
||||
|
name: 'Microsoft Corporation', |
||||
|
symbol: 'MSFT' |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
const activities = await importService.import({ |
||||
|
isDryRun: true, |
||||
|
maxActivitiesToImport: Number.MAX_SAFE_INTEGER, |
||||
|
accountsWithBalancesDto: [], |
||||
|
activitiesDto: [ |
||||
|
{ |
||||
|
currency: 'USD', |
||||
|
dataSource: 'YAHOO', |
||||
|
date: '2024-01-15T00:00:00.000Z', |
||||
|
fee: 19, |
||||
|
quantity: 5, |
||||
|
symbol: 'MSFT', |
||||
|
type: 'BUY', |
||||
|
unitPrice: 298.58 |
||||
|
} as any |
||||
|
], |
||||
|
assetProfilesWithMarketDataDto: [], |
||||
|
tagsDto: [], |
||||
|
user: { |
||||
|
id: 'test-user-id', |
||||
|
settings: { settings: { baseCurrency: 'EUR' } } |
||||
|
} as any |
||||
|
}); |
||||
|
|
||||
|
expect(activities).toHaveLength(1); |
||||
|
expect(activities[0].valueInBaseCurrency).toBe(1350.5); |
||||
|
expect(activities[0].value).toBeCloseTo(1492.9); |
||||
|
expect(exchangeRateDataServiceMock.toCurrencyAtDate).toHaveBeenCalledWith( |
||||
|
expect.closeTo(1492.9), |
||||
|
'USD', |
||||
|
'EUR', |
||||
|
expect.any(Date) |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
it('should fall back to asset profile currency when activity currency is not set', async () => { |
||||
|
exchangeRateDataServiceMock.toCurrencyAtDate.mockResolvedValue(450); |
||||
|
|
||||
|
dataProviderServiceMock.getAssetProfiles.mockResolvedValue({ |
||||
|
AAPL: { |
||||
|
currency: 'EUR', |
||||
|
dataSource: 'YAHOO', |
||||
|
name: 'Apple Inc.', |
||||
|
symbol: 'AAPL' |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
const activities = await importService.import({ |
||||
|
isDryRun: true, |
||||
|
maxActivitiesToImport: Number.MAX_SAFE_INTEGER, |
||||
|
accountsWithBalancesDto: [], |
||||
|
activitiesDto: [ |
||||
|
{ |
||||
|
currency: undefined, |
||||
|
dataSource: 'YAHOO', |
||||
|
date: '2024-06-01T00:00:00.000Z', |
||||
|
fee: 0, |
||||
|
quantity: 2, |
||||
|
symbol: 'AAPL', |
||||
|
type: 'BUY', |
||||
|
unitPrice: 250 |
||||
|
} as any |
||||
|
], |
||||
|
assetProfilesWithMarketDataDto: [], |
||||
|
tagsDto: [], |
||||
|
user: { |
||||
|
id: 'test-user-id', |
||||
|
settings: { settings: { baseCurrency: 'CHF' } } |
||||
|
} as any |
||||
|
}); |
||||
|
|
||||
|
expect(activities).toHaveLength(1); |
||||
|
expect(activities[0].valueInBaseCurrency).toBe(450); |
||||
|
|
||||
|
// Should fall back to asset profile currency (EUR) when activity currency is undefined
|
||||
|
expect(exchangeRateDataServiceMock.toCurrencyAtDate).toHaveBeenCalledWith( |
||||
|
500, |
||||
|
'EUR', |
||||
|
'CHF', |
||||
|
expect.any(Date) |
||||
|
); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
Loading…
Reference in new issue