|
|
"""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" |
|
|
assert user_id[3:].isdigit() |
|
|
|
|
|
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 |
|
|
|
|
|
def test_generate_user_id_uniqueness(self): |
|
|
"""Test that multiple calls generate different IDs.""" |
|
|
ids = [generate_user_id("Test") for _ in range(10)] |
|
|
|
|
|
assert len(set(ids)) > 5 |
|
|
|
|
|
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 |
|
|
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="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): |
|
|
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" |
|
|
|