c85c0068a2
- 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
143 lines
5.1 KiB
Python
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"
|