7b435d4263
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m32s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 11s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 9s
build / build (push) Successful in 25s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m18s
Testy / Kontrola składni wszystkich warstw (push) Successful in 31s
Testy / Build obrazu silnika B (swisseph) (push) Failing after 13m6s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Failing after 13m25s
Pierwsza technika relacyjna z pełnym UI (Returns były już w kalendarzu od LOG-12). Dwie osoby → aspekty MIĘDZY ich horoskopami (planeta osoby A do planety osoby B). Silnik: `find_cross_aspects(a, b, orb, luminary_bonus, minor)` — każdy obiekt A × każdy obiekt B. `obj1` = osoba A, `obj2` = osoba B. Statyczne (dwa natale, brak wspólnego czasu) → bez applying/separating. Par sztywnych (NN/SN) NIE wycinamy — między dwiema osobami to realny aspekt, nie artefakt definicji. Wspólny matcher `_first_aspect` (z find_aspects), więc orb/bonus/aspekty poboczne działają tak samo. Endpoint `POST /chart/synastry` (dwie osoby + zodiak + ustawienia aspektów) → pozycje obu + siatka aspektów z glifami. Prezentacja: zakładka „Synastria", formularz dwóch osób (pętla po a_/b_), tabela aspektów A · aspekt · B · orb. Weryfikacja na żywym API: 13+13 obiektów, 63 aspekty synastryczne z poprawnymi glifami i bonusem świateł (A.Sun ☌ B.Venus przy orbie 8.67 = 8+2). Testy: logika +4 (cross-aspekty, kolejność A/B, brak filtra par sztywnych, brak applying), prezentacja +7 (trasa, formularz dwóch osób, klient, tabela). Logika 277, prezentacja 228. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
"""Synastria — technika relacyjna (PRE-04)."""
|
|
import pathlib
|
|
|
|
APP = pathlib.Path(__file__).resolve().parents[1] / "app"
|
|
TPL = (APP / "templates" / "synastry.html").read_text(encoding="utf-8")
|
|
BASE = (APP / "templates" / "base.html").read_text(encoding="utf-8")
|
|
MAIN = (APP / "main.py").read_text(encoding="utf-8")
|
|
CLIENT = (APP / "clients" / "logic_client.py").read_text(encoding="utf-8")
|
|
|
|
|
|
def _client():
|
|
import os
|
|
|
|
os.environ.pop("APP_PASSWORD", None)
|
|
from starlette.testclient import TestClient
|
|
|
|
from app.main import app
|
|
|
|
return TestClient(app)
|
|
|
|
|
|
def test_tab_is_in_the_menu():
|
|
assert 'href="/synastry"' in BASE and "Synastria" in BASE
|
|
|
|
|
|
def test_routes_exist():
|
|
assert '@app.get("/synastry"' in MAIN and '@app.post("/synastry"' in MAIN
|
|
|
|
|
|
def test_get_renders_two_person_form():
|
|
r = _client().get("/synastry")
|
|
assert r.status_code == 200
|
|
# dwie osoby: pola z prefiksami a_ i b_
|
|
for pfx in ("a_", "b_"):
|
|
assert f'name="{pfx}date"' in r.text and f'name="{pfx}time"' in r.text
|
|
|
|
|
|
def test_form_has_both_people_and_shared_aspect_settings():
|
|
"""Pola dwóch osób generuje pętla — sprawdzamy WYRENDEROWANY formularz."""
|
|
html = _client().get("/synastry").text
|
|
for pfx in ("a_", "b_"):
|
|
assert f'name="{pfx}person"' in html
|
|
assert f'name="{pfx}lat"' in html
|
|
assert 'name="aspect_orb"' in html and 'name="aspect_minor"' in html
|
|
|
|
|
|
def test_handler_calls_synastry_with_both_moments():
|
|
assert "logic.synastry(" in MAIN
|
|
assert '"when_utc": iso_a' in MAIN and '"when_utc": iso_b' in MAIN
|
|
|
|
|
|
def test_client_posts_to_synastry_endpoint():
|
|
assert 'self._post("/chart/synastry"' in CLIENT
|
|
assert '"person_a": person_a' in CLIENT and '"person_b": person_b' in CLIENT
|
|
|
|
|
|
def test_result_table_shows_cross_aspects():
|
|
"""Wynik: kolumny osoba A · aspekt · osoba B · orb."""
|
|
assert "Aspekty synastryczne" in TPL
|
|
assert "a.obj1" in TPL and "a.obj2" in TPL and "a.glyph" in TPL
|