from __future__ import annotations import sys from pathlib import Path import pytest SCRIPTS = Path(__file__).resolve().parents[1] / "scripts" if str(SCRIPTS) not in sys.path: sys.path.insert(0, str(SCRIPTS)) import domain_calculation_service as calculation_service # noqa: E402 BIRTH_PLACE = { "year": 1997, "month": 8, "day": 8, "lat": 36.420487, "lon": 114.209936, "tz": 8, "ayanamsa": "lahiri", } def test_evening_probes_are_not_the_range_midpoint() -> None: clocks = calculation_service.declared_window_probe_clocks("18:00", "22:59") assert clocks[0] == "18:00" assert clocks[-1] == "22:59" assert len(clocks) == 4 assert "20:29" not in clocks assert "20:30" not in clocks assert "12:00" not in clocks def test_unknown_day_probes_keep_explicit_clocks_including_midnight() -> None: clocks = calculation_service.declared_window_probe_clocks("00:00", "23:59") assert clocks[0] == "00:00" assert clocks[-1] == "23:59" assert len(clocks) == 4 def test_window_packet_rejects_a_single_birth_minute() -> None: with pytest.raises(calculation_service.CalculationError, match="single birth minute"): calculation_service.compute_declared_window_chart({ **BIRTH_PLACE, "range_start": "18:00", "range_end": "22:59", "hour": 20, "minute": 30, }) def test_window_packet_probes_always_pass_hour_and_minute(monkeypatch: pytest.MonkeyPatch) -> None: seen: list[tuple[int, int]] = [] real = calculation_service.compute_chart def wrapped(payload: dict) -> dict: assert "hour" in payload assert "minute" in payload seen.append((int(payload["hour"]), int(payload["minute"]))) return real(payload) monkeypatch.setattr(calculation_service, "compute_chart", wrapped) packet = calculation_service.compute_declared_window_chart({ **BIRTH_PLACE, "range_start": "18:00", "range_end": "22:59", }) assert packet["probe_count"] == 4 assert seen == [(18, 0), (19, 40), (21, 19), (22, 59)] assert packet["answer_policy"]["can_answer_precise_timing"] is False assert packet["answer_policy"]["birth_time_confidence"] == "declared_window" assert "hour" not in packet assert "minute" not in packet assert "birth_time" not in packet assert packet["stable_layers"]["planet_signs"]["Sun"] assert len(packet["varying_layers"].get("ascendant_signs", [])) >= 2 def test_api_handler_rejects_hour_on_declared_window() -> None: from jyotish_api_server import BadRequest, JyotishAPIHandler handler = JyotishAPIHandler.__new__(JyotishAPIHandler) with pytest.raises(BadRequest, match="single birth minute"): handler._compute_declared_window_chart({ **BIRTH_PLACE, "range_start": "18:00", "range_end": "22:59", "hour": 12, "minute": 0, })