Merge pull request #66 from aguzererler/jules-17548469684748509551-99819dec

🧪 [Fix Finnhub API error handling and add coverage]
This commit is contained in:
ahmet guzererler 2026-03-21 17:27:49 +01:00 committed by GitHub
commit b0424a36d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 71 additions and 1 deletions

View File

@ -756,6 +756,32 @@ class TestGetBasicFinancials:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# 10.5 finnhub_news — _fetch_company_news_data helper
# ---------------------------------------------------------------------------
class TestFetchCompanyNewsData:
"""_fetch_company_news_data handles errors by returning an empty list."""
_PATCH_TARGET = "tradingagents.dataflows.finnhub_news._make_api_request"
def test_fetch_company_news_data_api_error_returns_empty_list(self):
from tradingagents.dataflows.finnhub_news import _fetch_company_news_data
with patch(self._PATCH_TARGET, side_effect=Exception("API failure")):
result = _fetch_company_news_data("AAPL", {"symbol": "AAPL"})
assert result == []
def test_fetch_company_news_data_invalid_response_type_returns_empty_list(self):
from tradingagents.dataflows.finnhub_news import _fetch_company_news_data
with patch(self._PATCH_TARGET, return_value={"error": "Not a list"}):
result = _fetch_company_news_data("AAPL", {"symbol": "AAPL"})
assert result == []
# 10. finnhub_news — get_company_news # 10. finnhub_news — get_company_news
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -892,6 +918,30 @@ class TestGetInsiderTransactions:
assert "AAPL" in result assert "AAPL" in result
def test_invalid_transaction_values_fall_back_to_raw_strings(self):
"""Testing the error path at line 220 where float conversion fails."""
from tradingagents.dataflows.finnhub_news import get_insider_transactions
invalid_txn = {
"data": [
{
"name": "Test Exec",
"transactionCode": "P",
"share": "invalid_share",
"price": "invalid_price",
"value": "invalid_value",
"transactionDate": "2024-01-10",
"filingDate": "2024-01-12",
}
]
}
with patch(self._PATCH_TARGET, return_value=_json_response(invalid_txn)):
result = get_insider_transactions("AAPL")
assert "invalid_share" in result
assert "invalid_price" in result
assert "invalid_value" in result
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 13. finnhub_scanner — get_market_movers_finnhub # 13. finnhub_scanner — get_market_movers_finnhub

View File

@ -5,16 +5,21 @@ transaction data using the Finnhub REST API. Output formats mirror the
Alpha Vantage news equivalents for consistent agent-facing data. Alpha Vantage news equivalents for consistent agent-facing data.
""" """
import logging
from datetime import datetime from datetime import datetime
from typing import Literal from typing import Literal
from .finnhub_common import ( from .finnhub_common import (
FinnhubError, FinnhubError,
ThirdPartyTimeoutError,
_make_api_request, _make_api_request,
_now_str, _now_str,
_to_unix_timestamp, _to_unix_timestamp,
) )
logger = logging.getLogger(__name__)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Type aliases # Type aliases
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -49,6 +54,21 @@ def _format_unix_ts(ts: int | None) -> str:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def _fetch_company_news_data(symbol: str, params: dict) -> list[dict]:
"""Helper to fetch company news and handle errors by returning an empty list."""
try:
response = _make_api_request("company-news", params)
except ThirdPartyTimeoutError:
raise
except Exception as e:
logger.error(f"Error fetching company news for {symbol}: {e}")
return []
if not isinstance(response, list):
return []
return response
def get_company_news(symbol: str, start_date: str, end_date: str) -> str: def get_company_news(symbol: str, start_date: str, end_date: str) -> str:
"""Fetch company-specific news via Finnhub /company-news. """Fetch company-specific news via Finnhub /company-news.
@ -73,7 +93,7 @@ def get_company_news(symbol: str, start_date: str, end_date: str) -> str:
"to": end_date, "to": end_date,
} }
articles: list[dict] = _make_api_request("company-news", params) articles: list[dict] = _fetch_company_news_data(symbol, params)
header = ( header = (
f"# Company News: {symbol} ({start_date} to {end_date}) — Finnhub\n" f"# Company News: {symbol} ({start_date} to {end_date}) — Finnhub\n"