feat(mma): Define TrackState and Metadata schema for track-scoped state
This commit is contained in:
172
tests/test_track_state_schema.py
Normal file
172
tests/test_track_state_schema.py
Normal file
@@ -0,0 +1,172 @@
|
||||
import pytest
|
||||
from datetime import datetime, timezone, timedelta
|
||||
|
||||
# Import necessary classes from models.py
|
||||
from models import Metadata, TrackState, Ticket
|
||||
|
||||
# --- Pytest Tests ---
|
||||
|
||||
def test_track_state_instantiation():
|
||||
"""Test creating a TrackState object."""
|
||||
now = datetime.now(timezone.utc)
|
||||
metadata = Metadata(
|
||||
id="track-123",
|
||||
name="Initial Setup",
|
||||
status="in_progress",
|
||||
created_at=now - timedelta(days=1),
|
||||
updated_at=now,
|
||||
)
|
||||
discussion = [
|
||||
{"role": "user", "content": "Hello", "ts": now - timedelta(hours=1)},
|
||||
{"role": "assistant", "content": "Hi there!", "ts": now - timedelta(hours=2)},
|
||||
]
|
||||
# Update Ticket instantiation to match models.py fields (description, assigned_to)
|
||||
tasks = [
|
||||
Ticket(id="task-a", description="Design UI", status="todo", assigned_to="dev1"),
|
||||
Ticket(id="task-b", description="Implement Backend", status="todo", assigned_to="dev2"),
|
||||
]
|
||||
|
||||
track_state = TrackState(
|
||||
metadata=metadata,
|
||||
discussion=discussion,
|
||||
tasks=tasks,
|
||||
)
|
||||
|
||||
assert track_state.metadata.id == "track-123"
|
||||
assert len(track_state.discussion) == 2
|
||||
assert len(track_state.tasks) == 2
|
||||
assert isinstance(track_state.tasks[0], Ticket)
|
||||
assert track_state.tasks[0].description == "Design UI"
|
||||
assert track_state.tasks[0].assigned_to == "dev1"
|
||||
|
||||
def test_track_state_to_dict():
|
||||
"""Test the to_dict() method for serialization."""
|
||||
now = datetime.now(timezone.utc)
|
||||
metadata = Metadata(
|
||||
id="track-456",
|
||||
name="Refinement Phase",
|
||||
status="completed",
|
||||
created_at=now - timedelta(days=5),
|
||||
updated_at=now - timedelta(days=2),
|
||||
)
|
||||
discussion = [
|
||||
{"role": "user", "content": "Need changes", "ts": now - timedelta(hours=3)},
|
||||
{"role": "assistant", "content": "Understood.", "ts": now - timedelta(hours=4)},
|
||||
]
|
||||
# Update Ticket instantiation
|
||||
tasks = [
|
||||
Ticket(id="task-c", description="Add feature X", status="in_progress", assigned_to="dev3"),
|
||||
]
|
||||
|
||||
track_state = TrackState(
|
||||
metadata=metadata,
|
||||
discussion=discussion,
|
||||
tasks=tasks,
|
||||
)
|
||||
|
||||
track_dict = track_state.to_dict()
|
||||
|
||||
assert track_dict["metadata"]["id"] == "track-456"
|
||||
assert track_dict["metadata"]["created_at"] == metadata.created_at.isoformat()
|
||||
assert track_dict["metadata"]["updated_at"] == metadata.updated_at.isoformat()
|
||||
assert len(track_dict["discussion"]) == 2
|
||||
assert track_dict["discussion"][0]["ts"] == discussion[0]["ts"].isoformat()
|
||||
assert len(track_dict["tasks"]) == 1
|
||||
# Use the Ticket's to_dict method for serialization
|
||||
assert track_dict["tasks"][0]["id"] == "task-c"
|
||||
assert track_dict["tasks"][0]["description"] == "Add feature X"
|
||||
assert track_dict["tasks"][0]["assigned_to"] == "dev3"
|
||||
|
||||
def test_track_state_from_dict():
|
||||
"""Test the from_dict() class method for deserialization."""
|
||||
now = datetime.now(timezone.utc)
|
||||
track_dict_data = {
|
||||
"metadata": {
|
||||
"id": "track-789",
|
||||
"name": "Final Review",
|
||||
"status": "pending",
|
||||
"created_at": (now - timedelta(days=10)).isoformat(),
|
||||
"updated_at": (now - timedelta(days=9)).isoformat(),
|
||||
},
|
||||
"discussion": [
|
||||
{"role": "user", "content": "Review complete.", "ts": (now - timedelta(hours=5)).isoformat()},
|
||||
],
|
||||
"tasks": [
|
||||
# Use fields from models.py Ticket definition for deserialization
|
||||
{"id": "task-d", "description": "Deploy", "status": "completed", "assigned_to": "ops1"},
|
||||
],
|
||||
}
|
||||
|
||||
track_state = TrackState.from_dict(track_dict_data)
|
||||
|
||||
assert isinstance(track_state, TrackState)
|
||||
assert track_state.metadata.id == "track-789"
|
||||
assert isinstance(track_state.metadata.created_at, datetime)
|
||||
assert track_state.metadata.created_at.isoformat() == track_dict_data["metadata"]["created_at"]
|
||||
assert len(track_state.discussion) == 1
|
||||
assert isinstance(track_state.discussion[0]["ts"], datetime)
|
||||
assert track_state.discussion[0]["ts"].isoformat() == track_dict_data["discussion"][0]["ts"]
|
||||
assert len(track_state.tasks) == 1
|
||||
assert isinstance(track_state.tasks[0], Ticket)
|
||||
assert track_state.tasks[0].id == "task-d"
|
||||
assert track_state.tasks[0].description == "Deploy"
|
||||
assert track_state.tasks[0].assigned_to == "ops1"
|
||||
|
||||
# Test case for empty lists and missing keys for robustness
|
||||
def test_track_state_from_dict_empty_and_missing():
|
||||
"""Test from_dict with empty lists and missing optional keys."""
|
||||
track_dict_data = {
|
||||
"metadata": {
|
||||
"id": "track-empty",
|
||||
"name": "Empty State",
|
||||
# created_at, updated_at, status are optional in from_dict logic
|
||||
},
|
||||
"discussion": [], # Empty discussion list
|
||||
"tasks": [], # Empty tasks list
|
||||
}
|
||||
|
||||
track_state = TrackState.from_dict(track_dict_data)
|
||||
|
||||
assert isinstance(track_state, TrackState)
|
||||
assert track_state.metadata.id == "track-empty"
|
||||
assert track_state.metadata.name == "Empty State"
|
||||
assert track_state.metadata.created_at is None
|
||||
assert track_state.metadata.updated_at is None
|
||||
assert track_state.metadata.status is None
|
||||
assert len(track_state.discussion) == 0
|
||||
assert len(track_state.tasks) == 0
|
||||
|
||||
# Test case for to_dict with None values or missing optional data
|
||||
def test_track_state_to_dict_with_none():
|
||||
"""Test to_dict with None values in optional fields."""
|
||||
now = datetime.now(timezone.utc)
|
||||
metadata = Metadata(
|
||||
id="track-none",
|
||||
name="None Test",
|
||||
status=None, # None status
|
||||
created_at=now,
|
||||
updated_at=None, # None updated_at
|
||||
)
|
||||
discussion = [
|
||||
{"role": "system", "content": "Info", "ts": None}, # None timestamp
|
||||
]
|
||||
# Update Ticket instantiation
|
||||
tasks = [
|
||||
Ticket(id="task-none", description="Task None", status="pending", assigned_to="anon"),
|
||||
]
|
||||
|
||||
track_state = TrackState(
|
||||
metadata=metadata,
|
||||
discussion=discussion,
|
||||
tasks=tasks,
|
||||
)
|
||||
|
||||
track_dict = track_state.to_dict()
|
||||
|
||||
assert track_dict["metadata"]["status"] is None
|
||||
# Check that isoformat was called on datetime object, not None
|
||||
assert track_dict["metadata"]["created_at"] == now.isoformat()
|
||||
assert track_dict["metadata"]["updated_at"] is None # This should be None as it's passed as None
|
||||
assert track_dict["discussion"][0]["ts"] is None
|
||||
assert track_dict["tasks"][0]["description"] == "Task None"
|
||||
assert track_dict["tasks"][0]["assigned_to"] == "anon"
|
||||
Reference in New Issue
Block a user