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.
@@ -3,14 +3,103 @@ import { Region } from "../client/collections";
3
3
  import { LaplaceConfiguration } from "../utilities/configuration";
4
4
  import "./client_test_suite";
5
5
  import {
6
- BaseBrokerStats,
7
6
  BrokerClient,
8
7
  BrokerSort,
8
+ SortDirection,
9
9
  BrokerStats,
10
- BrokerStockStats,
11
- StockBrokerStats,
12
- StockOverallStats,
10
+ Broker,
11
+ BrokerStock,
12
+ BrokerList,
13
+ BrokerItem,
13
14
  } from "../client/broker";
15
+ import { AssetType, AssetClass } from "../client/stocks";
16
+ import { PaginatedResponse } from "../client/capital_increase";
17
+
18
+ const mockBroker: Broker = {
19
+ id: 1001,
20
+ symbol: "BIYKR",
21
+ name: "BİYİKLI YATIRIM",
22
+ longName: "Bıyıklı Yatırım Menkul Değerler A.Ş.",
23
+ logo: "https://example.com/biykr.png"
24
+ };
25
+
26
+ const mockBroker2: Broker = {
27
+ id: 1002,
28
+ symbol: "GEDIK",
29
+ name: "GEDİK YATIRIM",
30
+ longName: "Gedik Yatırım Menkul Değerler A.Ş.",
31
+ logo: "https://example.com/gedik.png"
32
+ };
33
+
34
+ const mockBroker3: Broker = {
35
+ id: 1001,
36
+ symbol: "BIYKR",
37
+ name: "BİYİKLI YATIRIM",
38
+ longName: "Bıyıklı Yatırım Menkul Değerler A.Ş.",
39
+ logo: "https://example.com/biykr.png",
40
+ supportedAssetClasses: [AssetClass.Equity]
41
+ };
42
+
43
+ const mockBroker4: Broker = {
44
+ id: 1002,
45
+ symbol: "GEDIK",
46
+ name: "GEDİK YATIRIM",
47
+ longName: "Gedik Yatırım Menkul Değerler A.Ş.",
48
+ logo: "https://example.com/gedik.png",
49
+ supportedAssetClasses: [AssetClass.Equity]
50
+ };
51
+
52
+ const mockStock: BrokerStock = {
53
+ id: "61dd0d6f0ec2114146342fd0",
54
+ symbol: "TUPRS",
55
+ name: "Tüpraş",
56
+ assetType: AssetType.Stock,
57
+ assetClass: AssetClass.Equity
58
+ };
59
+
60
+ const mockStock2: BrokerStock = {
61
+ id: "61dd0d6f0ec2114146342fd1",
62
+ symbol: "GARAN",
63
+ name: "Garanti Bankası",
64
+ assetType: AssetType.Stock,
65
+ assetClass: AssetClass.Equity
66
+ };
67
+
68
+ const mockBrokerStats: BrokerStats = {
69
+ totalBuyAmount: 1000000,
70
+ totalSellAmount: 800000,
71
+ netAmount: 200000,
72
+ totalBuyVolume: 50000,
73
+ totalSellVolume: 40000,
74
+ totalVolume: 90000,
75
+ totalAmount: 1800000,
76
+ averageCost: 20.5
77
+ };
78
+
79
+ const mockBrokerItem: BrokerItem = {
80
+ ...mockBrokerStats,
81
+ broker: mockBroker,
82
+ stock: mockStock
83
+ };
84
+
85
+ const mockBrokerItem2: BrokerItem = {
86
+ ...mockBrokerStats,
87
+ totalBuyAmount: 900000,
88
+ totalSellAmount: 700000,
89
+ broker: mockBroker2,
90
+ stock: mockStock2
91
+ };
92
+
93
+ const mockBrokerList: BrokerList = {
94
+ recordCount: 2,
95
+ items: [mockBrokerItem, mockBrokerItem2],
96
+ totalStats: mockBrokerStats
97
+ };
98
+
99
+ const mockBrokersPaginatedResponse: PaginatedResponse<Broker> = {
100
+ recordCount: 2,
101
+ items: [mockBroker3, mockBroker4]
102
+ };
14
103
 
15
104
  describe("BrokerClient", () => {
16
105
  let brokerClient: BrokerClient;
@@ -32,35 +121,23 @@ describe("BrokerClient", () => {
32
121
  const fromDate = "2025-05-20";
33
122
  const toDate = "2025-05-28";
34
123
 
35
- test("getMarketBrokers returns valid and fully typed data", async () => {
36
- const response = await brokerClient.getMarketBrokers(
37
- Region.Tr,
38
- "2025-05-27",
39
- "2025-05-28",
40
- BrokerSort.Volume,
41
- 0,
42
- 5
43
- );
44
-
45
- expect(response).toBeDefined();
46
- expect(typeof response.recordCount).toBe("number");
47
-
48
- const stats = response.totalStats;
49
- expect(stats).toMatchObject<BaseBrokerStats>({
50
- totalBuyAmount: expect.any(Number),
51
- totalSellAmount: expect.any(Number),
52
- netAmount: expect.any(Number),
53
- totalBuyVolume: expect.any(Number),
54
- totalSellVolume: expect.any(Number),
55
- totalVolume: expect.any(Number),
56
- totalAmount: expect.any(Number),
57
- });
124
+ describe("Integration Tests", () => {
125
+ test("getMarketBrokers returns valid and fully typed data", async () => {
126
+ const response = await brokerClient.getMarketBrokers(
127
+ Region.Tr,
128
+ BrokerSort.TotalVolume,
129
+ SortDirection.Desc,
130
+ "2025-05-27",
131
+ "2025-05-28",
132
+ 0,
133
+ 5
134
+ );
58
135
 
59
- expect(Array.isArray(response.items)).toBe(true);
60
- expect(response.items.length).toBeGreaterThan(0);
136
+ expect(response).toBeDefined();
137
+ expect(typeof response.recordCount).toBe("number");
61
138
 
62
- for (const item of response.items) {
63
- expect(item).toMatchObject<BrokerStats>({
139
+ const stats = response.totalStats;
140
+ expect(stats).toMatchObject<BrokerStats>({
64
141
  totalBuyAmount: expect.any(Number),
65
142
  totalSellAmount: expect.any(Number),
66
143
  netAmount: expect.any(Number),
@@ -68,30 +145,50 @@ describe("BrokerClient", () => {
68
145
  totalSellVolume: expect.any(Number),
69
146
  totalVolume: expect.any(Number),
70
147
  totalAmount: expect.any(Number),
71
- broker: {
72
- id: expect.any(Number),
73
- symbol: expect.any(String),
74
- name: expect.any(String),
75
- longName: expect.any(String),
76
- logo: expect.any(String),
77
- },
78
148
  });
79
- }
80
- });
81
149
 
82
- test("getTopMarketBrokers returns fully typed top and rest stats", async () => {
83
- const response = await brokerClient.getTopMarketBrokers(
84
- region,
85
- fromDate,
86
- toDate,
87
- BrokerSort.Volume
88
- );
150
+ expect(Array.isArray(response.items)).toBe(true);
151
+ expect(response.items.length).toBeGreaterThan(0);
89
152
 
90
- expect(response).toBeDefined();
153
+ for (const item of response.items) {
154
+ expect(item).toMatchObject<BrokerStats>({
155
+ totalBuyAmount: expect.any(Number),
156
+ totalSellAmount: expect.any(Number),
157
+ netAmount: expect.any(Number),
158
+ totalBuyVolume: expect.any(Number),
159
+ totalSellVolume: expect.any(Number),
160
+ totalVolume: expect.any(Number),
161
+ totalAmount: expect.any(Number),
162
+ });
91
163
 
92
- const statsList = [response.topStats, response.restStats];
93
- for (const stats of statsList) {
94
- expect(stats).toMatchObject<BaseBrokerStats>({
164
+ if (item.broker) {
165
+ expect(item.broker).toMatchObject({
166
+ id: expect.any(Number),
167
+ symbol: expect.any(String),
168
+ name: expect.any(String),
169
+ longName: expect.any(String),
170
+ logo: expect.any(String),
171
+ });
172
+ }
173
+ }
174
+ });
175
+
176
+ test("getMarketStocks returns valid stock data", async () => {
177
+ const response = await brokerClient.getMarketStocks(
178
+ region,
179
+ BrokerSort.TotalVolume,
180
+ SortDirection.Desc,
181
+ fromDate,
182
+ toDate,
183
+ 0,
184
+ 5
185
+ );
186
+
187
+ expect(response).toBeDefined();
188
+ expect(typeof response.recordCount).toBe("number");
189
+
190
+ const stats = response.totalStats;
191
+ expect(stats).toMatchObject<BrokerStats>({
95
192
  totalBuyAmount: expect.any(Number),
96
193
  totalSellAmount: expect.any(Number),
97
194
  netAmount: expect.any(Number),
@@ -100,13 +197,49 @@ describe("BrokerClient", () => {
100
197
  totalVolume: expect.any(Number),
101
198
  totalAmount: expect.any(Number),
102
199
  });
103
- }
104
200
 
105
- expect(Array.isArray(response.topItems)).toBe(true);
106
- expect(response.topItems.length).toBeGreaterThan(0);
201
+ expect(Array.isArray(response.items)).toBe(true);
202
+
203
+ for (const item of response.items) {
204
+ expect(item).toMatchObject<BrokerStats>({
205
+ totalBuyAmount: expect.any(Number),
206
+ totalSellAmount: expect.any(Number),
207
+ netAmount: expect.any(Number),
208
+ totalBuyVolume: expect.any(Number),
209
+ totalSellVolume: expect.any(Number),
210
+ totalVolume: expect.any(Number),
211
+ totalAmount: expect.any(Number),
212
+ });
213
+
214
+ if (item.stock) {
215
+ expect(item.stock).toMatchObject({
216
+ id: expect.any(String),
217
+ symbol: expect.any(String),
218
+ name: expect.any(String),
219
+ assetType: expect.any(String),
220
+ assetClass: expect.any(String),
221
+ });
222
+ }
223
+ }
224
+ });
225
+
226
+ test("getBrokersByStock returns brokers for specific stock", async () => {
227
+ const response = await brokerClient.getBrokersByStock(
228
+ "TUPRS",
229
+ region,
230
+ BrokerSort.TotalVolume,
231
+ SortDirection.Desc,
232
+ fromDate,
233
+ toDate,
234
+ 0,
235
+ 5
236
+ );
237
+
238
+ expect(response).toBeDefined();
239
+ expect(typeof response.recordCount).toBe("number");
107
240
 
108
- for (const item of response.topItems) {
109
- expect(item).toMatchObject<BrokerStats>({
241
+ const stats = response.totalStats;
242
+ expect(stats).toMatchObject<BrokerStats>({
110
243
  totalBuyAmount: expect.any(Number),
111
244
  totalSellAmount: expect.any(Number),
112
245
  netAmount: expect.any(Number),
@@ -114,45 +247,54 @@ describe("BrokerClient", () => {
114
247
  totalSellVolume: expect.any(Number),
115
248
  totalVolume: expect.any(Number),
116
249
  totalAmount: expect.any(Number),
117
- broker: {
118
- id: expect.any(Number),
119
- symbol: expect.any(String),
120
- name: expect.any(String),
121
- longName: expect.any(String),
122
- logo: expect.any(String),
123
- },
124
250
  });
125
- }
126
- });
127
251
 
128
- test("getStockBrokers returns full broker stats with averageCost", async () => {
129
- const response = await brokerClient.getStockBrokers(
130
- region,
131
- fromDate,
132
- toDate,
133
- BrokerSort.Volume,
134
- "TUPRS",
135
- 0,
136
- 5
137
- );
138
-
139
- expect(response).toBeDefined();
140
- expect(typeof response.recordCount).toBe("number");
141
-
142
- expect(response.totalStats).toMatchObject<StockOverallStats>({
143
- totalBuyAmount: expect.any(Number),
144
- totalSellAmount: expect.any(Number),
145
- netAmount: expect.any(Number),
146
- totalBuyVolume: expect.any(Number),
147
- totalSellVolume: expect.any(Number),
148
- totalVolume: expect.any(Number),
149
- totalAmount: expect.any(Number),
150
- averageCost: expect.any(Number),
252
+ expect(Array.isArray(response.items)).toBe(true);
253
+
254
+ for (const item of response.items) {
255
+ expect(item).toMatchObject<BrokerStats>({
256
+ totalBuyAmount: expect.any(Number),
257
+ totalSellAmount: expect.any(Number),
258
+ netAmount: expect.any(Number),
259
+ totalBuyVolume: expect.any(Number),
260
+ totalSellVolume: expect.any(Number),
261
+ totalVolume: expect.any(Number),
262
+ totalAmount: expect.any(Number),
263
+ });
264
+
265
+ if (item.broker) {
266
+ expect(item.broker).toMatchObject({
267
+ id: expect.any(Number),
268
+ symbol: expect.any(String),
269
+ name: expect.any(String),
270
+ longName: expect.any(String),
271
+ logo: expect.any(String),
272
+ });
273
+ }
274
+
275
+ if ("averageCost" in item) {
276
+ expect(item.averageCost).toEqual(expect.any(Number));
277
+ }
278
+ }
151
279
  });
152
280
 
153
- for (const item of response.items) {
154
- expect(item).toMatchObject<StockBrokerStats>({
155
- averageCost: expect.any(Number),
281
+ test("getStocksByBroker returns stocks for specific broker", async () => {
282
+ const response = await brokerClient.getStocksByBroker(
283
+ "BIYKR",
284
+ region,
285
+ BrokerSort.TotalVolume,
286
+ SortDirection.Desc,
287
+ fromDate,
288
+ toDate,
289
+ 0,
290
+ 5
291
+ );
292
+
293
+ expect(response).toBeDefined();
294
+ expect(typeof response.recordCount).toBe("number");
295
+
296
+ const stats = response.totalStats;
297
+ expect(stats).toMatchObject<BrokerStats>({
156
298
  totalBuyAmount: expect.any(Number),
157
299
  totalSellAmount: expect.any(Number),
158
300
  netAmount: expect.any(Number),
@@ -160,103 +302,372 @@ describe("BrokerClient", () => {
160
302
  totalSellVolume: expect.any(Number),
161
303
  totalVolume: expect.any(Number),
162
304
  totalAmount: expect.any(Number),
163
- broker: {
305
+ });
306
+
307
+ expect(Array.isArray(response.items)).toBe(true);
308
+
309
+ for (const item of response.items) {
310
+ expect(item).toMatchObject<BrokerStats>({
311
+ totalBuyAmount: expect.any(Number),
312
+ totalSellAmount: expect.any(Number),
313
+ netAmount: expect.any(Number),
314
+ totalBuyVolume: expect.any(Number),
315
+ totalSellVolume: expect.any(Number),
316
+ totalVolume: expect.any(Number),
317
+ totalAmount: expect.any(Number),
318
+ });
319
+
320
+ if (item.stock) {
321
+ expect(item.stock).toMatchObject({
322
+ id: expect.any(String),
323
+ symbol: expect.any(String),
324
+ name: expect.any(String),
325
+ assetType: expect.any(String),
326
+ assetClass: expect.any(String),
327
+ });
328
+ }
329
+ }
330
+ });
331
+
332
+ test("getBrokers with assetClass parameter", async () => {
333
+ const response = await brokerClient.getBrokers(
334
+ Region.Tr,
335
+ 0,
336
+ 10,
337
+ AssetClass.Equity
338
+ );
339
+
340
+ expect(response).toBeDefined();
341
+ expect(typeof response.recordCount).toBe("number");
342
+ expect(Array.isArray(response.items)).toBe(true);
343
+
344
+ for (const broker of response.items) {
345
+ expect(broker).toMatchObject({
164
346
  id: expect.any(Number),
165
347
  symbol: expect.any(String),
166
348
  name: expect.any(String),
167
349
  longName: expect.any(String),
168
350
  logo: expect.any(String),
169
- },
170
- });
171
- }
172
- });
173
-
174
- test("getTopStockBrokers returns fully typed top & rest stats with averageCost", async () => {
175
- const response = await brokerClient.getTopStockBrokers(
176
- region,
177
- fromDate,
178
- toDate,
179
- BrokerSort.Volume,
180
- "TUPRS"
181
- );
351
+ });
352
+ expect(Array.isArray(broker.supportedAssetClasses)).toBe(true);
353
+ expect(broker.supportedAssetClasses).toEqual([AssetClass.Equity]);
354
+ }
355
+ });
182
356
 
183
- expect(response).toBeDefined();
357
+ test("getBrokers without assetClass parameter", async () => {
358
+ const response = await brokerClient.getBrokers(
359
+ Region.Tr,
360
+ 0,
361
+ 10
362
+ );
184
363
 
185
- for (const stats of [response.topStats, response.restStats]) {
186
- expect(stats).toMatchObject<StockOverallStats>({
187
- totalBuyAmount: expect.any(Number),
188
- totalSellAmount: expect.any(Number),
189
- netAmount: expect.any(Number),
190
- totalBuyVolume: expect.any(Number),
191
- totalSellVolume: expect.any(Number),
192
- totalVolume: expect.any(Number),
193
- totalAmount: expect.any(Number),
194
- averageCost: expect.any(Number),
195
- });
196
- }
364
+ expect(response).toBeDefined();
365
+ expect(typeof response.recordCount).toBe("number");
366
+ expect(Array.isArray(response.items)).toBe(true);
197
367
 
198
- for (const item of response.topItems) {
199
- expect(item).toMatchObject<StockBrokerStats>({
200
- averageCost: expect.any(Number),
201
- totalBuyAmount: expect.any(Number),
202
- totalSellAmount: expect.any(Number),
203
- netAmount: expect.any(Number),
204
- totalBuyVolume: expect.any(Number),
205
- totalSellVolume: expect.any(Number),
206
- totalVolume: expect.any(Number),
207
- totalAmount: expect.any(Number),
208
- broker: {
368
+ for (const broker of response.items) {
369
+ expect(broker).toMatchObject({
209
370
  id: expect.any(Number),
210
371
  symbol: expect.any(String),
211
372
  name: expect.any(String),
212
373
  longName: expect.any(String),
213
374
  logo: expect.any(String),
214
- },
215
- });
216
- }
375
+ });
376
+ }
377
+ });
217
378
  });
218
379
 
219
- test("getTopBrokersForBroker returns top brokers without averageCost", async () => {
220
- const response = await brokerClient.getTopStocksForBroker(
221
- region,
222
- fromDate,
223
- toDate,
224
- BrokerSort.Volume,
225
- "BIYKR"
226
- );
380
+ describe("Mock Tests", () => {
381
+ beforeEach(() => {
382
+ jest.clearAllMocks();
383
+ });
227
384
 
228
- expect(response).toBeDefined();
385
+ describe("getMarketBrokers", () => {
386
+ test("should return market brokers with stats", async () => {
387
+ jest.spyOn(brokerClient, 'getMarketBrokers').mockResolvedValue(mockBrokerList);
229
388
 
230
- for (const stats of [response.topStats, response.restStats]) {
231
- expect(stats).toMatchObject<BaseBrokerStats>({
232
- totalBuyAmount: expect.any(Number),
233
- totalSellAmount: expect.any(Number),
234
- netAmount: expect.any(Number),
235
- totalBuyVolume: expect.any(Number),
236
- totalSellVolume: expect.any(Number),
237
- totalVolume: expect.any(Number),
238
- totalAmount: expect.any(Number),
389
+ const response = await brokerClient.getMarketBrokers(
390
+ Region.Tr,
391
+ BrokerSort.TotalVolume,
392
+ SortDirection.Desc,
393
+ fromDate,
394
+ toDate,
395
+ 0,
396
+ 5
397
+ );
398
+
399
+ expect(response.recordCount).toBe(2);
400
+ expect(response.items).toHaveLength(2);
401
+ expect(response.totalStats).toEqual(mockBrokerStats);
402
+
403
+ const firstItem = response.items[0];
404
+ expect(firstItem.broker?.symbol).toBe("BIYKR");
405
+ expect(firstItem.totalBuyAmount).toBe(1000000);
406
+ expect(firstItem.totalSellAmount).toBe(800000);
407
+
408
+ expect(brokerClient.getMarketBrokers).toHaveBeenCalledWith(
409
+ Region.Tr,
410
+ BrokerSort.TotalVolume,
411
+ SortDirection.Desc,
412
+ fromDate,
413
+ toDate,
414
+ 0,
415
+ 5
416
+ );
239
417
  });
240
- }
241
418
 
242
- for (const item of response.topItems) {
243
- expect(item).toMatchObject<BrokerStockStats>({
244
- totalBuyAmount: expect.any(Number),
245
- totalSellAmount: expect.any(Number),
246
- netAmount: expect.any(Number),
247
- totalBuyVolume: expect.any(Number),
248
- totalSellVolume: expect.any(Number),
249
- totalVolume: expect.any(Number),
250
- totalAmount: expect.any(Number),
251
- stock: {
252
- id: expect.any(String),
253
- symbol: expect.any(String),
254
- name: expect.any(String),
255
- assetType: expect.any(String),
256
- assetClass: expect.any(String),
257
- region: expect.any(String),
258
- },
419
+ test("should handle empty response", async () => {
420
+ const emptyResponse: BrokerList = {
421
+ recordCount: 0,
422
+ items: [],
423
+ totalStats: {
424
+ totalBuyAmount: 0,
425
+ totalSellAmount: 0,
426
+ netAmount: 0,
427
+ totalBuyVolume: 0,
428
+ totalSellVolume: 0,
429
+ totalVolume: 0,
430
+ totalAmount: 0
431
+ }
432
+ };
433
+ jest.spyOn(brokerClient, 'getMarketBrokers').mockResolvedValue(emptyResponse);
434
+
435
+ const response = await brokerClient.getMarketBrokers(
436
+ Region.Tr,
437
+ BrokerSort.TotalVolume,
438
+ SortDirection.Desc,
439
+ fromDate,
440
+ toDate,
441
+ 0,
442
+ 5
443
+ );
444
+
445
+ expect(response.recordCount).toBe(0);
446
+ expect(response.items).toHaveLength(0);
447
+ expect(response.totalStats.totalAmount).toBe(0);
448
+ });
449
+ });
450
+
451
+ describe("getMarketStocks", () => {
452
+ test("should return market stocks with stats", async () => {
453
+ jest.spyOn(brokerClient, 'getMarketStocks').mockResolvedValue(mockBrokerList);
454
+
455
+ const response = await brokerClient.getMarketStocks(
456
+ Region.Tr,
457
+ BrokerSort.TotalVolume,
458
+ SortDirection.Desc,
459
+ fromDate,
460
+ toDate,
461
+ 0,
462
+ 5
463
+ );
464
+
465
+ expect(response.recordCount).toBe(2);
466
+ expect(response.items).toHaveLength(2);
467
+ expect(response.totalStats).toEqual(mockBrokerStats);
468
+
469
+ const firstItem = response.items[0];
470
+ expect(firstItem.stock?.symbol).toBe("TUPRS");
471
+ expect(firstItem.stock?.assetType).toBe(AssetType.Stock);
472
+ expect(firstItem.stock?.assetClass).toBe(AssetClass.Equity);
473
+
474
+ expect(brokerClient.getMarketStocks).toHaveBeenCalledWith(
475
+ Region.Tr,
476
+ BrokerSort.TotalVolume,
477
+ SortDirection.Desc,
478
+ fromDate,
479
+ toDate,
480
+ 0,
481
+ 5
482
+ );
483
+ });
484
+ });
485
+
486
+ describe("getBrokersByStock", () => {
487
+ test("should return brokers for specific stock", async () => {
488
+ jest.spyOn(brokerClient, 'getBrokersByStock').mockResolvedValue(mockBrokerList);
489
+
490
+ const response = await brokerClient.getBrokersByStock(
491
+ "TUPRS",
492
+ Region.Tr,
493
+ BrokerSort.TotalVolume,
494
+ SortDirection.Desc,
495
+ fromDate,
496
+ toDate,
497
+ 0,
498
+ 5
499
+ );
500
+
501
+ expect(response.recordCount).toBe(2);
502
+ expect(response.items).toHaveLength(2);
503
+ expect(response.totalStats).toEqual(mockBrokerStats);
504
+
505
+ const firstItem = response.items[0];
506
+ expect(firstItem.broker?.symbol).toBe("BIYKR");
507
+ expect(firstItem.averageCost).toBe(20.5);
508
+
509
+ expect(brokerClient.getBrokersByStock).toHaveBeenCalledWith(
510
+ "TUPRS",
511
+ Region.Tr,
512
+ BrokerSort.TotalVolume,
513
+ SortDirection.Desc,
514
+ fromDate,
515
+ toDate,
516
+ 0,
517
+ 5
518
+ );
259
519
  });
260
- }
520
+
521
+ test("should handle invalid stock symbol", async () => {
522
+ jest.spyOn(brokerClient, 'getBrokersByStock').mockRejectedValue(new Error("Invalid stock symbol"));
523
+
524
+ await expect(brokerClient.getBrokersByStock(
525
+ "INVALID",
526
+ Region.Tr,
527
+ BrokerSort.TotalVolume,
528
+ SortDirection.Desc,
529
+ fromDate,
530
+ toDate,
531
+ 0,
532
+ 5
533
+ )).rejects.toThrow("Invalid stock symbol");
534
+ });
535
+ });
536
+
537
+ describe("getStocksByBroker", () => {
538
+ test("should return stocks for specific broker", async () => {
539
+ jest.spyOn(brokerClient, 'getStocksByBroker').mockResolvedValue(mockBrokerList);
540
+
541
+ const response = await brokerClient.getStocksByBroker(
542
+ "BIYKR",
543
+ Region.Tr,
544
+ BrokerSort.TotalVolume,
545
+ SortDirection.Desc,
546
+ fromDate,
547
+ toDate,
548
+ 0,
549
+ 5
550
+ );
551
+
552
+ expect(response.recordCount).toBe(2);
553
+ expect(response.items).toHaveLength(2);
554
+ expect(response.totalStats).toEqual(mockBrokerStats);
555
+
556
+ const firstItem = response.items[0];
557
+ expect(firstItem.stock?.symbol).toBe("TUPRS");
558
+ expect(firstItem.stock?.assetType).toBe(AssetType.Stock);
559
+
560
+ expect(brokerClient.getStocksByBroker).toHaveBeenCalledWith(
561
+ "BIYKR",
562
+ Region.Tr,
563
+ BrokerSort.TotalVolume,
564
+ SortDirection.Desc,
565
+ fromDate,
566
+ toDate,
567
+ 0,
568
+ 5
569
+ );
570
+ });
571
+
572
+ test("should handle invalid broker symbol", async () => {
573
+ jest.spyOn(brokerClient, 'getStocksByBroker').mockRejectedValue(new Error("Invalid broker symbol"));
574
+
575
+ await expect(brokerClient.getStocksByBroker(
576
+ "INVALID",
577
+ Region.Tr,
578
+ BrokerSort.TotalVolume,
579
+ SortDirection.Desc,
580
+ fromDate,
581
+ toDate,
582
+ 0,
583
+ 5
584
+ )).rejects.toThrow("Invalid broker symbol");
585
+ });
586
+ });
587
+
588
+ describe("getBrokers", () => {
589
+ test("should return paginated broker list", async () => {
590
+ jest.spyOn(brokerClient, 'getBrokers').mockResolvedValue(mockBrokersPaginatedResponse);
591
+
592
+ const response = await brokerClient.getBrokers(
593
+ Region.Tr,
594
+ 0,
595
+ 5,
596
+ AssetClass.Equity
597
+ );
598
+
599
+ expect(response.recordCount).toBe(2);
600
+ expect(response.items).toHaveLength(2);
601
+
602
+ const firstBroker = response.items[0];
603
+ expect(firstBroker.id).toBe(1001);
604
+ expect(firstBroker.symbol).toBe("BIYKR");
605
+ expect(firstBroker.name).toBe("BİYİKLI YATIRIM");
606
+ expect(firstBroker.longName).toBe("Bıyıklı Yatırım Menkul Değerler A.Ş.");
607
+ expect(firstBroker.logo).toBe("https://example.com/biykr.png");
608
+ expect(firstBroker.supportedAssetClasses).toEqual([AssetClass.Equity]);
609
+
610
+ expect(brokerClient.getBrokers).toHaveBeenCalledWith(
611
+ Region.Tr,
612
+ 0,
613
+ 5,
614
+ AssetClass.Equity
615
+ );
616
+ });
617
+
618
+ test("should handle getBrokers without assetClass parameter", async () => {
619
+ jest.spyOn(brokerClient, 'getBrokers').mockResolvedValue(mockBrokersPaginatedResponse);
620
+
621
+ const response = await brokerClient.getBrokers(
622
+ Region.Tr,
623
+ 0,
624
+ 5
625
+ );
626
+
627
+ expect(response.recordCount).toBe(2);
628
+ expect(response.items).toHaveLength(2);
629
+
630
+ const firstBroker = response.items[0];
631
+ expect(firstBroker.id).toBe(1001);
632
+ expect(firstBroker.symbol).toBe("BIYKR");
633
+ expect(firstBroker.name).toBe("BİYİKLI YATIRIM");
634
+ expect(firstBroker.longName).toBe("Bıyıklı Yatırım Menkul Değerler A.Ş.");
635
+ expect(firstBroker.logo).toBe("https://example.com/biykr.png");
636
+
637
+ expect(brokerClient.getBrokers).toHaveBeenCalledWith(
638
+ Region.Tr,
639
+ 0,
640
+ 5
641
+ );
642
+ });
643
+
644
+ test("should handle empty brokers response", async () => {
645
+ const emptyResponse: PaginatedResponse<Broker> = {
646
+ recordCount: 0,
647
+ items: []
648
+ };
649
+ jest.spyOn(brokerClient, 'getBrokers').mockResolvedValue(emptyResponse);
650
+
651
+ const response = await brokerClient.getBrokers(
652
+ Region.Tr,
653
+ 0,
654
+ 10
655
+ );
656
+
657
+ expect(response.recordCount).toBe(0);
658
+ expect(response.items).toHaveLength(0);
659
+ });
660
+
661
+ test("should handle getBrokers error", async () => {
662
+ jest.spyOn(brokerClient, 'getBrokers').mockRejectedValue(new Error("Unsupported asset class"));
663
+
664
+ await expect(brokerClient.getBrokers(
665
+ Region.Tr,
666
+ 0,
667
+ 10,
668
+ AssetClass.Crypto
669
+ )).rejects.toThrow("Unsupported asset class");
670
+ });
671
+ });
261
672
  });
262
- });
673
+ });