laplace-api 4.0.0 → 4.2.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,10 +1,81 @@
1
1
  import { Logger } from 'winston';
2
2
  import { LaplaceConfiguration } from '../utilities/configuration';
3
- import { FinancialFundamentalsClient, TopMoverDirection } from '../client/financial_fundamentals';
3
+ import {
4
+ FinancialFundamentalsClient,
5
+ TopMoverDirection,
6
+ StockDividend,
7
+ StockStats,
8
+ TopMover
9
+ } from '../client/financial_fundamentals';
4
10
  import './client_test_suite';
5
11
  import { Region } from '../client/collections';
6
12
  import { AssetType, AssetClass } from '../client/stocks';
7
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
+ ];
78
+
8
79
  describe('FinancialFundamentals', () => {
9
80
  let stockClient: FinancialFundamentalsClient;
10
81
 
@@ -20,29 +91,29 @@ describe('FinancialFundamentals', () => {
20
91
  stockClient = new FinancialFundamentalsClient(config, logger);
21
92
  });
22
93
 
23
- test("GetStockDividend", async () => {
24
- const resp = await stockClient.getStockDividends("TUPRS", Region.Tr);
25
- expect(resp).not.toBeEmpty();
26
-
27
- const firstDividend = resp[0];
28
- expect(typeof firstDividend.date).toBe("string");
29
- expect(() => new Date(firstDividend.date)).not.toThrow();
30
- expect(new Date(firstDividend.date).getTime()).not.toBeNaN();
94
+ describe("Integration Tests", () => {
95
+ test("GetStockDividend", async () => {
96
+ const resp = await stockClient.getStockDividends("TUPRS", Region.Tr);
97
+ expect(resp).not.toBeEmpty();
31
98
 
32
- expect(typeof firstDividend.netAmount).toBe("number");
33
- expect(typeof firstDividend.netRatio).toBe("number");
34
- expect(typeof firstDividend.grossAmount).toBe("number");
35
- expect(typeof firstDividend.grossRatio).toBe("number");
36
- expect(typeof firstDividend.priceThen).toBe("number");
37
- expect(typeof firstDividend.stoppageRatio).toBe("number");
38
- expect(typeof firstDividend.stoppageAmount).toBe("number");
39
- });
40
-
41
- test('GetStockStats', async () => {
42
- const resp = await stockClient.getStockStats(['TUPRS'], Region.Tr);
43
- expect(resp).not.toBeEmpty();
44
- expect(resp.length).toBe(1);
45
-
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
+ });
112
+
113
+ test('GetStockStats', async () => {
114
+ const resp = await stockClient.getStockStats(['TUPRS'], Region.Tr);
115
+ expect(resp).not.toBeEmpty();
116
+ expect(resp.length).toBe(1);
46
117
 
47
118
  var currentStockStats = resp[0];
48
119
  expect(currentStockStats).not.toBeEmpty();
@@ -53,7 +124,7 @@ describe('FinancialFundamentals', () => {
53
124
  expect(currentStockStats.pbRatio).not.toBe(0.0);
54
125
  expect(currentStockStats.yearLow).toBeGreaterThan(0.0);
55
126
  expect(currentStockStats.yearHigh).toBeGreaterThan(0.0);
56
- expect(typeof currentStockStats.weeklyReturn).toBe('number');;
127
+ expect(typeof currentStockStats.weeklyReturn).toBe('number');
57
128
  expect(typeof currentStockStats.monthlyReturn).toBe('number');
58
129
  expect(typeof currentStockStats['3MonthReturn']).toBe('number');
59
130
  expect(typeof currentStockStats.ytdReturn).toBe('number');
@@ -68,48 +139,218 @@ describe('FinancialFundamentals', () => {
68
139
  expect(currentStockStats.lowerPriceLimit).toBeGreaterThan(0.0);
69
140
  expect(currentStockStats.dayOpen).toBeGreaterThan(0.0);
70
141
  expect(typeof currentStockStats.eps).toBe('number');
71
- });
142
+ });
72
143
 
73
- describe('GetTopMovers', () => {
74
- const region = Region.Tr;
75
- const page = 0;
76
- const pageSize = 20;
77
-
78
- async function testTopMovers(direction: TopMoverDirection, shouldBePositive: boolean) {
79
- const result = await stockClient.getTopMovers(region, page, pageSize, direction, AssetType.Stock, AssetClass.Equity);
144
+ describe('GetTopMovers', () => {
145
+ const region = Region.Tr;
146
+ const page = 0;
147
+ const pageSize = 20;
80
148
 
81
- expect(Array.isArray(result)).toBe(true);
82
- 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
+ }
83
175
 
84
- result.forEach(mover => {
85
- expect(mover).toHaveProperty('symbol');
86
- expect(mover).toHaveProperty('change');
87
- expect(typeof mover.symbol).toBe('string');
88
- expect(typeof mover.change).toBe('number');
176
+ test('should return gainers data', async () => {
177
+ await testTopMovers(TopMoverDirection.Gainers, true);
89
178
  });
90
179
 
91
- const directionCheck = result.every(mover =>
92
- shouldBePositive ? mover.change > 0 : mover.change < 0
93
- );
94
- expect(directionCheck).toBe(true);
180
+ test('should return losers data', async () => {
181
+ await testTopMovers(TopMoverDirection.Losers, false);
182
+ });
183
+ });
184
+ });
185
+
186
+ describe("Mock Tests", () => {
187
+ beforeEach(() => {
188
+ jest.clearAllMocks();
189
+ });
95
190
 
96
- const assetTypeCheck = result.every(mover => mover.assetType === AssetType.Stock)
191
+ describe("getStockDividends", () => {
192
+ test("should return dividends with mock data", async () => {
193
+ jest.spyOn(stockClient, 'getStockDividends').mockResolvedValue(mockDividendsResponse);
97
194
 
98
- expect(assetTypeCheck).toBe(true);
195
+ const resp = await stockClient.getStockDividends("TUPRS", Region.Tr);
99
196
 
100
- const assetClassCheck = result.every(mover => mover.assetClass === AssetClass.Equity)
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);
101
208
 
102
- expect(assetClassCheck).toBe(true);
103
-
104
- expect(result.length).toBeLessThanOrEqual(pageSize);
105
- }
106
-
107
- test('should return gainers data', async () => {
108
- await testTopMovers(TopMoverDirection.Gainers, true);
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
+ });
109
218
  });
110
-
111
- test('should return losers data', async () => {
112
- 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
+ });
113
354
  });
114
355
  });
115
356
  });