laplace-api 4.0.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.
- package/.github/workflows/publish.yml +37 -0
- package/.github/workflows/test.yml +25 -0
- package/README.md +461 -2
- package/package.json +1 -1
- package/src/client/broker.ts +9 -7
- package/src/client/capital_increase.ts +7 -12
- package/src/client/collections.ts +57 -28
- package/src/client/financial_fundamentals.ts +2 -5
- package/src/client/financial_ratios.ts +114 -95
- package/src/client/live-price-web-socket.ts +84 -11
- package/src/client/live-price.ts +204 -77
- package/src/client/politician.ts +75 -0
- package/src/client/stocks.ts +73 -0
- package/src/test/broker.test.ts +583 -148
- package/src/test/capital_increase.test.ts +186 -39
- package/src/test/collections.test.ts +445 -60
- package/src/test/custom_theme.test.ts +242 -60
- package/src/test/financial_fundamentals.test.ts +297 -56
- package/src/test/financial_ratios.test.ts +363 -92
- package/src/test/funds.test.ts +275 -68
- package/src/test/key-insight.test.ts +81 -19
- package/src/test/live-price.test.ts +425 -64
- package/src/test/politician.test.ts +253 -0
- package/src/test/readme.test.ts +483 -0
- package/src/test/search.test.ts +301 -65
- package/src/test/stocks.test.ts +764 -152
- package/src/utilities/configuration.ts +23 -10
- package/src/utilities/test.env +2 -2
package/src/test/broker.test.ts
CHANGED
|
@@ -7,7 +7,99 @@ import {
|
|
|
7
7
|
BrokerSort,
|
|
8
8
|
SortDirection,
|
|
9
9
|
BrokerStats,
|
|
10
|
+
Broker,
|
|
11
|
+
BrokerStock,
|
|
12
|
+
BrokerList,
|
|
13
|
+
BrokerItem,
|
|
10
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
|
+
};
|
|
11
103
|
|
|
12
104
|
describe("BrokerClient", () => {
|
|
13
105
|
let brokerClient: BrokerClient;
|
|
@@ -29,36 +121,23 @@ describe("BrokerClient", () => {
|
|
|
29
121
|
const fromDate = "2025-05-20";
|
|
30
122
|
const toDate = "2025-05-28";
|
|
31
123
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
expect(response).toBeDefined();
|
|
44
|
-
expect(typeof response.recordCount).toBe("number");
|
|
45
|
-
|
|
46
|
-
const stats = response.totalStats;
|
|
47
|
-
expect(stats).toMatchObject<BrokerStats>({
|
|
48
|
-
totalBuyAmount: expect.any(Number),
|
|
49
|
-
totalSellAmount: expect.any(Number),
|
|
50
|
-
netAmount: expect.any(Number),
|
|
51
|
-
totalBuyVolume: expect.any(Number),
|
|
52
|
-
totalSellVolume: expect.any(Number),
|
|
53
|
-
totalVolume: expect.any(Number),
|
|
54
|
-
totalAmount: expect.any(Number),
|
|
55
|
-
});
|
|
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
|
+
);
|
|
56
135
|
|
|
57
|
-
|
|
58
|
-
|
|
136
|
+
expect(response).toBeDefined();
|
|
137
|
+
expect(typeof response.recordCount).toBe("number");
|
|
59
138
|
|
|
60
|
-
|
|
61
|
-
expect(
|
|
139
|
+
const stats = response.totalStats;
|
|
140
|
+
expect(stats).toMatchObject<BrokerStats>({
|
|
62
141
|
totalBuyAmount: expect.any(Number),
|
|
63
142
|
totalSellAmount: expect.any(Number),
|
|
64
143
|
netAmount: expect.any(Number),
|
|
@@ -68,47 +147,48 @@ describe("BrokerClient", () => {
|
|
|
68
147
|
totalAmount: expect.any(Number),
|
|
69
148
|
});
|
|
70
149
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
150
|
+
expect(Array.isArray(response.items)).toBe(true);
|
|
151
|
+
expect(response.items.length).toBeGreaterThan(0);
|
|
152
|
+
|
|
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),
|
|
78
162
|
});
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
163
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
expect(response).toBeDefined();
|
|
95
|
-
expect(typeof response.recordCount).toBe("number");
|
|
96
|
-
|
|
97
|
-
const stats = response.totalStats;
|
|
98
|
-
expect(stats).toMatchObject<BrokerStats>({
|
|
99
|
-
totalBuyAmount: expect.any(Number),
|
|
100
|
-
totalSellAmount: expect.any(Number),
|
|
101
|
-
netAmount: expect.any(Number),
|
|
102
|
-
totalBuyVolume: expect.any(Number),
|
|
103
|
-
totalSellVolume: expect.any(Number),
|
|
104
|
-
totalVolume: expect.any(Number),
|
|
105
|
-
totalAmount: expect.any(Number),
|
|
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
|
+
}
|
|
106
174
|
});
|
|
107
175
|
|
|
108
|
-
|
|
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");
|
|
109
189
|
|
|
110
|
-
|
|
111
|
-
expect(
|
|
190
|
+
const stats = response.totalStats;
|
|
191
|
+
expect(stats).toMatchObject<BrokerStats>({
|
|
112
192
|
totalBuyAmount: expect.any(Number),
|
|
113
193
|
totalSellAmount: expect.any(Number),
|
|
114
194
|
netAmount: expect.any(Number),
|
|
@@ -118,48 +198,48 @@ describe("BrokerClient", () => {
|
|
|
118
198
|
totalAmount: expect.any(Number),
|
|
119
199
|
});
|
|
120
200
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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),
|
|
128
212
|
});
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
213
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
expect(response).toBeDefined();
|
|
146
|
-
expect(typeof response.recordCount).toBe("number");
|
|
147
|
-
|
|
148
|
-
const stats = response.totalStats;
|
|
149
|
-
expect(stats).toMatchObject<BrokerStats>({
|
|
150
|
-
totalBuyAmount: expect.any(Number),
|
|
151
|
-
totalSellAmount: expect.any(Number),
|
|
152
|
-
netAmount: expect.any(Number),
|
|
153
|
-
totalBuyVolume: expect.any(Number),
|
|
154
|
-
totalSellVolume: expect.any(Number),
|
|
155
|
-
totalVolume: expect.any(Number),
|
|
156
|
-
totalAmount: expect.any(Number),
|
|
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
|
+
}
|
|
157
224
|
});
|
|
158
225
|
|
|
159
|
-
|
|
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
|
+
);
|
|
160
237
|
|
|
161
|
-
|
|
162
|
-
expect(
|
|
238
|
+
expect(response).toBeDefined();
|
|
239
|
+
expect(typeof response.recordCount).toBe("number");
|
|
240
|
+
|
|
241
|
+
const stats = response.totalStats;
|
|
242
|
+
expect(stats).toMatchObject<BrokerStats>({
|
|
163
243
|
totalBuyAmount: expect.any(Number),
|
|
164
244
|
totalSellAmount: expect.any(Number),
|
|
165
245
|
netAmount: expect.any(Number),
|
|
@@ -169,52 +249,52 @@ describe("BrokerClient", () => {
|
|
|
169
249
|
totalAmount: expect.any(Number),
|
|
170
250
|
});
|
|
171
251
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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),
|
|
179
263
|
});
|
|
180
|
-
}
|
|
181
264
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
+
}
|
|
187
274
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
BrokerSort.TotalVolume,
|
|
193
|
-
SortDirection.Desc,
|
|
194
|
-
fromDate,
|
|
195
|
-
toDate,
|
|
196
|
-
0,
|
|
197
|
-
5
|
|
198
|
-
);
|
|
199
|
-
|
|
200
|
-
expect(response).toBeDefined();
|
|
201
|
-
expect(typeof response.recordCount).toBe("number");
|
|
202
|
-
|
|
203
|
-
const stats = response.totalStats;
|
|
204
|
-
expect(stats).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),
|
|
275
|
+
if ("averageCost" in item) {
|
|
276
|
+
expect(item.averageCost).toEqual(expect.any(Number));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
212
279
|
});
|
|
213
280
|
|
|
214
|
-
|
|
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
|
+
);
|
|
215
292
|
|
|
216
|
-
|
|
217
|
-
expect(
|
|
293
|
+
expect(response).toBeDefined();
|
|
294
|
+
expect(typeof response.recordCount).toBe("number");
|
|
295
|
+
|
|
296
|
+
const stats = response.totalStats;
|
|
297
|
+
expect(stats).toMatchObject<BrokerStats>({
|
|
218
298
|
totalBuyAmount: expect.any(Number),
|
|
219
299
|
totalSellAmount: expect.any(Number),
|
|
220
300
|
netAmount: expect.any(Number),
|
|
@@ -224,15 +304,370 @@ describe("BrokerClient", () => {
|
|
|
224
304
|
totalAmount: expect.any(Number),
|
|
225
305
|
});
|
|
226
306
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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({
|
|
346
|
+
id: expect.any(Number),
|
|
230
347
|
symbol: expect.any(String),
|
|
231
348
|
name: expect.any(String),
|
|
232
|
-
|
|
233
|
-
|
|
349
|
+
longName: expect.any(String),
|
|
350
|
+
logo: expect.any(String),
|
|
351
|
+
});
|
|
352
|
+
expect(Array.isArray(broker.supportedAssetClasses)).toBe(true);
|
|
353
|
+
expect(broker.supportedAssetClasses).toEqual([AssetClass.Equity]);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
test("getBrokers without assetClass parameter", async () => {
|
|
358
|
+
const response = await brokerClient.getBrokers(
|
|
359
|
+
Region.Tr,
|
|
360
|
+
0,
|
|
361
|
+
10
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
expect(response).toBeDefined();
|
|
365
|
+
expect(typeof response.recordCount).toBe("number");
|
|
366
|
+
expect(Array.isArray(response.items)).toBe(true);
|
|
367
|
+
|
|
368
|
+
for (const broker of response.items) {
|
|
369
|
+
expect(broker).toMatchObject({
|
|
370
|
+
id: expect.any(Number),
|
|
371
|
+
symbol: expect.any(String),
|
|
372
|
+
name: expect.any(String),
|
|
373
|
+
longName: expect.any(String),
|
|
374
|
+
logo: expect.any(String),
|
|
234
375
|
});
|
|
235
376
|
}
|
|
236
|
-
}
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
describe("Mock Tests", () => {
|
|
381
|
+
beforeEach(() => {
|
|
382
|
+
jest.clearAllMocks();
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
describe("getMarketBrokers", () => {
|
|
386
|
+
test("should return market brokers with stats", async () => {
|
|
387
|
+
jest.spyOn(brokerClient, 'getMarketBrokers').mockResolvedValue(mockBrokerList);
|
|
388
|
+
|
|
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
|
+
);
|
|
417
|
+
});
|
|
418
|
+
|
|
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
|
+
);
|
|
519
|
+
});
|
|
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
|
+
});
|
|
237
672
|
});
|
|
238
|
-
});
|
|
673
|
+
});
|