| | """Unit tests for project tools.""" |
| |
|
| | import pytest |
| | from app.tools.projects import ( |
| | create_project, list_projects, join_project, check_project_id_available |
| | ) |
| | from app.database import SessionLocal |
| | from app.models import Project, ProjectMembership |
| |
|
| |
|
| | class TestCheckProjectIdAvailable: |
| | """Test project ID availability checking.""" |
| |
|
| | def test_available_id(self, create_user): |
| | """Test checking an available project ID.""" |
| | result = check_project_id_available("nonexistent-project") |
| | |
| | assert result["available"] == True |
| | assert result["project_id"] == "nonexistent-project" |
| |
|
| | def test_unavailable_id(self, create_user): |
| | """Test checking an ID that's already taken.""" |
| | user = create_user("Test", "User") |
| | |
| | |
| | create_project("takenid", "Description", user.id) |
| | |
| | |
| | result = check_project_id_available("takenid") |
| | |
| | assert result["available"] == False |
| | assert result["project_id"] == "takenid" |
| |
|
| |
|
| | class TestCreateProject: |
| | """Test project creation with name as ID.""" |
| |
|
| | def test_create_project_uses_name_as_id(self, create_user): |
| | """Test that project name is used as project ID.""" |
| | user = create_user("Creator", "Test") |
| | |
| | result = create_project("fastgate", "A fast gateway", user.id) |
| | |
| | assert result["id"] == "fastgate" |
| | assert result["name"] == "fastgate" |
| | assert result["description"] == "A fast gateway" |
| | assert result["created_by"] == user.id |
| |
|
| | def test_create_project_adds_owner_membership(self, create_user): |
| | """Test that creator is added as owner.""" |
| | user = create_user("Owner", "Test") |
| | |
| | result = create_project("ownerproj", "Test", user.id) |
| | |
| | db = SessionLocal() |
| | try: |
| | membership = db.query(ProjectMembership).filter( |
| | ProjectMembership.project_id == result["id"], |
| | ProjectMembership.user_id == user.id |
| | ).first() |
| | |
| | assert membership is not None |
| | assert membership.role == "owner" |
| | finally: |
| | db.close() |
| |
|
| | def test_create_project_duplicate_id_fails(self, create_user): |
| | """Test that creating project with existing ID fails.""" |
| | user = create_user("Test", "User") |
| | |
| | |
| | create_project("duplicate", "First project", user.id) |
| | |
| | |
| | result = create_project("duplicate", "Second project", user.id) |
| | |
| | assert "error" in result |
| | assert "already exists" in result["error"] |
| |
|
| | def test_create_project_nonexistent_user(self): |
| | """Test creating project with non-existent user fails.""" |
| | result = create_project("orphan", "No owner", "nonexistent-user-id") |
| | |
| | assert "error" in result |
| | assert "not found" in result["error"] |
| |
|
| |
|
| | class TestListProjects: |
| | """Test listing user's projects.""" |
| |
|
| | def test_list_projects_empty(self, create_user): |
| | """Test listing projects for user with no projects.""" |
| | user = create_user("New", "User") |
| | |
| | result = list_projects(user.id) |
| | |
| | assert "projects" in result |
| | assert len(result["projects"]) == 0 |
| |
|
| | def test_list_projects_with_owned_project(self, create_user): |
| | """Test listing projects includes owned projects.""" |
| | user = create_user("Owner", "Test") |
| | create_project("ownedproj", "My project", user.id) |
| | |
| | result = list_projects(user.id) |
| | |
| | assert len(result["projects"]) == 1 |
| | assert result["projects"][0]["name"] == "ownedproj" |
| | assert result["projects"][0]["role"] == "owner" |
| |
|
| | def test_list_projects_with_member_project(self, create_user): |
| | """Test listing projects includes joined projects.""" |
| | owner = create_user("Owner", "Test") |
| | member = create_user("Member", "Test") |
| | |
| | create_project("sharedproj", "Shared project", owner.id) |
| | join_project("sharedproj", member.id) |
| | |
| | result = list_projects(member.id) |
| | |
| | assert len(result["projects"]) == 1 |
| | assert result["projects"][0]["name"] == "sharedproj" |
| | assert result["projects"][0]["role"] == "member" |
| |
|
| |
|
| | class TestJoinProject: |
| | """Test joining existing projects.""" |
| |
|
| | def test_join_project_success(self, create_user): |
| | """Test successfully joining a project.""" |
| | owner = create_user("Owner", "Test") |
| | member = create_user("Member", "Test") |
| | |
| | create_project("jointest", "Test project", owner.id) |
| | result = join_project("jointest", member.id) |
| | |
| | assert "message" in result |
| | assert result["project_id"] == "jointest" |
| | assert result["role"] == "member" |
| |
|
| | def test_join_project_already_member(self, create_user): |
| | """Test joining a project you're already a member of.""" |
| | owner = create_user("Owner", "Test") |
| | member = create_user("Member", "Test") |
| | |
| | create_project("alreadyin", "Test project", owner.id) |
| | join_project("alreadyin", member.id) |
| | |
| | |
| | result = join_project("alreadyin", member.id) |
| | |
| | assert "Already a member" in result.get("message", "") |
| |
|
| | def test_join_nonexistent_project(self, create_user): |
| | """Test joining a project that doesn't exist.""" |
| | user = create_user("User", "Test") |
| | |
| | result = join_project("doesnotexist", user.id) |
| | |
| | assert "error" in result |
| | assert "not found" in result["error"] |
| |
|
| | def test_join_project_nonexistent_user(self, create_user): |
| | """Test joining with non-existent user.""" |
| | owner = create_user("Owner", "Test") |
| | create_project("validproj", "Test", owner.id) |
| | |
| | result = join_project("validproj", "nonexistent-user") |
| | |
| | assert "error" in result |
| | assert "not found" in result["error"] |
| |
|