laplace-api 3.1.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,82 @@
1
1
  import { Logger } from 'winston';
2
2
  import { LaplaceConfiguration } from '../utilities/configuration';
3
- import { Client } from '../client/client';
4
- import { FinancialFundamentalsClient, TopMoverDirection } from '../client/financial_fundamentals';
5
- import { Region } from '../client/collections';
3
+ import {
4
+ FinancialFundamentalsClient,
5
+ TopMoverDirection,
6
+ StockDividend,
7
+ StockStats,
8
+ TopMover
9
+ } from '../client/financial_fundamentals';
6
10
  import './client_test_suite';
7
- import { AssetType } from '../client/stocks';
11
+ import { Region } from '../client/collections';
12
+ import { AssetType, AssetClass } from '../client/stocks';
13
+
14
+ const mockDividendsResponse: StockDividend[] = [
15
+ {
16
+ date: "2024-03-14T10:00:00Z",
17
+ netAmount: 8.75,
18
+ netRatio: 0.0875,
19
+ grossAmount: 10.0,
20
+ grossRatio: 0.10,
21
+ priceThen: 425.5,
22
+ stoppageRatio: 0.15,
23
+ stoppageAmount: 1.25
24
+ },
25
+ {
26
+ date: "2023-03-15T10:00:00Z",
27
+ netAmount: 7.0,
28
+ netRatio: 0.07,
29
+ grossAmount: 8.0,
30
+ grossRatio: 0.08,
31
+ priceThen: 380.0,
32
+ stoppageRatio: 0.15,
33
+ stoppageAmount: 1.0
34
+ }
35
+ ];
36
+
37
+ const mockStockStatsResponse: StockStats[] = [
38
+ {
39
+ symbol: "TUPRS",
40
+ previousClose: 425.5,
41
+ marketCap: 106375000000,
42
+ peRatio: 5.8,
43
+ pbRatio: 2.1,
44
+ yearLow: 320.5,
45
+ yearHigh: 450.2,
46
+ weeklyReturn: 0.025,
47
+ monthlyReturn: 0.058,
48
+ "3MonthReturn": 0.125,
49
+ ytdReturn: 0.15,
50
+ yearlyReturn: 0.45,
51
+ "3YearReturn": 1.25,
52
+ "5YearReturn": 2.85,
53
+ latestPrice: 428.5,
54
+ dailyChange: 0.007,
55
+ dayLow: 424.0,
56
+ dayHigh: 429.5,
57
+ upperPriceLimit: 468.05,
58
+ lowerPriceLimit: 382.95,
59
+ dayOpen: 426.0,
60
+ eps: 73.45
61
+ }
62
+ ];
63
+
64
+ const mockTopMoversResponse: TopMover[] = [
65
+ {
66
+ symbol: "TUPRS",
67
+ change: 5.8,
68
+ assetClass: AssetClass.Equity,
69
+ assetType: AssetType.Stock
70
+ },
71
+ {
72
+ symbol: "SASA",
73
+ change: 4.2,
74
+ assetClass: AssetClass.Equity,
75
+ assetType: AssetType.Stock
76
+ }
77
+ ];
8
78
 
9
79
  describe('FinancialFundamentals', () => {
10
- let client: Client;
11
80
  let stockClient: FinancialFundamentalsClient;
12
81
 
13
82
  beforeAll(() => {
@@ -22,16 +91,29 @@ describe('FinancialFundamentals', () => {
22
91
  stockClient = new FinancialFundamentalsClient(config, logger);
23
92
  });
24
93
 
25
- test('GetStockDividends', async () => {
26
- const resp = await stockClient.getStockDividends('TUPRS', Region.Tr);
27
- expect(resp).not.toBeEmpty();
28
- });
94
+ describe("Integration Tests", () => {
95
+ test("GetStockDividend", async () => {
96
+ const resp = await stockClient.getStockDividends("TUPRS", Region.Tr);
97
+ expect(resp).not.toBeEmpty();
98
+
99
+ const firstDividend = resp[0];
100
+ expect(typeof firstDividend.date).toBe("string");
101
+ expect(() => new Date(firstDividend.date)).not.toThrow();
102
+ expect(new Date(firstDividend.date).getTime()).not.toBeNaN();
103
+
104
+ expect(typeof firstDividend.netAmount).toBe("number");
105
+ expect(typeof firstDividend.netRatio).toBe("number");
106
+ expect(typeof firstDividend.grossAmount).toBe("number");
107
+ expect(typeof firstDividend.grossRatio).toBe("number");
108
+ expect(typeof firstDividend.priceThen).toBe("number");
109
+ expect(typeof firstDividend.stoppageRatio).toBe("number");
110
+ expect(typeof firstDividend.stoppageAmount).toBe("number");
111
+ });
29
112
 
30
- test('GetStockStats', async () => {
31
- const resp = await stockClient.getStockStats(['TUPRS'], Region.Tr);
32
- expect(resp).not.toBeEmpty();
33
- expect(resp.length).toBe(1);
34
-
113
+ test('GetStockStats', async () => {
114
+ const resp = await stockClient.getStockStats(['TUPRS'], Region.Tr);
115
+ expect(resp).not.toBeEmpty();
116
+ expect(resp.length).toBe(1);
35
117
 
36
118
  var currentStockStats = resp[0];
37
119
  expect(currentStockStats).not.toBeEmpty();
@@ -42,7 +124,7 @@ describe('FinancialFundamentals', () => {
42
124
  expect(currentStockStats.pbRatio).not.toBe(0.0);
43
125
  expect(currentStockStats.yearLow).toBeGreaterThan(0.0);
44
126
  expect(currentStockStats.yearHigh).toBeGreaterThan(0.0);
45
- expect(typeof currentStockStats.weeklyReturn).toBe('number');;
127
+ expect(typeof currentStockStats.weeklyReturn).toBe('number');
46
128
  expect(typeof currentStockStats.monthlyReturn).toBe('number');
47
129
  expect(typeof currentStockStats['3MonthReturn']).toBe('number');
48
130
  expect(typeof currentStockStats.ytdReturn).toBe('number');
@@ -57,44 +139,218 @@ describe('FinancialFundamentals', () => {
57
139
  expect(currentStockStats.lowerPriceLimit).toBeGreaterThan(0.0);
58
140
  expect(currentStockStats.dayOpen).toBeGreaterThan(0.0);
59
141
  expect(typeof currentStockStats.eps).toBe('number');
60
- });
142
+ });
61
143
 
62
- describe('GetTopMovers', () => {
63
- const region = Region.Tr;
64
- const page = 0;
65
- const pageSize = 20;
66
-
67
- async function testTopMovers(direction: TopMoverDirection, shouldBePositive: boolean) {
68
- const result = await stockClient.getTopMovers(region, page, pageSize, direction, AssetType.Stock);
144
+ describe('GetTopMovers', () => {
145
+ const region = Region.Tr;
146
+ const page = 0;
147
+ const pageSize = 20;
69
148
 
70
- expect(Array.isArray(result)).toBe(true);
71
- expect(result.length).toBeGreaterThan(0);
149
+ async function testTopMovers(direction: TopMoverDirection, shouldBePositive: boolean) {
150
+ const result = await stockClient.getTopMovers(region, page, pageSize, direction, AssetType.Stock, AssetClass.Equity);
151
+
152
+ expect(Array.isArray(result)).toBe(true);
153
+ expect(result.length).toBeGreaterThan(0);
154
+
155
+ result.forEach(mover => {
156
+ expect(mover).toHaveProperty('symbol');
157
+ expect(mover).toHaveProperty('change');
158
+ expect(typeof mover.symbol).toBe('string');
159
+ expect(typeof mover.change).toBe('number');
160
+ });
161
+
162
+ const directionCheck = result.every(mover =>
163
+ shouldBePositive ? mover.change > 0 : mover.change < 0
164
+ );
165
+ expect(directionCheck).toBe(true);
166
+
167
+ const assetTypeCheck = result.every(mover => mover.assetType === AssetType.Stock)
168
+ expect(assetTypeCheck).toBe(true);
169
+
170
+ const assetClassCheck = result.every(mover => mover.assetClass === AssetClass.Equity)
171
+ expect(assetClassCheck).toBe(true);
172
+
173
+ expect(result.length).toBeLessThanOrEqual(pageSize);
174
+ }
72
175
 
73
- result.forEach(mover => {
74
- expect(mover).toHaveProperty('symbol');
75
- expect(mover).toHaveProperty('change');
76
- expect(typeof mover.symbol).toBe('string');
77
- expect(typeof mover.change).toBe('number');
176
+ test('should return gainers data', async () => {
177
+ await testTopMovers(TopMoverDirection.Gainers, true);
78
178
  });
79
179
 
80
- const directionCheck = result.every(mover =>
81
- shouldBePositive ? mover.change > 0 : mover.change < 0
82
- );
83
- expect(directionCheck).toBe(true);
180
+ test('should return losers data', async () => {
181
+ await testTopMovers(TopMoverDirection.Losers, false);
182
+ });
183
+ });
184
+ });
84
185
 
85
- const assetTypeCheck = result.every(mover => mover.assetType === AssetType.Stock)
186
+ describe("Mock Tests", () => {
187
+ beforeEach(() => {
188
+ jest.clearAllMocks();
189
+ });
86
190
 
87
- expect(assetTypeCheck).toBe(true);
88
-
89
- expect(result.length).toBeLessThanOrEqual(pageSize);
90
- }
91
-
92
- test('should return gainers data', async () => {
93
- await testTopMovers(TopMoverDirection.Gainers, true);
191
+ describe("getStockDividends", () => {
192
+ test("should return dividends with mock data", async () => {
193
+ jest.spyOn(stockClient, 'getStockDividends').mockResolvedValue(mockDividendsResponse);
194
+
195
+ const resp = await stockClient.getStockDividends("TUPRS", Region.Tr);
196
+
197
+ expect(resp).toHaveLength(2);
198
+
199
+ const firstDividend = resp[0];
200
+ expect(firstDividend.date).toBe("2024-03-14T10:00:00Z");
201
+ expect(firstDividend.netAmount).toBe(8.75);
202
+ expect(firstDividend.netRatio).toBe(0.0875);
203
+ expect(firstDividend.grossAmount).toBe(10.0);
204
+ expect(firstDividend.grossRatio).toBe(0.10);
205
+ expect(firstDividend.priceThen).toBe(425.5);
206
+ expect(firstDividend.stoppageRatio).toBe(0.15);
207
+ expect(firstDividend.stoppageAmount).toBe(1.25);
208
+
209
+ expect(stockClient.getStockDividends).toHaveBeenCalledWith("TUPRS", Region.Tr);
210
+ });
211
+
212
+ test("should handle empty dividends", async () => {
213
+ jest.spyOn(stockClient, 'getStockDividends').mockResolvedValue([]);
214
+
215
+ const resp = await stockClient.getStockDividends("NO_DIVIDEND_STOCK", Region.Tr);
216
+ expect(resp).toHaveLength(0);
217
+ });
94
218
  });
95
-
96
- test('should return losers data', async () => {
97
- await testTopMovers(TopMoverDirection.Losers, false);
219
+
220
+ describe("getStockStats", () => {
221
+ test("should return stock stats with mock data", async () => {
222
+ jest.spyOn(stockClient, 'getStockStats').mockResolvedValue(mockStockStatsResponse);
223
+
224
+ const resp = await stockClient.getStockStats(["TUPRS"], Region.Tr);
225
+
226
+ expect(resp).toHaveLength(1);
227
+
228
+ const stats = resp[0];
229
+ expect(stats.symbol).toBe("TUPRS");
230
+ expect(stats.previousClose).toBe(425.5);
231
+ expect(stats.marketCap).toBe(106375000000);
232
+ expect(stats.peRatio).toBe(5.8);
233
+ expect(stats.pbRatio).toBe(2.1);
234
+ expect(stats.yearLow).toBe(320.5);
235
+ expect(stats.yearHigh).toBe(450.2);
236
+ expect(stats.weeklyReturn).toBe(0.025);
237
+ expect(stats.monthlyReturn).toBe(0.058);
238
+ expect(stats["3MonthReturn"]).toBe(0.125);
239
+ expect(stats.ytdReturn).toBe(0.15);
240
+ expect(stats.yearlyReturn).toBe(0.45);
241
+ expect(stats["3YearReturn"]).toBe(1.25);
242
+ expect(stats["5YearReturn"]).toBe(2.85);
243
+ expect(stats.latestPrice).toBe(428.5);
244
+ expect(stats.dailyChange).toBe(0.007);
245
+ expect(stats.dayLow).toBe(424.0);
246
+ expect(stats.dayHigh).toBe(429.5);
247
+ expect(stats.upperPriceLimit).toBe(468.05);
248
+ expect(stats.lowerPriceLimit).toBe(382.95);
249
+ expect(stats.dayOpen).toBe(426.0);
250
+ expect(stats.eps).toBe(73.45);
251
+
252
+ expect(stockClient.getStockStats).toHaveBeenCalledWith(["TUPRS"], Region.Tr);
253
+ });
254
+
255
+ test("should handle multiple symbols", async () => {
256
+ const multipleStatsResponse = [
257
+ mockStockStatsResponse[0],
258
+ { ...mockStockStatsResponse[0], symbol: "SASA", marketCap: 52000000000 }
259
+ ];
260
+ jest.spyOn(stockClient, 'getStockStats').mockResolvedValue(multipleStatsResponse);
261
+
262
+ const resp = await stockClient.getStockStats(["TUPRS", "SASA"], Region.Tr);
263
+ expect(resp).toHaveLength(2);
264
+ expect(resp[0].symbol).toBe("TUPRS");
265
+ expect(resp[1].symbol).toBe("SASA");
266
+ });
267
+ });
268
+
269
+ describe("getTopMovers", () => {
270
+ test("should return gainers with mock data", async () => {
271
+ jest.spyOn(stockClient, 'getTopMovers').mockResolvedValue(mockTopMoversResponse);
272
+
273
+ const resp = await stockClient.getTopMovers(
274
+ Region.Tr,
275
+ 0,
276
+ 10,
277
+ TopMoverDirection.Gainers,
278
+ AssetType.Stock,
279
+ AssetClass.Equity
280
+ );
281
+
282
+ expect(resp).toHaveLength(2);
283
+
284
+ const firstMover = resp[0];
285
+ expect(firstMover.symbol).toBe("TUPRS");
286
+ expect(firstMover.change).toBe(5.8);
287
+ expect(firstMover.assetClass).toBe(AssetClass.Equity);
288
+ expect(firstMover.assetType).toBe(AssetType.Stock);
289
+
290
+ expect(resp.every(mover => mover.change > 0)).toBe(true);
291
+
292
+ expect(stockClient.getTopMovers).toHaveBeenCalledWith(
293
+ Region.Tr,
294
+ 0,
295
+ 10,
296
+ TopMoverDirection.Gainers,
297
+ AssetType.Stock,
298
+ AssetClass.Equity
299
+ );
300
+ });
301
+
302
+ test("should return losers with mock data", async () => {
303
+ const losersResponse = mockTopMoversResponse.map(mover => ({
304
+ ...mover,
305
+ change: -Math.abs(mover.change)
306
+ }));
307
+ jest.spyOn(stockClient, 'getTopMovers').mockResolvedValue(losersResponse);
308
+
309
+ const resp = await stockClient.getTopMovers(
310
+ Region.Tr,
311
+ 0,
312
+ 10,
313
+ TopMoverDirection.Losers,
314
+ AssetType.Stock,
315
+ AssetClass.Equity
316
+ );
317
+
318
+ expect(resp.every(mover => mover.change < 0)).toBe(true);
319
+
320
+ expect(stockClient.getTopMovers).toHaveBeenCalledWith(
321
+ Region.Tr,
322
+ 0,
323
+ 10,
324
+ TopMoverDirection.Losers,
325
+ AssetType.Stock,
326
+ AssetClass.Equity
327
+ );
328
+ });
329
+
330
+ test("should handle pagination", async () => {
331
+ jest.spyOn(stockClient, 'getTopMovers').mockResolvedValue([mockTopMoversResponse[0]]);
332
+
333
+ const resp = await stockClient.getTopMovers(
334
+ Region.Tr,
335
+ 1,
336
+ 1,
337
+ TopMoverDirection.Gainers,
338
+ AssetType.Stock,
339
+ AssetClass.Equity
340
+ );
341
+
342
+ expect(resp).toHaveLength(1);
343
+ expect(resp[0].symbol).toBe("TUPRS");
344
+
345
+ expect(stockClient.getTopMovers).toHaveBeenCalledWith(
346
+ Region.Tr,
347
+ 1,
348
+ 1,
349
+ TopMoverDirection.Gainers,
350
+ AssetType.Stock,
351
+ AssetClass.Equity
352
+ );
353
+ });
98
354
  });
99
355
  });
100
356
  });