UNPKG

laplace-api

Version:

Client library for Laplace API for the US stock market and BIST (Istanbul stock market) fundamental financial data.

325 lines (266 loc) 11.3 kB
import { Logger } from 'winston'; import { LaplaceConfiguration } from '../utilities/configuration'; import { FinancialFundamentalsClient, TopMoverDirection } from '../client/financial_fundamentals'; import './client_test_suite'; import { Region } from '../client/collections'; import { AssetType, AssetClass } from '../client/stocks'; const mockDividendsResponse = [ { "date": "2019-12-18T06:16:00Z", "currency": "TRY", "netAmount": 0.00007635, "netRatio": 0.000396200399251687, "grossAmount": 0.000509, "grossRatio": 0.00264133599501125, "priceThen": 19.399, "stoppageRatio": 0.85, "stoppageAmount": 0.00043265 } ]; const mockStockStatsResponse = [ { "previousClose": 307, "ytdReturn": 0.339439655172414, "yearlyReturn": 2.6855575955102, "marketCap": 1425000000000, "peRatio": 60.2794409292471, "pbRatio": 7.32754994352451, "yearLow": 80.56935, "yearHigh": 339.25, "3YearReturn": 4.65564820832651, "5YearReturn": 17.2118318670087, "3MonthReturn": 0.682320503304819, "monthlyReturn": -0.0792592592592593, "weeklyReturn": 0.0375626043405676, "symbol": "ASELS", "latestPrice": 310.75, "dailyChange": 0.012214983713355, "dayHigh": 314.75, "dayLow": 306, "lowerPriceLimit": 276.5, "upperPriceLimit": 337.5, "dayOpen": 307.25, "eps": 4.89223038095817 } ]; const mockTopMoversResponse = [ { "symbol": "ISKPL", "assetClass": "equity", "assetType": "stock", "change": 10 } ]; describe('FinancialFundamentals', () => { let stockClient: FinancialFundamentalsClient; beforeAll(() => { const config = (global as any).testSuite.config as LaplaceConfiguration; const logger: Logger = { info: jest.fn(), error: jest.fn(), warn: jest.fn(), debug: jest.fn(), } as unknown as Logger; stockClient = new FinancialFundamentalsClient(config, logger); }); describe("Integration Tests", () => { test("GetStockDividend", async () => { const resp = await stockClient.getStockDividends("TUPRS", Region.Tr); expect(resp).not.toBeEmpty(); const firstDividend = resp[0]; expect(typeof firstDividend.date).toBe("string"); expect(() => new Date(firstDividend.date)).not.toThrow(); expect(new Date(firstDividend.date).getTime()).not.toBeNaN(); expect(typeof firstDividend.currency).toBe("string"); expect(typeof firstDividend.netAmount).toBe("number"); expect(typeof firstDividend.netRatio).toBe("number"); expect(typeof firstDividend.grossAmount).toBe("number"); expect(typeof firstDividend.grossRatio).toBe("number"); expect(typeof firstDividend.priceThen).toBe("number"); expect(typeof firstDividend.stoppageRatio).toBe("number"); expect(typeof firstDividend.stoppageAmount).toBe("number"); }); test('GetStockStats', async () => { const resp = await stockClient.getStockStats(['TUPRS'], Region.Tr); expect(resp).not.toBeEmpty(); expect(resp.length).toBe(1); const currentStockStats = resp[0]; expect(currentStockStats).not.toBeEmpty(); expect(currentStockStats.symbol).toBe('TUPRS'); expect(currentStockStats.previousClose).toBeGreaterThan(0.0); expect(currentStockStats.marketCap).toBeGreaterThan(0.0); expect(currentStockStats.peRatio).not.toBe(0.0); expect(currentStockStats.pbRatio).not.toBe(0.0); expect(currentStockStats.yearLow).toBeGreaterThan(0.0); expect(currentStockStats.yearHigh).toBeGreaterThan(0.0); expect(typeof currentStockStats.weeklyReturn).toBe('number'); expect(typeof currentStockStats.monthlyReturn).toBe('number'); expect(typeof currentStockStats['3MonthReturn']).toBe('number'); expect(typeof currentStockStats.ytdReturn).toBe('number'); expect(typeof currentStockStats.yearlyReturn).toBe('number'); expect(typeof currentStockStats['3YearReturn']).toBe('number'); expect(typeof currentStockStats['5YearReturn']).toBe('number'); expect(currentStockStats.latestPrice).toBeGreaterThan(0.0); expect(typeof currentStockStats.dailyChange).toBe('number'); expect(currentStockStats.dayLow).toBeGreaterThan(0.0); expect(currentStockStats.dayHigh).toBeGreaterThan(0.0); expect(currentStockStats.upperPriceLimit).toBeGreaterThan(0.0); expect(currentStockStats.lowerPriceLimit).toBeGreaterThan(0.0); expect(currentStockStats.dayOpen).toBeGreaterThan(0.0); expect(typeof currentStockStats.eps).toBe('number'); }); describe('GetTopMovers', () => { const region = Region.Tr; const page = 0; const pageSize = 20; async function testTopMovers(direction: TopMoverDirection, shouldBePositive: boolean) { const result = await stockClient.getTopMovers(region, pageSize, direction, page, AssetType.Stock, AssetClass.Equity); expect(Array.isArray(result)).toBe(true); expect(result.length).toBeGreaterThan(0); result.forEach(mover => { expect(mover).toHaveProperty('symbol'); expect(mover).toHaveProperty('change'); expect(typeof mover.symbol).toBe('string'); expect(typeof mover.change).toBe('number'); }); const directionCheck = result.every(mover => shouldBePositive ? mover.change > 0 : mover.change < 0 ); expect(directionCheck).toBe(true); const assetTypeCheck = result.every(mover => mover.assetType === AssetType.Stock) expect(assetTypeCheck).toBe(true); const assetClassCheck = result.every(mover => mover.assetClass === AssetClass.Equity) expect(assetClassCheck).toBe(true); expect(result.length).toBeLessThanOrEqual(pageSize); } test('should return gainers data', async () => { await testTopMovers(TopMoverDirection.Gainers, true); }); test('should return losers data', async () => { await testTopMovers(TopMoverDirection.Losers, false); }); }); }); describe("Mock Tests", () => { let client: FinancialFundamentalsClient; let cli: { request: jest.Mock }; beforeEach(() => { cli = { request: jest.fn() }; const config = (global as any).testSuite.config as LaplaceConfiguration; const logger: Logger = { info: jest.fn(), error: jest.fn(), warn: jest.fn(), debug: jest.fn(), } as unknown as Logger; client = new FinancialFundamentalsClient(config, logger, cli as any); }); describe("getStockDividends", () => { test("calls correct endpoint/params and matches raw response", async () => { cli.request.mockResolvedValueOnce({ data: mockDividendsResponse }); const resp = await client.getStockDividends("TUPRS", Region.Tr); expect(cli.request).toHaveBeenCalledTimes(1); const call = cli.request.mock.calls[0][0]; expect(call.method).toBe("GET"); expect(call.url).toBe("/api/v2/stock/dividends"); expect(call.params).toEqual({ symbol: "TUPRS", region: Region.Tr }); expect(resp).toHaveLength(1); const d = resp[0]; expect(d.date).toBe("2019-12-18T06:16:00Z"); expect(d.currency).toBe("TRY"); expect(d.netAmount).toBe(0.00007635); expect(d.netRatio).toBe(0.000396200399251687); expect(d.grossAmount).toBe(0.000509); expect(d.grossRatio).toBe(0.00264133599501125); expect(d.priceThen).toBe(19.399); expect(d.stoppageRatio).toBe(0.85); expect(d.stoppageAmount).toBe(0.00043265); }); test("bubbles up request error", async () => { cli.request.mockRejectedValueOnce(new Error("Invalid symbol")); await expect(client.getStockDividends("INVALID", Region.Tr)).rejects.toThrow( "Invalid symbol" ); }); }); describe("getStockStats", () => { test("calls correct endpoint/params and matches raw response", async () => { cli.request.mockResolvedValueOnce({ data: mockStockStatsResponse }); const resp = await client.getStockStats(["ASELS"], Region.Tr); expect(cli.request).toHaveBeenCalledTimes(1); const call = cli.request.mock.calls[0][0]; expect(call.method).toBe("GET"); expect(call.url).toBe("/api/v2/stock/stats"); expect(call.params).toEqual({ symbols: "ASELS", region: Region.Tr }); expect(resp).toHaveLength(1); const s = resp[0]; expect(s.symbol).toBe("ASELS"); expect(s.previousClose).toBe(307); expect(s.ytdReturn).toBe(0.339439655172414); expect(s.yearlyReturn).toBe(2.6855575955102); expect(s.marketCap).toBe(1425000000000); expect(s.peRatio).toBe(60.2794409292471); expect(s.pbRatio).toBe(7.32754994352451); expect(s.yearLow).toBe(80.56935); expect(s.yearHigh).toBe(339.25); expect(s["3YearReturn"]).toBe(4.65564820832651); expect(s["5YearReturn"]).toBe(17.2118318670087); expect(s["3MonthReturn"]).toBe(0.682320503304819); expect(s.monthlyReturn).toBe(-0.0792592592592593); expect(s.weeklyReturn).toBe(0.0375626043405676); expect(s.latestPrice).toBe(310.75); expect(s.dailyChange).toBe(0.012214983713355); expect(s.dayHigh).toBe(314.75); expect(s.dayLow).toBe(306); expect(s.dayOpen).toBe(307.25); expect(s.lowerPriceLimit).toBe(276.5); expect(s.upperPriceLimit).toBe(337.5); expect(s.eps).toBe(4.89223038095817); }); test("bubbles up request error", async () => { cli.request.mockRejectedValueOnce(new Error("Invalid symbols")); await expect(client.getStockStats([""], Region.Tr)).rejects.toThrow("Invalid symbols"); }); }); describe("getTopMovers", () => { test("calls correct endpoint/params and matches raw response", async () => { cli.request.mockResolvedValueOnce({ data: mockTopMoversResponse }); const resp = await client.getTopMovers( Region.Tr, 10, TopMoverDirection.Gainers, 0, AssetType.Stock, AssetClass.Equity ); expect(cli.request).toHaveBeenCalledTimes(1); const call = cli.request.mock.calls[0][0]; expect(call.method).toBe("GET"); expect(call.url).toBe("/api/v2/stock/top-movers"); expect(call.params).toEqual({ region: Region.Tr, pageSize: 10, direction: TopMoverDirection.Gainers, page: 0, assetType: AssetType.Stock, assetClass: AssetClass.Equity, }); expect(resp).toHaveLength(1); const m = resp[0]; expect(m.symbol).toBe("ISKPL"); expect(m.change).toBe(10); expect(m.assetType).toBe("stock"); expect(m.assetClass).toBe("equity"); }); test("bubbles up request error", async () => { cli.request.mockRejectedValueOnce(new Error("Bad request")); await expect( client.getTopMovers(Region.Tr, 10, TopMoverDirection.Gainers) ).rejects.toThrow("Bad request"); }); }); }); });