620 lines
22 KiB
Python
620 lines
22 KiB
Python
|
|
"""Comprehensive tests for Tarot attributes, alphabets, ciphers, and numerology."""
|
|||
|
|
|
|||
|
|
from datetime import datetime
|
|||
|
|
|
|||
|
|
import pytest
|
|||
|
|
from src.tarot.attributes import (
|
|||
|
|
Month, Day, Weekday, Hour, ClockHour, Zodiac, Suit, Meaning, Letter, Sephera, Degree, Element,
|
|||
|
|
AstrologicalInfluence, TreeOfLife, Correspondences, CardImage,
|
|||
|
|
EnglishAlphabet, GreekAlphabet, HebrewAlphabet, Number, Color, Planet, God,
|
|||
|
|
Cipher, CipherResult,
|
|||
|
|
)
|
|||
|
|
from src.tarot.card.data import CardDataLoader, calculate_digital_root
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# Basic Attribute Tests
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
class TestMonth:
|
|||
|
|
def test_month_creation(self):
|
|||
|
|
month = Month(1, "January", "Capricorn", "Aquarius")
|
|||
|
|
assert month.number == 1
|
|||
|
|
assert month.name == "January"
|
|||
|
|
assert month.zodiac_start == "Capricorn"
|
|||
|
|
|
|||
|
|
def test_month_all_months(self):
|
|||
|
|
months = [
|
|||
|
|
Month(i, f"Month_{i}", "Sign_1", "Sign_2")
|
|||
|
|
for i in range(1, 13)
|
|||
|
|
]
|
|||
|
|
assert len(months) == 12
|
|||
|
|
assert months[0].number == 1
|
|||
|
|
assert months[11].number == 12
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestDay:
|
|||
|
|
def test_day_creation(self):
|
|||
|
|
day = Day(1, "Sunday", "Sun")
|
|||
|
|
assert day.number == 1
|
|||
|
|
assert day.name == "Sunday"
|
|||
|
|
assert day.planetary_correspondence == "Sun"
|
|||
|
|
|
|||
|
|
def test_all_weekdays(self):
|
|||
|
|
days = [
|
|||
|
|
Day(i, f"Day_{i}", f"Planet_{i}")
|
|||
|
|
for i in range(1, 8)
|
|||
|
|
]
|
|||
|
|
assert len(days) == 7
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestWeekday:
|
|||
|
|
def test_weekday_creation(self):
|
|||
|
|
weekday = Weekday(1, "Monday", "Moon")
|
|||
|
|
assert weekday.name == "Monday"
|
|||
|
|
assert weekday.planetary_correspondence == "Moon"
|
|||
|
|
assert weekday.is_weekend is False
|
|||
|
|
|
|||
|
|
def test_weekday_invalid_number(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
Weekday(0, "Zero", "Sun")
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestClockHour:
|
|||
|
|
def test_clock_hour_creation(self):
|
|||
|
|
hour = ClockHour(13, 1, "PM", "Mars", "Afternoon surge")
|
|||
|
|
assert hour.hour_24 == 13
|
|||
|
|
assert hour.hour_12 == 1
|
|||
|
|
assert hour.time_of_day == "Night"
|
|||
|
|
|
|||
|
|
def test_clock_hour_invalid_period(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
ClockHour(12, 12, "XX", "Sun")
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestZodiac:
|
|||
|
|
def test_zodiac_creation(self):
|
|||
|
|
zodiac = Zodiac("Aries", "♈", "Fire", "Mars", "Mar 21 - Apr 19")
|
|||
|
|
assert zodiac.name == "Aries"
|
|||
|
|
assert zodiac.element == "Fire"
|
|||
|
|
assert zodiac.ruling_planet == "Mars"
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestSuit:
|
|||
|
|
def test_suit_creation(self):
|
|||
|
|
suit = Suit("Cups", "Water", "Chalice", 1)
|
|||
|
|
assert suit.name == "Cups"
|
|||
|
|
assert suit.element == "Water"
|
|||
|
|
assert suit.number == 1
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestMeaning:
|
|||
|
|
def test_meaning_creation(self):
|
|||
|
|
meaning = Meaning("This is positive", "This is negative")
|
|||
|
|
assert meaning.upright == "This is positive"
|
|||
|
|
assert meaning.reversed == "This is negative"
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# Sepheric Tests
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
class TestSephera:
|
|||
|
|
def test_sephera_creation(self):
|
|||
|
|
sephera = Sephera(1, "Kether", "כתר", "Crown", "Metatron", "Chaioth", "Primum")
|
|||
|
|
assert sephera.number == 1
|
|||
|
|
assert sephera.name == "Kether"
|
|||
|
|
assert sephera.hebrew_name == "כתר"
|
|||
|
|
|
|||
|
|
def test_all_sephera(self):
|
|||
|
|
sephera_list = [
|
|||
|
|
Sephera(i, f"Sephera_{i}", "Hebrew", "Meaning", "Angel", "Order", "Chakra")
|
|||
|
|
for i in range(1, 11)
|
|||
|
|
]
|
|||
|
|
assert len(sephera_list) == 10
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# Alphabet Tests
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
class TestEnglishAlphabet:
|
|||
|
|
def test_english_letter_creation(self):
|
|||
|
|
letter = EnglishAlphabet("A", 1, "ay")
|
|||
|
|
assert letter.letter == "A"
|
|||
|
|
assert letter.position == 1
|
|||
|
|
assert letter.sound == "ay"
|
|||
|
|
|
|||
|
|
def test_english_invalid_position_low(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
EnglishAlphabet("A", 0, "ay")
|
|||
|
|
|
|||
|
|
def test_english_invalid_position_high(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
EnglishAlphabet("A", 27, "ay")
|
|||
|
|
|
|||
|
|
def test_english_invalid_letter(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
EnglishAlphabet("AB", 1, "ay")
|
|||
|
|
|
|||
|
|
def test_english_all_letters(self):
|
|||
|
|
letters = [EnglishAlphabet(chr(65 + i), i + 1, "sound") for i in range(26)]
|
|||
|
|
assert len(letters) == 26
|
|||
|
|
assert letters[0].letter == "A"
|
|||
|
|
assert letters[25].letter == "Z"
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestGreekAlphabet:
|
|||
|
|
def test_greek_letter_creation(self):
|
|||
|
|
letter = GreekAlphabet("Α", 1, "alpha")
|
|||
|
|
assert letter.letter == "Α"
|
|||
|
|
assert letter.position == 1
|
|||
|
|
assert letter.transliteration == "alpha"
|
|||
|
|
|
|||
|
|
def test_greek_invalid_position_low(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
GreekAlphabet("Α", 0, "alpha")
|
|||
|
|
|
|||
|
|
def test_greek_invalid_position_high(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
GreekAlphabet("Α", 25, "alpha")
|
|||
|
|
|
|||
|
|
def test_greek_all_letters(self):
|
|||
|
|
letters = [GreekAlphabet(f"Α{i}", i + 1, f"greek_{i}") for i in range(24)]
|
|||
|
|
assert len(letters) == 24
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestHebrewAlphabet:
|
|||
|
|
def test_hebrew_letter_creation(self):
|
|||
|
|
letter = HebrewAlphabet("א", 1, "aleph", "Start")
|
|||
|
|
assert letter.letter == "א"
|
|||
|
|
assert letter.position == 1
|
|||
|
|
assert letter.transliteration == "aleph"
|
|||
|
|
assert letter.meaning == "Start"
|
|||
|
|
|
|||
|
|
def test_hebrew_invalid_position_low(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
HebrewAlphabet("א", 0, "aleph", "Start")
|
|||
|
|
|
|||
|
|
def test_hebrew_invalid_position_high(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
HebrewAlphabet("א", 23, "aleph", "Start")
|
|||
|
|
|
|||
|
|
def test_hebrew_all_letters(self):
|
|||
|
|
letters = [HebrewAlphabet(f"א{i}", i + 1, f"hebrew_{i}", f"meaning_{i}") for i in range(22)]
|
|||
|
|
assert len(letters) == 22
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# Number Tests
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
class TestNumber:
|
|||
|
|
def test_number_creation(self):
|
|||
|
|
num = Number(1, "Kether", "Spirit", 0) # compliment is auto-calculated
|
|||
|
|
assert num.value == 1
|
|||
|
|
assert num.sephera == "Kether"
|
|||
|
|
assert num.compliment == 8 # 10 - 1 = 9, but 9->9, so 1->8
|
|||
|
|
|
|||
|
|
def test_number_compliments(self):
|
|||
|
|
"""Test that compliments are auto-calculated correctly."""
|
|||
|
|
test_cases = [(1, 8), (2, 7), (3, 6), (4, 5), (5, 4), (6, 3), (7, 2), (8, 1), (9, 9)]
|
|||
|
|
for value, expected_compliment in test_cases:
|
|||
|
|
num = Number(value, f"Sephera_{value}", "Element", 0)
|
|||
|
|
assert num.compliment == expected_compliment
|
|||
|
|
|
|||
|
|
def test_number_invalid_value_low(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
Number(0, "Sephera", "Element", 0)
|
|||
|
|
|
|||
|
|
def test_number_invalid_value_high(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
Number(10, "Sephera", "Element", 0)
|
|||
|
|
|
|||
|
|
def test_all_numbers(self):
|
|||
|
|
numbers = [Number(i, f"Sephera_{i}", "Element", 0) for i in range(1, 10)]
|
|||
|
|
assert len(numbers) == 9
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# Color Tests
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
class TestColor:
|
|||
|
|
def test_color_creation(self):
|
|||
|
|
color = Color("Red", "#FF0000", (255, 0, 0), "Gevurah", 5, "Fire", "Briah", "Power")
|
|||
|
|
assert color.name == "Red"
|
|||
|
|
assert color.hex_value == "#FF0000"
|
|||
|
|
assert color.rgb == (255, 0, 0)
|
|||
|
|
assert color.number == 5
|
|||
|
|
|
|||
|
|
def test_color_invalid_hex_format(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
Color("Red", "FF0000", (255, 0, 0), "Gevurah", 5, "Fire", "Briah", "Power")
|
|||
|
|
|
|||
|
|
def test_color_invalid_hex_length(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
Color("Red", "#FF00", (255, 0, 0), "Gevurah", 5, "Fire", "Briah", "Power")
|
|||
|
|
|
|||
|
|
def test_color_invalid_rgb_low(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
Color("Red", "#FF0000", (-1, 0, 0), "Gevurah", 5, "Fire", "Briah", "Power")
|
|||
|
|
|
|||
|
|
def test_color_invalid_rgb_high(self):
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
Color("Red", "#FF0000", (256, 0, 0), "Gevurah", 5, "Fire", "Briah", "Power")
|
|||
|
|
|
|||
|
|
def test_color_all_valid_rgb(self):
|
|||
|
|
for r in [0, 128, 255]:
|
|||
|
|
for g in [0, 128, 255]:
|
|||
|
|
for b in [0, 128, 255]:
|
|||
|
|
color = Color("Test", "#000000", (r, g, b), "Sephera", 1, "Element", "Scale", "Meaning")
|
|||
|
|
assert color.rgb == (r, g, b)
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# Planet Tests
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestPlanet:
|
|||
|
|
def test_planet_creation(self):
|
|||
|
|
number = Number(6, "Tiphareth", "Fire", 0)
|
|||
|
|
color = Color("Gold", "#FFD700", (255, 215, 0), "Tiphareth", 6, "Fire", "Yetzirah", "Beauty")
|
|||
|
|
planet = Planet(
|
|||
|
|
name="Sun",
|
|||
|
|
symbol="☉",
|
|||
|
|
element="Fire",
|
|||
|
|
ruling_zodiac=["Leo"],
|
|||
|
|
associated_numbers=[number],
|
|||
|
|
associated_letters=["Resh"],
|
|||
|
|
keywords=["Vitality"],
|
|||
|
|
color=color,
|
|||
|
|
description="Center",
|
|||
|
|
)
|
|||
|
|
assert planet.name == "Sun"
|
|||
|
|
assert planet.color is color
|
|||
|
|
assert planet.associated_numbers[0].value == 6
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestGod:
|
|||
|
|
def test_god_creation(self):
|
|||
|
|
number = Number(6, "Tiphareth", "Fire", 0)
|
|||
|
|
planet = Planet(
|
|||
|
|
name="Sun",
|
|||
|
|
symbol="☉",
|
|||
|
|
element="Fire",
|
|||
|
|
ruling_zodiac=["Leo"],
|
|||
|
|
associated_numbers=[number],
|
|||
|
|
associated_letters=["Resh"],
|
|||
|
|
keywords=["Vitality"],
|
|||
|
|
color=None,
|
|||
|
|
description="Center",
|
|||
|
|
)
|
|||
|
|
god = God(
|
|||
|
|
name="Ra",
|
|||
|
|
culture="Egyptian",
|
|||
|
|
pantheon="Solar",
|
|||
|
|
domains=["Consciousness"],
|
|||
|
|
epithets=["Sun God"],
|
|||
|
|
mythology="Solar deity",
|
|||
|
|
sephera_numbers=[6],
|
|||
|
|
path_numbers=[15],
|
|||
|
|
planets=["Sun"],
|
|||
|
|
elements=["Fire"],
|
|||
|
|
zodiac_signs=["Leo"],
|
|||
|
|
associated_planet=planet,
|
|||
|
|
associated_element=None,
|
|||
|
|
associated_numbers=[number],
|
|||
|
|
tarot_trumps=["XIX - The Sun"],
|
|||
|
|
keywords=["Vitality"],
|
|||
|
|
description="Solar current",
|
|||
|
|
)
|
|||
|
|
assert god.culture_key() == "egyptian"
|
|||
|
|
assert god.primary_number() is number
|
|||
|
|
assert 6 in god.sephera_numbers
|
|||
|
|
|
|||
|
|
def test_god_without_planet(self):
|
|||
|
|
god = God(
|
|||
|
|
name="Hecate",
|
|||
|
|
culture="Greek",
|
|||
|
|
pantheon="Chthonic",
|
|||
|
|
domains=["Magic"],
|
|||
|
|
epithets=["Triple Goddess"],
|
|||
|
|
mythology="Guardian of crossroads",
|
|||
|
|
sephera_numbers=[],
|
|||
|
|
path_numbers=[29],
|
|||
|
|
planets=[],
|
|||
|
|
elements=["Water"],
|
|||
|
|
zodiac_signs=["Pisces"],
|
|||
|
|
associated_planet=None,
|
|||
|
|
associated_element=None,
|
|||
|
|
associated_numbers=[],
|
|||
|
|
tarot_trumps=["XVIII - The Moon"],
|
|||
|
|
keywords=["Mystery"],
|
|||
|
|
description="Night guide",
|
|||
|
|
)
|
|||
|
|
assert god.primary_number() is None
|
|||
|
|
assert "water" in [elem.lower() for elem in god.elements]
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# Cipher Tests
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
class TestCipher:
|
|||
|
|
def test_cipher_mapping_basic(self):
|
|||
|
|
cipher = Cipher("Test", "test", [1, 2, 3])
|
|||
|
|
mapping = cipher.mapping_for_alphabet(["A", "B", "C"])
|
|||
|
|
assert mapping == {"A": 1, "B": 2, "C": 3}
|
|||
|
|
|
|||
|
|
def test_cipher_cycle_expansion(self):
|
|||
|
|
cipher = Cipher("Cycle", "cycle", [1, 2], cycle=True)
|
|||
|
|
mapping = cipher.mapping_for_alphabet(["A", "B", "C", "D"])
|
|||
|
|
assert mapping["C"] == 1
|
|||
|
|
assert mapping["D"] == 2
|
|||
|
|
|
|||
|
|
def test_cipher_subset(self):
|
|||
|
|
cipher = Cipher("Subset", "subset", [5, 6], letter_subset={"A", "C"})
|
|||
|
|
mapping = cipher.mapping_for_alphabet(["A", "B", "C"])
|
|||
|
|
assert "B" not in mapping
|
|||
|
|
assert mapping["C"] == 6
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestCipherResult:
|
|||
|
|
def test_cipher_result_totals(self):
|
|||
|
|
cipher = Cipher("Test", "test", [1, 2, 3])
|
|||
|
|
result = CipherResult("abc", cipher, "english", (1, 2, 3))
|
|||
|
|
assert result.total == 6
|
|||
|
|
assert result.as_string("-") == "1-2-3"
|
|||
|
|
assert str(result) == "123"
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# Digital Root Tests
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
class TestDigitalRoot:
|
|||
|
|
def test_digital_root_single_digit(self):
|
|||
|
|
"""Single digits should return themselves."""
|
|||
|
|
for i in range(1, 10):
|
|||
|
|
assert calculate_digital_root(i) == i
|
|||
|
|
|
|||
|
|
def test_digital_root_two_digit(self):
|
|||
|
|
"""Test two-digit numbers."""
|
|||
|
|
assert calculate_digital_root(10) == 1 # 1+0 = 1
|
|||
|
|
assert calculate_digital_root(14) == 5 # 1+4 = 5
|
|||
|
|
assert calculate_digital_root(19) == 1 # 1+9 = 10, 1+0 = 1
|
|||
|
|
assert calculate_digital_root(18) == 9 # 1+8 = 9
|
|||
|
|
|
|||
|
|
def test_digital_root_large_numbers(self):
|
|||
|
|
"""Test large numbers."""
|
|||
|
|
assert calculate_digital_root(99) == 9 # 9+9 = 18, 1+8 = 9
|
|||
|
|
assert calculate_digital_root(100) == 1 # 1+0+0 = 1
|
|||
|
|
assert calculate_digital_root(123) == 6 # 1+2+3 = 6
|
|||
|
|
|
|||
|
|
def test_digital_root_tarot_cards(self):
|
|||
|
|
"""Test digital root for Tarot card numbers."""
|
|||
|
|
# Major Arcana cards 0-21
|
|||
|
|
assert calculate_digital_root(14) == 5 # Card 14 (Temperance) -> 5
|
|||
|
|
assert calculate_digital_root(21) == 3 # Card 21 (The World) -> 3
|
|||
|
|
assert calculate_digital_root(1) == 1 # Card 1 (Magician) -> 1
|
|||
|
|
|
|||
|
|
def test_digital_root_invalid_input(self):
|
|||
|
|
"""Test that invalid inputs raise errors."""
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
calculate_digital_root(0)
|
|||
|
|
|
|||
|
|
with pytest.raises(ValueError):
|
|||
|
|
calculate_digital_root(-5)
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============================================================================
|
|||
|
|
# CardDataLoader Tests
|
|||
|
|
# ============================================================================
|
|||
|
|
|
|||
|
|
class TestCardDataLoader:
|
|||
|
|
@pytest.fixture
|
|||
|
|
def loader(self):
|
|||
|
|
return CardDataLoader()
|
|||
|
|
|
|||
|
|
def test_loader_initialization(self, loader):
|
|||
|
|
"""Test that loader initializes correctly."""
|
|||
|
|
assert loader is not None
|
|||
|
|
|
|||
|
|
def test_load_numbers(self, loader):
|
|||
|
|
"""Test loading numbers."""
|
|||
|
|
for i in range(1, 10):
|
|||
|
|
num = loader.number(i)
|
|||
|
|
assert num is not None
|
|||
|
|
assert num.value == i
|
|||
|
|
assert num.compliment == (9 - i if i != 9 else 9)
|
|||
|
|
|
|||
|
|
def test_load_colors(self, loader):
|
|||
|
|
"""Test loading colors."""
|
|||
|
|
for i in range(1, 11):
|
|||
|
|
color = loader.color(i)
|
|||
|
|
assert color is not None
|
|||
|
|
assert color.number == i
|
|||
|
|
|
|||
|
|
def test_load_sephera(self, loader):
|
|||
|
|
"""Test loading individual Sephiroth."""
|
|||
|
|
for i in range(1, 11):
|
|||
|
|
sephera = loader.sephera(i)
|
|||
|
|
assert sephera is not None
|
|||
|
|
assert sephera.number == i
|
|||
|
|
|
|||
|
|
def test_load_ciphers(self, loader):
|
|||
|
|
"""Ensure cipher catalog is populated."""
|
|||
|
|
ciphers = loader.cipher()
|
|||
|
|
assert "english_simple" in ciphers
|
|||
|
|
assert ciphers["english_simple"].default_alphabet == "english"
|
|||
|
|
|
|||
|
|
def test_word_cipher_request(self, loader):
|
|||
|
|
"""word().cipher() should return meaningful totals."""
|
|||
|
|
result = loader.word("tarot").cipher("english_simple")
|
|||
|
|
assert isinstance(result, CipherResult)
|
|||
|
|
assert result.total == 74
|
|||
|
|
assert result.alphabet_name == "english"
|
|||
|
|
|
|||
|
|
def test_word_cipher_custom_alphabet(self, loader):
|
|||
|
|
result = loader.word("אמש").cipher("kabbalah_three_mother")
|
|||
|
|
assert result.values == (1, 40, 300)
|
|||
|
|
|
|||
|
|
def test_trigram_line_diagram(self, loader):
|
|||
|
|
from letter import trigram
|
|||
|
|
tri = trigram.trigram.name("Zhen") # Thunder
|
|||
|
|
assert tri is not None
|
|||
|
|
assert tri.data.line_diagram == "|::"
|
|||
|
|
|
|||
|
|
def test_hexagram_line_diagram(self, loader):
|
|||
|
|
from letter import hexagram
|
|||
|
|
hex_result = hexagram.hexagram.filter('number:1').first()
|
|||
|
|
assert hex_result is not None
|
|||
|
|
assert hex_result.data.line_diagram == "||||||"
|
|||
|
|
|
|||
|
|
def test_color_by_number(self, loader):
|
|||
|
|
"""Test getting color by number with digital root."""
|
|||
|
|
# 14 -> digital root 5 -> Gevurah -> Red Scarlet
|
|||
|
|
color = loader.color_by_number(14)
|
|||
|
|
assert color is not None
|
|||
|
|
assert color.number == 5
|
|||
|
|
assert "Red" in color.name
|
|||
|
|
|
|||
|
|
def test_number_by_digital_root(self, loader):
|
|||
|
|
"""Test getting number by digital root."""
|
|||
|
|
num = loader.number_by_digital_root(14)
|
|||
|
|
assert num is not None
|
|||
|
|
assert num.value == 5
|
|||
|
|
|
|||
|
|
def test_digital_root_method(self, loader):
|
|||
|
|
"""Test the digital root method on loader."""
|
|||
|
|
assert loader.digital_root(14) == 5
|
|||
|
|
assert loader.digital_root(99) == 9
|
|||
|
|
assert loader.digital_root(5) == 5
|
|||
|
|
|
|||
|
|
def test_cipher_lookup(self, loader):
|
|||
|
|
"""Test loading individual cipher definitions."""
|
|||
|
|
systems = ["hebrew_standard", "english_simple", "greek_isopsephy", "reduction"]
|
|||
|
|
for system_name in systems:
|
|||
|
|
cipher = loader.cipher(system_name)
|
|||
|
|
assert cipher is not None
|
|||
|
|
assert cipher.key == system_name
|
|||
|
|
|
|||
|
|
def test_planet_lookup(self, loader):
|
|||
|
|
"""Test loading planetary correspondences."""
|
|||
|
|
planets = loader.planet()
|
|||
|
|
assert "mercury" in planets
|
|||
|
|
mercury = loader.planet("Mercury")
|
|||
|
|
assert mercury is not None
|
|||
|
|
assert mercury.associated_letters[0] == "Beth"
|
|||
|
|
assert mercury.associated_numbers and mercury.associated_numbers[0].value == 8
|
|||
|
|
|
|||
|
|
def test_weekday_lookup(self, loader):
|
|||
|
|
weekdays = loader.weekday()
|
|||
|
|
assert "monday" in weekdays
|
|||
|
|
sunday = loader.weekday("Sunday")
|
|||
|
|
assert sunday is not None
|
|||
|
|
assert sunday.is_weekend is True
|
|||
|
|
assert sunday.planetary_correspondence == "Sun"
|
|||
|
|
|
|||
|
|
def test_clock_hour_lookup(self, loader):
|
|||
|
|
hours = loader.clock_hour()
|
|||
|
|
assert len(hours) == 24
|
|||
|
|
midnight = loader.clock_hour(0)
|
|||
|
|
assert midnight is not None
|
|||
|
|
assert midnight.period == "AM"
|
|||
|
|
assert midnight.time_of_day == "Day"
|
|||
|
|
afternoon = loader.clock_hour(15)
|
|||
|
|
assert afternoon is not None
|
|||
|
|
assert afternoon.period == "PM"
|
|||
|
|
assert afternoon.time_of_day == "Night"
|
|||
|
|
|
|||
|
|
def test_god_registry(self, loader):
|
|||
|
|
gods = loader.god()
|
|||
|
|
assert "apollo" in gods
|
|||
|
|
assert "ra" in gods
|
|||
|
|
apollo = gods["apollo"]
|
|||
|
|
assert apollo.culture == "Greek"
|
|||
|
|
assert apollo.associated_planet is not None
|
|||
|
|
assert apollo.associated_planet.name == "Sun"
|
|||
|
|
|
|||
|
|
def test_gods_by_culture(self, loader):
|
|||
|
|
greek_gods = loader.gods_by_culture("Greek")
|
|||
|
|
assert greek_gods
|
|||
|
|
assert all(god.culture == "Greek" for god in greek_gods.values())
|
|||
|
|
assert "apollo" in greek_gods
|
|||
|
|
assert "ra" not in greek_gods
|
|||
|
|
|
|||
|
|
def test_god_with_culture_filter(self, loader):
|
|||
|
|
apollo = loader.god("Apollo", culture="Greek")
|
|||
|
|
assert apollo is not None
|
|||
|
|
assert apollo.culture == "Greek"
|
|||
|
|
assert apollo.associated_planet is not None
|
|||
|
|
assert loader.god("Apollo", culture="Roman") is None
|
|||
|
|
|
|||
|
|
def test_temporal_correspondence(self, loader):
|
|||
|
|
moment = datetime(2024, 3, 21, 15, 30)
|
|||
|
|
snapshot = loader.temporal_correspondence(moment)
|
|||
|
|
|
|||
|
|
assert snapshot.timestamp == moment
|
|||
|
|
assert snapshot.weekday is not None
|
|||
|
|
assert snapshot.weekday.name == "Thursday"
|
|||
|
|
assert snapshot.clock_hour is not None
|
|||
|
|
assert snapshot.clock_hour.hour_24 == 15
|
|||
|
|
assert snapshot.planet is not None
|
|||
|
|
assert snapshot.planet.name == snapshot.clock_hour.planetary_ruler
|
|||
|
|
if snapshot.number is not None:
|
|||
|
|
assert snapshot.color is snapshot.number.color
|
|||
|
|
assert snapshot.card.name # deterministic card returned
|
|||
|
|
assert snapshot.hexagram is not None
|
|||
|
|
|
|||
|
|
def test_alphabet_catalog(self, loader):
|
|||
|
|
"""Test loading alphabets."""
|
|||
|
|
alphabets = loader.alphabet()
|
|||
|
|
assert "english" in alphabets
|
|||
|
|
assert "greek" in alphabets
|
|||
|
|
assert "hebrew" in alphabets
|
|||
|
|
|
|||
|
|
assert len(alphabets["english"]) == 26
|
|||
|
|
assert len(alphabets["greek"]) == 24
|
|||
|
|
assert len(alphabets["hebrew"]) == 22
|
|||
|
|
|
|||
|
|
def test_sephera_loaded(self, loader):
|
|||
|
|
"""Test that all 10 Sephiroth are loaded."""
|
|||
|
|
sephera_count = 0
|
|||
|
|
for i in range(1, 11):
|
|||
|
|
color = loader.color(i)
|
|||
|
|
if color is not None and color.sephera:
|
|||
|
|
sephera_count += 1
|
|||
|
|
assert sephera_count == 10
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestDigitalRootIntegration:
|
|||
|
|
"""Integration tests for digital root with Tarot cards."""
|
|||
|
|
|
|||
|
|
def test_all_major_arcana_digital_roots(self):
|
|||
|
|
"""Test digital root for all Major Arcana cards (0-21)."""
|
|||
|
|
loader = CardDataLoader()
|
|||
|
|
|
|||
|
|
# All Major Arcana cards should map to colors 1-9
|
|||
|
|
for card_num in range(22):
|
|||
|
|
if card_num == 0:
|
|||
|
|
continue # Skip The Fool (0)
|
|||
|
|
|
|||
|
|
color = loader.color_by_number(card_num)
|
|||
|
|
assert color is not None
|
|||
|
|
assert 1 <= color.number <= 9
|
|||
|
|
|
|||
|
|
def test_color_consistency(self):
|
|||
|
|
"""Test that equivalent numbers map to same color."""
|
|||
|
|
loader = CardDataLoader()
|
|||
|
|
|
|||
|
|
# 5 and 14 should map to same color (both have digital root 5)
|
|||
|
|
color_5 = loader.color_by_number(5)
|
|||
|
|
color_14 = loader.color_by_number(14)
|
|||
|
|
assert color_5 is not None
|
|||
|
|
assert color_14 is not None
|
|||
|
|
assert color_5.number == color_14.number
|
|||
|
|
assert color_5.hex_value == color_14.hex_value
|