Files
stonks-oracle/tests/test_news_adapter.py
T
Celes Renata c85c0068a2 fix: clean up utcnow deprecation warnings, fix 12 failing tests, add CI/CD pipeline manifests
- Replace all datetime.utcnow() with datetime.now(tz=timezone.utc) across 8 files
- Fix 12 failing tests to match current implementation behavior
- Fix pytest_plugins in non-top-level conftest (moved to root conftest.py)
- Auto-fix 189 lint issues (import sorting, unused imports)
- Add CI/CD pipeline infrastructure (ARC, ArgoCD, Kargo manifests)
- Add values-beta.yaml and values-paper.yaml for staged deployments
- Update GitHub Actions workflow to use self-hosted-gremlin runners
- Add integration-test job to CI pipeline

Result: 1596 passed, 0 failed, 0 warnings
2026-04-18 03:59:28 +00:00

143 lines
5.1 KiB
Python

"""Tests for the Polygon.io news adapter.
Validates request building, response parsing, and error handling.
"""
from services.adapters.news_adapter import NewsDataAdapter, PolygonNewsAdapter
# --- Fake Polygon news responses ---
NEWS_RESPONSE = {
"results": [
{
"id": "abc123",
"publisher": {"name": "Reuters", "homepage_url": "https://reuters.com"},
"title": "Apple Reports Record Revenue",
"article_url": "https://reuters.com/apple-record",
"tickers": ["AAPL"],
"published_utc": "2026-04-10T14:30:00Z",
"description": "Apple Inc. reported record quarterly revenue.",
"keywords": ["earnings", "apple", "revenue"],
},
{
"id": "def456",
"publisher": {"name": "Bloomberg", "homepage_url": "https://bloomberg.com"},
"title": "Apple Supply Chain Update",
"article_url": "https://bloomberg.com/apple-supply",
"tickers": ["AAPL", "TSM"],
"published_utc": "2026-04-10T12:00:00Z",
"description": "Supply chain adjustments for upcoming product cycle.",
"keywords": ["supply_chain", "apple"],
},
],
"status": "OK",
"request_id": "req-news-001",
"count": 2,
"next_url": "https://api.polygon.io/v2/reference/news?cursor=abc",
}
EMPTY_NEWS_RESPONSE = {
"results": [],
"status": "OK",
"request_id": "req-news-002",
"count": 0,
}
class TestPolygonNewsSourceType:
def test_source_type(self):
adapter = PolygonNewsAdapter(api_key="k")
assert adapter.source_type() == "news_api"
def test_inherits_news_data_adapter(self):
assert issubclass(PolygonNewsAdapter, NewsDataAdapter)
def test_bucket_name(self):
adapter = PolygonNewsAdapter(api_key="k")
assert adapter.bucket_name() == "stonks-raw-news"
class TestPolygonNewsBuildRequest:
def setup_method(self):
self.adapter = PolygonNewsAdapter(api_key="test-key", base_url="https://api.polygon.io")
def test_default_request(self):
url, params = self.adapter._build_request("AAPL", {})
assert url == "https://api.polygon.io/v2/reference/news"
assert params["apiKey"] == "test-key"
assert params["ticker"] == "AAPL"
assert params["limit"] == "20"
def test_custom_limit(self):
_, params = self.adapter._build_request("AAPL", {"limit": 50})
assert params["limit"] == "50"
def test_limit_capped_at_1000(self):
_, params = self.adapter._build_request("AAPL", {"limit": 5000})
assert params["limit"] == "1000"
def test_order_param(self):
_, params = self.adapter._build_request("AAPL", {"order": "asc"})
assert params["order"] == "asc"
def test_date_filters(self):
config = {
"published_utc_gte": "2026-04-01",
"published_utc_lte": "2026-04-10",
}
_, params = self.adapter._build_request("AAPL", config)
assert params["published_utc.gte"] == "2026-04-01"
assert params["published_utc.lte"] == "2026-04-10"
def test_no_date_filters_when_absent(self):
_, params = self.adapter._build_request("AAPL", {})
assert "published_utc.gte" not in params
assert "published_utc.lte" not in params
def test_trailing_slash_stripped(self):
adapter = PolygonNewsAdapter(api_key="k", base_url="https://api.polygon.io/")
url, _ = adapter._build_request("AAPL", {})
assert "//v2" not in url
class TestPolygonNewsExtractItems:
def setup_method(self):
self.adapter = PolygonNewsAdapter(api_key="k")
def test_extract_articles(self):
items = self.adapter._extract_items(NEWS_RESPONSE)
assert len(items) == 2
assert items[0]["title"] == "Apple Reports Record Revenue"
assert items[1]["tickers"] == ["AAPL", "TSM"]
def test_extract_empty_results(self):
items = self.adapter._extract_items(EMPTY_NEWS_RESPONSE)
assert items == []
def test_extract_missing_results_key(self):
items = self.adapter._extract_items({"status": "OK"})
assert items == []
def test_extract_non_list_results(self):
items = self.adapter._extract_items({"results": "unexpected"})
assert items == []
class TestPolygonNewsErrorResult:
def test_error_result_fields(self):
adapter = PolygonNewsAdapter(api_key="k")
result = adapter._error_result("AAPL", "rate limited", 150.0, http_status=429, raw=b"slow down")
assert not result.ok
assert result.error == "rate limited"
assert result.http_status == 429
assert result.response_time_ms == 150.0
assert result.raw_payload == b"slow down"
assert result.metadata["provider"] == "polygon"
assert result.source_type == "news_api"
def test_error_result_defaults(self):
adapter = PolygonNewsAdapter(api_key="k")
result = adapter._error_result("MSFT", "timeout", 200.0)
assert result.http_status is None
assert result.raw_payload == b""
assert result.ticker == "MSFT"