"""Unit tests for models module.""" import pytest from datetime import datetime from app.database import SessionLocal, init_db from app.models import ( User, Project, Task, LogEntry, ProjectMembership, generate_uuid, generate_user_id, TaskStatus, ActorType, ActionType ) class TestGenerateUserId: """Test user ID generation function.""" def test_generate_user_id_format(self): """Test generated ID has correct format: 3 letters + 4 digits.""" user_id = generate_user_id("Alice") assert len(user_id) == 7 assert user_id[:3] == "ali" # First 3 letters lowercase assert user_id[3:].isdigit() # Last 4 are digits def test_generate_user_id_lowercase(self): """Test first name is lowercased.""" user_id = generate_user_id("JOHN") assert user_id[:3] == "joh" def test_generate_user_id_short_name(self): """Test with name shorter than 3 characters.""" user_id = generate_user_id("Jo") assert user_id[:2] == "jo" assert len(user_id) == 6 # 2 letters + 4 digits def test_generate_user_id_uniqueness(self): """Test that multiple calls generate different IDs.""" ids = [generate_user_id("Test") for _ in range(10)] # With 4 random digits, collisions are unlikely assert len(set(ids)) > 5 # At least some should be unique def test_generate_user_id_example(self): """Test example from requirements: Amal -> ama + 4 digits.""" user_id = generate_user_id("Amal") assert user_id.startswith("ama") assert len(user_id) == 7 class TestGenerateUuid: """Test UUID generation function.""" def test_generate_uuid_format(self): """Test UUID is valid format.""" uuid = generate_uuid() assert len(uuid) == 36 # Standard UUID length with hyphens assert uuid.count("-") == 4 def test_generate_uuid_uniqueness(self): """Test UUIDs are unique.""" uuids = [generate_uuid() for _ in range(100)] assert len(set(uuids)) == 100 class TestUserModel: """Test User model.""" def test_user_creation(self, db_session): """Test creating a user with new fields.""" user_id = generate_user_id("Test") user = User( id=user_id, first_name="Test", last_name="User" ) db_session.add(user) db_session.commit() assert user.id == user_id assert user.first_name == "Test" assert user.last_name == "User" assert user.created_at is not None def test_user_name_property(self, db_session): """Test the name property returns full name.""" user_id = generate_user_id("John") user = User(id=user_id, first_name="John", last_name="Doe") db_session.add(user) db_session.commit() assert user.name == "John Doe" def test_user_optional_avatar(self, db_session): """Test avatar_url is optional.""" user_id = generate_user_id("Jane") user = User(id=user_id, first_name="Jane", last_name="Smith") db_session.add(user) db_session.commit() assert user.avatar_url is None def test_user_with_avatar(self, db_session): """Test user with avatar URL.""" user_id = generate_user_id("Bob") user = User( id=user_id, first_name="Bob", last_name="Builder", avatar_url="https://example.com/avatar.jpg" ) db_session.add(user) db_session.commit() assert user.avatar_url == "https://example.com/avatar.jpg" class TestProjectModel: """Test Project model.""" def test_project_with_name_as_id(self, db_session, create_user): """Test creating project with name as ID.""" user = create_user("Owner", "Test") project = Project( id="myproject", # Name used as ID name="myproject", description="Test project", created_by=user.id ) db_session.add(project) db_session.commit() assert project.id == "myproject" assert project.name == "myproject" def test_project_id_uniqueness(self, db_session, create_user): """Test that duplicate project IDs fail.""" user = create_user("Owner", "Test") project1 = Project(id="unique", name="unique", description="First", created_by=user.id) db_session.add(project1) db_session.commit() project2 = Project(id="unique", name="unique", description="Second", created_by=user.id) db_session.add(project2) with pytest.raises(Exception): # IntegrityError db_session.commit() class TestTaskModel: """Test Task model.""" def test_task_status_enum(self): """Test TaskStatus enum values.""" assert TaskStatus.todo.value == "todo" assert TaskStatus.in_progress.value == "in_progress" assert TaskStatus.done.value == "done" def test_task_default_status(self, db_session, create_user): """Test task defaults to 'todo' status.""" user = create_user("Dev", "Test") project = Project(id="taskproj", name="taskproj", description="Test", created_by=user.id) db_session.add(project) db_session.commit() task = Task( project_id=project.id, title="Test Task", description="Test description" ) db_session.add(task) db_session.commit() assert task.status == TaskStatus.todo class TestEnums: """Test enum definitions.""" def test_actor_type_enum(self): """Test ActorType enum.""" assert ActorType.human.value == "human" assert ActorType.agent.value == "agent" def test_action_type_enum(self): """Test ActionType enum.""" assert ActionType.task_completed.value == "task_completed" assert ActionType.doc_generated.value == "doc_generated" assert ActionType.query_answered.value == "query_answered"