import uuid from datetime import datetime import pytest from sqlalchemy import select from app.models.lifecycle import LifecycleProject, ProjectStage from app.models.organization import Organization from app.models.user import User class TestLifecycleProjectModel: def test_lifecycle_project_table_name(self): assert LifecycleProject.__tablename__ == "lifecycle_projects" def test_project_stage_table_name(self): assert ProjectStage.__tablename__ == "project_stages" def test_lifecycle_project_has_required_fields(self): fields = LifecycleProject.__table__.columns.keys() assert "id" in fields assert "organization_id" in fields assert "brand_name" in fields assert "brand_aliases" in fields assert "current_stage" in fields assert "status" in fields assert "created_by" in fields assert "created_at" in fields assert "updated_at" in fields def test_project_stage_has_required_fields(self): fields = ProjectStage.__table__.columns.keys() assert "id" in fields assert "project_id" in fields assert "stage_number" in fields assert "status" in fields assert "started_at" in fields assert "completed_at" in fields assert "notes" in fields assert "metrics" in fields def test_lifecycle_project_field_types(self): columns = LifecycleProject.__table__.columns id_type = str(columns["id"].type).upper() assert "UUID" in id_type or "CHAR" in id_type org_id_type = str(columns["organization_id"].type).upper() assert "UUID" in org_id_type or "CHAR" in org_id_type brand_name_type = str(columns["brand_name"].type).upper() assert "VARCHAR" in brand_name_type or "STRING" in brand_name_type assert "INTEGER" in str(columns["current_stage"].type).upper() status_type = str(columns["status"].type).upper() assert "VARCHAR" in status_type or "STRING" in status_type def test_project_stage_field_types(self): columns = ProjectStage.__table__.columns id_type = str(columns["id"].type).upper() assert "UUID" in id_type or "CHAR" in id_type project_id_type = str(columns["project_id"].type).upper() assert "UUID" in project_id_type or "CHAR" in project_id_type assert "INTEGER" in str(columns["stage_number"].type).upper() status_type = str(columns["status"].type).upper() assert "VARCHAR" in status_type or "STRING" in status_type def test_lifecycle_project_relationships_defined(self): relationships = LifecycleProject.__mapper__.relationships rel_keys = relationships.keys() assert "stages" in rel_keys assert "organization" in rel_keys assert "creator" in rel_keys def test_project_stage_relationships_defined(self): relationships = ProjectStage.__mapper__.relationships rel_keys = relationships.keys() assert "project" in rel_keys def test_lifecycle_project_default_stage(self): columns = LifecycleProject.__table__.columns stage_col = columns["current_stage"] assert stage_col.server_default is not None def test_lifecycle_project_default_status(self): columns = LifecycleProject.__table__.columns status_col = columns["status"] assert status_col.server_default is not None def test_project_stage_default_status(self): columns = ProjectStage.__table__.columns status_col = columns["status"] assert status_col.server_default is not None @pytest.mark.asyncio async def test_lifecycle_project_create(self, async_session, test_user): org = Organization( name="Lifecycle Test Org", slug="lifecycle-test-org", ) async_session.add(org) await async_session.commit() await async_session.refresh(org) project = LifecycleProject( id=uuid.uuid4(), organization_id=org.id, brand_name="Test Brand", brand_aliases=["TB", "TestBrand"], current_stage=1, status="active", created_by=test_user.id, ) async_session.add(project) await async_session.commit() await async_session.refresh(project) assert project.id is not None assert project.organization_id == org.id assert project.brand_name == "Test Brand" assert project.brand_aliases == ["TB", "TestBrand"] assert project.current_stage == 1 assert project.status == "active" assert project.created_by == test_user.id assert project.created_at is not None assert project.updated_at is not None @pytest.mark.asyncio async def test_lifecycle_project_default_values(self, async_session, test_user): org = Organization( name="Default Lifecycle Org", slug="default-lifecycle-org", ) async_session.add(org) await async_session.commit() await async_session.refresh(org) project = LifecycleProject( organization_id=org.id, brand_name="Default Brand", created_by=test_user.id, ) async_session.add(project) await async_session.commit() await async_session.refresh(project) assert project.brand_aliases == [] assert project.current_stage == 1 assert project.status == "active" @pytest.mark.asyncio async def test_project_stage_create(self, async_session, test_user): org = Organization( name="Stage Test Org", slug="stage-test-org", ) async_session.add(org) await async_session.commit() await async_session.refresh(org) project = LifecycleProject( organization_id=org.id, brand_name="Stage Test Brand", created_by=test_user.id, ) async_session.add(project) await async_session.commit() await async_session.refresh(project) stage = ProjectStage( id=uuid.uuid4(), project_id=project.id, stage_number=1, status="in_progress", notes="Starting brand awareness phase", metrics={"awareness_score": 45}, ) async_session.add(stage) await async_session.commit() await async_session.refresh(stage) assert stage.id is not None assert stage.project_id == project.id assert stage.stage_number == 1 assert stage.status == "in_progress" assert stage.notes == "Starting brand awareness phase" assert stage.metrics == {"awareness_score": 45} assert stage.started_at is None assert stage.completed_at is None @pytest.mark.asyncio async def test_project_stage_default_values(self, async_session, test_user): org = Organization( name="Default Stage Org", slug="default-stage-org", ) async_session.add(org) await async_session.commit() await async_session.refresh(org) project = LifecycleProject( organization_id=org.id, brand_name="Default Stage Brand", created_by=test_user.id, ) async_session.add(project) await async_session.commit() await async_session.refresh(project) stage = ProjectStage( project_id=project.id, stage_number=2, ) async_session.add(stage) await async_session.commit() await async_session.refresh(stage) assert stage.status == "pending" assert stage.notes is None assert stage.metrics is None