Browse Source

Bugfix/data provider mapping in get data provider (#8195)

* Fix data source mapping in data provider service

* Update changelog
pull/8158/merge
Thomas Kaul 7 hours ago
committed by GitHub
parent
commit
7db2bbe6a5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      CHANGELOG.md
  2. 112
      apps/api/src/services/data-provider/data-provider.service.spec.ts
  3. 36
      apps/api/src/services/data-provider/data-provider.service.ts

4
CHANGELOG.md

@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improved the accessibility of the _Google_ icon on the registration page
- Improved the search by ISIN number in the _Financial Modeling Prep_ service
### Fixed
- Fixed the data source mapping in the data provider service to apply only to the mapped data source
## 3.87.0 - 2026-10-17
### Added

112
apps/api/src/services/data-provider/data-provider.service.spec.ts

@ -0,0 +1,112 @@
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { DataProviderInterface } from '@ghostfolio/api/services/data-provider/interfaces/data-provider.interface';
import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service';
import { PrismaService } from '@ghostfolio/api/services/prisma/prisma.service';
import { PropertyService } from '@ghostfolio/api/services/property/property.service';
import { DataSource } from '@prisma/client';
import { DataProviderService } from './data-provider.service';
/**
* Gives the service with some of the data providers in the order of the
* module, so that EOD_HISTORICAL_DATA comes before MANUAL and YAHOO
*/
function createDataProviderService(dataProviderMapping?: {
[dataProviderName: string]: string;
}) {
const dataProviderInterfaces = [
DataSource.EOD_HISTORICAL_DATA,
DataSource.FINANCIAL_MODELING_PREP,
DataSource.MANUAL,
DataSource.YAHOO
].map((dataSource) => {
return {
getName: () => {
return dataSource;
}
} as DataProviderInterface;
});
return new DataProviderService(
{} as ConfigurationService,
dataProviderInterfaces,
{} as MarketDataService,
{} as PrismaService,
{
getByKey: jest.fn().mockResolvedValue(dataProviderMapping)
} as unknown as PropertyService,
{} as RedisCacheService
);
}
describe('DataProviderService', () => {
describe('getDataProvider', () => {
it('gives the data provider of the data source without a mapping', async () => {
const dataProviderService = createDataProviderService();
await dataProviderService.onModuleInit();
expect(
dataProviderService.getDataProvider(DataSource.YAHOO).getName()
).toBe(DataSource.YAHOO);
});
it('gives the mapped data provider of a data source with a mapping', async () => {
const dataProviderService = createDataProviderService({
[DataSource.YAHOO]: DataSource.FINANCIAL_MODELING_PREP
});
await dataProviderService.onModuleInit();
expect(
dataProviderService.getDataProvider(DataSource.YAHOO).getName()
).toBe(DataSource.FINANCIAL_MODELING_PREP);
});
it('gives the data provider of the data source if the mapping of another data source comes first', async () => {
const dataProviderService = createDataProviderService({
[DataSource.EOD_HISTORICAL_DATA]: DataSource.FINANCIAL_MODELING_PREP
});
await dataProviderService.onModuleInit();
expect(
dataProviderService
.getDataProvider(DataSource.EOD_HISTORICAL_DATA)
.getName()
).toBe(DataSource.FINANCIAL_MODELING_PREP);
expect(
dataProviderService.getDataProvider(DataSource.MANUAL).getName()
).toBe(DataSource.MANUAL);
expect(
dataProviderService.getDataProvider(DataSource.YAHOO).getName()
).toBe(DataSource.YAHOO);
});
it('gives the data provider of the data source if the mapped data provider does not exist', async () => {
const dataProviderService = createDataProviderService({
[DataSource.YAHOO]: 'UNKNOWN'
});
await dataProviderService.onModuleInit();
expect(
dataProviderService.getDataProvider(DataSource.YAHOO).getName()
).toBe(DataSource.YAHOO);
});
it('throws an error if no data provider has been found', async () => {
const dataProviderService = createDataProviderService();
await dataProviderService.onModuleInit();
expect(() => {
return dataProviderService.getDataProvider(DataSource.COINGECKO);
}).toThrow('No data provider has been found.');
});
});
});

36
apps/api/src/services/data-provider/data-provider.service.ts

@ -157,26 +157,32 @@ export class DataProviderService implements OnModuleInit {
return response;
}
/**
* Gives the data provider of the data source, or the data provider which
* the data source mapping gives for this data source
*/
public getDataProvider(providerName: DataSource) {
for (const dataProviderInterface of this.dataProviderInterfaces) {
if (this.dataProviderMapping[dataProviderInterface.getName()]) {
const mappedDataProviderInterface = this.dataProviderInterfaces.find(
(currentDataProviderInterface) => {
return (
currentDataProviderInterface.getName() ===
this.dataProviderMapping[dataProviderInterface.getName()]
);
}
const mappedDataProviderInterface = this.dataProviderInterfaces.find(
(dataProviderInterface) => {
return (
dataProviderInterface.getName() ===
this.dataProviderMapping[providerName]
);
if (mappedDataProviderInterface) {
return mappedDataProviderInterface;
}
}
);
if (mappedDataProviderInterface) {
return mappedDataProviderInterface;
}
if (dataProviderInterface.getName() === providerName) {
return dataProviderInterface;
const dataProviderInterface = this.dataProviderInterfaces.find(
(currentDataProviderInterface) => {
return currentDataProviderInterface.getName() === providerName;
}
);
if (dataProviderInterface) {
return dataProviderInterface;
}
throw new Error('No data provider has been found.');

Loading…
Cancel
Save