"""Tests for data models.""" from datetime import datetime, date import pytest from tracker.models import Project, Session, Note, NoteType, Change class TestProjectCreation: """Tests for Project model creation.""" def test_project_creation_with_all_fields(self, sample_project_data): """Test creating a project with all fields specified.""" project = Project(**sample_project_data) assert project.id == sample_project_data["id"] assert project.name == sample_project_data["name"] assert project.slug == sample_project_data["slug"] assert project.description == sample_project_data["description"] assert project.type == sample_project_data["type"] assert project.status == sample_project_data["status"] assert project.tags == sample_project_data["tags"] assert project.root_path == sample_project_data["root_path"] assert project.repo_path == sample_project_data["repo_path"] assert project.created_at == sample_project_data["created_at"] assert project.updated_at == sample_project_data["updated_at"] assert project.last_session_at is None def test_project_creation_with_defaults(self): """Test creating a project with default values.""" now = datetime.now() project = Project( id="test-id", name="Test", slug="test", created_at=now, updated_at=now, ) assert project.description == "" assert project.type == "misc" assert project.status == "inbox" assert project.tags == [] assert project.root_path == "" assert project.repo_path is None assert project.last_session_at is None def test_project_status_validation(self): """Test that project status can be set to valid values.""" valid_statuses = ["inbox", "next", "active", "blocked", "waiting", "done", "archived"] for status in valid_statuses: project = Project( id="test-id", name="Test", slug="test", created_at=datetime.now(), updated_at=datetime.now(), status=status, ) assert project.status == status def test_project_type_validation(self): """Test that project type can be set to valid values.""" valid_types = ["code", "homelab", "automation", "agent", "research", "misc"] for project_type in valid_types: project = Project( id="test-id", name="Test", slug="test", created_at=datetime.now(), updated_at=datetime.now(), type=project_type, ) assert project.type == project_type class TestSessionCreation: """Tests for Session model creation.""" def test_session_creation_with_all_fields(self, mock_session): """Test creating a session with all fields specified.""" assert mock_session.id == "session-123" assert mock_session.project_slug == "test-project" assert mock_session.started_at == datetime(2024, 1, 15, 10, 0, 0) assert mock_session.ended_at == datetime(2024, 1, 15, 11, 30, 0) assert mock_session.duration_minutes == 90 assert mock_session.objective == "Complete initial implementation" assert mock_session.summary == "Worked on core features" assert len(mock_session.work_done) == 2 assert len(mock_session.changes) == 1 assert len(mock_session.decisions) == 1 assert len(mock_session.blockers) == 0 assert len(mock_session.next_steps) == 2 assert len(mock_session.references) == 1 assert len(mock_session.raw_notes) == 2 def test_session_creation_with_defaults(self): """Test creating a session with required fields only.""" session = Session( id="session-1", project_slug="test-project", started_at=datetime.now(), ) assert session.ended_at is None assert session.duration_minutes is None assert session.objective == "" assert session.summary == "" assert session.work_done == [] assert session.changes == [] assert session.decisions == [] assert session.blockers == [] assert session.next_steps == [] assert session.references == [] assert session.raw_notes == [] def test_session_with_optional_datetime_fields(self): """Test session with ended_at but no duration_minutes.""" session = Session( id="session-1", project_slug="test-project", started_at=datetime(2024, 1, 15, 10, 0, 0), ended_at=datetime(2024, 1, 15, 11, 0, 0), ) assert session.ended_at is not None assert session.duration_minutes is None class TestNoteTypes: """Tests for Note and NoteType models.""" def test_note_creation(self, sample_note): """Test creating a note.""" assert sample_note.type == NoteType.WORK assert sample_note.text == "Completed the implementation of feature X" assert sample_note.created_at == datetime(2024, 1, 15, 10, 30, 0) def test_note_type_enum_values(self): """Test that NoteType enum has expected values.""" assert NoteType.WORK.value == "work" assert NoteType.CHANGE.value == "change" assert NoteType.BLOCKER.value == "blocker" assert NoteType.DECISION.value == "decision" assert NoteType.IDEA.value == "idea" assert NoteType.REFERENCE.value == "reference" def test_note_type_assignment(self): """Test assigning different note types to a note.""" for note_type in NoteType: note = Note(type=note_type, text="Test note") assert note.type == note_type def test_note_default_created_at(self): """Test that note has default created_at timestamp.""" note = Note(type=NoteType.WORK, text="Test note") assert note.created_at is not None assert isinstance(note.created_at, datetime) def test_note_raw_notes_structure(self, mock_session): """Test that raw_notes in session have expected structure.""" assert len(mock_session.raw_notes) == 2 assert mock_session.raw_notes[0]["type"] == "work" assert mock_session.raw_notes[0]["text"] == "Working on feature A" assert "timestamp" in mock_session.raw_notes[0] class TestChangeValidation: """Tests for Change model validation.""" def test_change_creation(self, sample_change): """Test creating a change.""" assert sample_change.date == date(2024, 1, 15) assert sample_change.type == "code" assert sample_change.title == "Added user authentication" assert sample_change.impact == "Improved security" assert sample_change.references == ["#123"] def test_change_creation_with_defaults(self): """Test creating a change with default values.""" change = Change( date=date(2024, 1, 15), type="docs", title="Updated documentation", ) assert change.impact == "" assert change.references == [] def test_change_date_as_date_not_datetime(self, sample_change): """Test that change date is stored as date object.""" assert isinstance(sample_change.date, date) assert not isinstance(sample_change.date, datetime) def test_change_types(self): """Test valid change types.""" valid_types = ["code", "infra", "config", "docs", "automation", "decision"] for change_type in valid_types: change = Change( date=date.today(), type=change_type, title=f"Test {change_type}", ) assert change.type == change_type def test_change_with_multiple_references(self): """Test change with multiple references.""" change = Change( date=date.today(), type="code", title="Major refactor", references=["#100", "#101", "#102"], ) assert len(change.references) == 3 assert "#100" in change.references assert "#102" in change.references