laplace-api
Version:
Client library for Laplace API for the US stock market and BIST (Istanbul stock market) fundamental financial data.
776 lines (633 loc) • 27.7 kB
text/typescript
import { Logger } from "winston";
import axios from "axios";
import { LaplaceConfiguration } from "../utilities/configuration";
import {
NewsClient,
NewsType,
NewsOrderBy,
NewsLane,
} from "../client/news";
import "./client_test_suite";
import { Region, Locale } from "../client/collections";
import { SortDirection } from "../client/broker";
const mockNewsHighlightsResponse = {
tech: [
"Alphabet ve Amazon'un desteğiyle Anthropic, 2026 başlarında Hindistan'ın Bengaluru kentinde bir ofis açacak."
],
other: [
"ABD Yüksek Mahkemesi, Epic Games'in davası kapsamında Google'ın Play uygulamalarındaki değişikliği engellemeyecek."
],
finance: [
"Fifth Third Bank, Comerica'yı 10,9 milyar dolara satın alacak ve böylece ABD'nin 9. en büyük bankası olacak."
],
consumer: [
"Tesla, rekabet ortamında pazar payını geri almak için daha ucuz Model Y ve Model 3'ü piyasaya sürdü; duyuru hisseleri etkiledi."
],
healthcare: [
"İ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."
],
energyAndUtilities: [
"ABD Enerji Bakanlığı, Stellantis ve GM'ye verilen 1,1 milyar dolarlık hibeleri iptal edebilir."
],
industrialsAndMaterials: [
"Boeing, bir grevi sona erdirmek için IAM Sendikası ile geçici bir anlaşmaya vardı; detaylar açıklanmadı."
]
};
const mockNewsCategoriesResponse = [
{ id: "13702", name: "General News" },
{ id: "13703", name: "Sector News" },
{ id: "13704", name: "Market News" },
{ id: "13705", name: "Stock Spesific News" }
];
const mockNewsLanesResponse = [
{ id: "global_macro", label: "Global Macro" },
{ id: "tr_ekonomi", label: "TR Ekonomi" },
{ id: "bist", label: "BIST" },
{ id: "fast_movers", label: "Fast Movers" }
];
const mockNewsHighlightsPaginatedResponse = {
items: [
{ id: "hl_1", createdAt: "2026-06-15T00:00:00Z", ...mockNewsHighlightsResponse },
{ id: "hl_2", createdAt: "2026-06-14T00:00:00Z", ...mockNewsHighlightsResponse }
],
recordCount: 2
};
const mockNewsResponse = {
items: [
{
id: "68e5a1b2c3d4e5f60718293a",
url: "https://www.reuters.com/business/energy/commonwealth-lng-wants-more-time-build-planned-export-facility-louisiana-2025-10-07/",
content: {
title: "Commonwealth LNG wants more time to build planned export facility in Louisiana",
content: [
"Commonwealth LNG has requested a four-year extension from federal regulators to construct & begin exporting liquefied natural gas..."
],
summary: [
"Commonwealth LNG has requested a four-year extension from federal regulators..."
],
description:
"Commonwealth LNG has asked federal regulators for a four-year extension...",
investorInsight:
"What it means for investors: The extension request could postpone..."
},
sectors: { id: "65533e047844ee7afe9941bf", name: "Energy" },
tickers: [{ id: "6203d1ba1e674875275558f7", name: "EQT Corp", symbol: "EQT" }],
imageUrl: "",
createdAt: "2025-10-07T17:10:01.560644Z",
publisher: { name: "Reuters", logoUrl: null },
timestamp: "2025-10-07T16:50:16Z",
categories: { id: "3", name: "Sector News", categoryType: "StockSpesific" },
industries: { id: "65533e441fa5c7b58afa0944", name: "Oil/Gas (Production and Exploration)" },
publisherUrl: "Reuters",
qualityScore: 0,
relatedTickers: [{ id: "6203d1ba1e674875275558f7", name: "EQT Corp", symbol: "EQT" }]
}
],
recordCount: 352
};
const mockNewsV2Response = {
items: mockNewsResponse.items.map(({ relatedTickers, ...rest }) => rest),
recordCount: mockNewsResponse.recordCount
};
describe("NewsClient", () => {
let client: NewsClient;
beforeAll(() => {
const config = (global as any).testSuite.config as LaplaceConfiguration;
const logger: Logger = {
info: jest.fn(),
error: jest.fn(),
warn: jest.fn(),
debug: jest.fn(),
} as unknown as Logger;
client = new NewsClient(config, logger);
});
describe("Integration Tests", () => {
jest.setTimeout(60_000);
test("getHighlights returns valid paginated data", async () => {
const resp = await client.getHighlights(Region.Us, Locale.Tr);
expect(resp).toBeDefined();
expect(typeof resp.recordCount).toBe("number");
expect(Array.isArray(resp.items)).toBe(true);
if (resp.items.length > 0) {
const item = resp.items[0];
expect(typeof item.id).toBe("string");
expect(typeof item.createdAt).toBe("string");
expect(Array.isArray(item.consumer)).toBe(true);
expect(Array.isArray(item.energyAndUtilities)).toBe(true);
expect(Array.isArray(item.finance)).toBe(true);
expect(Array.isArray(item.healthcare)).toBe(true);
expect(Array.isArray(item.industrialsAndMaterials)).toBe(true);
expect(Array.isArray(item.tech)).toBe(true);
expect(Array.isArray(item.other)).toBe(true);
}
});
test("getHighlights narrows to a date range", async () => {
const resp = await client.getHighlights(Region.Us, Locale.Tr, {
from: "2026-06-01",
to: "2026-07-01",
skip: 0,
top: 20,
});
expect(resp).toBeDefined();
expect(typeof resp.recordCount).toBe("number");
expect(Array.isArray(resp.items)).toBe(true);
});
test("getNewsCategories returns valid data", async () => {
const resp = await client.getNewsCategories(Locale.En);
expect(Array.isArray(resp)).toBe(true);
expect(resp.length).toBeGreaterThan(0);
const c = resp[0];
expect(typeof c.id).toBe("string");
expect(typeof c.name).toBe("string");
});
test("getNewsLanes returns valid data", async () => {
const resp = await client.getNewsLanes();
expect(Array.isArray(resp)).toBe(true);
if (resp.length > 0) {
const l = resp[0];
expect(typeof l.id).toBe("string");
expect(typeof l.label).toBe("string");
}
});
test("getApiSourceNames returns valid data", async () => {
const resp = await client.getApiSourceNames();
expect(Array.isArray(resp)).toBe(true);
if (resp.length > 0) {
const s = resp[0];
expect(typeof s.id).toBe("string");
expect(typeof s.name).toBe("string");
}
});
test("getNews returns valid paginated data", async () => {
const resp = await client.getNews(Region.Us, Locale.Tr, {
newsType: NewsType.BRIEFS,
page: 0,
size: 10,
orderBy: NewsOrderBy.TIMESTAMP,
orderByDirection: SortDirection.Desc,
});
expect(resp).toBeDefined();
expect(typeof resp.recordCount).toBe("number");
expect(resp.recordCount).toBeGreaterThanOrEqual(0);
expect(Array.isArray(resp.items)).toBe(true);
if (resp.items.length > 0) {
const n = resp.items[0];
expect(typeof n.id).toBe("string");
expect(typeof n.url).toBe("string");
expect(typeof n.imageUrl).toBe("string");
expect(typeof n.timestamp).toBe("string");
expect(typeof n.publisherUrl).toBe("string");
expect(typeof n.qualityScore).toBe("number");
expect(typeof n.createdAt).toBe("string");
expect(n.publisher).toBeDefined();
expect(typeof n.publisher.name).toBe("string");
expect(
typeof n.publisher.logoUrl === "string" || n.publisher.logoUrl == null
).toBe(true);
expect(Array.isArray(n.relatedTickers)).toBe(true);
if (n.relatedTickers.length > 0) {
const t = n.relatedTickers[0];
expect(typeof t.id).toBe("string");
expect(typeof t.name).toBe("string");
expect(typeof t.symbol === "string" || t.symbol == null).toBe(true);
}
if (n.tickers != null) {
expect(Array.isArray(n.tickers)).toBe(true);
}
if (n.categories != null) {
expect(typeof n.categories.id).toBe("string");
expect(typeof n.categories.name).toBe("string");
expect(
typeof n.categories.categoryType === "string" ||
n.categories.categoryType == null ||
n.categories.categoryType === undefined
).toBe(true);
}
if (n.sectors != null) {
expect(typeof n.sectors.id).toBe("string");
expect(typeof n.sectors.name).toBe("string");
}
if (n.industries != null) {
expect(typeof n.industries.id).toBe("string");
expect(typeof n.industries.name).toBe("string");
}
if (n.content != null) {
expect(typeof n.content.title).toBe("string");
expect(typeof n.content.description).toBe("string");
expect(Array.isArray(n.content.content)).toBe(true);
expect(Array.isArray(n.content.summary)).toBe(true);
expect(typeof n.content.investorInsight).toBe("string");
}
}
});
test("getNewsV2 returns valid paginated data", async () => {
const resp = await client.getNewsV2(Region.Us, Locale.Tr, {
newsType: NewsType.BRIEFS,
page: 0,
size: 10,
orderBy: NewsOrderBy.TIMESTAMP,
orderByDirection: SortDirection.Desc,
});
expect(resp).toBeDefined();
expect(typeof resp.recordCount).toBe("number");
expect(resp.recordCount).toBeGreaterThanOrEqual(0);
expect(Array.isArray(resp.items)).toBe(true);
if (resp.items.length > 0) {
const n = resp.items[0];
expect(typeof n.id).toBe("string");
expect(typeof n.url).toBe("string");
expect(typeof n.imageUrl).toBe("string");
expect(typeof n.timestamp).toBe("string");
expect(typeof n.publisherUrl).toBe("string");
expect(typeof n.qualityScore).toBe("number");
expect(typeof n.createdAt).toBe("string");
expect((n as any).relatedTickers).toBeUndefined();
expect(n.publisher).toBeDefined();
expect(typeof n.publisher.name).toBe("string");
}
});
test("streamNews yields item before timeout or throws gracefully if none arrive", async () => {
let newsItemsReceived = 0;
const { events, cancel } = client.streamNews(Region.Us, Locale.Tr);
const receivePromise = (async () => {
for await (const items of events) {
if (items && items.length > 0) {
newsItemsReceived += items.length;
break;
}
}
})();
const timeoutPromise = new Promise((resolve) => setTimeout(resolve, 8000));
await Promise.race([receivePromise, timeoutPromise]);
cancel();
expect(newsItemsReceived).toBeGreaterThanOrEqual(0);
});
});
describe("Mock Tests", () => {
let client: NewsClient;
let cli: { request: jest.Mock };
beforeEach(() => {
cli = { request: jest.fn() };
const config = (global as any).testSuite.config as LaplaceConfiguration;
const logger: Logger = {
info: jest.fn(),
error: jest.fn(),
warn: jest.fn(),
debug: jest.fn()
} as unknown as Logger;
client = new NewsClient(config, logger, cli as any);
});
describe("getHighlights", () => {
test("calls correct endpoint/params and matches raw response", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsHighlightsPaginatedResponse });
const resp = await client.getHighlights(Region.Tr, Locale.Tr);
expect(cli.request).toHaveBeenCalledTimes(1);
const call = cli.request.mock.calls[0][0];
expect(call.method).toBe("GET");
expect(call.url).toBe("/api/v1/news/highlights");
expect(call.params).toEqual({ region: Region.Tr, locale: Locale.Tr });
expect(resp.recordCount).toBe(2);
expect(resp.items).toHaveLength(2);
expect(resp.items[0].id).toBe("hl_1");
expect(resp.items[0].createdAt).toBe("2026-06-15T00:00:00Z");
expect(resp.items[0].tech).toEqual(mockNewsHighlightsResponse.tech);
expect(resp.items[0].consumer).toEqual(mockNewsHighlightsResponse.consumer);
});
test("sends from/to/skip/top when provided", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsHighlightsPaginatedResponse });
await client.getHighlights(Region.Us, Locale.Tr, {
from: "2026-06-01",
to: "2026-07-01",
skip: 0,
top: 20,
});
const call = cli.request.mock.calls[0][0];
expect(call.params).toEqual({
region: Region.Us,
locale: Locale.Tr,
from: "2026-06-01",
to: "2026-07-01",
skip: 0,
top: 20,
});
});
test("omits from/to/skip/top when not provided", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsHighlightsPaginatedResponse });
await client.getHighlights(Region.Us, Locale.Tr, {});
const call = cli.request.mock.calls[0][0];
expect(call.params).toEqual({ region: Region.Us, locale: Locale.Tr });
});
test("bubbles up request error", async () => {
cli.request.mockRejectedValueOnce(new Error("Failed to fetch highlights"));
await expect(client.getHighlights(Region.Tr, Locale.Tr)).rejects.toThrow(
"Failed to fetch highlights"
);
expect(cli.request).toHaveBeenCalledTimes(1);
});
});
describe("getNewsCategories", () => {
test("calls correct endpoint/params and matches raw response", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsCategoriesResponse });
const resp = await client.getNewsCategories(Locale.En);
expect(cli.request).toHaveBeenCalledTimes(1);
const call = cli.request.mock.calls[0][0];
expect(call.method).toBe("GET");
expect(call.url).toBe("/api/v1/news/categories");
expect(call.params).toEqual({ locale: Locale.En });
expect(resp).toEqual(mockNewsCategoriesResponse);
});
test("does not send locale when undefined", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsCategoriesResponse });
await client.getNewsCategories();
const call = cli.request.mock.calls[0][0];
expect(call.params).toEqual({});
});
test("bubbles up request error", async () => {
cli.request.mockRejectedValueOnce(new Error("Failed to fetch categories"));
await expect(client.getNewsCategories(Locale.En)).rejects.toThrow(
"Failed to fetch categories"
);
expect(cli.request).toHaveBeenCalledTimes(1);
});
});
describe("getNewsLanes", () => {
test("calls correct endpoint and matches raw response", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsLanesResponse });
const resp = await client.getNewsLanes();
expect(cli.request).toHaveBeenCalledTimes(1);
const call = cli.request.mock.calls[0][0];
expect(call.method).toBe("GET");
expect(call.url).toBe("/api/v1/news/lanes");
expect(call.params).toEqual({});
expect(resp).toEqual(mockNewsLanesResponse);
});
test("sends region when provided", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsLanesResponse });
await client.getNewsLanes(Region.Us);
const call = cli.request.mock.calls[0][0];
expect(call.params).toEqual({ region: Region.Us });
});
test("bubbles up request error", async () => {
cli.request.mockRejectedValueOnce(new Error("Failed to fetch lanes"));
await expect(client.getNewsLanes()).rejects.toThrow(
"Failed to fetch lanes"
);
expect(cli.request).toHaveBeenCalledTimes(1);
});
});
describe("getApiSourceNames", () => {
const mockApiSourceNames = [
{ id: "BBCBusiness", name: "BBC Business" },
{ id: "MarketWatch", name: "MarketWatch" },
{ id: "GazeteOksijen", name: "Gazete Oksijen" }
];
test("calls correct endpoint and matches raw response", async () => {
cli.request.mockResolvedValueOnce({ data: mockApiSourceNames });
const resp = await client.getApiSourceNames();
expect(cli.request).toHaveBeenCalledTimes(1);
const call = cli.request.mock.calls[0][0];
expect(call.method).toBe("GET");
expect(call.url).toBe("/api/v1/news/api-source-names");
expect(call.params).toEqual({});
expect(resp).toEqual(mockApiSourceNames);
});
test("sends region and language when provided", async () => {
cli.request.mockResolvedValueOnce({ data: mockApiSourceNames });
await client.getApiSourceNames(Region.Us, Locale.Tr);
const call = cli.request.mock.calls[0][0];
expect(call.params).toEqual({ region: Region.Us, language: Locale.Tr });
});
test("bubbles up request error", async () => {
cli.request.mockRejectedValueOnce(
new Error("Failed to fetch api source names")
);
await expect(client.getApiSourceNames()).rejects.toThrow(
"Failed to fetch api source names"
);
expect(cli.request).toHaveBeenCalledTimes(1);
});
});
describe("getNews", () => {
test("calls correct endpoint/params and matches raw response", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsResponse });
const resp = await client.getNews(Region.Tr, Locale.Tr, {
lane: NewsLane.BIST,
apiSource: "BBCBusiness,MarketWatch",
newsType: NewsType.BRIEFS,
page: 1,
size: 10,
orderBy: NewsOrderBy.TIMESTAMP,
orderByDirection: SortDirection.Desc,
symbols: "AAPL,MSFT",
categoryIds: "1,2",
sectorIds: "65533e047844ee7afe9941bf",
industryIds: "65533e441fa5c7b58afa0944",
qualityScoreMin: 7,
qualityScoreMax: 10,
timestampFrom: "2026-05-01",
timestampTo: "2026-06-01",
});
expect(cli.request).toHaveBeenCalledTimes(1);
const call = cli.request.mock.calls[0][0];
expect(call.method).toBe("GET");
expect(call.url).toBe("/api/v1/news");
expect(call.params).toEqual({
region: Region.Tr,
locale: Locale.Tr,
lane: NewsLane.BIST,
apiSource: "BBCBusiness,MarketWatch",
newsType: NewsType.BRIEFS,
page: 1,
size: 10,
orderBy: NewsOrderBy.TIMESTAMP,
orderByDirection: SortDirection.Desc,
symbols: "AAPL,MSFT",
categoryIds: "1,2",
sectorIds: "65533e047844ee7afe9941bf",
industryIds: "65533e441fa5c7b58afa0944",
qualityScoreMin: 7,
qualityScoreMax: 10,
timestampFrom: "2026-05-01",
timestampTo: "2026-06-01",
});
expect(resp.recordCount).toBe(352);
expect(resp.items).toHaveLength(1);
const n = resp.items[0];
expect(n.id).toBe(mockNewsResponse.items[0].id);
expect(n.url).toBe(mockNewsResponse.items[0].url);
expect(n.imageUrl).toBe(mockNewsResponse.items[0].imageUrl);
expect(n.timestamp).toBe(mockNewsResponse.items[0].timestamp);
expect(n.publisherUrl).toBe(mockNewsResponse.items[0].publisherUrl);
expect(n.qualityScore).toBe(mockNewsResponse.items[0].qualityScore);
expect(n.createdAt).toBe(mockNewsResponse.items[0].createdAt);
expect(n.publisher.name).toBe(mockNewsResponse.items[0].publisher.name);
expect(n.publisher.logoUrl).toBeNull();
expect(n.relatedTickers).toHaveLength(1);
expect(n.relatedTickers[0].id).toBe(mockNewsResponse.items[0].relatedTickers[0].id);
expect(n.relatedTickers[0].name).toBe(mockNewsResponse.items[0].relatedTickers[0].name);
expect(n.relatedTickers[0].symbol).toBe(mockNewsResponse.items[0].relatedTickers[0].symbol);
expect(n.tickers).toHaveLength(1);
expect(n.tickers![0].symbol).toBe("EQT");
expect(n.categories?.id).toBe(mockNewsResponse.items[0].categories.id);
expect(n.categories?.name).toBe(mockNewsResponse.items[0].categories.name);
expect(n.categories?.categoryType).toBe(mockNewsResponse.items[0].categories.categoryType);
expect(n.sectors?.id).toBe(mockNewsResponse.items[0].sectors.id);
expect(n.sectors?.name).toBe(mockNewsResponse.items[0].sectors.name);
expect(n.industries?.id).toBe(mockNewsResponse.items[0].industries.id);
expect(n.industries?.name).toBe(mockNewsResponse.items[0].industries.name);
expect(n.content?.title).toBe(mockNewsResponse.items[0].content.title);
expect(n.content?.description).toBe(mockNewsResponse.items[0].content.description);
expect(n.content?.content).toEqual(mockNewsResponse.items[0].content.content);
expect(n.content?.summary).toEqual(mockNewsResponse.items[0].content.summary);
expect(n.content?.investorInsight).toBe(mockNewsResponse.items[0].content.investorInsight);
});
test("does not send optional params when undefined", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsResponse });
await client.getNews(Region.Tr, Locale.Tr);
const call = cli.request.mock.calls[0][0];
expect(call.params).toEqual({
region: Region.Tr,
locale: Locale.Tr
});
});
test("bubbles up request error", async () => {
cli.request.mockRejectedValueOnce(new Error("Failed to fetch news"));
await expect(
client.getNews(Region.Tr, Locale.Tr, {
newsType: NewsType.REUTERS,
page: 0,
size: 10,
orderBy: NewsOrderBy.TIMESTAMP,
orderByDirection: SortDirection.Desc,
})
).rejects.toThrow("Failed to fetch news");
expect(cli.request).toHaveBeenCalledTimes(1);
});
});
describe("getNewsV2", () => {
test("calls correct endpoint/params and matches raw response", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsV2Response });
const resp = await client.getNewsV2(Region.Tr, Locale.Tr, {
lane: NewsLane.GLOBAL_MACRO,
apiSource: "BBCBusiness,MarketWatch",
newsType: NewsType.BRIEFS,
page: 1,
size: 10,
orderBy: NewsOrderBy.TIMESTAMP,
orderByDirection: SortDirection.Desc,
symbols: "AAPL,MSFT",
categoryIds: "1,2",
sectorIds: "65533e047844ee7afe9941bf",
industryIds: "65533e441fa5c7b58afa0944",
qualityScoreMin: 7,
qualityScoreMax: 10,
timestampFrom: "2026-05-01",
timestampTo: "2026-06-01",
});
expect(cli.request).toHaveBeenCalledTimes(1);
const call = cli.request.mock.calls[0][0];
expect(call.method).toBe("GET");
expect(call.url).toBe("/api/v2/news");
expect(call.params).toEqual({
region: Region.Tr,
locale: Locale.Tr,
lane: NewsLane.GLOBAL_MACRO,
apiSource: "BBCBusiness,MarketWatch",
newsType: NewsType.BRIEFS,
page: 1,
size: 10,
orderBy: NewsOrderBy.TIMESTAMP,
orderByDirection: SortDirection.Desc,
symbols: "AAPL,MSFT",
categoryIds: "1,2",
sectorIds: "65533e047844ee7afe9941bf",
industryIds: "65533e441fa5c7b58afa0944",
qualityScoreMin: 7,
qualityScoreMax: 10,
timestampFrom: "2026-05-01",
timestampTo: "2026-06-01",
});
expect(resp.recordCount).toBe(352);
expect(resp.items).toHaveLength(1);
const n = resp.items[0];
expect((n as any).relatedTickers).toBeUndefined();
expect(n.id).toBe(mockNewsV2Response.items[0].id);
expect(n.url).toBe(mockNewsV2Response.items[0].url);
});
test("does not send optional params when undefined", async () => {
cli.request.mockResolvedValueOnce({ data: mockNewsV2Response });
await client.getNewsV2(Region.Tr, Locale.Tr);
const call = cli.request.mock.calls[0][0];
expect(call.params).toEqual({
region: Region.Tr,
locale: Locale.Tr
});
});
test("bubbles up request error", async () => {
cli.request.mockRejectedValueOnce(new Error("Failed to fetch news v2"));
await expect(
client.getNewsV2(Region.Tr, Locale.Tr, {
newsType: NewsType.REUTERS,
page: 0,
size: 10,
orderBy: NewsOrderBy.TIMESTAMP,
orderByDirection: SortDirection.Desc,
})
).rejects.toThrow("Failed to fetch news v2");
expect(cli.request).toHaveBeenCalledTimes(1);
});
});
describe("streamNews", () => {
test("calls correct endpoint/params and correctly yields stream entities", async () => {
const eventsList: any[] = [];
// Mock get response to return a readable stream
const mockStreamData = [
"data: " + JSON.stringify([{ url: "http://example.com/stream-news-1", publiser: { name: "test-publisher" } }]) + "\n\n",
"data: " + JSON.stringify([{ url: "http://example.com/stream-news-2", publiser: { name: "test-publisher-2" } }]) + "\n\n",
];
const mockAsyncIterator = {
async *[Symbol.asyncIterator]() {
for (const chunk of mockStreamData) {
yield new TextEncoder().encode(chunk);
}
}
};
const axiosGetSpy = jest.spyOn(axios, 'get').mockResolvedValueOnce({
data: mockAsyncIterator
});
const { events, cancel } = client.streamNews(Region.Us, Locale.Tr);
for await (const newsList of events) {
eventsList.push(newsList);
}
expect(axiosGetSpy).toHaveBeenCalledTimes(1);
const callArgs = axiosGetSpy.mock.calls[0];
expect(callArgs[0]).toBe(`${client["baseUrl"]}/api/v1/news/stream?locale=tr®ion=us`);
expect(callArgs[1]?.responseType).toBe('stream');
expect(eventsList).toHaveLength(2);
expect(eventsList[0][0].url).toBe("http://example.com/stream-news-1");
expect(eventsList[1][0].url).toBe("http://example.com/stream-news-2");
cancel();
axiosGetSpy.mockRestore();
});
test("calls correct endpoint with optional parameters", async () => {
const mockAsyncIterator = {
async *[Symbol.asyncIterator]() {
yield new TextEncoder().encode("data: " + JSON.stringify([]) + "\n\n");
}
};
const axiosGetSpy = jest.spyOn(axios, 'get').mockResolvedValueOnce({
data: mockAsyncIterator
});
const { events, cancel } = client.streamNews(Region.Us, Locale.En, ["tech"], ["AAPL"], ["category"], ["software"], NewsLane.GLOBAL_MACRO, ["BBCBusiness"]);
for await (const _ of events) {
break;
}
expect(axiosGetSpy).toHaveBeenCalledTimes(1);
const callArgs = axiosGetSpy.mock.calls[0];
expect(callArgs[0]).toBe(`${client["baseUrl"]}/api/v1/news/stream?locale=en®ion=us&lane=global_macro&apiSource=BBCBusiness§orIds=tech&symbols=AAPL&categoryIds=category&industryIds=software`);
cancel();
axiosGetSpy.mockRestore();
});
});
});
});