laplace-api 4.8.0 → 5.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,204 +1,434 @@
1
1
  import { Logger } from "winston";
2
+ import axios from "axios";
2
3
  import { LaplaceConfiguration } from "../utilities/configuration";
3
4
  import {
4
- NewsClient,
5
- NewsHighlights,
6
- News,
7
- NewsType,
8
- NewsOrderBy,
5
+ NewsClient,
6
+ NewsType,
7
+ NewsOrderBy,
9
8
  } from "../client/news";
10
9
  import "./client_test_suite";
11
10
  import { Region, Locale } from "../client/collections";
12
11
  import { SortDirection } from "../client/broker";
13
- import { PaginatedResponse } from "../client/capital_increase";
14
-
15
- const mockNewsHighlightsResponse: NewsHighlights = {
16
- consumer: ["news1", "news2"],
17
- energyAndUtilities: ["news3"],
18
- finance: ["news4", "news5"],
19
- healthcare: ["news6"],
20
- industrialsAndMaterials: ["news7"],
21
- tech: ["news8"],
22
- other: ["news9"]
12
+
13
+ const mockNewsHighlightsResponse = {
14
+ tech: [
15
+ "Alphabet ve Amazon'un desteğiyle Anthropic, 2026 başlarında Hindistan'ın Bengaluru kentinde bir ofis açacak."
16
+ ],
17
+ other: [
18
+ "ABD Yüksek Mahkemesi, Epic Games'in davası kapsamında Google'ın Play uygulamalarındaki değişikliği engellemeyecek."
19
+ ],
20
+ finance: [
21
+ "Fifth Third Bank, Comerica'yı 10,9 milyar dolara satın alacak ve böylece ABD'nin 9. en büyük bankası olacak."
22
+ ],
23
+ consumer: [
24
+ "Tesla, rekabet ortamında pazar payını geri almak için daha ucuz Model Y ve Model 3'ü piyasaya sürdü; duyuru hisseleri etkiledi."
25
+ ],
26
+ healthcare: [
27
+ "İlaç üreticileri, Amgen ve Novo Nordisk'in de dahil olduğu şekilde, Trump'ın ilaç fiyatlarını düşürme planıyla uyumlu olarak tele-sağlık satışlarını artırıyor."
28
+ ],
29
+ energyAndUtilities: [
30
+ "ABD Enerji Bakanlığı, Stellantis ve GM'ye verilen 1,1 milyar dolarlık hibeleri iptal edebilir."
31
+ ],
32
+ industrialsAndMaterials: [
33
+ "Boeing, bir grevi sona erdirmek için IAM Sendikası ile geçici bir anlaşmaya vardı; detaylar açıklanmadı."
34
+ ]
23
35
  };
24
36
 
25
- const mockNewsResponse: News[] = [
37
+ const mockNewsResponse = {
38
+ items: [
26
39
  {
27
- url: "https://example.com/news1",
28
- imageUrl: "https://example.com/image1.jpg",
29
- timestamp: "2024-03-14T10:00:00Z",
30
- publisherUrl: "https://example.com",
31
- publisher: {
32
- name: "Example Publisher",
33
- logoUrl: "https://example.com/logo.png"
34
- },
35
- relatedTickers: [
36
- {
37
- id: "1",
38
- name: "Ticker 1",
39
- symbol: "TCK1"
40
- }
40
+ url: "https://www.reuters.com/business/energy/commonwealth-lng-wants-more-time-build-planned-export-facility-louisiana-2025-10-07/",
41
+ content: {
42
+ title: "Commonwealth LNG wants more time to build planned export facility in Louisiana",
43
+ content: [
44
+ "Commonwealth LNG has requested a four-year extension from federal regulators to construct & begin exporting liquefied natural gas..."
41
45
  ],
42
- qualityScore: 85,
43
- createdAt: "2024-03-14T09:00:00Z"
44
- },
45
- {
46
- url: "https://example.com/news2",
47
- imageUrl: "https://example.com/image2.jpg",
48
- timestamp: "2024-03-14T11:00:00Z",
49
- publisherUrl: "https://example.com",
50
- publisher: {
51
- name: "Example Publisher 2"
52
- },
53
- relatedTickers: [],
54
- qualityScore: 90,
55
- createdAt: "2024-03-14T10:00:00Z"
46
+ summary: [
47
+ "Commonwealth LNG has requested a four-year extension from federal regulators..."
48
+ ],
49
+ description:
50
+ "Commonwealth LNG has asked federal regulators for a four-year extension...",
51
+ investorInsight:
52
+ "What it means for investors: The extension request could postpone..."
53
+ },
54
+ sectors: { name: "Energy", meanType: 9, newsCount: 1 },
55
+ tickers: [{ id: "6203d1ba1e674875275558f7", name: "EQT Corp", symbol: "EQT" }],
56
+ imageUrl: "",
57
+ createdAt: "2025-10-07T17:10:01.560644Z",
58
+ publisher: { name: "Reuters", logoUrl: null },
59
+ timestamp: "2025-10-07T16:50:16Z",
60
+ categories: { name: "Sector News", newsCount: 1, categoryType: "StockSpesific" },
61
+ industries: { name: "Oil/Gas (Production and Exploration)", meanType: 78 },
62
+ publisherUrl: "Reuters",
63
+ qualityScore: 0,
64
+ relatedTickers: [{ id: "6203d1ba1e674875275558f7", name: "EQT Corp", symbol: "EQT" }]
56
65
  }
57
- ];
58
-
59
- const mockPaginatedNewsResponse: PaginatedResponse<News> = {
60
- recordCount: 2,
61
- items: mockNewsResponse
66
+ ],
67
+ recordCount: 352
62
68
  };
63
69
 
64
- describe("News Client", () => {
70
+ describe("NewsClient", () => {
71
+ let client: NewsClient;
72
+
73
+ beforeAll(() => {
74
+ const config = (global as any).testSuite.config as LaplaceConfiguration;
75
+ const logger: Logger = {
76
+ info: jest.fn(),
77
+ error: jest.fn(),
78
+ warn: jest.fn(),
79
+ debug: jest.fn(),
80
+ } as unknown as Logger;
81
+
82
+ client = new NewsClient(config, logger);
83
+ });
84
+
85
+ describe("Integration Tests", () => {
86
+ jest.setTimeout(60_000);
87
+
88
+ test("getHighlights returns valid data", async () => {
89
+ const resp = await client.getHighlights(Region.Us, Locale.Tr);
90
+
91
+ expect(resp).toBeDefined();
92
+
93
+ expect(Array.isArray(resp.consumer)).toBe(true);
94
+ expect(Array.isArray(resp.energyAndUtilities)).toBe(true);
95
+ expect(Array.isArray(resp.finance)).toBe(true);
96
+ expect(Array.isArray(resp.healthcare)).toBe(true);
97
+ expect(Array.isArray(resp.industrialsAndMaterials)).toBe(true);
98
+ expect(Array.isArray(resp.tech)).toBe(true);
99
+ expect(Array.isArray(resp.other)).toBe(true);
100
+
101
+ const first = resp.tech?.[0];
102
+ if (first != null) expect(typeof first).toBe("string");
103
+ });
104
+
105
+ test("getNews returns valid paginated data", async () => {
106
+ const resp = await client.getNews(
107
+ Region.Us,
108
+ Locale.Tr,
109
+ NewsType.BRIEFS,
110
+ 0,
111
+ 10,
112
+ NewsOrderBy.TIMESTAMP,
113
+ SortDirection.Desc
114
+ );
115
+
116
+ expect(resp).toBeDefined();
117
+ expect(typeof resp.recordCount).toBe("number");
118
+ expect(resp.recordCount).toBeGreaterThanOrEqual(0);
119
+ expect(Array.isArray(resp.items)).toBe(true);
120
+
121
+ if (resp.items.length > 0) {
122
+ const n = resp.items[0];
123
+
124
+ expect(typeof n.url).toBe("string");
125
+ expect(typeof n.imageUrl).toBe("string");
126
+ expect(typeof n.timestamp).toBe("string");
127
+ expect(typeof n.publisherUrl).toBe("string");
128
+ expect(typeof n.qualityScore).toBe("number");
129
+ expect(typeof n.createdAt).toBe("string");
130
+
131
+ expect(n.publisher).toBeDefined();
132
+ expect(typeof n.publisher.name).toBe("string");
133
+ expect(
134
+ typeof n.publisher.logoUrl === "string" || n.publisher.logoUrl == null
135
+ ).toBe(true);
136
+
137
+ expect(Array.isArray(n.relatedTickers)).toBe(true);
138
+ if (n.relatedTickers.length > 0) {
139
+ const t = n.relatedTickers[0];
140
+ expect(typeof t.id).toBe("string");
141
+ expect(typeof t.name).toBe("string");
142
+ expect(typeof t.symbol === "string" || t.symbol == null).toBe(true);
143
+ }
144
+
145
+ if (n.tickers != null) {
146
+ expect(Array.isArray(n.tickers)).toBe(true);
147
+ }
148
+
149
+ if (n.categories != null) {
150
+ expect(typeof n.categories.name).toBe("string");
151
+ expect(typeof n.categories.newsCount).toBe("number");
152
+ expect(
153
+ typeof n.categories.categoryType === "string" ||
154
+ n.categories.categoryType == null ||
155
+ n.categories.categoryType === undefined
156
+ ).toBe(true);
157
+ expect(
158
+ typeof n.categories.meanType === "number" ||
159
+ n.categories.meanType == null ||
160
+ n.categories.meanType === undefined
161
+ ).toBe(true);
162
+ }
163
+
164
+ if (n.sectors != null) {
165
+ expect(typeof n.sectors.name).toBe("string");
166
+ expect(typeof n.sectors.newsCount).toBe("number");
167
+ expect(
168
+ typeof n.sectors.categoryType === "string" ||
169
+ n.sectors.categoryType == null ||
170
+ n.sectors.categoryType === undefined
171
+ ).toBe(true);
172
+ expect(
173
+ typeof n.sectors.meanType === "number" ||
174
+ n.sectors.meanType == null ||
175
+ n.sectors.meanType === undefined
176
+ ).toBe(true);
177
+ }
178
+
179
+ if (n.industries != null) {
180
+ expect(typeof n.industries.name).toBe("string");
181
+ expect(typeof n.industries.meanType).toBe("number");
182
+ }
183
+
184
+ if (n.content != null) {
185
+ expect(typeof n.content.title).toBe("string");
186
+ expect(typeof n.content.description).toBe("string");
187
+ expect(Array.isArray(n.content.content)).toBe(true);
188
+ expect(Array.isArray(n.content.summary)).toBe(true);
189
+ expect(typeof n.content.investorInsight).toBe("string");
190
+ }
191
+ }
192
+ });
193
+
194
+ test("streamNews yields item before timeout or throws gracefully if none arrive", async () => {
195
+ let newsItemsReceived = 0;
196
+ const { events, cancel } = client.streamNews(Locale.Tr);
197
+
198
+ const receivePromise = (async () => {
199
+ for await (const items of events) {
200
+ if (items && items.length > 0) {
201
+ newsItemsReceived += items.length;
202
+ break;
203
+ }
204
+ }
205
+ })();
206
+
207
+ const timeoutPromise = new Promise((resolve) => setTimeout(resolve, 8000));
208
+ await Promise.race([receivePromise, timeoutPromise]);
209
+ cancel();
210
+ expect(newsItemsReceived).toBeGreaterThanOrEqual(0);
211
+ });
212
+ });
213
+
214
+ describe("Mock Tests", () => {
65
215
  let client: NewsClient;
216
+ let cli: { request: jest.Mock };
217
+
218
+ beforeEach(() => {
219
+ cli = { request: jest.fn() };
220
+
221
+ const config = (global as any).testSuite.config as LaplaceConfiguration;
222
+ const logger: Logger = {
223
+ info: jest.fn(),
224
+ error: jest.fn(),
225
+ warn: jest.fn(),
226
+ debug: jest.fn()
227
+ } as unknown as Logger;
228
+
229
+ client = new NewsClient(config, logger, cli as any);
230
+ });
66
231
 
67
- beforeAll(() => {
68
- const config = (global as any).testSuite.config as LaplaceConfiguration;
69
- const logger: Logger = {
70
- info: jest.fn(),
71
- error: jest.fn(),
72
- warn: jest.fn(),
73
- debug: jest.fn(),
74
- } as unknown as Logger;
232
+ describe("getHighlights", () => {
233
+ test("calls correct endpoint/params and matches raw response", async () => {
234
+ cli.request.mockResolvedValueOnce({ data: mockNewsHighlightsResponse });
75
235
 
76
- client = new NewsClient(config, logger);
236
+ const resp = await client.getHighlights(Region.Tr, Locale.Tr);
237
+
238
+ expect(cli.request).toHaveBeenCalledTimes(1);
239
+ const call = cli.request.mock.calls[0][0];
240
+
241
+ expect(call.method).toBe("GET");
242
+ expect(call.url).toBe("/api/v1/news/highlights");
243
+ expect(call.params).toEqual({ region: Region.Tr, locale: Locale.Tr });
244
+
245
+ expect(resp.consumer).toEqual(mockNewsHighlightsResponse.consumer);
246
+ expect(resp.energyAndUtilities).toEqual(mockNewsHighlightsResponse.energyAndUtilities);
247
+ expect(resp.finance).toEqual(mockNewsHighlightsResponse.finance);
248
+ expect(resp.healthcare).toEqual(mockNewsHighlightsResponse.healthcare);
249
+ expect(resp.industrialsAndMaterials).toEqual(mockNewsHighlightsResponse.industrialsAndMaterials);
250
+ expect(resp.tech).toEqual(mockNewsHighlightsResponse.tech);
251
+ expect(resp.other).toEqual(mockNewsHighlightsResponse.other);
252
+ });
253
+
254
+ test("bubbles up request error", async () => {
255
+ cli.request.mockRejectedValueOnce(new Error("Failed to fetch highlights"));
256
+
257
+ await expect(client.getHighlights(Region.Tr, Locale.Tr)).rejects.toThrow(
258
+ "Failed to fetch highlights"
259
+ );
260
+
261
+ expect(cli.request).toHaveBeenCalledTimes(1);
262
+ });
77
263
  });
78
264
 
79
- describe("Integration Tests", () => {
80
- describe("getHighlights", () => {
81
- test("should return news highlights for region and locale", async () => {
82
- const resp = await client.getHighlights(Region.Tr, Locale.Tr);
83
-
84
- expect(resp).toBeDefined();
85
- expect(Array.isArray(resp.consumer)).toBe(true);
86
- expect(Array.isArray(resp.energyAndUtilities)).toBe(true);
87
- expect(Array.isArray(resp.finance)).toBe(true);
88
- expect(Array.isArray(resp.healthcare)).toBe(true);
89
- expect(Array.isArray(resp.industrialsAndMaterials)).toBe(true);
90
- expect(Array.isArray(resp.tech)).toBe(true);
91
- expect(Array.isArray(resp.other)).toBe(true);
92
- });
265
+ describe("getNews", () => {
266
+ test("calls correct endpoint/params and matches raw response", async () => {
267
+ cli.request.mockResolvedValueOnce({ data: mockNewsResponse });
268
+
269
+ const resp = await client.getNews(
270
+ Region.Tr,
271
+ Locale.Tr,
272
+ NewsType.BRIEFS,
273
+ 1,
274
+ 10,
275
+ NewsOrderBy.TIMESTAMP,
276
+ SortDirection.Desc,
277
+ undefined
278
+ );
279
+
280
+ expect(cli.request).toHaveBeenCalledTimes(1);
281
+ const call = cli.request.mock.calls[0][0];
282
+
283
+ expect(call.method).toBe("GET");
284
+ expect(call.url).toBe("/api/v1/news");
285
+ expect(call.params).toEqual({
286
+ region: Region.Tr,
287
+ locale: Locale.Tr,
288
+ newsType: NewsType.BRIEFS,
289
+ page: 1,
290
+ size: 10,
291
+ orderBy: NewsOrderBy.TIMESTAMP,
292
+ orderByDirection: SortDirection.Desc
93
293
  });
94
294
 
95
- describe("getNews", () => {
96
- test("should return paginated news list", async () => {
97
- const resp = await client.getNews(
98
- Region.Tr,
99
- Locale.Tr,
100
- NewsType.BRIEFS,
101
- 1,
102
- 10,
103
- NewsOrderBy.TIMESTAMP,
104
- SortDirection.Desc,
105
- null
106
- );
107
-
108
- expect(resp).toBeDefined();
109
- expect(typeof resp.recordCount).toBe("number");
110
- expect(Array.isArray(resp.items)).toBe(true);
111
-
112
- if (resp.items.length > 0) {
113
- const firstNews = resp.items[0];
114
- expect(typeof firstNews.url).toBe("string");
115
- expect(typeof firstNews.timestamp).toBe("string");
116
- expect(typeof firstNews.publisher).toBe("object");
117
- expect(Array.isArray(firstNews.relatedTickers)).toBe(true);
118
- }
119
- });
295
+ expect(resp.recordCount).toBe(352);
296
+ expect(resp.items).toHaveLength(1);
297
+
298
+ const n = resp.items[0];
299
+
300
+ expect(n.url).toBe(mockNewsResponse.items[0].url);
301
+ expect(n.imageUrl).toBe(mockNewsResponse.items[0].imageUrl);
302
+ expect(n.timestamp).toBe(mockNewsResponse.items[0].timestamp);
303
+ expect(n.publisherUrl).toBe(mockNewsResponse.items[0].publisherUrl);
304
+ expect(n.qualityScore).toBe(mockNewsResponse.items[0].qualityScore);
305
+ expect(n.createdAt).toBe(mockNewsResponse.items[0].createdAt);
306
+
307
+ expect(n.publisher.name).toBe(mockNewsResponse.items[0].publisher.name);
308
+ expect(n.publisher.logoUrl).toBeNull();
309
+
310
+ expect(n.relatedTickers).toHaveLength(1);
311
+ expect(n.relatedTickers[0].id).toBe(mockNewsResponse.items[0].relatedTickers[0].id);
312
+ expect(n.relatedTickers[0].name).toBe(mockNewsResponse.items[0].relatedTickers[0].name);
313
+ expect(n.relatedTickers[0].symbol).toBe(mockNewsResponse.items[0].relatedTickers[0].symbol);
314
+
315
+ expect(n.tickers).toHaveLength(1);
316
+ expect(n.tickers![0].symbol).toBe("EQT");
317
+
318
+ expect(n.categories?.name).toBe(mockNewsResponse.items[0].categories.name);
319
+ expect(n.categories?.newsCount).toBe(mockNewsResponse.items[0].categories.newsCount);
320
+ expect(n.categories?.categoryType).toBe(mockNewsResponse.items[0].categories.categoryType);
321
+
322
+ expect(n.sectors?.name).toBe(mockNewsResponse.items[0].sectors.name);
323
+ expect(n.sectors?.newsCount).toBe(mockNewsResponse.items[0].sectors.newsCount);
324
+ expect(n.sectors?.meanType).toBe(mockNewsResponse.items[0].sectors.meanType);
325
+
326
+ expect(n.industries?.name).toBe(mockNewsResponse.items[0].industries.name);
327
+ expect(n.industries?.meanType).toBe(mockNewsResponse.items[0].industries.meanType);
328
+
329
+ expect(n.content?.title).toBe(mockNewsResponse.items[0].content.title);
330
+ expect(n.content?.description).toBe(mockNewsResponse.items[0].content.description);
331
+ expect(n.content?.content).toEqual(mockNewsResponse.items[0].content.content);
332
+ expect(n.content?.summary).toEqual(mockNewsResponse.items[0].content.summary);
333
+ expect(n.content?.investorInsight).toBe(mockNewsResponse.items[0].content.investorInsight);
334
+ });
335
+
336
+ test("does not send optional params when undefined", async () => {
337
+ cli.request.mockResolvedValueOnce({ data: mockNewsResponse });
338
+
339
+ await client.getNews(Region.Tr, Locale.Tr);
340
+
341
+ const call = cli.request.mock.calls[0][0];
342
+ expect(call.params).toEqual({
343
+ region: Region.Tr,
344
+ locale: Locale.Tr
120
345
  });
346
+ });
347
+
348
+ test("bubbles up request error", async () => {
349
+ cli.request.mockRejectedValueOnce(new Error("Failed to fetch news"));
350
+
351
+ await expect(
352
+ client.getNews(
353
+ Region.Tr,
354
+ Locale.Tr,
355
+ NewsType.REUTERS,
356
+ 0,
357
+ 10,
358
+ NewsOrderBy.TIMESTAMP,
359
+ SortDirection.Desc
360
+ )
361
+ ).rejects.toThrow("Failed to fetch news");
362
+
363
+ expect(cli.request).toHaveBeenCalledTimes(1);
364
+ });
121
365
  });
122
366
 
123
- describe("Mock Tests", () => {
124
- beforeEach(() => {
125
- jest.clearAllMocks();
367
+ describe("streamNews", () => {
368
+ test("calls correct endpoint/params and correctly yields stream entities", async () => {
369
+ const eventsList: any[] = [];
370
+
371
+ // Mock get response to return a readable stream
372
+ const mockStreamData = [
373
+ "data: " + JSON.stringify([{ url: "http://example.com/stream-news-1", publiser: { name: "test-publisher" } }]) + "\n\n",
374
+ "data: " + JSON.stringify([{ url: "http://example.com/stream-news-2", publiser: { name: "test-publisher-2" } }]) + "\n\n",
375
+ ];
376
+
377
+ const mockAsyncIterator = {
378
+ async *[Symbol.asyncIterator]() {
379
+ for (const chunk of mockStreamData) {
380
+ yield new TextEncoder().encode(chunk);
381
+ }
382
+ }
383
+ };
384
+
385
+ const axiosGetSpy = jest.spyOn(axios, 'get').mockResolvedValueOnce({
386
+ data: mockAsyncIterator
126
387
  });
127
388
 
128
- describe("getHighlights", () => {
129
- test("should return news highlights with mock data", async () => {
130
- jest.spyOn(client, 'getHighlights').mockResolvedValue(mockNewsHighlightsResponse);
389
+ const { events, cancel } = client.streamNews(Locale.Tr);
131
390
 
132
- const resp = await client.getHighlights(Region.Tr, Locale.Tr);
391
+ for await (const newsList of events) {
392
+ eventsList.push(newsList);
393
+ }
133
394
 
134
- expect(resp).toBeDefined();
135
- expect(resp.consumer).toHaveLength(2);
136
- expect(resp.energyAndUtilities).toHaveLength(1);
137
- expect(resp.finance).toHaveLength(2);
138
- expect(resp.tech).toHaveLength(1);
395
+ expect(axiosGetSpy).toHaveBeenCalledTimes(1);
396
+ const callArgs = axiosGetSpy.mock.calls[0];
397
+ expect(callArgs[0]).toBe(`${client["baseUrl"]}/api/v1/news/stream?locale=tr`);
398
+ expect(callArgs[1]?.responseType).toBe('stream');
139
399
 
140
- expect(client.getHighlights).toHaveBeenCalledWith(Region.Tr, Locale.Tr);
141
- });
400
+ expect(eventsList).toHaveLength(2);
401
+ expect(eventsList[0][0].url).toBe("http://example.com/stream-news-1");
402
+ expect(eventsList[1][0].url).toBe("http://example.com/stream-news-2");
142
403
 
143
- test("should handle API errors for highlights", async () => {
144
- jest.spyOn(client, 'getHighlights').mockRejectedValue(new Error("Failed to fetch highlights"));
404
+ cancel();
405
+ axiosGetSpy.mockRestore();
406
+ });
145
407
 
146
- await expect(client.getHighlights(Region.Tr, Locale.Tr))
147
- .rejects.toThrow("Failed to fetch highlights");
148
- });
149
- });
408
+ test("calls correct endpoint with optional parameters", async () => {
409
+ const mockAsyncIterator = {
410
+ async *[Symbol.asyncIterator]() {
411
+ yield new TextEncoder().encode("data: " + JSON.stringify([]) + "\n\n");
412
+ }
413
+ };
150
414
 
151
- describe("getNews", () => {
152
- test("should return paginated news with mock data", async () => {
153
- jest.spyOn(client, 'getNews').mockResolvedValue(mockPaginatedNewsResponse);
154
-
155
- const resp = await client.getNews(
156
- Region.Tr,
157
- Locale.Tr,
158
- NewsType.BRIEFS,
159
- 1,
160
- 10,
161
- NewsOrderBy.TIMESTAMP,
162
- SortDirection.Desc,
163
- null
164
- );
165
-
166
- expect(resp.items).toHaveLength(2);
167
- expect(resp.recordCount).toBe(2);
168
-
169
- const firstNews = resp.items[0];
170
- expect(firstNews.url).toBe("https://example.com/news1");
171
- expect(firstNews.publisher.name).toBe("Example Publisher");
172
- expect(firstNews.relatedTickers).toHaveLength(1);
173
- expect(firstNews.qualityScore).toBe(85);
174
-
175
- expect(client.getNews).toHaveBeenCalledWith(
176
- Region.Tr,
177
- Locale.Tr,
178
- NewsType.BRIEFS,
179
- 1,
180
- 10,
181
- NewsOrderBy.TIMESTAMP,
182
- SortDirection.Desc,
183
- null
184
- );
185
- });
186
-
187
- test("should handle API errors for news", async () => {
188
- jest.spyOn(client, 'getNews').mockRejectedValue(new Error("Failed to fetch news"));
189
-
190
- await expect(client.getNews(
191
- Region.Tr,
192
- Locale.Tr,
193
- NewsType.BRIEFS,
194
- 1,
195
- 10,
196
- NewsOrderBy.TIMESTAMP,
197
- SortDirection.Desc,
198
- null
199
- )).rejects.toThrow("Failed to fetch news");
200
- });
415
+ const axiosGetSpy = jest.spyOn(axios, 'get').mockResolvedValueOnce({
416
+ data: mockAsyncIterator
201
417
  });
418
+
419
+ const { events, cancel } = client.streamNews(Locale.En, ["tech"], ["AAPL"], ["category"], ["software"]);
420
+
421
+ for await (const _ of events) {
422
+ break;
423
+ }
424
+
425
+ expect(axiosGetSpy).toHaveBeenCalledTimes(1);
426
+ const callArgs = axiosGetSpy.mock.calls[0];
427
+ expect(callArgs[0]).toBe(`${client["baseUrl"]}/api/v1/news/stream?locale=en&sectors=tech&tickers=AAPL&categories=category&industries=software`);
428
+
429
+ cancel();
430
+ axiosGetSpy.mockRestore();
431
+ });
202
432
  });
433
+ });
203
434
  });
204
-