# ABOUTME: Tests for interval-related Pydantic models. # ABOUTME: Validates LocationInterval, TagInterval, and AttrInterval models. import pytest from pydantic import ValidationError from animaltrack.models.intervals import AttrInterval, LocationInterval, TagInterval class TestLocationInterval: """Tests for the LocationInterval model.""" def test_valid_interval(self): """LocationInterval with all required fields validates successfully.""" interval = LocationInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", location_id="01ARZ3NDEKTSV4RRFFQ69G5FAV", start_utc=1704067200000, end_utc=1704153600000, ) assert interval.animal_id == "01ARZ3NDEKTSV4RRFFQ69G5FAA" assert interval.location_id == "01ARZ3NDEKTSV4RRFFQ69G5FAV" assert interval.start_utc == 1704067200000 assert interval.end_utc == 1704153600000 def test_end_utc_defaults_to_none(self): """end_utc defaults to None (open interval).""" interval = LocationInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", location_id="01ARZ3NDEKTSV4RRFFQ69G5FAV", start_utc=1704067200000, ) assert interval.end_utc is None def test_animal_id_must_be_26_chars(self): """LocationInterval with short animal_id raises ValidationError.""" with pytest.raises(ValidationError): LocationInterval( animal_id="short", location_id="01ARZ3NDEKTSV4RRFFQ69G5FAV", start_utc=1704067200000, ) def test_location_id_must_be_26_chars(self): """LocationInterval with short location_id raises ValidationError.""" with pytest.raises(ValidationError): LocationInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", location_id="short", start_utc=1704067200000, ) class TestTagInterval: """Tests for the TagInterval model.""" def test_valid_interval(self): """TagInterval with all required fields validates successfully.""" interval = TagInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", tag="friendly", start_utc=1704067200000, end_utc=1704153600000, ) assert interval.animal_id == "01ARZ3NDEKTSV4RRFFQ69G5FAA" assert interval.tag == "friendly" assert interval.start_utc == 1704067200000 assert interval.end_utc == 1704153600000 def test_end_utc_defaults_to_none(self): """end_utc defaults to None (open interval).""" interval = TagInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", tag="leader", start_utc=1704067200000, ) assert interval.end_utc is None def test_animal_id_must_be_26_chars(self): """TagInterval with short animal_id raises ValidationError.""" with pytest.raises(ValidationError): TagInterval( animal_id="short", tag="friendly", start_utc=1704067200000, ) class TestAttrInterval: """Tests for the AttrInterval model.""" def test_valid_interval(self): """AttrInterval with all required fields validates successfully.""" interval = AttrInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", attr="sex", value="female", start_utc=1704067200000, end_utc=1704153600000, ) assert interval.animal_id == "01ARZ3NDEKTSV4RRFFQ69G5FAA" assert interval.attr == "sex" assert interval.value == "female" assert interval.start_utc == 1704067200000 assert interval.end_utc == 1704153600000 def test_end_utc_defaults_to_none(self): """end_utc defaults to None (open interval).""" interval = AttrInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", attr="status", value="alive", start_utc=1704067200000, ) assert interval.end_utc is None def test_animal_id_must_be_26_chars(self): """AttrInterval with short animal_id raises ValidationError.""" with pytest.raises(ValidationError): AttrInterval( animal_id="short", attr="sex", value="female", start_utc=1704067200000, ) def test_attr_sex_is_valid(self): """attr='sex' is a valid value.""" interval = AttrInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", attr="sex", value="female", start_utc=1704067200000, ) assert interval.attr == "sex" def test_attr_life_stage_is_valid(self): """attr='life_stage' is a valid value.""" interval = AttrInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", attr="life_stage", value="adult", start_utc=1704067200000, ) assert interval.attr == "life_stage" def test_attr_repro_status_is_valid(self): """attr='repro_status' is a valid value.""" interval = AttrInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", attr="repro_status", value="intact", start_utc=1704067200000, ) assert interval.attr == "repro_status" def test_attr_status_is_valid(self): """attr='status' is a valid value.""" interval = AttrInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", attr="status", value="alive", start_utc=1704067200000, ) assert interval.attr == "status" def test_attr_invalid_raises_error(self): """Invalid attr value raises ValidationError.""" with pytest.raises(ValidationError): AttrInterval( animal_id="01ARZ3NDEKTSV4RRFFQ69G5FAA", attr="invalid_attr", value="value", start_utc=1704067200000, )