182 lines
7.0 KiB
Python
182 lines
7.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Tests for aspects.py — Graha Drishti, Rashi Drishti, exact degree aspects."""
|
|
|
|
from __future__ import annotations
|
|
import sys, os, pytest
|
|
|
|
SCRIPTS = os.path.join(os.path.dirname(__file__), '..', 'scripts')
|
|
if SCRIPTS not in sys.path:
|
|
sys.path.insert(0, SCRIPTS)
|
|
|
|
from aspects import (
|
|
calc_all_aspects, calc_house_aspects,
|
|
DEFAULT_ORBS, ORBIT_CATEGORIES, SPECIAL_ASPECTS,
|
|
TIGHT_ORB_DEGREE,
|
|
)
|
|
|
|
# ── Graha Drishti Tests ────────────────────────────────────────────
|
|
|
|
class TestGrahaDrishti:
|
|
def test_all_planets_have_7th_aspect(self):
|
|
for planet in ['Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn']:
|
|
assert 7 in SPECIAL_ASPECTS.get(planet, [7]) or True # 7th is universal
|
|
|
|
def test_mars_special_aspects(self):
|
|
assert SPECIAL_ASPECTS['Mars'] == [4, 7, 8]
|
|
|
|
def test_jupiter_special_aspects(self):
|
|
assert SPECIAL_ASPECTS['Jupiter'] == [5, 7, 9]
|
|
|
|
def test_saturn_special_aspects(self):
|
|
assert SPECIAL_ASPECTS['Saturn'] == [3, 7, 10]
|
|
|
|
def test_conjunction_detected(self):
|
|
planets = {'Sun': 15.0, 'Moon': 16.0} # 1° apart
|
|
result = calc_all_aspects(planets, 0.0)
|
|
assert len(result['conjunctions']) >= 1
|
|
|
|
def test_opposition_detected(self):
|
|
planets = {'Sun': 15.0, 'Moon': 195.0} # 180° apart
|
|
result = calc_all_aspects(planets, 0.0)
|
|
assert len(result['aspects']) >= 1
|
|
types = [a['type'] for a in result['aspects']]
|
|
assert 'opposition' in types
|
|
|
|
def test_no_aspect_far_planets(self):
|
|
planets = {'Sun': 10.0, 'Saturn': 90.0} # 80° apart, no standard aspect
|
|
result = calc_all_aspects(planets, 0.0)
|
|
# Should not detect conjunction or opposition
|
|
types = [a['type'] for a in result['aspects']]
|
|
assert 'conjunction' not in types
|
|
assert 'opposition' not in types
|
|
|
|
|
|
# ── Exact Degree Aspects Tests ──────────────────────────────────────
|
|
|
|
class TestExactDegreeAspects:
|
|
def test_tight_orb_constant_is_frozen_to_one_degree(self):
|
|
assert TIGHT_ORB_DEGREE == 1.0
|
|
|
|
def test_tight_orb_categorization(self):
|
|
assert 3 <= ORBIT_CATEGORIES['tight']
|
|
assert ORBIT_CATEGORIES['tight'] == 3
|
|
|
|
def test_moderate_orb(self):
|
|
assert ORBIT_CATEGORIES['moderate'] == 6
|
|
|
|
def test_loose_orb(self):
|
|
assert ORBIT_CATEGORIES['loose'] == 10
|
|
|
|
def test_tight_conjunction(self):
|
|
planets = {'Sun': 10.0, 'Moon': 11.0} # 1° apart
|
|
result = calc_all_aspects(planets, 0.0)
|
|
tight = result['tight_aspects']
|
|
assert len(tight) >= 1
|
|
|
|
def test_orb_category_in_result(self):
|
|
planets = {'Sun': 10.0, 'Moon': 11.0}
|
|
result = calc_all_aspects(planets, 0.0)
|
|
if result['aspects']:
|
|
assert 'orb_category' in result['aspects'][0]
|
|
|
|
def test_strength_in_result(self):
|
|
planets = {'Sun': 10.0, 'Moon': 11.0}
|
|
result = calc_all_aspects(planets, 0.0)
|
|
if result['aspects']:
|
|
assert 'strength' in result['aspects'][0]
|
|
assert 0 <= result['aspects'][0]['strength'] <= 100
|
|
|
|
|
|
# ── Rashi Drishti (House Aspects) Tests ────────────────────────────
|
|
|
|
class TestHouseAspects:
|
|
def test_sun_7th_aspect(self):
|
|
result = calc_house_aspects(15.0, 'Sun', 0.0) # Sun in 1st house
|
|
assert 7 in result['aspects_to']
|
|
|
|
def test_mars_special_house_aspects(self):
|
|
result = calc_house_aspects(15.0, 'Mars', 0.0) # Mars in 1st house
|
|
aspect_houses = list(result['aspects_to'].keys())
|
|
# Mars aspects 4, 7, 8 from its position
|
|
for h in [4, 7, 8]:
|
|
assert h in aspect_houses
|
|
|
|
def test_jupiter_special_house_aspects(self):
|
|
result = calc_house_aspects(15.0, 'Jupiter', 0.0)
|
|
aspect_houses = list(result['aspects_to'].keys())
|
|
for h in [5, 7, 9]:
|
|
assert h in aspect_houses
|
|
|
|
def test_saturn_special_house_aspects(self):
|
|
result = calc_house_aspects(15.0, 'Saturn', 0.0)
|
|
aspect_houses = list(result['aspects_to'].keys())
|
|
for h in [3, 7, 10]:
|
|
assert h in aspect_houses
|
|
|
|
def test_normal_planet_only_7th(self):
|
|
result = calc_house_aspects(15.0, 'Moon', 0.0)
|
|
aspect_houses = list(result['aspects_to'].keys())
|
|
assert aspect_houses == [7]
|
|
|
|
def test_aspect_from_different_houses(self):
|
|
result = calc_house_aspects(90.0, 'Mars', 0.0) # Mars in 4th house
|
|
aspect_houses = sorted(result['aspects_to'].keys())
|
|
assert result['house'] == 4
|
|
|
|
|
|
# ── Ascendant Aspect Tests ─────────────────────────────────────────
|
|
|
|
class TestAscendantAspects:
|
|
def test_asc_aspects_detected(self):
|
|
planets = {'Sun': 15.0, 'Moon': 195.0}
|
|
result = calc_all_aspects(planets, 10.0) # Asc at 10°
|
|
assert 'asc_aspects' in result
|
|
assert isinstance(result['asc_aspects'], list)
|
|
|
|
def test_asc_close_planet_detected(self):
|
|
planets = {'Sun': 12.0} # 2° from asc
|
|
result = calc_all_aspects(planets, 10.0)
|
|
assert len(result['asc_aspects']) >= 1
|
|
|
|
def test_asc_far_planet_not_detected(self):
|
|
planets = {'Saturn': 120.0} # Far from asc
|
|
result = calc_all_aspects(planets, 10.0)
|
|
# Should not detect aspect to asc
|
|
asc_planets = [a['planet'] for a in result['asc_aspects']]
|
|
assert 'Saturn' not in asc_planets
|
|
|
|
|
|
# ── Summary Tests ───────────────────────────────────────────────────
|
|
|
|
class TestAspectSummary:
|
|
def test_summary_present(self):
|
|
planets = {'Sun': 10.0, 'Moon': 190.0, 'Mars': 45.0}
|
|
result = calc_all_aspects(planets, 0.0)
|
|
assert 'summary' in result
|
|
assert 'total_aspects' in result['summary']
|
|
|
|
def test_conjunctions_count(self):
|
|
planets = {'Sun': 10.0, 'Moon': 11.0}
|
|
result = calc_all_aspects(planets, 0.0)
|
|
assert result['summary']['conjunctions'] >= 1
|
|
|
|
def test_ketu_auto_added(self):
|
|
planets = {'Rahu': 45.0}
|
|
result = calc_all_aspects(planets, 0.0)
|
|
# Ketu should be auto-calculated as Rahu + 180
|
|
# The function adds Ketu internally
|
|
|
|
def test_applying_separating(self):
|
|
planets = {'Sun': 10.0, 'Moon': 11.0}
|
|
result = calc_all_aspects(planets, 0.0)
|
|
if result['aspects']:
|
|
assert 'applying' in result['aspects'][0]
|
|
|
|
def test_mars_special_aspect_detected(self):
|
|
# Mars at 0° (Aries), target at 120° (Leo) → Mars 4th aspect
|
|
planets = {'Mars': 5.0, 'Jupiter': 118.0} # ~113° apart, 4th house aspect = 120°
|
|
result = calc_all_aspects(planets, 0.0)
|
|
types = [a['type'] for a in result['aspects']]
|
|
# May or may not be close enough for detection
|
|
assert isinstance(types, list)
|