phase 14-15: docker build validation and helm deployment
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
"""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"
|
||||
Reference in New Issue
Block a user