|
@@ -103,16 +103,18 @@ def test_sqlite_summary_cache_does_not_create_placeholder_row():
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_prune_clusters_deletes_rows_older_than_retention():
|
|
def test_prune_clusters_deletes_rows_older_than_retention():
|
|
|
|
|
+ from datetime import datetime, timezone, timedelta
|
|
|
with tempfile.TemporaryDirectory() as td:
|
|
with tempfile.TemporaryDirectory() as td:
|
|
|
db = Path(td) / "news.sqlite"
|
|
db = Path(td) / "news.sqlite"
|
|
|
store = SQLiteClusterStore(db)
|
|
store = SQLiteClusterStore(db)
|
|
|
|
|
+ now_str = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S+00:00")
|
|
|
store.upsert_clusters([
|
|
store.upsert_clusters([
|
|
|
{
|
|
{
|
|
|
"cluster_id": "fresh",
|
|
"cluster_id": "fresh",
|
|
|
"headline": "Fresh",
|
|
"headline": "Fresh",
|
|
|
"summary": "Fresh summary",
|
|
"summary": "Fresh summary",
|
|
|
"entities": ["Bitcoin"],
|
|
"entities": ["Bitcoin"],
|
|
|
- "timestamp": "Wed, 01 Apr 2026 12:00:00 GMT",
|
|
|
|
|
|
|
+ "timestamp": now_str,
|
|
|
"articles": [],
|
|
"articles": [],
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
@@ -120,17 +122,11 @@ def test_prune_clusters_deletes_rows_older_than_retention():
|
|
|
"headline": "Stale",
|
|
"headline": "Stale",
|
|
|
"summary": "Stale summary",
|
|
"summary": "Stale summary",
|
|
|
"entities": ["Iran"],
|
|
"entities": ["Iran"],
|
|
|
- "timestamp": "Wed, 01 Apr 2026 11:00:00 GMT",
|
|
|
|
|
|
|
+ "timestamp": "2025-01-01T11:00:00+00:00",
|
|
|
"articles": [],
|
|
"articles": [],
|
|
|
},
|
|
},
|
|
|
], topic="other")
|
|
], topic="other")
|
|
|
|
|
|
|
|
- with store._conn() as conn:
|
|
|
|
|
- conn.execute(
|
|
|
|
|
- "UPDATE clusters SET updated_at=? WHERE cluster_id=?",
|
|
|
|
|
- ("2025-01-01T00:00:00+00:00", "stale"),
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
deleted = store.prune_clusters(retention_days=30)
|
|
deleted = store.prune_clusters(retention_days=30)
|
|
|
|
|
|
|
|
assert deleted == 1
|
|
assert deleted == 1
|
|
@@ -589,9 +585,12 @@ def test_poller_persists_clusters_under_post_enrichment_topic(monkeypatch):
|
|
|
the post-enrichment topic so SQL filtering and dashboard groupings see the
|
|
the post-enrichment topic so SQL filtering and dashboard groupings see the
|
|
|
real classification."""
|
|
real classification."""
|
|
|
import asyncio
|
|
import asyncio
|
|
|
|
|
+ from datetime import datetime, timezone
|
|
|
|
|
|
|
|
import news_mcp.jobs.poller as poller
|
|
import news_mcp.jobs.poller as poller
|
|
|
|
|
|
|
|
|
|
+ _now_str = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S+00:00")
|
|
|
|
|
+
|
|
|
captured = {"upserts": []}
|
|
captured = {"upserts": []}
|
|
|
|
|
|
|
|
class DummyStore:
|
|
class DummyStore:
|
|
@@ -656,7 +655,7 @@ def test_poller_persists_clusters_under_post_enrichment_topic(monkeypatch):
|
|
|
"sentiment": "neutral",
|
|
"sentiment": "neutral",
|
|
|
"importance": 0.0,
|
|
"importance": 0.0,
|
|
|
"sources": ["S"],
|
|
"sources": ["S"],
|
|
|
- "timestamp": "Wed, 01 Apr 2026 12:00:00 GMT",
|
|
|
|
|
|
|
+ "timestamp": _now_str,
|
|
|
"articles": [],
|
|
"articles": [],
|
|
|
}
|
|
}
|
|
|
]
|
|
]
|
|
@@ -681,7 +680,7 @@ def test_poller_persists_clusters_under_post_enrichment_topic(monkeypatch):
|
|
|
async def _mock_fetch2(limit, url_list=None):
|
|
async def _mock_fetch2(limit, url_list=None):
|
|
|
return [
|
|
return [
|
|
|
{"title": "SEC fines firm", "url": "https://example.com/a", "source": "S",
|
|
{"title": "SEC fines firm", "url": "https://example.com/a", "source": "S",
|
|
|
- "timestamp": "Wed, 01 Apr 2026 12:00:00 GMT", "summary": "..."},
|
|
|
|
|
|
|
+ "timestamp": _now_str, "summary": "..."},
|
|
|
]
|
|
]
|
|
|
monkeypatch.setattr(poller, "fetch_news_articles", _mock_fetch2)
|
|
monkeypatch.setattr(poller, "fetch_news_articles", _mock_fetch2)
|
|
|
monkeypatch.setattr(poller, "dedup_and_cluster_articles", fake_cluster)
|
|
monkeypatch.setattr(poller, "dedup_and_cluster_articles", fake_cluster)
|