|
@@ -84,9 +84,10 @@ async def call_astro_tool(
|
|
|
|
|
|
|
|
# Albert Einstein: 1879-03-14 11:30 AM LMT (UTC+0:53), Ulm, Germany
|
|
# Albert Einstein: 1879-03-14 11:30 AM LMT (UTC+0:53), Ulm, Germany
|
|
|
# Rodden AA (birth certificate)
|
|
# Rodden AA (birth certificate)
|
|
|
|
|
+# Note: direct-call tests use UTC datetime (10:37 UTC = 11:30 LMT)
|
|
|
EINSTEIN = {
|
|
EINSTEIN = {
|
|
|
"name": "Albert Einstein",
|
|
"name": "Albert Einstein",
|
|
|
- "datetime": "1879-03-14T11:30:00+00:53",
|
|
|
|
|
|
|
+ "datetime": "1879-03-14T10:37:00", # UTC (11:30 LMT - 53min)
|
|
|
"lat": 48.39841,
|
|
"lat": 48.39841,
|
|
|
"lon": 9.99155,
|
|
"lon": 9.99155,
|
|
|
"planets": {
|
|
"planets": {
|
|
@@ -102,7 +103,7 @@ EINSTEIN = {
|
|
|
"neptune": ("Taurus", 7.87, False),
|
|
"neptune": ("Taurus", 7.87, False),
|
|
|
"pluto": ("Taurus", 24.73, False),
|
|
"pluto": ("Taurus", 24.73, False),
|
|
|
"chiron": ("Taurus", 5.55, False),
|
|
"chiron": ("Taurus", 5.55, False),
|
|
|
- "true_node": ("Aquarius", 1.48, True),
|
|
|
|
|
|
|
+ "true_node": ("Aquarius", 2.73, True),
|
|
|
"mean_node": ("Aquarius", 1.48, True),
|
|
"mean_node": ("Aquarius", 1.48, True),
|
|
|
},
|
|
},
|
|
|
"angles": {
|
|
"angles": {
|
|
@@ -113,9 +114,10 @@ EINSTEIN = {
|
|
|
|
|
|
|
|
# Chaka Khan: 1953-03-23 9:05 PM CST (UTC-6), Chicago, IL
|
|
# Chaka Khan: 1953-03-23 9:05 PM CST (UTC-6), Chicago, IL
|
|
|
# Rodden AA
|
|
# Rodden AA
|
|
|
|
|
+# Note: direct-call tests use UTC datetime (03:05 UTC next day = 21:05 CST)
|
|
|
CHAKA_KHAN = {
|
|
CHAKA_KHAN = {
|
|
|
"name": "Chaka Khan",
|
|
"name": "Chaka Khan",
|
|
|
- "datetime": "1953-03-23T21:05:00-06:00",
|
|
|
|
|
|
|
+ "datetime": "1953-03-24T03:05:00", # UTC (21:05 CST + 6h)
|
|
|
"lat": 41.87811,
|
|
"lat": 41.87811,
|
|
|
"lon": -87.62980,
|
|
"lon": -87.62980,
|
|
|
"planets": {
|
|
"planets": {
|
|
@@ -130,7 +132,7 @@ CHAKA_KHAN = {
|
|
|
"neptune": ("Libra", 23.05, True),
|
|
"neptune": ("Libra", 23.05, True),
|
|
|
"pluto": ("Leo", 21.15, True),
|
|
"pluto": ("Leo", 21.15, True),
|
|
|
"chiron": ("Capricornus", 20.22, False),
|
|
"chiron": ("Capricornus", 20.22, False),
|
|
|
- "true_node": ("Aquarius", 9.73, True),
|
|
|
|
|
|
|
+ "true_node": ("Aquarius", 11.14, False),
|
|
|
"mean_node": ("Aquarius", 9.73, True),
|
|
"mean_node": ("Aquarius", 9.73, True),
|
|
|
},
|
|
},
|
|
|
"angles": {
|
|
"angles": {
|
|
@@ -139,6 +141,35 @@ CHAKA_KHAN = {
|
|
|
},
|
|
},
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+# Donald Trump: 1946-06-14 10:54 AM EDT (UTC-4), Queens, NY
|
|
|
|
|
+# Rodden AA
|
|
|
|
|
+# Note: direct-call tests use UTC datetime (14:54 UTC = 10:54 EDT)
|
|
|
|
|
+TRUMP = {
|
|
|
|
|
+ "name": "Donald Trump",
|
|
|
|
|
+ "datetime": "1946-06-14T14:54:00", # UTC (10:54 EDT + 4h)
|
|
|
|
|
+ "lat": 40.72677,
|
|
|
|
|
+ "lon": -73.74152,
|
|
|
|
|
+ "planets": {
|
|
|
|
|
+ "sun": ("Gemini", 22.93, False),
|
|
|
|
|
+ "moon": ("Sagittarius", 21.20, False),
|
|
|
|
|
+ "mercury": ("Cancer", 8.87, False),
|
|
|
|
|
+ "venus": ("Cancer", 25.73, False),
|
|
|
|
|
+ "mars": ("Leo", 26.78, False),
|
|
|
|
|
+ "jupiter": ("Libra", 17.45, True),
|
|
|
|
|
+ "saturn": ("Cancer", 23.82, False),
|
|
|
|
|
+ "uranus": ("Gemini", 17.90, False),
|
|
|
|
|
+ "neptune": ("Libra", 5.85, True),
|
|
|
|
|
+ "pluto": ("Leo", 10.05, False),
|
|
|
|
|
+ "chiron": ("Libra", 14.92, False),
|
|
|
|
|
+ "true_node": ("Gemini", 20.75, True),
|
|
|
|
|
+ "mean_node": ("Gemini", 20.75, True),
|
|
|
|
|
+ },
|
|
|
|
|
+ "angles": {
|
|
|
|
|
+ "ascendant": ("Leo", 29.93),
|
|
|
|
|
+ "midheaven": ("Taurus", 24.40),
|
|
|
|
|
+ },
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
|
|
|
def _check_planets(result: dict, ref: dict, tol: float = 0.5) -> list[str]:
|
|
def _check_planets(result: dict, ref: dict, tol: float = 0.5) -> list[str]:
|
|
|
"""Check planetary positions against reference. Returns list of errors."""
|
|
"""Check planetary positions against reference. Returns list of errors."""
|
|
@@ -336,6 +367,83 @@ class TestLiveChakaKhan:
|
|
|
f"Retrograde mismatch: expected {expected}, got {retro_names}"
|
|
f"Retrograde mismatch: expected {expected}, got {retro_names}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+# ── Tests: Donald Trump ───────────────────────────────────────────────
|
|
|
|
|
+
|
|
|
|
|
+class TestLiveTrump:
|
|
|
|
|
+ """Call live astro-mcp server for Donald Trump's chart and verify."""
|
|
|
|
|
+
|
|
|
|
|
+ @pytest.mark.asyncio
|
|
|
|
|
+ async def test_natal_chart_planets(self):
|
|
|
|
|
+ result = await call_astro_tool(
|
|
|
|
|
+ "calculate_natal_chart",
|
|
|
|
|
+ {
|
|
|
|
|
+ "birth_datetime": TRUMP["datetime"],
|
|
|
|
|
+ "latitude": TRUMP["lat"],
|
|
|
|
|
+ "longitude": TRUMP["lon"],
|
|
|
|
|
+ "house_system": "placidus",
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+ assert "error" not in result, f"Server error: {result.get('error')}"
|
|
|
|
|
+ errors = _check_planets(result, TRUMP)
|
|
|
|
|
+ assert not errors, "Planet mismatches:\n" + "\n".join(errors)
|
|
|
|
|
+
|
|
|
|
|
+ @pytest.mark.asyncio
|
|
|
|
|
+ async def test_natal_chart_angles(self):
|
|
|
|
|
+ result = await call_astro_tool(
|
|
|
|
|
+ "calculate_natal_chart",
|
|
|
|
|
+ {
|
|
|
|
|
+ "birth_datetime": TRUMP["datetime"],
|
|
|
|
|
+ "latitude": TRUMP["lat"],
|
|
|
|
|
+ "longitude": TRUMP["lon"],
|
|
|
|
|
+ "house_system": "placidus",
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+ assert "error" not in result
|
|
|
|
|
+ errors = _check_angles(result, TRUMP)
|
|
|
|
|
+ assert not errors, "Angle mismatches:\n" + "\n".join(errors)
|
|
|
|
|
+
|
|
|
|
|
+ @pytest.mark.asyncio
|
|
|
|
|
+ async def test_natal_chart_houses(self):
|
|
|
|
|
+ result = await call_astro_tool(
|
|
|
|
|
+ "calculate_natal_chart",
|
|
|
|
|
+ {
|
|
|
|
|
+ "birth_datetime": TRUMP["datetime"],
|
|
|
|
|
+ "latitude": TRUMP["lat"],
|
|
|
|
|
+ "longitude": TRUMP["lon"],
|
|
|
|
|
+ "house_system": "placidus",
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+ assert "error" not in result
|
|
|
|
|
+ assert "houses" in result
|
|
|
|
|
+ assert len(result["houses"]) == 12
|
|
|
|
|
+ house_numbers = sorted(h["house"] for h in result["houses"])
|
|
|
|
|
+ assert house_numbers == list(range(1, 13))
|
|
|
|
|
+ for h in result["houses"]:
|
|
|
|
|
+ assert "sign" in h
|
|
|
|
|
+ assert "degree" in h
|
|
|
|
|
+ assert "absolute_lon" in h
|
|
|
|
|
+
|
|
|
|
|
+ @pytest.mark.asyncio
|
|
|
|
|
+ async def test_natal_chart_aspects(self):
|
|
|
|
|
+ result = await call_astro_tool(
|
|
|
|
|
+ "calculate_natal_chart",
|
|
|
|
|
+ {
|
|
|
|
|
+ "birth_datetime": TRUMP["datetime"],
|
|
|
|
|
+ "latitude": TRUMP["lat"],
|
|
|
|
|
+ "longitude": TRUMP["lon"],
|
|
|
|
|
+ "house_system": "placidus",
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+ assert "error" not in result
|
|
|
|
|
+ assert "aspects" in result
|
|
|
|
|
+ assert len(result["aspects"]) > 0
|
|
|
|
|
+ for asp in result["aspects"]:
|
|
|
|
|
+ assert "body1" in asp
|
|
|
|
|
+ assert "body2" in asp
|
|
|
|
|
+ assert "aspect" in asp
|
|
|
|
|
+ assert "orb" in asp
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
# ── Tests: _byId tools with DB celebrities ────────────────────────────
|
|
# ── Tests: _byId tools with DB celebrities ────────────────────────────
|
|
|
|
|
|
|
|
class TestLiveByNickname:
|
|
class TestLiveByNickname:
|
|
@@ -365,3 +473,14 @@ class TestLiveByNickname:
|
|
|
assert result.get("chart_type") == "natal"
|
|
assert result.get("chart_type") == "natal"
|
|
|
errors = _check_planets(result, CHAKA_KHAN)
|
|
errors = _check_planets(result, CHAKA_KHAN)
|
|
|
assert not errors, "Planet mismatches:\n" + "\n".join(errors)
|
|
assert not errors, "Planet mismatches:\n" + "\n".join(errors)
|
|
|
|
|
+
|
|
|
|
|
+ @pytest.mark.asyncio
|
|
|
|
|
+ async def test_trump_by_nickname(self):
|
|
|
|
|
+ result = await call_astro_tool(
|
|
|
|
|
+ "calculate_natal_chart_by_id",
|
|
|
|
|
+ {"person_id": "trump", "house_system": "placidus"},
|
|
|
|
|
+ )
|
|
|
|
|
+ assert "error" not in result
|
|
|
|
|
+ assert result.get("chart_type") == "natal"
|
|
|
|
|
+ errors = _check_planets(result, TRUMP)
|
|
|
|
|
+ assert not errors, "Planet mismatches:\n" + "\n".join(errors)
|