scaffolded PySwiss microservice: Django 6.0 project at pyswiss/ (core/ settings, apps/charts/), GET /api/chart/ + GET /api/charts/ views, EphemerisSnapshot model + migration, populate_ephemeris management command, 41 ITs (integrated + unit, all green); separate .venv with pyswisseph 2.10.3.2
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-04-13 19:03:45 -04:00
parent 97ec2f6ee6
commit b8af0041cc
23 changed files with 780 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
"""
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)