[OND211-2329]: Added tests to delete group.
This commit is contained in:
parent
3ffe94b58e
commit
4c8ea1d21a
2 changed files with 419 additions and 0 deletions
|
|
@ -781,3 +781,29 @@ def list_group_members(
|
|||
url=url, headers=headers, auth=auth, params=params
|
||||
)
|
||||
return res.json()
|
||||
|
||||
|
||||
def delete_group(
|
||||
auth: Union[AuthBase, str, None],
|
||||
group_id: str,
|
||||
*,
|
||||
headers: Dict[str, str] = HEADERS,
|
||||
) -> Dict[str, Any]:
|
||||
"""Delete a group.
|
||||
|
||||
Args:
|
||||
auth: Authentication object (AuthBase subclass), token string, or None.
|
||||
group_id: The group ID to delete.
|
||||
headers: Optional HTTP headers. Defaults to HEADERS.
|
||||
|
||||
Returns:
|
||||
JSON response as a dictionary containing the deletion result.
|
||||
|
||||
Raises:
|
||||
requests.RequestException: If the HTTP request fails.
|
||||
"""
|
||||
url: str = f"{HOST_ADDRESS}{GROUP_API_URL}/{group_id}"
|
||||
res: requests.Response = requests.delete(
|
||||
url=url, headers=headers, auth=auth
|
||||
)
|
||||
return res.json()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,393 @@
|
|||
#
|
||||
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from common import (
|
||||
add_group_members,
|
||||
add_users_to_team,
|
||||
create_group,
|
||||
create_team,
|
||||
create_user,
|
||||
delete_group,
|
||||
encrypt_password,
|
||||
get_user_info,
|
||||
login_as_user,
|
||||
)
|
||||
from configs import INVALID_API_TOKEN
|
||||
from libs.auth import RAGFlowWebApiAuth
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Test Classes
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@pytest.mark.p1
|
||||
class TestAuthorization:
|
||||
"""Tests for authentication behavior when deleting a group."""
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("invalid_auth", "expected_code", "expected_message"),
|
||||
[
|
||||
(None, 401, "Unauthorized"),
|
||||
(RAGFlowWebApiAuth(INVALID_API_TOKEN), 401, "Unauthorized"),
|
||||
],
|
||||
)
|
||||
def test_invalid_auth(
|
||||
self,
|
||||
invalid_auth: RAGFlowWebApiAuth | None,
|
||||
expected_code: int,
|
||||
expected_message: str,
|
||||
web_api_auth: RAGFlowWebApiAuth,
|
||||
) -> None:
|
||||
"""Test deleting a group with invalid or missing authentication."""
|
||||
# Create a team and group first
|
||||
team_name: str = f"Test Team {uuid.uuid4().hex[:8]}"
|
||||
team_payload: dict[str, str] = {"name": team_name}
|
||||
team_res: dict[str, Any] = create_team(web_api_auth, team_payload)
|
||||
if team_res["code"] != 0:
|
||||
pytest.skip("Team creation failed, skipping auth test")
|
||||
|
||||
tenant_id: str = team_res["data"]["id"]
|
||||
|
||||
group_name: str = f"Test Group {uuid.uuid4().hex[:8]}"
|
||||
group_payload: dict[str, str] = {
|
||||
"name": group_name,
|
||||
"tenant_id": tenant_id,
|
||||
}
|
||||
group_res: dict[str, Any] = create_group(web_api_auth, group_payload)
|
||||
if group_res["code"] != 0:
|
||||
pytest.skip("Group creation failed, skipping auth test")
|
||||
|
||||
group_id: str = group_res["data"]["id"]
|
||||
|
||||
# Try to delete group with invalid auth
|
||||
res: dict[str, Any] = delete_group(invalid_auth, group_id)
|
||||
assert res["code"] == expected_code, res
|
||||
if expected_message:
|
||||
assert expected_message in res["message"]
|
||||
|
||||
|
||||
@pytest.mark.p1
|
||||
class TestDeleteGroup:
|
||||
"""Comprehensive tests for deleting a group."""
|
||||
|
||||
@pytest.fixture
|
||||
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
|
||||
"""Create a test team for use in tests."""
|
||||
team_payload: dict[str, str] = {"name": f"Test Team {uuid.uuid4().hex[:8]}"}
|
||||
res: dict[str, Any] = create_team(web_api_auth, team_payload)
|
||||
assert res["code"] == 0
|
||||
return res["data"]
|
||||
|
||||
@pytest.fixture
|
||||
def test_group(
|
||||
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
|
||||
) -> dict[str, Any]:
|
||||
"""Create a test group for use in tests."""
|
||||
group_payload: dict[str, str] = {
|
||||
"name": f"Test Group {uuid.uuid4().hex[:8]}",
|
||||
"tenant_id": test_team["id"],
|
||||
}
|
||||
res: dict[str, Any] = create_group(web_api_auth, group_payload)
|
||||
assert res["code"] == 0
|
||||
return res["data"]
|
||||
|
||||
@pytest.fixture
|
||||
def test_group_with_members(
|
||||
self,
|
||||
web_api_auth: RAGFlowWebApiAuth,
|
||||
test_group: dict[str, Any],
|
||||
test_team: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
"""Create a test group and add the current user as a member."""
|
||||
# Get current user ID
|
||||
user_info_res: dict[str, Any] = get_user_info(web_api_auth)
|
||||
if user_info_res["code"] == 0:
|
||||
user_id: str = user_info_res["data"]["id"]
|
||||
# Add current user to group (they're already team owner/admin)
|
||||
add_payload: dict[str, list[str]] = {"user_ids": [user_id]}
|
||||
add_group_members(web_api_auth, test_group["id"], add_payload)
|
||||
return test_group
|
||||
|
||||
@pytest.mark.p1
|
||||
def test_delete_group_success(
|
||||
self,
|
||||
web_api_auth: RAGFlowWebApiAuth,
|
||||
test_group_with_members: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test successfully deleting a group."""
|
||||
group_id: str = test_group_with_members["id"]
|
||||
|
||||
# Delete the group
|
||||
res: dict[str, Any] = delete_group(web_api_auth, group_id)
|
||||
assert res["code"] == 0, res
|
||||
assert res["data"] is True
|
||||
assert "deleted successfully" in res["message"].lower()
|
||||
|
||||
@pytest.mark.p1
|
||||
def test_delete_group_invalid_id(
|
||||
self, web_api_auth: RAGFlowWebApiAuth
|
||||
) -> None:
|
||||
"""Test deleting a group with an invalid group ID."""
|
||||
invalid_id: str = f"invalid_{uuid.uuid4().hex[:8]}"
|
||||
res: dict[str, Any] = delete_group(web_api_auth, invalid_id)
|
||||
assert res["code"] == 102 # DATA_ERROR
|
||||
assert "not found" in res["message"].lower()
|
||||
|
||||
@pytest.mark.p1
|
||||
def test_delete_group_not_team_admin_or_owner(
|
||||
self,
|
||||
web_api_auth: RAGFlowWebApiAuth,
|
||||
test_group: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test deleting a group when user is not team admin or owner."""
|
||||
# Create a new user with encrypted password
|
||||
email: str = f"testuser_{uuid.uuid4().hex[:8]}@example.com"
|
||||
password = "TestPassword123!"
|
||||
encrypted_password = encrypt_password(password)
|
||||
user_payload: dict[str, str] = {
|
||||
"email": email,
|
||||
"password": encrypted_password,
|
||||
"nickname": "Test User",
|
||||
}
|
||||
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
|
||||
if user_res["code"] != 0:
|
||||
pytest.skip("User creation failed")
|
||||
|
||||
# Add user to team as normal member
|
||||
team_id: str = test_group["tenant_id"]
|
||||
add_payload: dict[str, list[str]] = {"users": [email]}
|
||||
add_users_to_team(web_api_auth, team_id, add_payload)
|
||||
|
||||
# Small delay to ensure user is fully created
|
||||
time.sleep(0.5)
|
||||
|
||||
# Login as the new user (normal member, not admin/owner)
|
||||
new_user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
|
||||
|
||||
# Try to delete group (user is member but not admin/owner)
|
||||
res: dict[str, Any] = delete_group(new_user_auth, test_group["id"])
|
||||
assert res["code"] == 108 # PERMISSION_ERROR
|
||||
assert "owner" in res["message"].lower() or "admin" in res["message"].lower()
|
||||
|
||||
@pytest.mark.p1
|
||||
def test_delete_group_response_structure(
|
||||
self,
|
||||
web_api_auth: RAGFlowWebApiAuth,
|
||||
test_group_with_members: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test that group deletion returns the expected response structure."""
|
||||
group_id: str = test_group_with_members["id"]
|
||||
|
||||
res: dict[str, Any] = delete_group(web_api_auth, group_id)
|
||||
assert res["code"] == 0
|
||||
assert "data" in res
|
||||
assert res["data"] is True
|
||||
assert "message" in res
|
||||
assert isinstance(res["message"], str)
|
||||
assert "deleted successfully" in res["message"].lower()
|
||||
|
||||
@pytest.mark.p1
|
||||
def test_delete_group_already_deleted(
|
||||
self,
|
||||
web_api_auth: RAGFlowWebApiAuth,
|
||||
test_group_with_members: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test deleting a group that has already been deleted."""
|
||||
group_id: str = test_group_with_members["id"]
|
||||
|
||||
# Delete the group first
|
||||
res1: dict[str, Any] = delete_group(web_api_auth, group_id)
|
||||
assert res1["code"] == 0
|
||||
|
||||
# Try to delete again
|
||||
res2: dict[str, Any] = delete_group(web_api_auth, group_id)
|
||||
# Should return error (group not found or already deleted)
|
||||
assert res2["code"] != 0
|
||||
assert "not found" in res2["message"].lower() or "deleted" in res2["message"].lower()
|
||||
|
||||
@pytest.mark.p1
|
||||
def test_delete_group_with_members(
|
||||
self,
|
||||
web_api_auth: RAGFlowWebApiAuth,
|
||||
test_group: dict[str, Any],
|
||||
test_team: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test deleting a group that has members."""
|
||||
# Create test users
|
||||
users = []
|
||||
for i in range(2):
|
||||
email = f"testuser{i}_{uuid.uuid4().hex[:8]}@example.com"
|
||||
password = "TestPassword123!"
|
||||
encrypted_password = encrypt_password(password)
|
||||
user_payload: dict[str, str] = {
|
||||
"email": email,
|
||||
"password": encrypted_password,
|
||||
"nickname": f"Test User {i}",
|
||||
}
|
||||
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
|
||||
if user_res["code"] == 0:
|
||||
users.append({"email": email, "id": user_res["data"]["id"]})
|
||||
|
||||
if not users:
|
||||
pytest.skip("User creation failed")
|
||||
|
||||
# Add users to team
|
||||
for user in users:
|
||||
add_payload: dict[str, list[str]] = {"users": [user["email"]]}
|
||||
add_users_to_team(web_api_auth, test_team["id"], add_payload)
|
||||
|
||||
# Add users to group
|
||||
user_ids: list[str] = [user["id"] for user in users]
|
||||
group_add_payload: dict[str, list[str]] = {"user_ids": user_ids}
|
||||
add_group_members(web_api_auth, test_group["id"], group_add_payload)
|
||||
|
||||
# Delete the group (should also remove all member relationships)
|
||||
res: dict[str, Any] = delete_group(web_api_auth, test_group["id"])
|
||||
assert res["code"] == 0, res
|
||||
assert res["data"] is True
|
||||
assert "member relationships" in res["message"].lower() or "deleted successfully" in res["message"].lower()
|
||||
|
||||
@pytest.mark.p1
|
||||
def test_delete_group_removes_member_relationships(
|
||||
self,
|
||||
web_api_auth: RAGFlowWebApiAuth,
|
||||
test_group: dict[str, Any],
|
||||
test_team: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test that deleting a group removes all member relationships."""
|
||||
from common import list_group_members
|
||||
|
||||
# Create and add a user to the group
|
||||
email = f"testuser_{uuid.uuid4().hex[:8]}@example.com"
|
||||
password = "TestPassword123!"
|
||||
encrypted_password = encrypt_password(password)
|
||||
user_payload: dict[str, str] = {
|
||||
"email": email,
|
||||
"password": encrypted_password,
|
||||
"nickname": "Test User",
|
||||
}
|
||||
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
|
||||
if user_res["code"] != 0:
|
||||
pytest.skip("User creation failed")
|
||||
|
||||
user_id: str = user_res["data"]["id"]
|
||||
|
||||
# Add user to team
|
||||
add_team_payload: dict[str, list[str]] = {"users": [email]}
|
||||
add_users_to_team(web_api_auth, test_team["id"], add_team_payload)
|
||||
|
||||
# Add user to group
|
||||
add_group_payload: dict[str, list[str]] = {"user_ids": [user_id]}
|
||||
add_group_members(web_api_auth, test_group["id"], add_group_payload)
|
||||
|
||||
# Verify user is in group
|
||||
list_res_before: dict[str, Any] = list_group_members(web_api_auth, test_group["id"])
|
||||
assert list_res_before["code"] == 0
|
||||
member_user_ids_before: set[str] = {
|
||||
member["user_id"] for member in list_res_before["data"]
|
||||
}
|
||||
assert user_id in member_user_ids_before
|
||||
|
||||
# Delete the group
|
||||
delete_res: dict[str, Any] = delete_group(web_api_auth, test_group["id"])
|
||||
assert delete_res["code"] == 0
|
||||
|
||||
# Try to list members (should fail - group deleted)
|
||||
list_res_after: dict[str, Any] = list_group_members(web_api_auth, test_group["id"])
|
||||
assert list_res_after["code"] != 0
|
||||
assert "not found" in list_res_after["message"].lower()
|
||||
|
||||
@pytest.mark.p2
|
||||
def test_delete_multiple_groups(
|
||||
self,
|
||||
web_api_auth: RAGFlowWebApiAuth,
|
||||
test_team: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test deleting multiple groups from the same team."""
|
||||
# Create multiple groups
|
||||
groups = []
|
||||
for i in range(3):
|
||||
group_name: str = f"Group {i} {uuid.uuid4().hex[:8]}"
|
||||
group_payload: dict[str, str] = {
|
||||
"name": group_name,
|
||||
"tenant_id": test_team["id"],
|
||||
}
|
||||
group_res: dict[str, Any] = create_group(web_api_auth, group_payload)
|
||||
if group_res["code"] == 0:
|
||||
groups.append(group_res["data"])
|
||||
|
||||
if not groups:
|
||||
pytest.skip("Group creation failed")
|
||||
|
||||
# Delete all groups
|
||||
for group in groups:
|
||||
res: dict[str, Any] = delete_group(web_api_auth, group["id"])
|
||||
assert res["code"] == 0, f"Failed to delete group {group['id']}: {res}"
|
||||
|
||||
@pytest.mark.p2
|
||||
def test_delete_group_empty_string_id(
|
||||
self, web_api_auth: RAGFlowWebApiAuth
|
||||
) -> None:
|
||||
"""Test deleting a group with empty string ID."""
|
||||
res: dict[str, Any] = delete_group(web_api_auth, "")
|
||||
assert res["code"] != 0
|
||||
assert "not found" in res["message"].lower() or res["code"] in [100, 102, 405]
|
||||
|
||||
@pytest.mark.p2
|
||||
def test_delete_group_special_characters_id(
|
||||
self, web_api_auth: RAGFlowWebApiAuth
|
||||
) -> None:
|
||||
"""Test deleting a group with special characters in ID."""
|
||||
invalid_id: str = "group-123_!@#$%"
|
||||
res: dict[str, Any] = delete_group(web_api_auth, invalid_id)
|
||||
assert res["code"] != 0
|
||||
assert "not found" in res["message"].lower() or res["code"] in [100, 102, 405]
|
||||
|
||||
@pytest.mark.p2
|
||||
def test_delete_group_and_recreate(
|
||||
self,
|
||||
web_api_auth: RAGFlowWebApiAuth,
|
||||
test_team: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test deleting a group and then recreating a group with the same name."""
|
||||
group_name: str = f"Test Group {uuid.uuid4().hex[:8]}"
|
||||
group_payload: dict[str, str] = {
|
||||
"name": group_name,
|
||||
"tenant_id": test_team["id"],
|
||||
}
|
||||
|
||||
# Create group
|
||||
create_res: dict[str, Any] = create_group(web_api_auth, group_payload)
|
||||
assert create_res["code"] == 0
|
||||
group_id: str = create_res["data"]["id"]
|
||||
|
||||
# Delete group
|
||||
delete_res: dict[str, Any] = delete_group(web_api_auth, group_id)
|
||||
assert delete_res["code"] == 0
|
||||
|
||||
# Recreate group with same name (should work - soft delete)
|
||||
recreate_res: dict[str, Any] = create_group(web_api_auth, group_payload)
|
||||
assert recreate_res["code"] == 0
|
||||
assert recreate_res["data"]["name"] == group_name
|
||||
|
||||
Loading…
Add table
Reference in a new issue