8f11340b38
Per post_module_taxonomy_de_cruft_20260627 Phase 2 (FR7). Each
'from src.models import X' for a moved class is rewritten to
'from src.<destination> import X':
Ticket, Track, WorkerContext, TrackState, TrackMetadata,
ThinkingSegment, EMPTY_TRACK_STATE -> src.mma
ProjectContext, ProjectMeta, ProjectOutput, ProjectFiles,
ProjectScreenshots, ProjectDiscussion, EMPTY_PROJECT_CONTEXT -> src.project
FileItem, Preset, ContextPreset, ContextFileEntry,
NamedViewPreset -> src.project_files
Tool, ToolPreset -> src.tool_presets
BiasProfile -> src.tool_bias
TextEditorConfig, ExternalEditorConfig,
EMPTY_TEXT_EDITOR_CONFIG -> src.external_editor
Persona -> src.personas
WorkspaceProfile -> src.workspace_manager
MCPServerConfig, MCPConfiguration, VectorStoreConfig,
RAGConfig, load_mcp_config -> src.mcp_client
NOT touched (kept on src.models; Phase 3 or Phase 4 will move them):
GenerateRequest, ConfirmRequest, DEFAULT_TOOL_CATEGORIES, Metadata, PROVIDERS
Migration was performed by the one-time script
scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/migrate_imports.py
which uses a class-to-module map and re.sub() to rewrite each
'from src.models import X' line.
Total: 85 import lines rewritten across 71 files.
Note: this commit depends on the v2 SHIPPED work
(origin/tier2/module_taxonomy_refactor_20260627) being merged into
this branch NEXT. On master (without the v2 SHIPPED commits), the
destination modules do not exist and these imports would fail.
160 lines
5.9 KiB
Python
160 lines
5.9 KiB
Python
from datetime import datetime, timezone, timedelta
|
|
|
|
# Import necessary classes from models.py
|
|
from src.mma import TrackState, Ticket
|
|
from src.models import Metadata
|
|
|
|
# --- Pytest Tests ---
|
|
|
|
def test_track_state_instantiation() -> None:
|
|
"""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() -> None:
|
|
"""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() -> None:
|
|
"""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() -> None:
|
|
"""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() -> 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" |