Files
python-tdd/pyswiss/apps/charts/tests/unit/test_populate_ephemeris.py

100 lines
4.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Unit tests for the populate_ephemeris management command.
pyswisseph calls are mocked — these tests verify date iteration,
snapshot persistence, and idempotency without touching the ephemeris.
Run:
pyswiss/.venv/Scripts/python pyswiss/manage.py test pyswiss/apps/charts
"""
from datetime import datetime, timezone
from unittest.mock import patch
from django.core.management import call_command
from django.test import TestCase
from apps.charts.models import EphemerisSnapshot
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
# 10 planets covering Fire×3, Earth×3, Air×2, Water×2 (one per sign)
# Expected: fire=3, water=2, earth=3, air=2, time=0, space=9
FAKE_PLANETS = {
'Sun': {'sign': 'Aries', 'degree': 10.0, 'retrograde': False},
'Moon': {'sign': 'Leo', 'degree': 130.0, 'retrograde': False},
'Mercury': {'sign': 'Sagittarius', 'degree': 250.0, 'retrograde': False},
'Venus': {'sign': 'Taurus', 'degree': 40.0, 'retrograde': False},
'Mars': {'sign': 'Virgo', 'degree': 160.0, 'retrograde': False},
'Jupiter': {'sign': 'Capricorn', 'degree': 280.0, 'retrograde': False},
'Saturn': {'sign': 'Gemini', 'degree': 70.0, 'retrograde': False},
'Uranus': {'sign': 'Aquarius', 'degree': 310.0, 'retrograde': False},
'Neptune': {'sign': 'Cancer', 'degree': 100.0, 'retrograde': False},
'Pluto': {'sign': 'Pisces', 'degree': 340.0, 'retrograde': False},
}
PATCH_TARGET = (
'apps.charts.management.commands.populate_ephemeris.get_planet_positions'
)
# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------
class PopulateEphemerisCommandTest(TestCase):
def _run(self, date_from, date_to):
with patch(PATCH_TARGET, return_value=FAKE_PLANETS):
call_command('populate_ephemeris',
date_from=date_from, date_to=date_to,
verbosity=0)
# ── date iteration ────────────────────────────────────────────────────
def test_creates_one_snapshot_per_day(self):
self._run('2000-01-01', '2000-01-03')
self.assertEqual(EphemerisSnapshot.objects.count(), 3)
def test_single_day_range_creates_one_snapshot(self):
self._run('2000-01-01', '2000-01-01')
self.assertEqual(EphemerisSnapshot.objects.count(), 1)
def test_snapshots_are_at_noon_utc(self):
self._run('2000-01-01', '2000-01-01')
snap = EphemerisSnapshot.objects.get()
self.assertEqual(snap.dt, datetime(2000, 1, 1, 12, 0, 0, tzinfo=timezone.utc))
# ── idempotency ───────────────────────────────────────────────────────
def test_rerunning_does_not_create_duplicates(self):
self._run('2000-01-01', '2000-01-03')
self._run('2000-01-01', '2000-01-03')
self.assertEqual(EphemerisSnapshot.objects.count(), 3)
def test_overlapping_ranges_do_not_duplicate(self):
self._run('2000-01-01', '2000-01-03')
self._run('2000-01-02', '2000-01-05')
self.assertEqual(EphemerisSnapshot.objects.count(), 5)
# ── element counts ────────────────────────────────────────────────────
def test_element_counts_are_persisted(self):
self._run('2000-01-01', '2000-01-01')
snap = EphemerisSnapshot.objects.get()
self.assertEqual(snap.fire, 3)
self.assertEqual(snap.water, 2)
self.assertEqual(snap.earth, 3)
self.assertEqual(snap.air, 2)
self.assertEqual(snap.time_el, 0)
self.assertEqual(snap.space_el, 9)
# ── chart_data payload ────────────────────────────────────────────────
def test_chart_data_contains_planets(self):
self._run('2000-01-01', '2000-01-01')
snap = EphemerisSnapshot.objects.get()
self.assertEqual(snap.chart_data['planets'], FAKE_PLANETS)