import pytest from fastapi.testclient import TestClient from bson import ObjectId from src.models.team import TeamModel from src.db.repositories.team_repository import team_repository @pytest.mark.asyncio async def test_create_team(client: TestClient, admin_api_key: tuple): """Test creating a new team (admin only)""" raw_key, _ = admin_api_key # Set up the headers with the admin API key headers = {"X-API-Key": raw_key} # Create a new team response = client.post( "/api/v1/teams", headers=headers, json={ "name": "New Test Team", "description": "A team created in a test" } ) # Check response assert response.status_code == 201 data = response.json() assert "id" in data assert data["name"] == "New Test Team" assert data["description"] == "A team created in a test" assert "created_at" in data @pytest.mark.asyncio async def test_create_team_non_admin(client: TestClient, user_api_key: tuple): """Test that non-admin users cannot create teams""" raw_key, _ = user_api_key # Set up the headers with a non-admin API key headers = {"X-API-Key": raw_key} # Try to create a new team response = client.post( "/api/v1/teams", headers=headers, json={ "name": "Unauthorized Team", "description": "A team that should not be created" } ) # Check that the request is forbidden assert response.status_code == 403 assert "detail" in response.json() assert "admin" in response.json()["detail"].lower() @pytest.mark.asyncio async def test_list_teams(client: TestClient, admin_api_key: tuple, test_team: TeamModel): """Test listing all teams (admin only)""" raw_key, _ = admin_api_key # Set up the headers headers = {"X-API-Key": raw_key} # List teams response = client.get( "/api/v1/teams", headers=headers ) # Check response assert response.status_code == 200 data = response.json() assert "teams" in data assert "total" in data assert data["total"] >= 1 # Should include at least the test team # Verify the test team is in the list team_ids = [team["id"] for team in data["teams"]] assert str(test_team.id) in team_ids @pytest.mark.asyncio async def test_list_teams_non_admin(client: TestClient, user_api_key: tuple): """Test that non-admin users cannot list all teams""" raw_key, _ = user_api_key # Set up the headers headers = {"X-API-Key": raw_key} # Try to list teams response = client.get( "/api/v1/teams", headers=headers ) # Check that the request is forbidden assert response.status_code == 403 assert "detail" in response.json() assert "admin" in response.json()["detail"].lower() @pytest.mark.asyncio async def test_get_team(client: TestClient, admin_api_key: tuple, test_team: TeamModel): """Test getting a specific team by ID""" raw_key, _ = admin_api_key # Set up the headers headers = {"X-API-Key": raw_key} # Get the team response = client.get( f"/api/v1/teams/{test_team.id}", headers=headers ) # Check response assert response.status_code == 200 data = response.json() assert data["id"] == str(test_team.id) assert data["name"] == test_team.name assert data["description"] == test_team.description assert "created_at" in data @pytest.mark.asyncio async def test_get_team_own(client: TestClient, user_api_key: tuple, test_team: TeamModel): """Test a regular user can get their own team""" raw_key, _ = user_api_key # Set up the headers headers = {"X-API-Key": raw_key} # Get the user's team response = client.get( f"/api/v1/teams/{test_team.id}", headers=headers ) # Check response assert response.status_code == 200 data = response.json() assert data["id"] == str(test_team.id) @pytest.mark.asyncio async def test_get_team_other(client: TestClient, user_api_key: tuple): """Test that a regular user cannot get another team""" raw_key, _ = user_api_key # Create another team other_team = TeamModel( name="Other Team", description="Another team for testing" ) created_team = await team_repository.create(other_team) # Set up the headers headers = {"X-API-Key": raw_key} # Try to get the other team response = client.get( f"/api/v1/teams/{created_team.id}", headers=headers ) # Check that the request is forbidden assert response.status_code == 403 assert "detail" in response.json() assert "not authorized" in response.json()["detail"].lower() @pytest.mark.asyncio async def test_update_team(client: TestClient, admin_api_key: tuple, test_team: TeamModel): """Test updating a team (admin only)""" raw_key, _ = admin_api_key # Set up the headers headers = {"X-API-Key": raw_key} # Update the team response = client.put( f"/api/v1/teams/{test_team.id}", headers=headers, json={ "name": "Updated Team Name", "description": "This team has been updated" } ) # Check response assert response.status_code == 200 data = response.json() assert data["id"] == str(test_team.id) assert data["name"] == "Updated Team Name" assert data["description"] == "This team has been updated" assert "updated_at" in data @pytest.mark.asyncio async def test_update_team_non_admin(client: TestClient, user_api_key: tuple, test_team: TeamModel): """Test that non-admin users cannot update teams""" raw_key, _ = user_api_key # Set up the headers headers = {"X-API-Key": raw_key} # Try to update the team response = client.put( f"/api/v1/teams/{test_team.id}", headers=headers, json={ "name": "Unauthorized Update", "description": "This update should not succeed" } ) # Check that the request is forbidden assert response.status_code == 403 assert "detail" in response.json() assert "admin" in response.json()["detail"].lower() @pytest.mark.asyncio async def test_delete_team(client: TestClient, admin_api_key: tuple): """Test deleting a team (admin only)""" raw_key, _ = admin_api_key # Create a team to delete team_to_delete = TeamModel( name="Team to Delete", description="This team will be deleted" ) created_team = await team_repository.create(team_to_delete) # Set up the headers headers = {"X-API-Key": raw_key} # Delete the team response = client.delete( f"/api/v1/teams/{created_team.id}", headers=headers ) # Check response assert response.status_code == 204 # Verify the team has been deleted deleted_team = await team_repository.get_by_id(created_team.id) assert deleted_team is None @pytest.mark.asyncio async def test_delete_team_non_admin(client: TestClient, user_api_key: tuple, test_team: TeamModel): """Test that non-admin users cannot delete teams""" raw_key, _ = user_api_key # Set up the headers headers = {"X-API-Key": raw_key} # Try to delete the team response = client.delete( f"/api/v1/teams/{test_team.id}", headers=headers ) # Check that the request is forbidden assert response.status_code == 403 assert "detail" in response.json() assert "admin" in response.json()["detail"].lower() @pytest.mark.asyncio async def test_invalid_team_id(client: TestClient, admin_api_key: tuple): """Test handling invalid team IDs""" raw_key, _ = admin_api_key # Set up the headers headers = {"X-API-Key": raw_key} # Try to get a team with an invalid ID response = client.get( "/api/v1/teams/invalid-id", headers=headers ) # Check that the request fails with a 400 error assert response.status_code == 400 assert "detail" in response.json() assert "invalid" in response.json()["detail"].lower() @pytest.mark.asyncio async def test_nonexistent_team(client: TestClient, admin_api_key: tuple): """Test handling requests for nonexistent teams""" raw_key, _ = admin_api_key # Set up the headers headers = {"X-API-Key": raw_key} # Try to get a team that doesn't exist nonexistent_id = str(ObjectId()) response = client.get( f"/api/v1/teams/{nonexistent_id}", headers=headers ) # Check that the request fails with a 404 error assert response.status_code == 404 assert "detail" in response.json() assert "not found" in response.json()["detail"].lower()