BUG-710: call getSevenGovernorsChart with ketuMode/siderealMode so calculation.ketu_mode is the engine school, not the request echo. BUG-711: stop forbidding /ephemeris in the sidebar contract. BUG-712: compare ephemeris event longitudes at 6 decimals and fail closed when the golden is missing.
80 lines
3.0 KiB
Python
80 lines
3.0 KiB
Python
"""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"})
|