# tests/models/syndarix/test_project.py """ Unit tests for the Project model. """ import uuid from datetime import datetime import pytest from sqlalchemy.exc import IntegrityError from app.models.syndarix import ( AutonomyLevel, Project, ProjectStatus, ) class TestProjectModel: """Tests for Project model creation and fields.""" def test_create_project_with_required_fields(self, db_session): """Test creating a project with only required fields.""" project = Project( id=uuid.uuid4(), name="Test Project", slug="test-project", ) db_session.add(project) db_session.commit() retrieved = db_session.query(Project).filter_by(slug="test-project").first() assert retrieved is not None assert retrieved.name == "Test Project" assert retrieved.slug == "test-project" assert retrieved.autonomy_level == AutonomyLevel.MILESTONE # Default assert retrieved.status == ProjectStatus.ACTIVE # Default assert retrieved.settings == {} # Default empty dict assert retrieved.description is None assert retrieved.owner_id is None def test_create_project_with_all_fields(self, db_session): """Test creating a project with all optional fields.""" project_id = uuid.uuid4() owner_id = uuid.uuid4() project = Project( id=project_id, name="Full Project", slug="full-project", description="A complete project with all fields", autonomy_level=AutonomyLevel.AUTONOMOUS, status=ProjectStatus.PAUSED, settings={"webhook_url": "https://example.com/webhook"}, owner_id=owner_id, ) db_session.add(project) db_session.commit() retrieved = db_session.query(Project).filter_by(id=project_id).first() assert retrieved.name == "Full Project" assert retrieved.slug == "full-project" assert retrieved.description == "A complete project with all fields" assert retrieved.autonomy_level == AutonomyLevel.AUTONOMOUS assert retrieved.status == ProjectStatus.PAUSED assert retrieved.settings == {"webhook_url": "https://example.com/webhook"} assert retrieved.owner_id == owner_id def test_project_unique_slug_constraint(self, db_session): """Test that projects cannot have duplicate slugs.""" project1 = Project( id=uuid.uuid4(), name="Project One", slug="duplicate-slug", ) db_session.add(project1) db_session.commit() project2 = Project( id=uuid.uuid4(), name="Project Two", slug="duplicate-slug", # Same slug ) db_session.add(project2) with pytest.raises(IntegrityError): db_session.commit() db_session.rollback() def test_project_timestamps(self, db_session): """Test that timestamps are automatically set.""" project = Project( id=uuid.uuid4(), name="Timestamp Project", slug="timestamp-project", ) db_session.add(project) db_session.commit() retrieved = db_session.query(Project).filter_by(slug="timestamp-project").first() assert isinstance(retrieved.created_at, datetime) assert isinstance(retrieved.updated_at, datetime) def test_project_update(self, db_session): """Test updating project fields.""" project = Project( id=uuid.uuid4(), name="Original Name", slug="original-slug", status=ProjectStatus.ACTIVE, ) db_session.add(project) db_session.commit() original_created_at = project.created_at # Update fields project.name = "Updated Name" project.status = ProjectStatus.COMPLETED project.settings = {"new_setting": "value"} db_session.commit() retrieved = db_session.query(Project).filter_by(slug="original-slug").first() assert retrieved.name == "Updated Name" assert retrieved.status == ProjectStatus.COMPLETED assert retrieved.settings == {"new_setting": "value"} assert retrieved.created_at == original_created_at assert retrieved.updated_at > original_created_at def test_project_delete(self, db_session): """Test deleting a project.""" project_id = uuid.uuid4() project = Project( id=project_id, name="Delete Me", slug="delete-me", ) db_session.add(project) db_session.commit() db_session.delete(project) db_session.commit() deleted = db_session.query(Project).filter_by(id=project_id).first() assert deleted is None def test_project_string_representation(self, db_session): """Test the string representation of a project.""" project = Project( id=uuid.uuid4(), name="Repr Project", slug="repr-project", status=ProjectStatus.ACTIVE, ) assert str(project) == "" assert repr(project) == "" class TestProjectEnums: """Tests for Project enum fields.""" def test_all_autonomy_levels(self, db_session): """Test that all autonomy levels can be stored.""" for level in AutonomyLevel: project = Project( id=uuid.uuid4(), name=f"Project {level.value}", slug=f"project-{level.value}", autonomy_level=level, ) db_session.add(project) db_session.commit() retrieved = db_session.query(Project).filter_by(slug=f"project-{level.value}").first() assert retrieved.autonomy_level == level def test_all_project_statuses(self, db_session): """Test that all project statuses can be stored.""" for status in ProjectStatus: project = Project( id=uuid.uuid4(), name=f"Project {status.value}", slug=f"project-status-{status.value}", status=status, ) db_session.add(project) db_session.commit() retrieved = db_session.query(Project).filter_by(slug=f"project-status-{status.value}").first() assert retrieved.status == status class TestProjectSettings: """Tests for Project JSON settings field.""" def test_complex_json_settings(self, db_session): """Test storing complex JSON in settings.""" complex_settings = { "mcp_servers": ["gitea", "slack", "file-system"], "webhook_urls": { "on_issue_created": "https://example.com/issue", "on_sprint_completed": "https://example.com/sprint", }, "notification_settings": { "email": True, "slack_channel": "#syndarix-updates", }, "tags": ["important", "client-a"], } project = Project( id=uuid.uuid4(), name="Complex Settings Project", slug="complex-settings", settings=complex_settings, ) db_session.add(project) db_session.commit() retrieved = db_session.query(Project).filter_by(slug="complex-settings").first() assert retrieved.settings == complex_settings assert retrieved.settings["mcp_servers"] == ["gitea", "slack", "file-system"] assert retrieved.settings["webhook_urls"]["on_issue_created"] == "https://example.com/issue" assert "important" in retrieved.settings["tags"] def test_empty_settings(self, db_session): """Test that empty settings defaults correctly.""" project = Project( id=uuid.uuid4(), name="Empty Settings", slug="empty-settings", ) db_session.add(project) db_session.commit() retrieved = db_session.query(Project).filter_by(slug="empty-settings").first() assert retrieved.settings == {} def test_update_settings(self, db_session): """Test updating settings field.""" project = Project( id=uuid.uuid4(), name="Update Settings", slug="update-settings", settings={"initial": "value"}, ) db_session.add(project) db_session.commit() # Update settings project.settings = {"updated": "new_value", "additional": "data"} db_session.commit() retrieved = db_session.query(Project).filter_by(slug="update-settings").first() assert retrieved.settings == {"updated": "new_value", "additional": "data"}