import json from datetime import datetime, timedelta from pathlib import Path import pytest from app import cycle_day_estimate, parse_iso_date, split_legacy_knowledge def test_parse_iso_date_accepts_today(): today = datetime.now().astimezone().date() assert parse_iso_date(today.isoformat()) == today def test_parse_iso_date_rejects_future_date(): today = datetime.now().astimezone().date() future = (today + timedelta(days=1)).isoformat() with pytest.raises(ValueError, match="future"): parse_iso_date(future) def test_cycle_estimate_is_transparent(): today = datetime.now().astimezone().date() day, explanation = cycle_day_estimate(today.isoformat(), 28) assert day == 1 assert "cannot confirm hormonal phase or ovulation" in explanation def test_legacy_splitter_retains_stable_ids(): text = ( "A sufficiently long first paragraph that should become a source chunk.\n\n" "A sufficiently long second paragraph that should become another chunk." ) chunks = split_legacy_knowledge(text) assert [chunk.source_id for chunk in chunks] == ["legacy-001", "legacy-002"] def test_active_sources_are_traceable(): source_path = Path(__file__).parents[1] / "knowledge" / "sources.json" records = json.loads(source_path.read_text(encoding="utf-8")) assert len(records) >= 5 assert len({record["source_id"] for record in records}) == len(records) for record in records: assert record["url"].startswith("https://") assert record["reviewed_at"] assert len(record["text"]) >= 100