From efe7875d0826684aaa00f55d0aef8906c71177f7 Mon Sep 17 00:00:00 2001 From: Thomas <4159106+dtslvr@users.noreply.github.com> Date: Sat, 3 Jul 2021 16:37:33 +0200 Subject: [PATCH] Extend current rate service test --- apps/api/src/app/app.module.ts | 2 + apps/api/src/app/core/core.module.ts | 30 +++++++ .../src/app/core/current-rate.service.spec.ts | 89 ++++++++++--------- apps/api/src/app/core/current-rate.service.ts | 41 +++++---- apps/api/src/app/core/market-data.service.ts | 20 +++++ apps/api/src/models/portfolio.spec.ts | 6 +- 6 files changed, 125 insertions(+), 63 deletions(-) create mode 100644 apps/api/src/app/core/core.module.ts create mode 100644 apps/api/src/app/core/market-data.service.ts diff --git a/apps/api/src/app/app.module.ts b/apps/api/src/app/app.module.ts index 6eed799bb..8dff979e4 100644 --- a/apps/api/src/app/app.module.ts +++ b/apps/api/src/app/app.module.ts @@ -22,6 +22,7 @@ import { AdminModule } from './admin/admin.module'; import { AppController } from './app.controller'; import { AuthModule } from './auth/auth.module'; import { CacheModule } from './cache/cache.module'; +import { CoreModule } from './core/core.module'; import { ExperimentalModule } from './experimental/experimental.module'; import { ExportModule } from './export/export.module'; import { ImportModule } from './import/import.module'; @@ -42,6 +43,7 @@ import { UserModule } from './user/user.module'; AuthModule, CacheModule, ConfigModule.forRoot(), + CoreModule, ExperimentalModule, ExportModule, ImportModule, diff --git a/apps/api/src/app/core/core.module.ts b/apps/api/src/app/core/core.module.ts new file mode 100644 index 000000000..2ae0ebf93 --- /dev/null +++ b/apps/api/src/app/core/core.module.ts @@ -0,0 +1,30 @@ +import { ConfigurationService } from '@ghostfolio/api/services/configuration.service'; +import { DataProviderService } from '@ghostfolio/api/services/data-provider.service'; +import { AlphaVantageService } from '@ghostfolio/api/services/data-provider/alpha-vantage/alpha-vantage.service'; +import { GhostfolioScraperApiService } from '@ghostfolio/api/services/data-provider/ghostfolio-scraper-api/ghostfolio-scraper-api.service'; +import { RakutenRapidApiService } from '@ghostfolio/api/services/data-provider/rakuten-rapid-api/rakuten-rapid-api.service'; +import { YahooFinanceService } from '@ghostfolio/api/services/data-provider/yahoo-finance/yahoo-finance.service'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { PrismaService } from '@ghostfolio/api/services/prisma.service'; +import { Module } from '@nestjs/common'; + +import { CurrentRateService } from './current-rate.service'; +import { MarketDataService } from './market-data.service'; + +@Module({ + imports: [], + controllers: [], + providers: [ + AlphaVantageService, + ConfigurationService, + CurrentRateService, + DataProviderService, + ExchangeRateDataService, + GhostfolioScraperApiService, + MarketDataService, + PrismaService, + RakutenRapidApiService, + YahooFinanceService + ] +}) +export class CoreModule {} diff --git a/apps/api/src/app/core/current-rate.service.spec.ts b/apps/api/src/app/core/current-rate.service.spec.ts index 905701c6d..9a3ea074f 100644 --- a/apps/api/src/app/core/current-rate.service.spec.ts +++ b/apps/api/src/app/core/current-rate.service.spec.ts @@ -1,60 +1,65 @@ import { CurrentRateService } from '@ghostfolio/api/app/core/current-rate.service'; -import { Currency } from '@prisma/client'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; -import { PrismaService } from '@ghostfolio/api/services/prisma.service'; +import { Currency, MarketData } from '@prisma/client'; -jest.mock('../../services/exchange-rate-data.service', () => { +import { MarketDataService } from './market-data.service'; + +jest.mock('./market-data.service', () => { return { - // eslint-disable-next-line @typescript-eslint/naming-convention - exchangeRateDataService: jest.fn().mockImplementation(() => { + MarketDataService: jest.fn().mockImplementation(() => { return { - toCurrency: (aValue: number, - aFromCurrency: Currency, - aToCurrency: Currency) => { - return 1 * aValue; + get: (date: Date, symbol: string) => { + return Promise.resolve({ + date, + symbol, + createdAt: date, + id: 'aefcbe3a-ee10-4c4f-9f2d-8ffad7b05584', + marketPrice: 1847.839966 + }); } - } + }; }) }; }); -// https://jestjs.io/docs/manual-mocks#mocking-node-modules -// jest.mock('?', () => { -// return { -// // eslint-disable-next-line @typescript-eslint/naming-convention -// prismaService: jest.fn().mockImplementation(() => { -// return { -// marketData: { -// findFirst: (data: any) => { -// return { -// marketPrice: 100 -// }; -// } -// } -// }; -// }) -// }; -// }); - -xdescribe('CurrentRateService', () => { +jest.mock('../../services/exchange-rate-data.service', () => { + return { + ExchangeRateDataService: jest.fn().mockImplementation(() => { + return { + initialize: () => Promise.resolve(), + toCurrency: (value: number) => { + return 1 * value; + } + }; + }) + }; +}); +describe('CurrentRateService', () => { + let currentRateService: CurrentRateService; let exchangeRateDataService: ExchangeRateDataService; - let prismaService: PrismaService; + let marketDataService: MarketDataService; - beforeEach(() => { - exchangeRateDataService = new ExchangeRateDataService(undefined); - prismaService = new PrismaService(); - }); + beforeAll(async () => { + exchangeRateDataService = new ExchangeRateDataService(null); + marketDataService = new MarketDataService(null); - it('getValue', () => { - const currentRateService = new CurrentRateService(exchangeRateDataService, prismaService); + await exchangeRateDataService.initialize(); - expect(currentRateService.getValue({ - date: new Date(), - symbol: 'AIA', - currency: Currency.USD, - userCurrency: Currency.CHF - })).toEqual(0); + currentRateService = new CurrentRateService( + exchangeRateDataService, + marketDataService + ); }); + it('getValue', async () => { + expect( + await currentRateService.getValue({ + currency: Currency.USD, + date: new Date(Date.UTC(2020, 0, 1, 0, 0, 0)), + symbol: 'AMZN', + userCurrency: Currency.CHF + }) + ).toEqual(1847.839966); + }); }); diff --git a/apps/api/src/app/core/current-rate.service.ts b/apps/api/src/app/core/current-rate.service.ts index fe1c470a6..b5167e8fc 100644 --- a/apps/api/src/app/core/current-rate.service.ts +++ b/apps/api/src/app/core/current-rate.service.ts @@ -1,32 +1,37 @@ -import { Currency } from '@prisma/client'; -import { PrismaService } from '@ghostfolio/api/services/prisma.service'; import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; +import { Injectable } from '@nestjs/common'; +import { Currency } from '@prisma/client'; -export class CurrentRateService { +import { MarketDataService } from './market-data.service'; +@Injectable() +export class CurrentRateService { public constructor( private readonly exchangeRateDataService: ExchangeRateDataService, - private prisma: PrismaService + private readonly marketDataService: MarketDataService ) {} - /** - * TODO: @dtslvr - */ - public async getValue({date, symbol, currency, userCurrency}: GetValueParams): Promise { - const marketData = await this.prisma.marketData.findFirst({ - select: { date: true, marketPrice: true }, - where: { date: date, symbol: symbol } + public async getValue({ + currency, + date, + symbol, + userCurrency + }: GetValueParams): Promise { + const marketData = await this.marketDataService.get({ + date, + symbol }); - console.log(marketData); // { date: Date, marketPrice: number } + if (marketData) { + return this.exchangeRateDataService.toCurrency( + marketData.marketPrice, + currency, + userCurrency + ); + } - return this.exchangeRateDataService.toCurrency( - marketData.marketPrice, - currency, - userCurrency - ); + throw new Error(`Value not found for ${symbol} at ${date}`); } - } export interface GetValueParams { diff --git a/apps/api/src/app/core/market-data.service.ts b/apps/api/src/app/core/market-data.service.ts new file mode 100644 index 000000000..6a16b2dee --- /dev/null +++ b/apps/api/src/app/core/market-data.service.ts @@ -0,0 +1,20 @@ +import { PrismaService } from '@ghostfolio/api/services/prisma.service'; +import { Injectable } from '@nestjs/common'; +import { MarketData } from '@prisma/client'; + +@Injectable() +export class MarketDataService { + public constructor(private prisma: PrismaService) {} + + public async get({ + date, + symbol + }: { + date: Date; + symbol: string; + }): Promise { + return await this.prisma.marketData.findFirst({ + where: { date, symbol } + }); + } +} diff --git a/apps/api/src/models/portfolio.spec.ts b/apps/api/src/models/portfolio.spec.ts index f8fcea69d..ebd888c46 100644 --- a/apps/api/src/models/portfolio.spec.ts +++ b/apps/api/src/models/portfolio.spec.ts @@ -78,14 +78,14 @@ jest.mock('../services/exchange-rate-data.service', () => { ExchangeRateDataService: jest.fn().mockImplementation(() => { return { initialize: () => Promise.resolve(), - toCurrency: (value: number) => value + toCurrency: (value: number) => { + return 1 * value; + } }; }) }; }); -jest.mock('../services/data-provider.service'); -jest.mock('../services/exchange-rate-data.service'); jest.mock('../services/rules.service'); const DEFAULT_ACCOUNT_ID = '693a834b-eb89-42c9-ae47-35196c25d269';