All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
4.4 KiB
Python
100 lines
4.4 KiB
Python
"""
|
||
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)
|