diff --git a/backend/app/api/routes/teams.py b/backend/app/api/routes/teams.py index febdf72..66430de 100644 --- a/backend/app/api/routes/teams.py +++ b/backend/app/api/routes/teams.py @@ -10,7 +10,8 @@ from app.models.base import ( Message, RowId, ) -from app.models.member import MemberTeamLink, MemberTeamLinkCreate, MemberTeamLinkUpdate +from app.models.member import MemberTeamLink, MemberTeamLinkCreate, MemberTeamLinkUpdate, MemberTeamLinksPublic, \ + MemberTeamLinkPublic from app.models.team import ( Team, TeamCreate, @@ -276,7 +277,7 @@ def load_member_link(team: Team, member_id: RowId): return link -@router.get("/{team_id}/members", response_model=TeamsPublic) +@router.get("/{team_id}/members", response_model=MemberTeamLinksPublic) def read_team_member_links( session: SessionDep, current_user: CurrentUser, team_id: RowId, skip: int = 0, limit: int = 100 ) -> Any: @@ -307,10 +308,10 @@ def read_team_member_links( count = session.exec(select(func.count()).select_from(data_query.subquery())).one() data = session.exec(data_query.offset(skip).limit(limit)).all() - return TeamsPublic(data=data, count=count) + return MemberTeamLinksPublic(data=data, count=count) -@router.get("/{team_id}/members/{member_id}", response_model=TeamPublic) +@router.get("/{team_id}/members/{member_id}", response_model=MemberTeamLinkPublic) def read_team_member_link(session: SessionDep, current_user: CurrentUser, team_id: RowId, member_id: RowId) -> Any: """ Get member link by member ID. @@ -328,7 +329,7 @@ def read_team_member_link(session: SessionDep, current_user: CurrentUser, team_i return link -@router.post("/{team_id}/members", response_model=TeamPublic) +@router.post("/{team_id}/members", response_model=MemberTeamLinkPublic) def create_team_member_link( *, session: SessionDep, current_user: CurrentUser, team_id: RowId, link_in: MemberTeamLinkCreate ) -> Any: @@ -357,7 +358,7 @@ def create_team_member_link( return link -@router.put("/{team_id}/members/{member_id}", response_model=TeamPublic) +@router.put("/{team_id}/members/{member_id}", response_model=MemberTeamLinkPublic) def update_team_member_link( *, session: SessionDep, current_user: CurrentUser, team_id: RowId, member_id: RowId, link_in: MemberTeamLinkUpdate ) -> Any: diff --git a/backend/app/tests/api/routes/test_member.py b/backend/app/tests/api/routes/test_member.py index d7084a6..950704a 100644 --- a/backend/app/tests/api/routes/test_member.py +++ b/backend/app/tests/api/routes/test_member.py @@ -253,6 +253,7 @@ def test_update_member(client: TestClient, superuser_token_headers: dict[str, st assert content["canceled_at"] == member_db.canceled_at assert content["canceled_reason"] == member_db.canceled_reason + def test_delete_member(client: TestClient, superuser_token_headers: dict[str, str], db: Session) -> None: member = create_random_member(db) member_id = member.id @@ -268,6 +269,128 @@ def test_delete_member(client: TestClient, superuser_token_headers: dict[str, st assert member_db is None -# TODO: Team link tests -# app/models/member.py 79 8 90% 91-96 -# app/api/routes/teams.py 122 26 79% 272-276, 287-310, 318-328, 339-357, 367-378, 386-398 +def test_create_team_member_link(client: TestClient, superuser_token_headers: dict[str, str], db: Session) -> None: + team = create_random_team(db) + member = create_random_member(db) + + data = { + "member_id": str(member.id), + "rank": MemberRank.TEAM_MEMBER + } + response = client.post( + f"{settings.API_V1_STR}/teams/{team.id}/members", + headers=superuser_token_headers, + json=data, + ) + assert response.status_code == status.HTTP_200_OK + content = response.json() + assert content["member_id"] == str(member.id) + assert content["team_id"] == str(team.id) + assert content["rank"] == data["rank"] + + +def test_read_team_member_links(client: TestClient, superuser_token_headers: dict[str, str], db: Session) -> None: + team = create_random_team(db) + member = create_random_member(db) + + link_in = MemberTeamLinkCreate(member_id=member.id, rank=MemberRank.TEAM_MEMBER) + MemberTeamLink.create(session=db, create_obj=link_in, team=team) + + response = client.get( + f"{settings.API_V1_STR}/teams/{team.id}/members", + headers=superuser_token_headers, + ) + assert response.status_code == status.HTTP_200_OK + content = response.json() + assert "count" in content and content["count"] >= 1 + assert "data" in content and isinstance(content["data"], list) + assert any(link["member_id"] == str(member.id) for link in content["data"]) + + +def test_read_team_member_link(client: TestClient, superuser_token_headers: dict[str, str], db: Session) -> None: + team = create_random_team(db) + member = create_random_member(db) + + link_in = MemberTeamLinkCreate(member_id=member.id, rank=MemberRank.TEAM_MEMBER) + MemberTeamLink.create(session=db, create_obj=link_in, team=team) + + response = client.get( + f"{settings.API_V1_STR}/teams/{team.id}/members/{member.id}", + headers=superuser_token_headers, + ) + assert response.status_code == status.HTTP_200_OK + content = response.json() + assert content["member_id"] == str(member.id) + assert content["team_id"] == str(team.id) + + +def test_read_team_member_link_not_found(client: TestClient, superuser_token_headers: dict[str, str], db: Session) -> None: + team = create_random_team(db) + + response = client.get( + f"{settings.API_V1_STR}/teams/{team.id}/members/{uuid.uuid4()}", + headers=superuser_token_headers, + ) + assert response.status_code == status.HTTP_404_NOT_FOUND + assert response.json()["detail"] == "Member not found" + + +def test_read_team_member_link_event_user(client: TestClient, event_user_token_headers: EventUserHeader, db: Session) -> None: + team = create_random_team(db, event=event_user_token_headers.event) + member = create_random_member(db) + + link_in = MemberTeamLinkCreate(member_id=member.id, rank=MemberRank.TEAM_MEMBER) + MemberTeamLink.create(session=db, create_obj=link_in, team=team) + + response = client.get( + f"{settings.API_V1_STR}/teams/{team.id}/members/{member.id}", + headers=event_user_token_headers.headers, + ) + assert response.status_code == status.HTTP_200_OK + content = response.json() + assert content["member_id"] == str(member.id) + assert content["team_id"] == str(team.id) + + +# TODO: Add event user test + +# TODO: Add created_by test + + +def test_update_team_member_link(client: TestClient, superuser_token_headers: dict[str, str], db: Session) -> None: + team = create_random_team(db) + member = create_random_member(db) + + link_in = MemberTeamLinkCreate(member_id=member.id, rank=MemberRank.TEAM_MEMBER) + MemberTeamLink.create(session=db, create_obj=link_in, team=team) + + data = {"rank": MemberRank.TEAM_LEADER} + response = client.put( + f"{settings.API_V1_STR}/teams/{team.id}/members/{member.id}", + headers=superuser_token_headers, + json=data, + ) + assert response.status_code == status.HTTP_200_OK + assert response.json()["rank"] == data["rank"] + + +def test_delete_team_member_link(client: TestClient, superuser_token_headers: dict[str, str], db: Session) -> None: + team = create_random_team(db) + member = create_random_member(db) + + link_in = MemberTeamLinkCreate(member_id=member.id, rank=MemberRank.TEAM_MEMBER) + MemberTeamLink.create(session=db, create_obj=link_in, team=team) + + response = client.delete( + f"{settings.API_V1_STR}/teams/{team.id}/members/{member.id}", + headers=superuser_token_headers, + ) + assert response.status_code == status.HTTP_200_OK + assert response.json()["message"] == "Team member link deleted successfully" + + # Verify deletion + response = client.get( + f"{settings.API_V1_STR}/teams/{team.id}/members/{member.id}", + headers=superuser_token_headers, + ) + assert response.status_code == status.HTTP_404_NOT_FOUND