laplace-api 5.2.3 → 5.5.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/package.json +1 -1
- package/src/client/news.ts +109 -35
- package/src/test/news.test.ts +230 -60
package/package.json
CHANGED
package/src/client/news.ts
CHANGED
|
@@ -22,8 +22,37 @@ export enum NewsType {
|
|
|
22
22
|
|
|
23
23
|
export enum NewsOrderBy {
|
|
24
24
|
TIMESTAMP = "timestamp",
|
|
25
|
+
QUALITY_SCORE = "quality_score",
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
export enum NewsLane {
|
|
29
|
+
GLOBAL_MACRO = "global_macro",
|
|
30
|
+
TR_EKONOMI = "tr_ekonomi",
|
|
31
|
+
BIST = "bist",
|
|
32
|
+
FAST_MOVERS = "fast_movers",
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface GetNewsParams {
|
|
36
|
+
lane?: NewsLane;
|
|
37
|
+
apiSource?: string;
|
|
38
|
+
newsType?: NewsType;
|
|
39
|
+
orderBy?: NewsOrderBy;
|
|
40
|
+
orderByDirection?: SortDirection;
|
|
41
|
+
symbols?: string;
|
|
42
|
+
categories?: string;
|
|
43
|
+
sectors?: string;
|
|
44
|
+
industries?: string;
|
|
45
|
+
qualityScoreMin?: number;
|
|
46
|
+
qualityScoreMax?: number;
|
|
47
|
+
timestampFrom?: string;
|
|
48
|
+
timestampTo?: string;
|
|
49
|
+
page?: number;
|
|
50
|
+
size?: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** @deprecated Use {@link GetNewsParams}; v1 and v2 now accept the same filters. */
|
|
54
|
+
export type GetNewsV2Params = GetNewsParams;
|
|
55
|
+
|
|
27
56
|
export interface News {
|
|
28
57
|
url: string;
|
|
29
58
|
imageUrl: string;
|
|
@@ -80,6 +109,21 @@ export interface NewsIndustry {
|
|
|
80
109
|
meanType: number;
|
|
81
110
|
}
|
|
82
111
|
|
|
112
|
+
export interface NewsCategory {
|
|
113
|
+
id: string;
|
|
114
|
+
name: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface NewsLaneInfo {
|
|
118
|
+
id: NewsLane;
|
|
119
|
+
label: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface NewsApiSource {
|
|
123
|
+
id: string;
|
|
124
|
+
name: string;
|
|
125
|
+
}
|
|
126
|
+
|
|
83
127
|
export class NewsClient extends Client {
|
|
84
128
|
async getHighlights(
|
|
85
129
|
region: Region,
|
|
@@ -96,59 +140,85 @@ export class NewsClient extends Client {
|
|
|
96
140
|
}
|
|
97
141
|
|
|
98
142
|
|
|
99
|
-
async
|
|
143
|
+
async getNewsCategories(locale?: Locale): Promise<NewsCategory[]> {
|
|
144
|
+
return this.sendRequest<NewsCategory[]>({
|
|
145
|
+
method: "GET",
|
|
146
|
+
url: "/api/v1/news/categories",
|
|
147
|
+
params: {
|
|
148
|
+
...(locale != null && { locale }),
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async getNewsLanes(): Promise<NewsLaneInfo[]> {
|
|
154
|
+
return this.sendRequest<NewsLaneInfo[]>({
|
|
155
|
+
method: "GET",
|
|
156
|
+
url: "/api/v1/news/lanes",
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async getApiSourceNames(): Promise<NewsApiSource[]> {
|
|
161
|
+
return this.sendRequest<NewsApiSource[]>({
|
|
162
|
+
method: "GET",
|
|
163
|
+
url: "/api/v1/news/api-source-names",
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private buildNewsFilterParams(
|
|
100
168
|
region: Region,
|
|
101
169
|
locale: Locale,
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
orderBy?: NewsOrderBy,
|
|
106
|
-
orderByDirection?: SortDirection,
|
|
107
|
-
extraFilters?: string
|
|
108
|
-
): Promise<PaginatedResponse<News>> {
|
|
109
|
-
const params = {
|
|
170
|
+
options?: GetNewsParams
|
|
171
|
+
): Record<string, unknown> {
|
|
172
|
+
return {
|
|
110
173
|
region,
|
|
111
174
|
locale,
|
|
112
|
-
...(
|
|
113
|
-
...(
|
|
114
|
-
...(
|
|
115
|
-
...(orderBy != null && { orderBy }),
|
|
116
|
-
...(orderByDirection != null && {
|
|
117
|
-
|
|
175
|
+
...(options?.lane != null && { lane: options.lane }),
|
|
176
|
+
...(options?.apiSource != null && { apiSource: options.apiSource }),
|
|
177
|
+
...(options?.newsType != null && { newsType: options.newsType }),
|
|
178
|
+
...(options?.orderBy != null && { orderBy: options.orderBy }),
|
|
179
|
+
...(options?.orderByDirection != null && {
|
|
180
|
+
orderByDirection: options.orderByDirection,
|
|
181
|
+
}),
|
|
182
|
+
...(options?.symbols != null && { symbols: options.symbols }),
|
|
183
|
+
...(options?.categories != null && { categories: options.categories }),
|
|
184
|
+
...(options?.sectors != null && { sectors: options.sectors }),
|
|
185
|
+
...(options?.industries != null && { industries: options.industries }),
|
|
186
|
+
...(options?.qualityScoreMin != null && {
|
|
187
|
+
qualityScoreMin: options.qualityScoreMin,
|
|
188
|
+
}),
|
|
189
|
+
...(options?.qualityScoreMax != null && {
|
|
190
|
+
qualityScoreMax: options.qualityScoreMax,
|
|
191
|
+
}),
|
|
192
|
+
...(options?.timestampFrom != null && {
|
|
193
|
+
timestampFrom: options.timestampFrom,
|
|
194
|
+
}),
|
|
195
|
+
...(options?.timestampTo != null && { timestampTo: options.timestampTo }),
|
|
196
|
+
...(options?.page != null && { page: options.page }),
|
|
197
|
+
...(options?.size != null && { size: options.size }),
|
|
118
198
|
};
|
|
199
|
+
}
|
|
119
200
|
|
|
201
|
+
async getNews(
|
|
202
|
+
region: Region,
|
|
203
|
+
locale: Locale,
|
|
204
|
+
options?: GetNewsParams
|
|
205
|
+
): Promise<PaginatedResponse<News>> {
|
|
120
206
|
return this.sendRequest<PaginatedResponse<News>>({
|
|
121
207
|
method: "GET",
|
|
122
208
|
url: "/api/v1/news",
|
|
123
|
-
params,
|
|
209
|
+
params: this.buildNewsFilterParams(region, locale, options),
|
|
124
210
|
});
|
|
125
211
|
}
|
|
126
212
|
|
|
127
213
|
async getNewsV2(
|
|
128
214
|
region: Region,
|
|
129
215
|
locale: Locale,
|
|
130
|
-
|
|
131
|
-
page?: number,
|
|
132
|
-
size?: number,
|
|
133
|
-
orderBy?: NewsOrderBy,
|
|
134
|
-
orderByDirection?: SortDirection,
|
|
135
|
-
extraFilters?: string
|
|
216
|
+
options?: GetNewsParams
|
|
136
217
|
): Promise<PaginatedResponse<NewsV2>> {
|
|
137
|
-
const params = {
|
|
138
|
-
region,
|
|
139
|
-
locale,
|
|
140
|
-
...(newsType != null && { newsType }),
|
|
141
|
-
...(page != null && { page }),
|
|
142
|
-
...(size != null && { size }),
|
|
143
|
-
...(orderBy != null && { orderBy }),
|
|
144
|
-
...(orderByDirection != null && { orderByDirection }),
|
|
145
|
-
...(extraFilters != null && { extraFilters }),
|
|
146
|
-
};
|
|
147
|
-
|
|
148
218
|
return this.sendRequest<PaginatedResponse<NewsV2>>({
|
|
149
219
|
method: "GET",
|
|
150
220
|
url: "/api/v2/news",
|
|
151
|
-
params,
|
|
221
|
+
params: this.buildNewsFilterParams(region, locale, options),
|
|
152
222
|
});
|
|
153
223
|
}
|
|
154
224
|
|
|
@@ -158,9 +228,13 @@ export class NewsClient extends Client {
|
|
|
158
228
|
sectors?: string[],
|
|
159
229
|
tickers?: string[],
|
|
160
230
|
categories?: string[],
|
|
161
|
-
industries?: string[]
|
|
231
|
+
industries?: string[],
|
|
232
|
+
lane?: NewsLane,
|
|
233
|
+
apiSource?: string[]
|
|
162
234
|
): { events: AsyncIterable<NewsV2[]>, cancel: () => void } {
|
|
163
235
|
let url = `${this["baseUrl"]}/api/v1/news/stream?locale=${locale}®ion=${region}`;
|
|
236
|
+
if (lane != null) url += `&lane=${encodeURIComponent(lane)}`;
|
|
237
|
+
if (apiSource?.length) url += `&apiSource=${encodeURIComponent(apiSource.join(","))}`;
|
|
164
238
|
if (sectors?.length) url += `§ors=${encodeURIComponent(sectors.join(","))}`;
|
|
165
239
|
if (tickers?.length) url += `&tickers=${encodeURIComponent(tickers.join(","))}`;
|
|
166
240
|
if (categories?.length) url += `&categories=${encodeURIComponent(categories.join(","))}`;
|
package/src/test/news.test.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
NewsClient,
|
|
6
6
|
NewsType,
|
|
7
7
|
NewsOrderBy,
|
|
8
|
+
NewsLane,
|
|
8
9
|
} from "../client/news";
|
|
9
10
|
import "./client_test_suite";
|
|
10
11
|
import { Region, Locale } from "../client/collections";
|
|
@@ -34,6 +35,20 @@ const mockNewsHighlightsResponse = {
|
|
|
34
35
|
]
|
|
35
36
|
};
|
|
36
37
|
|
|
38
|
+
const mockNewsCategoriesResponse = [
|
|
39
|
+
{ id: "13702", name: "General News" },
|
|
40
|
+
{ id: "13703", name: "Sector News" },
|
|
41
|
+
{ id: "13704", name: "Market News" },
|
|
42
|
+
{ id: "13705", name: "Stock Spesific News" }
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const mockNewsLanesResponse = [
|
|
46
|
+
{ id: "global_macro", label: "Global Macro" },
|
|
47
|
+
{ id: "tr_ekonomi", label: "TR Ekonomi" },
|
|
48
|
+
{ id: "bist", label: "BIST" },
|
|
49
|
+
{ id: "fast_movers", label: "Fast Movers" }
|
|
50
|
+
];
|
|
51
|
+
|
|
37
52
|
const mockNewsResponse = {
|
|
38
53
|
items: [
|
|
39
54
|
{
|
|
@@ -107,16 +122,47 @@ describe("NewsClient", () => {
|
|
|
107
122
|
if (first != null) expect(typeof first).toBe("string");
|
|
108
123
|
});
|
|
109
124
|
|
|
125
|
+
test("getNewsCategories returns valid data", async () => {
|
|
126
|
+
const resp = await client.getNewsCategories(Locale.En);
|
|
127
|
+
|
|
128
|
+
expect(Array.isArray(resp)).toBe(true);
|
|
129
|
+
expect(resp.length).toBeGreaterThan(0);
|
|
130
|
+
|
|
131
|
+
const c = resp[0];
|
|
132
|
+
expect(typeof c.id).toBe("string");
|
|
133
|
+
expect(typeof c.name).toBe("string");
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("getNewsLanes returns valid data", async () => {
|
|
137
|
+
const resp = await client.getNewsLanes();
|
|
138
|
+
|
|
139
|
+
expect(Array.isArray(resp)).toBe(true);
|
|
140
|
+
if (resp.length > 0) {
|
|
141
|
+
const l = resp[0];
|
|
142
|
+
expect(typeof l.id).toBe("string");
|
|
143
|
+
expect(typeof l.label).toBe("string");
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("getApiSourceNames returns valid data", async () => {
|
|
148
|
+
const resp = await client.getApiSourceNames();
|
|
149
|
+
|
|
150
|
+
expect(Array.isArray(resp)).toBe(true);
|
|
151
|
+
if (resp.length > 0) {
|
|
152
|
+
const s = resp[0];
|
|
153
|
+
expect(typeof s.id).toBe("string");
|
|
154
|
+
expect(typeof s.name).toBe("string");
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
110
158
|
test("getNews returns valid paginated data", async () => {
|
|
111
|
-
const resp = await client.getNews(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
SortDirection.Desc
|
|
119
|
-
);
|
|
159
|
+
const resp = await client.getNews(Region.Us, Locale.Tr, {
|
|
160
|
+
newsType: NewsType.BRIEFS,
|
|
161
|
+
page: 0,
|
|
162
|
+
size: 10,
|
|
163
|
+
orderBy: NewsOrderBy.TIMESTAMP,
|
|
164
|
+
orderByDirection: SortDirection.Desc,
|
|
165
|
+
});
|
|
120
166
|
|
|
121
167
|
expect(resp).toBeDefined();
|
|
122
168
|
expect(typeof resp.recordCount).toBe("number");
|
|
@@ -197,15 +243,13 @@ describe("NewsClient", () => {
|
|
|
197
243
|
});
|
|
198
244
|
|
|
199
245
|
test("getNewsV2 returns valid paginated data", async () => {
|
|
200
|
-
const resp = await client.getNewsV2(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
SortDirection.Desc
|
|
208
|
-
);
|
|
246
|
+
const resp = await client.getNewsV2(Region.Us, Locale.Tr, {
|
|
247
|
+
newsType: NewsType.BRIEFS,
|
|
248
|
+
page: 0,
|
|
249
|
+
size: 10,
|
|
250
|
+
orderBy: NewsOrderBy.TIMESTAMP,
|
|
251
|
+
orderByDirection: SortDirection.Desc,
|
|
252
|
+
});
|
|
209
253
|
|
|
210
254
|
expect(resp).toBeDefined();
|
|
211
255
|
expect(typeof resp.recordCount).toBe("number");
|
|
@@ -300,20 +344,123 @@ describe("NewsClient", () => {
|
|
|
300
344
|
});
|
|
301
345
|
});
|
|
302
346
|
|
|
347
|
+
describe("getNewsCategories", () => {
|
|
348
|
+
test("calls correct endpoint/params and matches raw response", async () => {
|
|
349
|
+
cli.request.mockResolvedValueOnce({ data: mockNewsCategoriesResponse });
|
|
350
|
+
|
|
351
|
+
const resp = await client.getNewsCategories(Locale.En);
|
|
352
|
+
|
|
353
|
+
expect(cli.request).toHaveBeenCalledTimes(1);
|
|
354
|
+
const call = cli.request.mock.calls[0][0];
|
|
355
|
+
|
|
356
|
+
expect(call.method).toBe("GET");
|
|
357
|
+
expect(call.url).toBe("/api/v1/news/categories");
|
|
358
|
+
expect(call.params).toEqual({ locale: Locale.En });
|
|
359
|
+
|
|
360
|
+
expect(resp).toEqual(mockNewsCategoriesResponse);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
test("does not send locale when undefined", async () => {
|
|
364
|
+
cli.request.mockResolvedValueOnce({ data: mockNewsCategoriesResponse });
|
|
365
|
+
|
|
366
|
+
await client.getNewsCategories();
|
|
367
|
+
|
|
368
|
+
const call = cli.request.mock.calls[0][0];
|
|
369
|
+
expect(call.params).toEqual({});
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
test("bubbles up request error", async () => {
|
|
373
|
+
cli.request.mockRejectedValueOnce(new Error("Failed to fetch categories"));
|
|
374
|
+
|
|
375
|
+
await expect(client.getNewsCategories(Locale.En)).rejects.toThrow(
|
|
376
|
+
"Failed to fetch categories"
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
expect(cli.request).toHaveBeenCalledTimes(1);
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
describe("getNewsLanes", () => {
|
|
384
|
+
test("calls correct endpoint and matches raw response", async () => {
|
|
385
|
+
cli.request.mockResolvedValueOnce({ data: mockNewsLanesResponse });
|
|
386
|
+
|
|
387
|
+
const resp = await client.getNewsLanes();
|
|
388
|
+
|
|
389
|
+
expect(cli.request).toHaveBeenCalledTimes(1);
|
|
390
|
+
const call = cli.request.mock.calls[0][0];
|
|
391
|
+
|
|
392
|
+
expect(call.method).toBe("GET");
|
|
393
|
+
expect(call.url).toBe("/api/v1/news/lanes");
|
|
394
|
+
|
|
395
|
+
expect(resp).toEqual(mockNewsLanesResponse);
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
test("bubbles up request error", async () => {
|
|
399
|
+
cli.request.mockRejectedValueOnce(new Error("Failed to fetch lanes"));
|
|
400
|
+
|
|
401
|
+
await expect(client.getNewsLanes()).rejects.toThrow(
|
|
402
|
+
"Failed to fetch lanes"
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
expect(cli.request).toHaveBeenCalledTimes(1);
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
describe("getApiSourceNames", () => {
|
|
410
|
+
const mockApiSourceNames = [
|
|
411
|
+
{ id: "BBCBusiness", name: "BBC Business" },
|
|
412
|
+
{ id: "MarketWatch", name: "MarketWatch" },
|
|
413
|
+
{ id: "GazeteOksijen", name: "Gazete Oksijen" }
|
|
414
|
+
];
|
|
415
|
+
|
|
416
|
+
test("calls correct endpoint and matches raw response", async () => {
|
|
417
|
+
cli.request.mockResolvedValueOnce({ data: mockApiSourceNames });
|
|
418
|
+
|
|
419
|
+
const resp = await client.getApiSourceNames();
|
|
420
|
+
|
|
421
|
+
expect(cli.request).toHaveBeenCalledTimes(1);
|
|
422
|
+
const call = cli.request.mock.calls[0][0];
|
|
423
|
+
|
|
424
|
+
expect(call.method).toBe("GET");
|
|
425
|
+
expect(call.url).toBe("/api/v1/news/api-source-names");
|
|
426
|
+
|
|
427
|
+
expect(resp).toEqual(mockApiSourceNames);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
test("bubbles up request error", async () => {
|
|
431
|
+
cli.request.mockRejectedValueOnce(
|
|
432
|
+
new Error("Failed to fetch api source names")
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
await expect(client.getApiSourceNames()).rejects.toThrow(
|
|
436
|
+
"Failed to fetch api source names"
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
expect(cli.request).toHaveBeenCalledTimes(1);
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
|
|
303
443
|
describe("getNews", () => {
|
|
304
444
|
test("calls correct endpoint/params and matches raw response", async () => {
|
|
305
445
|
cli.request.mockResolvedValueOnce({ data: mockNewsResponse });
|
|
306
446
|
|
|
307
|
-
const resp = await client.getNews(
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
NewsType.BRIEFS,
|
|
311
|
-
1,
|
|
312
|
-
10,
|
|
313
|
-
NewsOrderBy.TIMESTAMP,
|
|
314
|
-
SortDirection.Desc,
|
|
315
|
-
|
|
316
|
-
|
|
447
|
+
const resp = await client.getNews(Region.Tr, Locale.Tr, {
|
|
448
|
+
lane: NewsLane.BIST,
|
|
449
|
+
apiSource: "BBCBusiness,MarketWatch",
|
|
450
|
+
newsType: NewsType.BRIEFS,
|
|
451
|
+
page: 1,
|
|
452
|
+
size: 10,
|
|
453
|
+
orderBy: NewsOrderBy.TIMESTAMP,
|
|
454
|
+
orderByDirection: SortDirection.Desc,
|
|
455
|
+
symbols: "AAPL,MSFT",
|
|
456
|
+
categories: "Sector News",
|
|
457
|
+
sectors: "Technology",
|
|
458
|
+
industries: "Software",
|
|
459
|
+
qualityScoreMin: 7,
|
|
460
|
+
qualityScoreMax: 10,
|
|
461
|
+
timestampFrom: "2026-05-01",
|
|
462
|
+
timestampTo: "2026-06-01",
|
|
463
|
+
});
|
|
317
464
|
|
|
318
465
|
expect(cli.request).toHaveBeenCalledTimes(1);
|
|
319
466
|
const call = cli.request.mock.calls[0][0];
|
|
@@ -323,11 +470,21 @@ describe("NewsClient", () => {
|
|
|
323
470
|
expect(call.params).toEqual({
|
|
324
471
|
region: Region.Tr,
|
|
325
472
|
locale: Locale.Tr,
|
|
473
|
+
lane: NewsLane.BIST,
|
|
474
|
+
apiSource: "BBCBusiness,MarketWatch",
|
|
326
475
|
newsType: NewsType.BRIEFS,
|
|
327
476
|
page: 1,
|
|
328
477
|
size: 10,
|
|
329
478
|
orderBy: NewsOrderBy.TIMESTAMP,
|
|
330
|
-
orderByDirection: SortDirection.Desc
|
|
479
|
+
orderByDirection: SortDirection.Desc,
|
|
480
|
+
symbols: "AAPL,MSFT",
|
|
481
|
+
categories: "Sector News",
|
|
482
|
+
sectors: "Technology",
|
|
483
|
+
industries: "Software",
|
|
484
|
+
qualityScoreMin: 7,
|
|
485
|
+
qualityScoreMax: 10,
|
|
486
|
+
timestampFrom: "2026-05-01",
|
|
487
|
+
timestampTo: "2026-06-01",
|
|
331
488
|
});
|
|
332
489
|
|
|
333
490
|
expect(resp.recordCount).toBe(352);
|
|
@@ -387,15 +544,13 @@ describe("NewsClient", () => {
|
|
|
387
544
|
cli.request.mockRejectedValueOnce(new Error("Failed to fetch news"));
|
|
388
545
|
|
|
389
546
|
await expect(
|
|
390
|
-
client.getNews(
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
SortDirection.Desc
|
|
398
|
-
)
|
|
547
|
+
client.getNews(Region.Tr, Locale.Tr, {
|
|
548
|
+
newsType: NewsType.REUTERS,
|
|
549
|
+
page: 0,
|
|
550
|
+
size: 10,
|
|
551
|
+
orderBy: NewsOrderBy.TIMESTAMP,
|
|
552
|
+
orderByDirection: SortDirection.Desc,
|
|
553
|
+
})
|
|
399
554
|
).rejects.toThrow("Failed to fetch news");
|
|
400
555
|
|
|
401
556
|
expect(cli.request).toHaveBeenCalledTimes(1);
|
|
@@ -406,16 +561,23 @@ describe("NewsClient", () => {
|
|
|
406
561
|
test("calls correct endpoint/params and matches raw response", async () => {
|
|
407
562
|
cli.request.mockResolvedValueOnce({ data: mockNewsV2Response });
|
|
408
563
|
|
|
409
|
-
const resp = await client.getNewsV2(
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
NewsType.BRIEFS,
|
|
413
|
-
1,
|
|
414
|
-
10,
|
|
415
|
-
NewsOrderBy.TIMESTAMP,
|
|
416
|
-
SortDirection.Desc,
|
|
417
|
-
|
|
418
|
-
|
|
564
|
+
const resp = await client.getNewsV2(Region.Tr, Locale.Tr, {
|
|
565
|
+
lane: NewsLane.GLOBAL_MACRO,
|
|
566
|
+
apiSource: "BBCBusiness,MarketWatch",
|
|
567
|
+
newsType: NewsType.BRIEFS,
|
|
568
|
+
page: 1,
|
|
569
|
+
size: 10,
|
|
570
|
+
orderBy: NewsOrderBy.TIMESTAMP,
|
|
571
|
+
orderByDirection: SortDirection.Desc,
|
|
572
|
+
symbols: "AAPL,MSFT",
|
|
573
|
+
categories: "Sector News",
|
|
574
|
+
sectors: "Technology",
|
|
575
|
+
industries: "Software",
|
|
576
|
+
qualityScoreMin: 7,
|
|
577
|
+
qualityScoreMax: 10,
|
|
578
|
+
timestampFrom: "2026-05-01",
|
|
579
|
+
timestampTo: "2026-06-01",
|
|
580
|
+
});
|
|
419
581
|
|
|
420
582
|
expect(cli.request).toHaveBeenCalledTimes(1);
|
|
421
583
|
const call = cli.request.mock.calls[0][0];
|
|
@@ -425,11 +587,21 @@ describe("NewsClient", () => {
|
|
|
425
587
|
expect(call.params).toEqual({
|
|
426
588
|
region: Region.Tr,
|
|
427
589
|
locale: Locale.Tr,
|
|
590
|
+
lane: NewsLane.GLOBAL_MACRO,
|
|
591
|
+
apiSource: "BBCBusiness,MarketWatch",
|
|
428
592
|
newsType: NewsType.BRIEFS,
|
|
429
593
|
page: 1,
|
|
430
594
|
size: 10,
|
|
431
595
|
orderBy: NewsOrderBy.TIMESTAMP,
|
|
432
|
-
orderByDirection: SortDirection.Desc
|
|
596
|
+
orderByDirection: SortDirection.Desc,
|
|
597
|
+
symbols: "AAPL,MSFT",
|
|
598
|
+
categories: "Sector News",
|
|
599
|
+
sectors: "Technology",
|
|
600
|
+
industries: "Software",
|
|
601
|
+
qualityScoreMin: 7,
|
|
602
|
+
qualityScoreMax: 10,
|
|
603
|
+
timestampFrom: "2026-05-01",
|
|
604
|
+
timestampTo: "2026-06-01",
|
|
433
605
|
});
|
|
434
606
|
|
|
435
607
|
expect(resp.recordCount).toBe(352);
|
|
@@ -457,15 +629,13 @@ describe("NewsClient", () => {
|
|
|
457
629
|
cli.request.mockRejectedValueOnce(new Error("Failed to fetch news v2"));
|
|
458
630
|
|
|
459
631
|
await expect(
|
|
460
|
-
client.getNewsV2(
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
SortDirection.Desc
|
|
468
|
-
)
|
|
632
|
+
client.getNewsV2(Region.Tr, Locale.Tr, {
|
|
633
|
+
newsType: NewsType.REUTERS,
|
|
634
|
+
page: 0,
|
|
635
|
+
size: 10,
|
|
636
|
+
orderBy: NewsOrderBy.TIMESTAMP,
|
|
637
|
+
orderByDirection: SortDirection.Desc,
|
|
638
|
+
})
|
|
469
639
|
).rejects.toThrow("Failed to fetch news v2");
|
|
470
640
|
|
|
471
641
|
expect(cli.request).toHaveBeenCalledTimes(1);
|
|
@@ -524,7 +694,7 @@ describe("NewsClient", () => {
|
|
|
524
694
|
data: mockAsyncIterator
|
|
525
695
|
});
|
|
526
696
|
|
|
527
|
-
const { events, cancel } = client.streamNews(Region.Us, Locale.En, ["tech"], ["AAPL"], ["category"], ["software"]);
|
|
697
|
+
const { events, cancel } = client.streamNews(Region.Us, Locale.En, ["tech"], ["AAPL"], ["category"], ["software"], NewsLane.GLOBAL_MACRO, ["BBCBusiness"]);
|
|
528
698
|
|
|
529
699
|
for await (const _ of events) {
|
|
530
700
|
break;
|
|
@@ -532,7 +702,7 @@ describe("NewsClient", () => {
|
|
|
532
702
|
|
|
533
703
|
expect(axiosGetSpy).toHaveBeenCalledTimes(1);
|
|
534
704
|
const callArgs = axiosGetSpy.mock.calls[0];
|
|
535
|
-
expect(callArgs[0]).toBe(`${client["baseUrl"]}/api/v1/news/stream?locale=en®ion=us§ors=tech&tickers=AAPL&categories=category&industries=software`);
|
|
705
|
+
expect(callArgs[0]).toBe(`${client["baseUrl"]}/api/v1/news/stream?locale=en®ion=us&lane=global_macro&apiSource=BBCBusiness§ors=tech&tickers=AAPL&categories=category&industries=software`);
|
|
536
706
|
|
|
537
707
|
cancel();
|
|
538
708
|
axiosGetSpy.mockRestore();
|