Skip to content

Commit 0dc79fe

Browse files
committed
Add tests for the util module (yes, they are AI-generated)
1 parent df6b92e commit 0dc79fe

1 file changed

Lines changed: 204 additions & 0 deletions

File tree

test/test_util.py

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
"""Test the utility functions."""
2+
3+
import datetime
4+
from unittest.mock import patch
5+
6+
import pytest
7+
8+
from gedcom7 import types, util
9+
10+
11+
def test_get_child_with_tag():
12+
"""Test getting a child structure by tag."""
13+
# Create parent structure with children
14+
parent = types.GedcomStructure(tag="PARENT", pointer="", text="", xref="")
15+
child1 = types.GedcomStructure(tag="CHILD1", pointer="", text="Child 1", xref="")
16+
child2 = types.GedcomStructure(tag="CHILD2", pointer="", text="Child 2", xref="")
17+
child3 = types.GedcomStructure(
18+
tag="CHILD1", pointer="", text="Child 3", xref=""
19+
) # Duplicate tag
20+
21+
parent.children = [child1, child2, child3]
22+
23+
# Test finding the first child with tag CHILD1
24+
result = util.get_first_child_with_tag(parent, "CHILD1")
25+
assert result == child1
26+
assert result.text == "Child 1"
27+
28+
# Test finding child with tag CHILD2
29+
result = util.get_first_child_with_tag(parent, "CHILD2")
30+
assert result == child2
31+
assert result.text == "Child 2"
32+
33+
34+
def test_no_matching_child():
35+
"""Test when no child matches the given tag."""
36+
parent = types.GedcomStructure(tag="PARENT", pointer="", text="", xref="")
37+
child = types.GedcomStructure(tag="CHILD", pointer="", text="Child", xref="")
38+
39+
parent.children = [child]
40+
41+
# Test with a tag that doesn't exist
42+
result = util.get_first_child_with_tag(parent, "NONEXISTENT")
43+
assert result is None
44+
45+
46+
def test_empty_children_list():
47+
"""Test with an empty children list."""
48+
parent = types.GedcomStructure(tag="PARENT", pointer="", text="", xref="")
49+
parent.children = []
50+
51+
result = util.get_first_child_with_tag(parent, "CHILD")
52+
assert result is None
53+
54+
55+
def test_valid_date_conversion():
56+
"""Test converting a valid GEDCOM DateExact to Python date."""
57+
# Test with all months
58+
months = [
59+
("JAN", 1),
60+
("FEB", 2),
61+
("MAR", 3),
62+
("APR", 4),
63+
("MAY", 5),
64+
("JUN", 6),
65+
("JUL", 7),
66+
("AUG", 8),
67+
("SEP", 9),
68+
("OCT", 10),
69+
("NOV", 11),
70+
("DEC", 12),
71+
]
72+
73+
for month_str, month_num in months:
74+
gedcom_date = types.DateExact(day=15, month=month_str, year=2023)
75+
python_date = util.date_exact_to_python_date(gedcom_date)
76+
77+
assert isinstance(python_date, datetime.date)
78+
assert python_date.day == 15
79+
assert python_date.month == month_num
80+
assert python_date.year == 2023
81+
82+
83+
def test_case_insensitive_month():
84+
"""Test that month names are case-insensitive."""
85+
# Test with lowercase
86+
gedcom_date = types.DateExact(day=15, month="jan", year=2023)
87+
python_date = util.date_exact_to_python_date(gedcom_date)
88+
89+
assert python_date.month == 1
90+
91+
# Test with mixed case
92+
gedcom_date = types.DateExact(day=15, month="Jul", year=2023)
93+
python_date = util.date_exact_to_python_date(gedcom_date)
94+
95+
assert python_date.month == 7
96+
97+
98+
def test_invalid_month():
99+
"""Test with an invalid month name."""
100+
gedcom_date = types.DateExact(day=15, month="INVALID", year=2023)
101+
102+
with pytest.raises(ValueError, match="Invalid month in date: INVALID"):
103+
util.date_exact_to_python_date(gedcom_date)
104+
105+
106+
def test_basic_time_conversion():
107+
"""Test basic time conversion with hours and minutes only."""
108+
gedcom_time = types.Time(hour=14, minute=30)
109+
python_time = util.time_to_python_time(gedcom_time)
110+
111+
assert isinstance(python_time, datetime.time)
112+
assert python_time.hour == 14
113+
assert python_time.minute == 30
114+
assert python_time.second == 0
115+
assert python_time.microsecond == 0
116+
assert python_time.tzinfo == datetime.timezone.utc
117+
118+
119+
def test_time_with_seconds():
120+
"""Test time conversion with seconds."""
121+
gedcom_time = types.Time(hour=14, minute=30, second=45)
122+
python_time = util.time_to_python_time(gedcom_time)
123+
124+
assert python_time.second == 45
125+
126+
127+
def test_time_with_fraction():
128+
"""Test time conversion with fractional seconds."""
129+
gedcom_time = types.Time(hour=14, minute=30, second=45, fraction=123456)
130+
python_time = util.time_to_python_time(gedcom_time)
131+
132+
assert python_time.second == 45
133+
assert python_time.microsecond == 123456
134+
135+
# Test with different fraction lengths
136+
gedcom_time = types.Time(hour=14, minute=30, second=45, fraction=5)
137+
python_time = util.time_to_python_time(gedcom_time)
138+
139+
assert python_time.second == 45
140+
assert python_time.microsecond == 500000
141+
142+
143+
def test_time_without_fraction_or_seconds():
144+
"""Test time conversion without fraction or seconds."""
145+
gedcom_time = types.Time(hour=14, minute=30, second=None, fraction=None)
146+
python_time = util.time_to_python_time(gedcom_time)
147+
148+
assert python_time.second == 0
149+
assert python_time.microsecond == 0
150+
151+
152+
def test_date_only():
153+
"""Test conversion with date only (no time)."""
154+
gedcom_date = types.DateExact(day=15, month="JAN", year=2023)
155+
python_datetime = util.date_exact_and_time_to_python_datetime(gedcom_date)
156+
157+
assert isinstance(python_datetime, datetime.datetime)
158+
assert python_datetime.day == 15
159+
assert python_datetime.month == 1
160+
assert python_datetime.year == 2023
161+
assert python_datetime.hour == 0
162+
assert python_datetime.minute == 0
163+
assert python_datetime.second == 0
164+
assert python_datetime.microsecond == 0
165+
assert python_datetime.tzinfo == datetime.timezone.utc
166+
167+
168+
def test_date_and_time():
169+
"""Test conversion with both date and time."""
170+
gedcom_date = types.DateExact(day=15, month="JAN", year=2023)
171+
gedcom_time = types.Time(hour=14, minute=30, second=45, fraction=123)
172+
173+
python_datetime = util.date_exact_and_time_to_python_datetime(
174+
gedcom_date, gedcom_time
175+
)
176+
177+
assert python_datetime.day == 15
178+
assert python_datetime.month == 1
179+
assert python_datetime.year == 2023
180+
assert python_datetime.hour == 14
181+
assert python_datetime.minute == 30
182+
assert python_datetime.second == 45
183+
assert python_datetime.microsecond == 123000
184+
assert python_datetime.tzinfo == datetime.timezone.utc
185+
186+
187+
def test_integration_with_other_functions():
188+
"""Test that the function integrates correctly with other utility functions."""
189+
with patch("gedcom7.util.date_exact_to_python_date") as mock_date_fn:
190+
with patch("gedcom7.util.time_to_python_time") as mock_time_fn:
191+
# Mock the return values
192+
mock_date_fn.return_value = datetime.date(2023, 1, 15)
193+
mock_time_fn.return_value = datetime.time(
194+
14, 30, 45, 123000, tzinfo=datetime.timezone.utc
195+
)
196+
197+
gedcom_date = types.DateExact(day=15, month="JAN", year=2023)
198+
gedcom_time = types.Time(hour=14, minute=30, second=45, fraction=123)
199+
200+
util.date_exact_and_time_to_python_datetime(gedcom_date, gedcom_time)
201+
202+
# Verify the functions were called with correct arguments
203+
mock_date_fn.assert_called_once_with(gedcom_date)
204+
mock_time_fn.assert_called_once_with(gedcom_time)

0 commit comments

Comments
 (0)