"""Module tests for sidereal ingress and station scanning.""" from __future__ import annotations import json import sys from pathlib import Path import pytest from scripts.ephemeris_events import EphemerisEventsError, build_ephemeris_events ROOT = Path(__file__).resolve().parents[1] GOLDEN = ROOT / "tests" / "golden" / "ephemeris_events_raman_20260915_90d.json" WINDOW = { "start_date": "2026-09-15", "end_date": "2026-12-14", "ayanamsa": "raman", "node_mode": "mean", } COORD_DECIMALS = 6 def _quantize_event(event: dict) -> dict: quantized = dict(event) for key in ("longitude", "speed_longitude"): if key in quantized and isinstance(quantized[key], (int, float)): quantized[key] = round(float(quantized[key]), COORD_DECIMALS) return quantized def _assert_events_match_golden(events: list) -> None: assert GOLDEN.exists(), ( f"missing golden {GOLDEN}; rebuild with scripts/generate_ephemeris_events_golden.py, " "do not let this test write the file" ) golden = json.loads(GOLDEN.read_text(encoding="utf-8")) assert [_quantize_event(item) for item in events] == [_quantize_event(item) for item in golden] for live, expected in zip(events, golden, strict=True): for key in ("kind", "date", "body"): assert live[key] == expected[key] for key in ("from_sign", "to_sign", "motion"): if key in expected: assert live.get(key) == expected[key] def test_raman_90_day_scan_matches_live_golden_and_has_both_kinds() -> None: result = build_ephemeris_events(WINDOW) _assert_events_match_golden(result["events"]) assert len(result["events"]) == 14 assert {item["kind"] for item in result["events"]} == {"ingress", "station"} assert [item["date"] for item in result["events"]] == sorted(item["date"] for item in result["events"]) assert result["calculation"]["ayanamsa"] == "raman" def test_missing_golden_fails_instead_of_rewriting(monkeypatch, tmp_path: Path) -> None: missing = tmp_path / "ephemeris_events_raman_20260915_90d.json" monkeypatch.setattr(sys.modules[__name__], "GOLDEN", missing) result = build_ephemeris_events(WINDOW) with pytest.raises(AssertionError, match="missing golden"): _assert_events_match_golden(result["events"]) assert not missing.exists() def test_lahiri_differs_from_raman_on_the_same_window() -> None: raman = build_ephemeris_events(WINDOW) lahiri = build_ephemeris_events({**WINDOW, "ayanamsa": "lahiri"}) assert raman["events"] != lahiri["events"] assert lahiri["calculation"]["ayanamsa"] == "lahiri" def test_range_over_730_days_is_rejected() -> None: with pytest.raises(EphemerisEventsError, match="730"): build_ephemeris_events({"start_date": "2020-01-01", "end_date": "2022-01-02", "ayanamsa": "raman"}) def test_unsupported_ayanamsa_is_rejected() -> None: with pytest.raises(EphemerisEventsError, match="unsupported ayanamsa"): build_ephemeris_events({**WINDOW, "ayanamsa": "not-a-real-ayanamsa"})