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.
@@ -5,8 +5,89 @@ import {
5
5
  FundsClient,
6
6
  FundType,
7
7
  HistoricalFundPricePeriod,
8
+ Fund,
9
+ FundStats,
10
+ FundDistribution,
11
+ FundAssetCategory,
12
+ FundHistoricalPrice,
13
+ FundContentType
8
14
  } from "../client/funds";
9
15
  import { Region } from "../client/collections";
16
+ import { AssetType } from "../client/stocks";
17
+
18
+ const mockFundsResponse: Fund[] = [
19
+ {
20
+ assetType: AssetType.Stock,
21
+ name: "Ak Portföy BIST 30 Endeksi Hisse Senedi Fonu",
22
+ symbol: "SPP",
23
+ active: true,
24
+ managementFee: 0.003,
25
+ riskLevel: 6,
26
+ fundType: FundType.STOCK_UMBRELLA_FUND,
27
+ ownerSymbol: "AKP"
28
+ },
29
+ {
30
+ assetType: AssetType.Stock,
31
+ name: "İş Portföy BIST 30 Endeksi Hisse Senedi Fonu",
32
+ symbol: "TI3",
33
+ active: true,
34
+ managementFee: 0.0035,
35
+ riskLevel: 6,
36
+ fundType: FundType.STOCK_UMBRELLA_FUND,
37
+ ownerSymbol: "IYP"
38
+ }
39
+ ];
40
+
41
+ const mockFundStatsResponse: FundStats = {
42
+ yearBeta: 0.95,
43
+ yearStdev: 0.12,
44
+ ytdReturn: 0.15,
45
+ yearMomentum: 0.08,
46
+ yearlyReturn: 0.25,
47
+ monthlyReturn: 0.03,
48
+ fiveYearReturn: 1.85,
49
+ sixMonthReturn: 0.18,
50
+ threeYearReturn: 0.95,
51
+ threeMonthReturn: 0.09
52
+ };
53
+
54
+ const mockFundDistributionResponse: FundDistribution = {
55
+ categories: [
56
+ {
57
+ category: FundAssetCategory.EQUITY,
58
+ percentage: 95.5,
59
+ assets: [
60
+ {
61
+ type: FundContentType.BIST_STOCK,
62
+ symbol: "GARAN",
63
+ wholePercentage: 9.8,
64
+ categoryPercentage: 10.26
65
+ }
66
+ ]
67
+ },
68
+ {
69
+ category: FundAssetCategory.LIQUID_DEPOSIT,
70
+ percentage: 4.5
71
+ }
72
+ ]
73
+ };
74
+
75
+ const mockHistoricalPricesResponse: FundHistoricalPrice[] = [
76
+ {
77
+ price: 15.25,
78
+ aum: 1250000000,
79
+ date: "2024-03-14T10:00:00Z",
80
+ shareCount: 82000000,
81
+ investorCount: 25000
82
+ },
83
+ {
84
+ price: 15.15,
85
+ aum: 1245000000,
86
+ date: "2024-03-13T10:00:00Z",
87
+ shareCount: 82180000,
88
+ investorCount: 24950
89
+ }
90
+ ];
10
91
 
11
92
  describe("Funds Client", () => {
12
93
  let client: FundsClient;
@@ -23,88 +104,214 @@ describe("Funds Client", () => {
23
104
  client = new FundsClient(config, logger);
24
105
  });
25
106
 
26
- describe("getFunds", () => {
27
- test("should return funds list for TR region", async () => {
28
- const resp = await client.getFunds(Region.Tr, 1, 10);
29
-
30
- expect(resp).toBeDefined();
31
- expect(Array.isArray(resp)).toBe(true);
32
- expect(resp.length).toBeGreaterThan(0);
33
-
34
- const fund = resp[0];
35
- expect(typeof fund.symbol).toBe("string");
36
- expect(typeof fund.name).toBe("string");
37
- expect(typeof fund.assetType).toBe("string");
38
- expect(typeof fund.managementFee).toBe("number");
39
- expect(typeof fund.riskLevel).toBe("number");
40
- expect(typeof fund.ownerSymbol).toBe("string");
41
- expect(Object.values(FundType)).toContain(fund.fundType);
107
+ describe("Integration Tests", () => {
108
+ describe("getFunds", () => {
109
+ test("should return funds list for TR region", async () => {
110
+ const resp = await client.getFunds(Region.Tr, 1, 10);
111
+
112
+ expect(resp).toBeDefined();
113
+ expect(Array.isArray(resp)).toBe(true);
114
+ expect(resp.length).toBeGreaterThan(0);
115
+
116
+ const fund = resp[0];
117
+ expect(typeof fund.symbol).toBe("string");
118
+ expect(typeof fund.name).toBe("string");
119
+ expect(typeof fund.assetType).toBe("string");
120
+ expect(typeof fund.managementFee).toBe("number");
121
+ expect(typeof fund.riskLevel).toBe("number");
122
+ expect(typeof fund.ownerSymbol).toBe("string");
123
+ expect(Object.values(FundType)).toContain(fund.fundType);
124
+ });
125
+
126
+ test("should handle pagination correctly", async () => {
127
+ const page1 = await client.getFunds(Region.Tr, 1, 5);
128
+ expect(page1.length).toBeLessThanOrEqual(5);
129
+ });
42
130
  });
43
131
 
44
- test("should handle pagination correctly", async () => {
45
- const page1 = await client.getFunds(Region.Tr, 1, 5);
132
+ describe("getFundStats", () => {
133
+ test("should return fund statistics", async () => {
134
+ const resp = await client.getFundStats("SPP", Region.Tr);
135
+
136
+ expect(resp).toBeDefined();
137
+ expect(typeof resp.yearBeta).toBe("number");
138
+ expect(typeof resp.yearStdev).toBe("number");
139
+ expect(typeof resp.ytdReturn).toBe("number");
140
+ expect(typeof resp.yearMomentum).toBe("number");
141
+ expect(typeof resp.yearlyReturn).toBe("number");
142
+ expect(typeof resp.monthlyReturn).toBe("number");
143
+ expect(typeof resp.fiveYearReturn).toBe("number");
144
+ expect(typeof resp.sixMonthReturn).toBe("number");
145
+ expect(typeof resp.threeYearReturn).toBe("number");
146
+ expect(typeof resp.threeMonthReturn).toBe("number");
147
+ });
46
148
 
47
- expect(page1.length).toBeLessThanOrEqual(5);
149
+ test("should handle invalid fund symbol", async () => {
150
+ await expect(
151
+ client.getFundStats("INVALID_FUND", Region.Tr)
152
+ ).rejects.toThrow();
153
+ });
48
154
  });
49
- });
50
155
 
51
- describe("getFundStats", () => {
52
- test("should return fund statistics", async () => {
53
- const resp = await client.getFundStats("SPP", Region.Tr);
54
-
55
- expect(resp).toBeDefined();
56
- expect(typeof resp.yearBeta).toBe("number");
57
- expect(typeof resp.yearStdev).toBe("number");
58
- expect(typeof resp.ytdReturn).toBe("number");
59
- expect(typeof resp.yearMomentum).toBe("number");
60
- expect(typeof resp.yearlyReturn).toBe("number");
61
- expect(typeof resp.monthlyReturn).toBe("number");
62
- expect(typeof resp.fiveYearReturn).toBe("number");
63
- expect(typeof resp.sixMonthReturn).toBe("number");
64
- expect(typeof resp.threeYearReturn).toBe("number");
65
- expect(typeof resp.threeMonthReturn).toBe("number");
156
+ describe("getFundDistribution", () => {
157
+ test("should return fund asset distribution", async () => {
158
+ const resp = await client.getFundDistribution("SPP", Region.Tr);
159
+
160
+ expect(resp).toBeDefined();
161
+ expect(Array.isArray(resp.categories)).toBe(true);
162
+
163
+ if (resp.categories.length > 0) {
164
+ const distribution = resp.categories[0];
165
+ expect(distribution.category).toBeDefined();
166
+ expect(typeof distribution.percentage).toBe("number");
167
+ }
168
+ });
66
169
  });
67
170
 
68
- test("should handle invalid fund symbol", async () => {
69
- await expect(
70
- client.getFundStats("INVALID_FUND", Region.Tr)
71
- ).rejects.toThrow();
171
+ describe("getHistoricalFundPrices", () => {
172
+ test("should return historical prices", async () => {
173
+ const resp = await client.getHistoricalFundPrices(
174
+ "SPP",
175
+ Region.Tr,
176
+ HistoricalFundPricePeriod.OneMonth
177
+ );
178
+
179
+ expect(resp).toBeDefined();
180
+ expect(Array.isArray(resp)).toBe(true);
181
+ expect(resp.length).toBeGreaterThan(0);
182
+
183
+ const pricePoint = resp[0];
184
+ expect(typeof pricePoint.price).toBe("number");
185
+ expect(typeof pricePoint.aum).toBe("number");
186
+ expect(pricePoint.date).toBeDefined();
187
+ expect(typeof pricePoint.shareCount).toBe("number");
188
+ expect(typeof pricePoint.investorCount).toBe("number");
189
+ });
72
190
  });
73
191
  });
74
192
 
75
- describe("getFundDistribution", () => {
76
- test("should return fund asset distribution", async () => {
77
- const resp = await client.getFundDistribution("SPP", Region.Tr);
193
+ describe("Mock Tests", () => {
194
+ beforeEach(() => {
195
+ jest.clearAllMocks();
196
+ });
197
+
198
+ describe("getFunds", () => {
199
+ test("should return funds list with mock data", async () => {
200
+ jest.spyOn(client, 'getFunds').mockResolvedValue(mockFundsResponse);
201
+
202
+ const resp = await client.getFunds(Region.Tr, 1, 10);
203
+
204
+ expect(resp).toHaveLength(2);
205
+
206
+ const firstFund = resp[0];
207
+ expect(firstFund.symbol).toBe("SPP");
208
+ expect(firstFund.name).toBe("Ak Portföy BIST 30 Endeksi Hisse Senedi Fonu");
209
+ expect(firstFund.assetType).toBe(AssetType.Stock);
210
+ expect(firstFund.managementFee).toBe(0.003);
211
+ expect(firstFund.riskLevel).toBe(6);
212
+ expect(firstFund.fundType).toBe(FundType.STOCK_UMBRELLA_FUND);
213
+ expect(firstFund.ownerSymbol).toBe("AKP");
214
+
215
+ expect(client.getFunds).toHaveBeenCalledWith(Region.Tr, 1, 10);
216
+ });
217
+
218
+ test("should handle pagination with mock data", async () => {
219
+ jest.spyOn(client, 'getFunds').mockResolvedValue([mockFundsResponse[0]]);
220
+
221
+ const resp = await client.getFunds(Region.Tr, 1, 1);
78
222
 
79
- expect(resp).toBeDefined();
80
- expect(Array.isArray(resp.categories)).toBe(true);
223
+ expect(resp).toHaveLength(1);
224
+ expect(resp[0].symbol).toBe("SPP");
81
225
 
82
- if (resp.categories.length > 0) {
83
- const distribution = resp.categories[0];
84
- expect(distribution.category).toBeDefined();
85
- expect(typeof distribution.percentage).toBe("number");
86
- }
226
+ expect(client.getFunds).toHaveBeenCalledWith(Region.Tr, 1, 1);
227
+ });
87
228
  });
88
- });
89
229
 
90
- describe("getHistoricalFundPrices", () => {
91
- test("should return historical prices", async () => {
92
- const resp = await client.getHistoricalFundPrices(
93
- "SPP",
94
- Region.Tr,
95
- HistoricalFundPricePeriod.OneMonth
96
- );
97
-
98
- expect(resp).toBeDefined();
99
- expect(Array.isArray(resp)).toBe(true);
100
- expect(resp.length).toBeGreaterThan(0);
101
-
102
- const pricePoint = resp[0];
103
- expect(typeof pricePoint.price).toBe("number");
104
- expect(typeof pricePoint.aum).toBe("number");
105
- expect(pricePoint.date).toBeDefined();
106
- expect(typeof pricePoint.shareCount).toBe("number");
107
- expect(typeof pricePoint.investorCount).toBe("number");
230
+ describe("getFundStats", () => {
231
+ test("should return fund statistics with mock data", async () => {
232
+ jest.spyOn(client, 'getFundStats').mockResolvedValue(mockFundStatsResponse);
233
+
234
+ const resp = await client.getFundStats("SPP", Region.Tr);
235
+
236
+ expect(resp.yearBeta).toBe(0.95);
237
+ expect(resp.yearStdev).toBe(0.12);
238
+ expect(resp.ytdReturn).toBe(0.15);
239
+ expect(resp.yearMomentum).toBe(0.08);
240
+ expect(resp.yearlyReturn).toBe(0.25);
241
+ expect(resp.monthlyReturn).toBe(0.03);
242
+ expect(resp.fiveYearReturn).toBe(1.85);
243
+ expect(resp.sixMonthReturn).toBe(0.18);
244
+ expect(resp.threeYearReturn).toBe(0.95);
245
+ expect(resp.threeMonthReturn).toBe(0.09);
246
+
247
+ expect(client.getFundStats).toHaveBeenCalledWith("SPP", Region.Tr);
248
+ });
249
+
250
+ test("should handle invalid fund symbol error", async () => {
251
+ jest.spyOn(client, 'getFundStats').mockRejectedValue(new Error("Fund not found"));
252
+
253
+ await expect(client.getFundStats("INVALID_FUND", Region.Tr))
254
+ .rejects.toThrow("Fund not found");
255
+ });
256
+ });
257
+
258
+ describe("getFundDistribution", () => {
259
+ test("should return fund distribution with mock data", async () => {
260
+ jest.spyOn(client, 'getFundDistribution').mockResolvedValue(mockFundDistributionResponse);
261
+
262
+ const resp = await client.getFundDistribution("SPP", Region.Tr);
263
+
264
+ expect(resp.categories).toHaveLength(2);
265
+
266
+ const equityCategory = resp.categories[0];
267
+ expect(equityCategory.category).toBe(FundAssetCategory.EQUITY);
268
+ expect(equityCategory.percentage).toBe(95.5);
269
+ expect(equityCategory.assets).toBeDefined();
270
+ expect(equityCategory.assets![0].symbol).toBe("GARAN");
271
+
272
+ const liquidCategory = resp.categories[1];
273
+ expect(liquidCategory.category).toBe(FundAssetCategory.LIQUID_DEPOSIT);
274
+ expect(liquidCategory.percentage).toBe(4.5);
275
+
276
+ expect(client.getFundDistribution).toHaveBeenCalledWith("SPP", Region.Tr);
277
+ });
278
+ });
279
+
280
+ describe("getHistoricalFundPrices", () => {
281
+ test("should return historical prices with mock data", async () => {
282
+ jest.spyOn(client, 'getHistoricalFundPrices').mockResolvedValue(mockHistoricalPricesResponse);
283
+
284
+ const resp = await client.getHistoricalFundPrices(
285
+ "SPP",
286
+ Region.Tr,
287
+ HistoricalFundPricePeriod.OneMonth
288
+ );
289
+
290
+ expect(resp).toHaveLength(2);
291
+
292
+ const firstPrice = resp[0];
293
+ expect(firstPrice.price).toBe(15.25);
294
+ expect(firstPrice.aum).toBe(1250000000);
295
+ expect(firstPrice.date).toBe("2024-03-14T10:00:00Z");
296
+ expect(firstPrice.shareCount).toBe(82000000);
297
+ expect(firstPrice.investorCount).toBe(25000);
298
+
299
+ expect(client.getHistoricalFundPrices).toHaveBeenCalledWith(
300
+ "SPP",
301
+ Region.Tr,
302
+ HistoricalFundPricePeriod.OneMonth
303
+ );
304
+ });
305
+
306
+ test("should handle invalid period error", async () => {
307
+ jest.spyOn(client, 'getHistoricalFundPrices').mockRejectedValue(new Error("Invalid period"));
308
+
309
+ await expect(client.getHistoricalFundPrices(
310
+ "SPP",
311
+ Region.Tr,
312
+ "INVALID_PERIOD" as HistoricalFundPricePeriod
313
+ )).rejects.toThrow("Invalid period");
314
+ });
108
315
  });
109
316
  });
110
317
  });
@@ -1,9 +1,19 @@
1
1
  import { Logger } from "winston";
2
2
  import { LaplaceConfiguration } from "../utilities/configuration";
3
3
  import "./client_test_suite";
4
- import { KeyInsightClient } from "../client/key-insights";
4
+ import { KeyInsightClient, KeyInsight } from "../client/key-insights";
5
5
  import { Region } from "../client/collections";
6
6
 
7
+ const mockTRKeyInsightResponse: KeyInsight = {
8
+ symbol: "TOASO",
9
+ insight: "Tofaş'ın net kârı, güçlü operasyonel performans ve yüksek ihracat gelirleri sayesinde geçen yılın aynı dönemine göre %85 artış gösterdi."
10
+ };
11
+
12
+ const mockUSKeyInsightResponse: KeyInsight = {
13
+ symbol: "AAPL",
14
+ insight: "Apple's revenue growth was driven by strong iPhone sales and continued expansion in services, with significant market share gains in emerging markets."
15
+ };
16
+
7
17
  describe("Key Insight", () => {
8
18
  let client: KeyInsightClient;
9
19
 
@@ -19,30 +29,82 @@ describe("Key Insight", () => {
19
29
  client = new KeyInsightClient(config, logger);
20
30
  });
21
31
 
22
- describe("getKeyInsights", () => {
23
- test("should return key insights for valid symbol", async () => {
24
- const resp = await client.getKeyInsights("TOASO", Region.Tr);
32
+ describe("Integration Tests", () => {
33
+ describe("getKeyInsights", () => {
34
+ test("should return key insights for valid symbol", async () => {
35
+ const resp = await client.getKeyInsights("TOASO", Region.Tr);
25
36
 
26
- expect(resp).toBeDefined();
27
- expect(resp.insight).toBeDefined();
28
- expect(resp.insight.length).toBeGreaterThan(0);
29
- expect(resp.symbol).toBe("TOASO");
30
- });
37
+ expect(resp).toBeDefined();
38
+ expect(resp.insight).toBeDefined();
39
+ expect(resp.insight.length).toBeGreaterThan(0);
40
+ expect(resp.symbol).toBe("TOASO");
41
+ });
42
+
43
+ test("should handle invalid symbol gracefully", async () => {
44
+ await expect(
45
+ client.getKeyInsights("INVALID_SYMBOL", Region.Tr)
46
+ ).rejects.toThrow();
47
+ });
48
+
49
+ test("should work with US region", async () => {
50
+ const resp = await client.getKeyInsights("AAPL", Region.Us);
51
+ expect(resp).toBeDefined();
52
+ expect(resp.symbol).toBe("AAPL");
53
+ });
31
54
 
32
- test("should handle invalid symbol gracefully", async () => {
33
- await expect(
34
- client.getKeyInsights("INVALID_SYMBOL", Region.Tr)
35
- ).rejects.toThrow();
55
+ test("should handle empty symbol", async () => {
56
+ await expect(client.getKeyInsights("", Region.Tr)).rejects.toThrow();
57
+ });
36
58
  });
59
+ });
37
60
 
38
- test("should work with US region", async () => {
39
- const resp = await client.getKeyInsights("AAPL", Region.Us);
40
- expect(resp).toBeDefined();
41
- expect(resp.symbol).toBe("AAPL");
61
+ describe("Mock Tests", () => {
62
+ beforeEach(() => {
63
+ jest.clearAllMocks();
42
64
  });
43
65
 
44
- test("should handle empty symbol", async () => {
45
- await expect(client.getKeyInsights("", Region.Tr)).rejects.toThrow();
66
+ describe("getKeyInsights", () => {
67
+ test("should return TR key insights with mock data", async () => {
68
+ jest.spyOn(client, 'getKeyInsights').mockResolvedValue(mockTRKeyInsightResponse);
69
+
70
+ const resp = await client.getKeyInsights("TOASO", Region.Tr);
71
+
72
+ expect(resp).toBeDefined();
73
+ expect(resp.symbol).toBe("TOASO");
74
+ expect(resp.insight).toBe(mockTRKeyInsightResponse.insight);
75
+
76
+ expect(client.getKeyInsights).toHaveBeenCalledWith("TOASO", Region.Tr);
77
+ });
78
+
79
+ test("should return US key insights with mock data", async () => {
80
+ jest.spyOn(client, 'getKeyInsights').mockResolvedValue(mockUSKeyInsightResponse);
81
+
82
+ const resp = await client.getKeyInsights("AAPL", Region.Us);
83
+
84
+ expect(resp).toBeDefined();
85
+ expect(resp.symbol).toBe("AAPL");
86
+ expect(resp.insight).toBe(mockUSKeyInsightResponse.insight);
87
+
88
+ expect(client.getKeyInsights).toHaveBeenCalledWith("AAPL", Region.Us);
89
+ });
90
+
91
+ test("should handle invalid symbol error", async () => {
92
+ jest.spyOn(client, 'getKeyInsights').mockRejectedValue(new Error("Symbol not found"));
93
+
94
+ await expect(client.getKeyInsights("INVALID_SYMBOL", Region.Tr))
95
+ .rejects.toThrow("Symbol not found");
96
+
97
+ expect(client.getKeyInsights).toHaveBeenCalledWith("INVALID_SYMBOL", Region.Tr);
98
+ });
99
+
100
+ test("should handle empty symbol error", async () => {
101
+ jest.spyOn(client, 'getKeyInsights').mockRejectedValue(new Error("Symbol cannot be empty"));
102
+
103
+ await expect(client.getKeyInsights("", Region.Tr))
104
+ .rejects.toThrow("Symbol cannot be empty");
105
+
106
+ expect(client.getKeyInsights).toHaveBeenCalledWith("", Region.Tr);
107
+ });
46
108
  });
47
109
  });
48
110
  });