Files

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)