[OND211-2329]: Updated team and permissions tests to remove test cache from db.

This commit is contained in:
Hetavi Shah 2025-11-25 17:40:27 +05:30
parent f307a18f55
commit d615f62e4b
13 changed files with 868 additions and 166 deletions

View file

@ -377,13 +377,49 @@ def add_models(auth: str):
def get_tenant_info(auth: str) -> str:
url: str = HOST_ADDRESS + f"/{VERSION}/user/tenant_info"
"""Fetch or lazily initialize the current tenant for the test user.
If the backend reports that no tenant exists yet (\"Tenant not found!\"), this
helper will create a default team/tenant for the authenticated user via the
public HTTP API and then re-query tenant info. This mirrors how other tests
prepare their own data and keeps changes confined to the test suite.
"""
authorization: Dict[str, str] = {"Authorization": auth}
response: requests.Response = requests.get(url=url, headers=authorization)
res: Dict[str, Any] = response.json()
if res.get("code") != 0:
raise Exception(res.get("message"))
return res["data"].get("tenant_id")
info_url: str = HOST_ADDRESS + f"/{VERSION}/user/tenant_info"
def _fetch() -> Dict[str, Any]:
response: requests.Response = requests.get(
url=info_url, headers=authorization
)
return response.json()
res: Dict[str, Any] = _fetch()
if res.get("code") == 0:
return res["data"].get("tenant_id")
message: str = str(res.get("message", ""))
if "tenant not found" in message.lower():
# Lazily create a default team for this test user
create_url: str = HOST_ADDRESS + f"/{VERSION}/tenant/create"
default_team_name: str = f"QA Default Team for {EMAIL}"
create_payload: Dict[str, Any] = {"name": default_team_name}
create_resp: requests.Response = requests.post(
url=create_url, headers=authorization, json=create_payload
)
create_body: Dict[str, Any] = create_resp.json()
if create_body.get("code") != 0:
raise Exception(
f"Failed to auto-create default tenant: {create_body.get('message')}"
)
# Re-fetch tenant info now that a tenant exists
res = _fetch()
if res.get("code") != 0:
raise Exception(res.get("message"))
return res["data"].get("tenant_id")
# Any other error bubbles up unchanged
raise Exception(message or "Unknown error retrieving tenant info")
@pytest.fixture(scope="session", autouse=True)

View file

@ -0,0 +1,121 @@
#
# 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.
#
"""Shared fixtures and utilities for canvas permissions HTTP API tests."""
from __future__ import annotations
from pathlib import Path
from typing import List, Any
import importlib.util
import pytest
from common import delete_canvas
from libs.auth import RAGFlowWebApiAuth
# ---------------------------------------------------------------------------
# Import cleanup helpers from root and team-management conftests
# ---------------------------------------------------------------------------
_root_conftest_path = Path(__file__).parent.parent.parent / "conftest.py"
_root_spec = importlib.util.spec_from_file_location(
"root_test_conftest", _root_conftest_path
)
_root_conftest_module = importlib.util.module_from_spec(_root_spec)
assert _root_spec.loader is not None
_root_spec.loader.exec_module(_root_conftest_module)
delete_user_from_db = _root_conftest_module.delete_user_from_db
_team_conftest_path = (
Path(__file__).parent.parent / "test_team_management" / "conftest.py"
)
_team_spec = importlib.util.spec_from_file_location(
"team_test_conftest", _team_conftest_path
)
_team_conftest_module = importlib.util.module_from_spec(_team_spec)
assert _team_spec.loader is not None
_team_spec.loader.exec_module(_team_conftest_module)
delete_team_from_db = _team_conftest_module.delete_team_from_db
# ---------------------------------------------------------------------------
# Cleanup fixtures for teams, users, and canvases
# ---------------------------------------------------------------------------
@pytest.fixture(scope="function")
def clear_teams(request: pytest.FixtureRequest) -> List[str]:
"""Fixture to clean up teams (tenants) created during canvas tests."""
created_team_ids: List[str] = []
def cleanup() -> None:
for tenant_id in created_team_ids:
try:
delete_team_from_db(tenant_id)
except Exception as exc: # pragma: no cover - best-effort cleanup
print(f"[clear_teams] Failed to delete test tenant {tenant_id}: {exc}")
request.addfinalizer(cleanup)
return created_team_ids
@pytest.fixture(scope="function")
def clear_team_users(request: pytest.FixtureRequest) -> List[str]:
"""Fixture to clean up users created in canvas-permissions tests.
Tests/fixtures should append created user *emails* to the returned list.
After each test, this fixture hard-deletes those users via the shared
`delete_user_from_db` helper used by the user-management tests.
"""
created_user_emails: List[str] = []
def cleanup() -> None:
for email in created_user_emails:
try:
delete_user_from_db(email)
except Exception as exc: # pragma: no cover - best-effort cleanup
print(f"[clear_team_users] Failed to delete user {email}: {exc}")
request.addfinalizer(cleanup)
return created_user_emails
@pytest.fixture(scope="function")
def clear_canvases(
request: pytest.FixtureRequest,
web_api_auth: RAGFlowWebApiAuth,
) -> List[str]:
"""Fixture to clean up canvases created during canvas-permissions tests."""
created_canvas_ids: List[str] = []
def cleanup() -> None:
if not created_canvas_ids:
return
try:
delete_payload: dict[str, Any] = {"canvas_ids": created_canvas_ids}
res: dict[str, Any] = delete_canvas(web_api_auth, delete_payload)
if res.get("code") != 0:
print(
f"[clear_canvases] Failed to delete canvases {created_canvas_ids}: {res}"
)
except Exception as exc: # pragma: no cover - best-effort cleanup
print(f"[clear_canvases] Exception while deleting canvases: {exc}")
request.addfinalizer(cleanup)
return created_canvas_ids

View file

@ -18,7 +18,7 @@ from __future__ import annotations
import json
import time
import uuid
from typing import Any
from typing import Any, List
import pytest
@ -40,25 +40,25 @@ from common import (
update_canvas_setting,
update_user_permissions,
)
from configs import INVALID_API_TOKEN
from libs.auth import RAGFlowWebApiAuth
# ---------------------------------------------------------------------------
# Test Classes
# ---------------------------------------------------------------------------
@pytest.mark.p1
class TestCanvasPermissions:
"""Comprehensive tests for canvas permissions with CRUD operations."""
@pytest.fixture
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def test_team(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: List[str],
) -> 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
if res["code"] != 0:
pytest.skip(f"Team creation failed in setup: {res}")
clear_teams.append(res["data"]["id"])
return res["data"]
@pytest.fixture
@ -66,6 +66,7 @@ class TestCanvasPermissions:
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
clear_team_users: List[str],
) -> dict[str, Any]:
"""Create a team with a user who has accepted the invitation."""
tenant_id: str = test_team["id"]
@ -80,13 +81,16 @@ class TestCanvasPermissions:
"nickname": "Test User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"User creation failed in setup: {user_res}")
clear_team_users.append(email)
user_id: str = user_res["data"]["id"]
# Add user to team
add_payload: dict[str, list[str]] = {"users": [email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
@ -94,7 +98,8 @@ class TestCanvasPermissions:
# Accept invitation as the user
user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
assert accept_res["code"] == 0
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
return {
"team": test_team,
@ -106,6 +111,7 @@ class TestCanvasPermissions:
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
clear_canvases: List[str],
) -> dict[str, Any]:
"""Create a canvas shared with team."""
# Simple canvas DSL
@ -129,7 +135,9 @@ class TestCanvasPermissions:
}
res: dict[str, Any] = create_canvas(web_api_auth, canvas_payload)
assert res["code"] == 0
if res["code"] != 0:
pytest.skip(f"Canvas creation failed in setup: {res}")
clear_canvases.append(res["data"]["id"])
return res["data"]
@pytest.mark.p1
@ -251,6 +259,7 @@ class TestCanvasPermissions:
web_api_auth: RAGFlowWebApiAuth,
team_with_user: dict[str, Any],
team_canvas: dict[str, Any],
clear_canvases: List[str],
) -> None:
"""Test that user with delete permission can delete canvas."""
# Create a new canvas for deletion
@ -267,8 +276,10 @@ class TestCanvasPermissions:
"canvas_category": "Agent",
}
create_res: dict[str, Any] = create_canvas(web_api_auth, canvas_payload)
assert create_res["code"] == 0
if create_res["code"] != 0:
pytest.skip(f"Canvas creation failed in setup: {create_res}")
canvas_id: str = create_res["data"]["id"]
clear_canvases.append(canvas_id)
user_id: str = team_with_user["user"]["id"]
user_email: str = team_with_user["user"]["email"]
@ -406,6 +417,7 @@ class TestCanvasPermissions:
self,
web_api_auth: RAGFlowWebApiAuth,
team_with_user: dict[str, Any],
clear_canvases: List[str],
) -> None:
"""Test that user with create permission can create team canvas."""
user_id: str = team_with_user["user"]["id"]
@ -437,6 +449,7 @@ class TestCanvasPermissions:
}
res: dict[str, Any] = create_canvas(user_auth, canvas_payload)
assert res["code"] == 0, res
clear_canvases.append(res["data"]["id"])
@pytest.mark.p1
def test_no_create_permission_denies_create_team_canvas(

View file

@ -0,0 +1,167 @@
#
# 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.
#
"""Shared fixtures and utilities for team management HTTP API tests."""
from __future__ import annotations
import os
import subprocess
import sys
from pathlib import Path
from typing import List
import importlib.util
import pytest
# ---------------------------------------------------------------------------
# Import user cleanup helper from root test conftest
# ---------------------------------------------------------------------------
_root_conftest_path = Path(__file__).parent.parent.parent / "conftest.py"
_root_spec = importlib.util.spec_from_file_location(
"root_test_conftest", _root_conftest_path
)
_root_conftest_module = importlib.util.module_from_spec(_root_spec)
assert _root_spec.loader is not None
_root_spec.loader.exec_module(_root_conftest_module)
delete_user_from_db = _root_conftest_module.delete_user_from_db
def delete_team_from_db(tenant_id: str) -> bool:
"""Hard-delete a test team (tenant) and related records directly from DB.
This is used only from tests to ensure that team-related test data does not
accumulate across runs. It does not touch application code or APIs.
"""
try:
current_dir: str = os.path.dirname(os.path.abspath(__file__))
# Project root: test/testcases/test_http_api/test_team_management/../../../../
project_root: str = os.path.abspath(
os.path.join(current_dir, "..", "..", "..", "..")
)
delete_script: str = f"""
import sys
sys.path.insert(0, '{project_root}')
# Remove test directories from path to avoid conflicts
test_paths = [p for p in sys.path if 'test/testcases' in p or 'testcases' in p]
for p in test_paths:
if p in sys.path:
sys.path.remove(p)
try:
from api.db.db_models import DB, Tenant, UserTenant, File
tenants = list(Tenant.select().where(Tenant.id == '{tenant_id}'))
if tenants:
with DB.atomic():
for tenant in tenants:
tid = tenant.id
try:
# Delete user-team relationships
UserTenant.delete().where(UserTenant.tenant_id == tid).execute()
# Delete files associated with this tenant
File.delete().where(File.tenant_id == tid).execute()
# Finally delete the tenant itself
Tenant.delete().where(Tenant.id == tid).execute()
except Exception as e:
print(f"Warning during team cleanup: {{e}}")
print(f"DELETED_TENANT:{tenant_id}")
else:
print(f"TENANT_NOT_FOUND:{tenant_id}")
except Exception as e:
print(f"ERROR:{{e}}")
import traceback
traceback.print_exc()
sys.exit(1)
"""
result = subprocess.run(
[sys.executable, "-c", delete_script],
capture_output=True,
text=True,
timeout=30,
)
output: str = result.stdout + result.stderr
if "DELETED_TENANT:" in output:
print(f"Successfully deleted tenant {tenant_id} from database")
return True
if "TENANT_NOT_FOUND:" in output:
print(f"Tenant {tenant_id} not found in database")
return False
print("Failed to delete tenant from database")
if output:
print(f"Output: {output}")
return False
except subprocess.TimeoutExpired:
print("Timeout while trying to delete tenant from database")
return False
except Exception as exc: # pragma: no cover - best-effort cleanup
print(f"Failed to delete tenant from database: {exc}")
return False
@pytest.fixture(scope="function")
def clear_teams(request: pytest.FixtureRequest) -> List[str]:
"""Fixture to clean up teams (tenants) created during tests.
Tests should append created team IDs to the returned list. After each test
this fixture will hard-delete those teams directly from the database.
"""
created_team_ids: List[str] = []
def cleanup() -> None:
for tenant_id in created_team_ids:
try:
delete_team_from_db(tenant_id)
except Exception as exc: # pragma: no cover - best-effort cleanup
print(
f"[clear_teams] Failed to delete test tenant {tenant_id}: {exc}"
)
request.addfinalizer(cleanup)
return created_team_ids
@pytest.fixture(scope="function")
def clear_team_users(request: pytest.FixtureRequest) -> List[str]:
"""Fixture to clean up users created in team-management tests.
Tests/fixtures should append created user *emails* to the returned list.
After each test, this fixture hard-deletes those users via the shared
`delete_user_from_db` helper used by the user-management tests.
"""
created_user_emails: List[str] = []
def cleanup() -> None:
for email in created_user_emails:
try:
delete_user_from_db(email)
except Exception as exc: # pragma: no cover - best-effort cleanup
print(f"[clear_team_users] Failed to delete user {email}: {exc}")
request.addfinalizer(cleanup)
return created_user_emails

View file

@ -55,15 +55,18 @@ class TestAuthorization:
expected_code: int,
expected_message: str,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
clear_team_users: list[str],
) -> None:
"""Test accepting invitation with invalid or missing authentication."""
# Create a team and send invitation first
team_payload: dict[str, str] = {"name": f"Test Team {uuid.uuid4().hex[:8]}"}
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")
pytest.skip(f"Team creation failed, skipping auth test: {team_res}")
tenant_id: str = team_res["data"]["id"]
clear_teams.append(tenant_id)
# Create and invite a user
email = f"testuser_{uuid.uuid4().hex[:8]}@example.com"
@ -76,7 +79,8 @@ class TestAuthorization:
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
if user_res["code"] != 0:
pytest.skip("User creation failed, skipping auth test")
pytest.skip(f"User creation failed, skipping auth test: {user_res}")
clear_team_users.append(email)
add_payload: dict[str, list[str]] = {"users": [email]}
add_users_to_team(web_api_auth, tenant_id, add_payload)
@ -93,15 +97,25 @@ class TestAcceptInvite:
"""Comprehensive tests for accepting team invitations."""
@pytest.fixture
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def test_team(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> 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
if res["code"] != 0:
pytest.skip(f"Team creation failed in setup: {res}")
clear_teams.append(res["data"]["id"])
return res["data"]
@pytest.fixture
def invited_user(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def invited_user(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_team_users: list[str],
) -> dict[str, Any]:
"""Create a test user who will be invited."""
email = f"inviteduser_{uuid.uuid4().hex[:8]}@example.com"
password = "TestPassword123!"
@ -112,7 +126,9 @@ class TestAcceptInvite:
"nickname": "Invited User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"Invited user creation failed in setup: {user_res}")
clear_team_users.append(email)
return {
"email": email,
"id": user_res["data"]["id"],
@ -130,7 +146,8 @@ class TestAcceptInvite:
tenant_id: str = test_team["id"]
add_payload: dict[str, list[str]] = {"users": [invited_user["email"]]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add invited user to team in setup: {add_res}")
return {
"team": test_team,
"invited_user": invited_user,
@ -197,7 +214,10 @@ class TestAcceptInvite:
@pytest.mark.p1
def test_accept_invitation_no_invitation(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
clear_team_users: list[str],
) -> None:
"""Test accepting an invitation when no invitation exists."""
# Create a user who is not invited
@ -210,7 +230,9 @@ class TestAcceptInvite:
"nickname": "Not Invited User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"User creation failed in setup: {user_res}")
clear_team_users.append(email)
# Login as the user
user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
@ -288,6 +310,7 @@ class TestAcceptInvite:
self,
web_api_auth: RAGFlowWebApiAuth,
team_with_invitation: dict[str, Any],
clear_team_users: list[str],
) -> None:
"""Test that a user cannot accept another user's invitation."""
# Create another user who is not invited
@ -300,7 +323,9 @@ class TestAcceptInvite:
"nickname": "Other User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"Other user creation failed in setup: {user_res}")
clear_team_users.append(email)
# Login as the other user
other_user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
@ -313,19 +338,26 @@ class TestAcceptInvite:
@pytest.mark.p2
def test_accept_invitation_multiple_invitations(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
clear_team_users: list[str],
) -> None:
"""Test accepting invitations to multiple teams."""
# Create two teams
team1_payload: dict[str, str] = {"name": f"Team 1 {uuid.uuid4().hex[:8]}"}
team1_res: dict[str, Any] = create_team(web_api_auth, team1_payload)
assert team1_res["code"] == 0
if team1_res["code"] != 0:
pytest.skip(f"Team 1 creation failed in setup: {team1_res}")
tenant_id_1: str = team1_res["data"]["id"]
clear_teams.append(tenant_id_1)
team2_payload: dict[str, str] = {"name": f"Team 2 {uuid.uuid4().hex[:8]}"}
team2_res: dict[str, Any] = create_team(web_api_auth, team2_payload)
assert team2_res["code"] == 0
if team2_res["code"] != 0:
pytest.skip(f"Team 2 creation failed in setup: {team2_res}")
tenant_id_2: str = team2_res["data"]["id"]
clear_teams.append(tenant_id_2)
# Create and invite a user to both teams
email = f"multiuser_{uuid.uuid4().hex[:8]}@example.com"
@ -337,7 +369,9 @@ class TestAcceptInvite:
"nickname": "Multi User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"Multi-invite user creation failed in setup: {user_res}")
clear_team_users.append(email)
# Invite to both teams
add_payload1: dict[str, list[str]] = {"users": [email]}

View file

@ -1,4 +1,5 @@
#
#
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@ -54,6 +55,7 @@ class TestAuthorization:
expected_code: int,
expected_message: str,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test adding users with invalid or missing authentication."""
# Create a team first
@ -63,6 +65,7 @@ class TestAuthorization:
pytest.skip("Team creation failed, skipping auth test")
tenant_id: str = team_res["data"]["id"]
clear_teams.append(tenant_id)
# Try to add users with invalid auth
add_payload: dict[str, list[str]] = {"users": ["test@example.com"]}
@ -77,15 +80,24 @@ class TestAddUsers:
"""Comprehensive tests for adding users to a team."""
@pytest.fixture
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def test_team(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> 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
clear_teams.append(res["data"]["id"])
return res["data"]
@pytest.fixture
def test_users(self, web_api_auth: RAGFlowWebApiAuth) -> list[dict[str, Any]]:
def test_users(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_team_users: list[str],
) -> list[dict[str, Any]]:
"""Create test users for use in tests."""
users = []
for i in range(5):
@ -99,7 +111,14 @@ class TestAddUsers:
}
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"], "password": password})
users.append(
{
"email": email,
"id": user_res["data"]["id"],
"password": password,
}
)
clear_team_users.append(email)
return users
@pytest.mark.p1

View file

@ -61,12 +61,15 @@ class TestAuthorization:
@pytest.mark.p1
@pytest.mark.usefixtures("clear_teams")
class TestTeamCreate:
"""Comprehensive tests for team creation API."""
@pytest.mark.p1
def test_create_team_with_name_and_user_id(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test creating a team with name and user_id."""
# Create team (user_id is optional, defaults to current authenticated user)
@ -80,6 +83,7 @@ class TestTeamCreate:
assert res["data"]["name"] == team_name
assert "owner_id" in res["data"]
assert "id" in res["data"]
clear_teams.append(res["data"]["id"])
assert "deleted successfully" not in res["message"].lower()
assert "created successfully" in res["message"].lower()
@ -136,7 +140,9 @@ class TestTeamCreate:
@pytest.mark.p1
def test_create_team_missing_user_id(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test creating a team without user_id (should use current authenticated user)."""
team_payload: dict[str, str] = {"name": "Test Team No User"}
@ -146,10 +152,13 @@ class TestTeamCreate:
assert "data" in res
assert "owner_id" in res["data"]
assert "created successfully" in res["message"].lower()
clear_teams.append(res["data"]["id"])
@pytest.mark.p1
def test_create_team_response_structure(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test that team creation returns the expected response structure."""
# Create team
@ -167,10 +176,13 @@ class TestTeamCreate:
assert res["data"]["name"] == team_name
assert "message" in res
assert "created successfully" in res["message"].lower()
clear_teams.append(res["data"]["id"])
@pytest.mark.p1
def test_create_multiple_teams_same_user(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test creating multiple teams for the same user."""
# Create first team
@ -195,6 +207,7 @@ class TestTeamCreate:
assert team_id_1 != team_id_2
assert res1["data"]["name"] == team_name_1
assert res2["data"]["name"] == team_name_2
clear_teams.extend([team_id_1, team_id_2])
@pytest.mark.p2
def test_create_team_with_whitespace_name(
@ -214,7 +227,9 @@ class TestTeamCreate:
@pytest.mark.p2
def test_create_team_special_characters_in_name(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test creating a team with special characters in name."""
# Create team with special characters
@ -225,6 +240,8 @@ class TestTeamCreate:
res: dict[str, Any] = create_team(web_api_auth, team_payload)
# Should succeed if special chars are allowed
assert res["code"] in (0, 101)
if res["code"] == 0:
clear_teams.append(res["data"]["id"])
@pytest.mark.p2
def test_create_team_empty_payload(
@ -240,7 +257,9 @@ class TestTeamCreate:
@pytest.mark.p3
def test_create_team_unicode_name(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test creating a team with unicode characters in name."""
# Create team with unicode name
@ -251,10 +270,14 @@ class TestTeamCreate:
res: dict[str, Any] = create_team(web_api_auth, team_payload)
# Should succeed if unicode is supported
assert res["code"] in (0, 101)
if res["code"] == 0:
clear_teams.append(res["data"]["id"])
@pytest.mark.p2
def test_team_creation_with_custom_models(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test creating team with custom model configurations."""
team_name: str = f"Custom Models Team {uuid.uuid4().hex[:8]}"
@ -273,10 +296,13 @@ class TestTeamCreate:
assert res["code"] == 0, res
assert res["data"]["name"] == team_name
assert "id" in res["data"]
clear_teams.append(res["data"]["id"])
@pytest.mark.p2
def test_multiple_teams_same_name_allowed(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test that multiple teams can have the same name."""
team_name: str = f"Duplicate Name {uuid.uuid4().hex[:8]}"
@ -296,10 +322,13 @@ class TestTeamCreate:
assert res1["data"]["name"] == res2["data"]["name"], (
"Both teams should have the same name"
)
clear_teams.extend([team_id_1, team_id_2])
@pytest.mark.p2
def test_team_creation_with_credit_limit(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test creating team with custom credit limit."""
team_name: str = f"Credit Test Team {uuid.uuid4().hex[:8]}"
@ -313,11 +342,14 @@ class TestTeamCreate:
# Should succeed
assert res["code"] == 0, res
clear_teams.append(res["data"]["id"])
# Note: Credit may not be in response, but should be set internally
@pytest.mark.p2
def test_team_name_with_special_characters(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test team names with special characters."""
special_names: list[str] = [
@ -334,12 +366,15 @@ class TestTeamCreate:
assert res["data"]["name"] == name, (
f"Team name should be preserved: {name}"
)
clear_teams.append(res["data"]["id"])
# If rejected, should have clear error
# (Current implementation accepts special chars)
@pytest.mark.p2
def test_team_creation_default_owner(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test that team creator is set as owner by default."""
team_name: str = f"Owner Test Team {uuid.uuid4().hex[:8]}"
@ -347,12 +382,15 @@ class TestTeamCreate:
assert res["code"] == 0, res
assert "owner_id" in res["data"], "Owner ID should be in response"
clear_teams.append(res["data"]["id"])
# Owner should be the authenticated user
# (Cannot verify without knowing web_api_auth user ID)
@pytest.mark.p2
def test_concurrent_team_creation(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test concurrent team creation."""
import concurrent.futures
@ -382,6 +420,7 @@ class TestTeamCreate:
assert len(team_ids) == len(set(team_ids)), (
"All team IDs should be unique"
)
clear_teams.extend(team_ids)
@pytest.mark.p2
def test_team_with_invalid_model_id(
@ -437,7 +476,9 @@ class TestTeamCreate:
@pytest.mark.p3
def test_team_unicode_name(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test team creation with full unicode name."""
unicode_names: list[str] = [
@ -450,17 +491,20 @@ class TestTeamCreate:
for name in unicode_names:
res: dict[str, Any] = create_team(web_api_auth, {"name": name})
# Should handle unicode properly
if res["code"] == 0:
# Verify unicode is preserved (may be normalized)
assert len(res["data"]["name"]) > 0, (
"Team name should not be empty after unicode"
)
clear_teams.append(res["data"]["id"])
@pytest.mark.p3
def test_team_creation_with_all_optional_params(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test team creation with all optional parameters."""
team_name: str = f"Full Params Team {uuid.uuid4().hex[:8]}"
@ -480,10 +524,13 @@ class TestTeamCreate:
# Should succeed
assert res["code"] == 0, res
assert res["data"]["name"] == team_name
clear_teams.append(res["data"]["id"])
@pytest.mark.p3
def test_team_max_name_length(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test team with maximum allowed name length."""
# API spec says max 100 characters
@ -493,6 +540,7 @@ class TestTeamCreate:
# Should accept 100 characters
assert res["code"] == 0, "100-character name should be accepted"
assert res["data"]["name"] == max_name
clear_teams.append(res["data"]["id"])
@pytest.mark.p3
def test_team_name_just_over_limit(
@ -513,7 +561,9 @@ class TestTeamCreate:
@pytest.mark.p3
def test_team_creation_idempotency(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test that repeated team creation creates separate teams."""
team_name: str = f"Idempotency Test {uuid.uuid4().hex[:8]}"
@ -529,10 +579,13 @@ class TestTeamCreate:
assert res1["data"]["id"] != res2["data"]["id"], (
"Should create different teams, not be idempotent"
)
clear_teams.extend([res1["data"]["id"], res2["data"]["id"]])
@pytest.mark.p3
def test_team_with_parser_ids(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test team creation with custom parser IDs."""
team_name: str = f"Parser Test {uuid.uuid4().hex[:8]}"
@ -545,4 +598,5 @@ class TestTeamCreate:
# Should accept valid parser IDs
assert res["code"] == 0, res
clear_teams.append(res["data"]["id"])

View file

@ -57,6 +57,8 @@ class TestAuthorization:
expected_code: int,
expected_message: str,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
clear_team_users: list[str],
) -> None:
"""Test demoting admin with invalid or missing authentication."""
# Create a team and add a user as admin first
@ -66,6 +68,7 @@ class TestAuthorization:
pytest.skip("Team creation failed, skipping auth test")
tenant_id: str = team_res["data"]["id"]
clear_teams.append(tenant_id)
# Create and add a user as admin
email = f"testuser_{uuid.uuid4().hex[:8]}@example.com"
@ -79,6 +82,7 @@ class TestAuthorization:
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
if user_res["code"] != 0:
pytest.skip("User creation failed, skipping auth test")
clear_team_users.append(email)
user_id: str = user_res["data"]["id"]
add_payload: dict[str, list[dict[str, str]]] = {
@ -105,15 +109,25 @@ class TestDemoteAdmin:
"""Comprehensive tests for demoting admins."""
@pytest.fixture
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def test_team(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> 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
if res["code"] != 0:
pytest.skip(f"Team creation failed in setup: {res}")
clear_teams.append(res["data"]["id"])
return res["data"]
@pytest.fixture
def test_users(self, web_api_auth: RAGFlowWebApiAuth) -> list[dict[str, Any]]:
def test_users(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_team_users: list[str],
) -> list[dict[str, Any]]:
"""Create test users for use in tests."""
users = []
for i in range(5):
@ -127,7 +141,14 @@ class TestDemoteAdmin:
}
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"], "password": password})
users.append(
{
"email": email,
"id": user_res["data"]["id"],
"password": password,
}
)
clear_team_users.append(email)
return users
@pytest.fixture
@ -148,7 +169,8 @@ class TestDemoteAdmin:
# Add user to team
add_payload: dict[str, list[str]] = {"users": [user_email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add admin user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
@ -156,12 +178,14 @@ class TestDemoteAdmin:
# Accept invitation
user_auth: RAGFlowWebApiAuth = login_as_user(user_email, user_password)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
assert accept_res["code"] == 0
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
# Promote user to admin (accept invitation doesn't set admin role)
user_id: str = test_users[0]["id"]
promote_res: dict[str, Any] = promote_admin(web_api_auth, tenant_id, user_id)
assert promote_res["code"] == 0
if promote_res["code"] != 0:
pytest.skip(f"Failed to promote user to admin in setup: {promote_res}")
return {
"team": test_team,
@ -205,14 +229,17 @@ class TestDemoteAdmin:
# Add user as normal member
add_payload: dict[str, list[str]] = {"users": [user_email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
# Accept invitation as normal user
user_auth: RAGFlowWebApiAuth = login_as_user(user_email, user_password)
accept_team_invitation(user_auth, tenant_id)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
user_id: str = test_users[0]["id"]
@ -267,19 +294,23 @@ class TestDemoteAdmin:
# Add user to team
add_payload: dict[str, list[str]] = {"users": [user_email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
# Accept invitation
user_auth: RAGFlowWebApiAuth = login_as_user(user_email, user_password)
accept_team_invitation(user_auth, tenant_id)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
# Promote user to admin
user_id: str = test_users[0]["id"]
promote_res: dict[str, Any] = promote_admin(web_api_auth, tenant_id, user_id)
assert promote_res["code"] == 0
if promote_res["code"] != 0:
pytest.skip(f"Failed to promote user to admin in setup: {promote_res}")
# Login as the admin
admin_auth: RAGFlowWebApiAuth = login_as_user(user_email, user_password)
@ -315,14 +346,17 @@ class TestDemoteAdmin:
# Add normal user to the team
add_payload: dict[str, list[str]] = {"users": [normal_user_email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add normal user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
# Accept invitation as normal user
normal_user_auth: RAGFlowWebApiAuth = login_as_user(normal_user_email, normal_user_password)
accept_team_invitation(normal_user_auth, tenant_id)
accept_res: dict[str, Any] = accept_team_invitation(normal_user_auth, tenant_id)
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
# Try to demote the admin (normal user should not be able to)
res: dict[str, Any] = demote_admin(normal_user_auth, tenant_id, admin_user_id)
@ -416,7 +450,9 @@ class TestDemoteAdmin:
# Add both users to team
add_payload: dict[str, list[str]] = {"users": user_emails}
add_users_to_team(web_api_auth, tenant_id, add_payload)
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
if add_res["code"] != 0:
pytest.skip(f"Failed to add users to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
@ -424,12 +460,16 @@ class TestDemoteAdmin:
# Accept invitations
for email, password in zip(user_emails, user_passwords):
user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
accept_team_invitation(user_auth, tenant_id)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
# Promote both users to admin
for user in test_users[:2]:
user_id: str = user["id"]
promote_admin(web_api_auth, tenant_id, user_id)
promote_res: dict[str, Any] = promote_admin(web_api_auth, tenant_id, user_id)
if promote_res["code"] != 0:
pytest.skip(f"Failed to promote user to admin in setup: {promote_res}")
# Demote one admin (should succeed since there's another admin)
first_admin_id: str = test_users[0]["id"]
@ -454,7 +494,9 @@ class TestDemoteAdmin:
# Add all users to team
add_payload: dict[str, list[str]] = {"users": user_emails}
add_users_to_team(web_api_auth, tenant_id, add_payload)
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
if add_res["code"] != 0:
pytest.skip(f"Failed to add users to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
@ -462,12 +504,16 @@ class TestDemoteAdmin:
# Accept invitations
for email, password in zip(user_emails, user_passwords):
user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
accept_team_invitation(user_auth, tenant_id)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
# Promote all users to admin
for user in test_users[:3]:
user_id: str = user["id"]
promote_admin(web_api_auth, tenant_id, user_id)
promote_res: dict[str, Any] = promote_admin(web_api_auth, tenant_id, user_id)
if promote_res["code"] != 0:
pytest.skip(f"Failed to promote user to admin in setup: {promote_res}")
# Demote first two admins (should succeed)
for user in test_users[:2]:

View file

@ -56,15 +56,18 @@ class TestAuthorization:
expected_code: int,
expected_message: str,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
clear_team_users: list[str],
) -> None:
"""Test promoting user with invalid or missing authentication."""
# Create a team and add a user first
team_payload: dict[str, str] = {"name": f"Test Team {uuid.uuid4().hex[:8]}"}
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")
pytest.skip(f"Team creation failed, skipping auth test: {team_res}")
tenant_id: str = team_res["data"]["id"]
clear_teams.append(tenant_id)
# Create and add a user
email = f"testuser_{uuid.uuid4().hex[:8]}@example.com"
@ -77,7 +80,8 @@ class TestAuthorization:
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
if user_res["code"] != 0:
pytest.skip("User creation failed, skipping auth test")
pytest.skip(f"User creation failed, skipping auth test: {user_res}")
clear_team_users.append(email)
user_id: str = user_res["data"]["id"]
add_payload: dict[str, list[str]] = {"users": [email]}
@ -102,15 +106,25 @@ class TestPromoteAdmin:
"""Comprehensive tests for promoting users to admin."""
@pytest.fixture
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def test_team(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> 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
if res["code"] != 0:
pytest.skip(f"Team creation failed in setup: {res}")
clear_teams.append(res["data"]["id"])
return res["data"]
@pytest.fixture
def test_users(self, web_api_auth: RAGFlowWebApiAuth) -> list[dict[str, Any]]:
def test_users(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_team_users: list[str],
) -> list[dict[str, Any]]:
"""Create test users for use in tests."""
users = []
for i in range(5):
@ -124,7 +138,14 @@ class TestPromoteAdmin:
}
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"], "password": password})
users.append(
{
"email": email,
"id": user_res["data"]["id"],
"password": password,
}
)
clear_team_users.append(email)
return users
@pytest.fixture
@ -145,7 +166,8 @@ class TestPromoteAdmin:
# Add user to team
add_payload: dict[str, list[str]] = {"users": [user_email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
@ -153,7 +175,8 @@ class TestPromoteAdmin:
# Accept invitation as the user
user_auth: RAGFlowWebApiAuth = login_as_user(user_email, user_password)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
assert accept_res["code"] == 0
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
return {
"team": test_team,
@ -197,7 +220,8 @@ class TestPromoteAdmin:
# Add user to team
add_payload: dict[str, list[str]] = {"users": [user_email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
@ -205,13 +229,15 @@ class TestPromoteAdmin:
# Accept invitation
user_auth: RAGFlowWebApiAuth = login_as_user(user_email, user_password)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
assert accept_res["code"] == 0
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
user_id: str = test_users[0]["id"]
# Promote user to admin first
promote_res: dict[str, Any] = promote_admin(web_api_auth, tenant_id, user_id)
assert promote_res["code"] == 0
if promote_res["code"] != 0:
pytest.skip(f"Failed to promote user to admin in setup: {promote_res}")
# Try to promote again (should return success but indicate already admin)
res: dict[str, Any] = promote_admin(web_api_auth, tenant_id, user_id)
@ -267,14 +293,17 @@ class TestPromoteAdmin:
# Add another user to the team
add_payload: dict[str, list[str]] = {"users": [other_user_email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add other user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
# Accept invitation as the other user
other_user_auth: RAGFlowWebApiAuth = login_as_user(other_user_email, other_user_password)
accept_team_invitation(other_user_auth, tenant_id)
accept_res: dict[str, Any] = accept_team_invitation(other_user_auth, tenant_id)
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
# Login as the normal user (not admin/owner)
normal_user_auth: RAGFlowWebApiAuth = login_as_user(normal_user_email, normal_user_password)
@ -350,7 +379,8 @@ class TestPromoteAdmin:
# Add user to team (they'll have invite role)
add_payload: dict[str, list[str]] = {"users": [user_email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
user_id: str = test_users[0]["id"]
@ -378,7 +408,8 @@ class TestPromoteAdmin:
# Add users to team
add_payload: dict[str, list[str]] = {"users": user_emails}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add users to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
@ -386,7 +417,9 @@ class TestPromoteAdmin:
# Accept invitations
for email, password in zip(user_emails, user_passwords):
user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
accept_team_invitation(user_auth, tenant_id)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
# Promote all users to admin
for user in test_users[:3]:

View file

@ -55,15 +55,18 @@ class TestAuthorization:
expected_code: int,
expected_message: str,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
clear_team_users: list[str],
) -> None:
"""Test rejecting invitation with invalid or missing authentication."""
# Create a team and send invitation first
team_payload: dict[str, str] = {"name": f"Test Team {uuid.uuid4().hex[:8]}"}
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")
pytest.skip(f"Team creation failed, skipping auth test: {team_res}")
tenant_id: str = team_res["data"]["id"]
clear_teams.append(tenant_id)
# Create and invite a user
email = f"testuser_{uuid.uuid4().hex[:8]}@example.com"
@ -76,7 +79,8 @@ class TestAuthorization:
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
if user_res["code"] != 0:
pytest.skip("User creation failed, skipping auth test")
pytest.skip(f"User creation failed, skipping auth test: {user_res}")
clear_team_users.append(email)
add_payload: dict[str, list[str]] = {"users": [email]}
add_users_to_team(web_api_auth, tenant_id, add_payload)
@ -93,15 +97,25 @@ class TestRejectInvite:
"""Comprehensive tests for rejecting team invitations."""
@pytest.fixture
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def test_team(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> 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
if res["code"] != 0:
pytest.skip(f"Team creation failed in setup: {res}")
clear_teams.append(res["data"]["id"])
return res["data"]
@pytest.fixture
def invited_user(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def invited_user(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_team_users: list[str],
) -> dict[str, Any]:
"""Create a test user who will be invited."""
email = f"inviteduser_{uuid.uuid4().hex[:8]}@example.com"
password = "TestPassword123!"
@ -112,7 +126,9 @@ class TestRejectInvite:
"nickname": "Invited User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"Invited user creation failed in setup: {user_res}")
clear_team_users.append(email)
return {
"email": email,
"id": user_res["data"]["id"],
@ -130,7 +146,8 @@ class TestRejectInvite:
tenant_id: str = test_team["id"]
add_payload: dict[str, list[str]] = {"users": [invited_user["email"]]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add invited user to team in setup: {add_res}")
return {
"team": test_team,
"invited_user": invited_user,
@ -157,7 +174,10 @@ class TestRejectInvite:
@pytest.mark.p1
def test_reject_invitation_no_invitation(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
clear_team_users: list[str],
) -> None:
"""Test rejecting an invitation when no invitation exists."""
# Create a user who is not invited
@ -170,7 +190,9 @@ class TestRejectInvite:
"nickname": "Not Invited User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"User creation failed in setup: {user_res}")
clear_team_users.append(email)
# Login as the user
user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
@ -294,6 +316,7 @@ class TestRejectInvite:
self,
web_api_auth: RAGFlowWebApiAuth,
team_with_invitation: dict[str, Any],
clear_team_users: list[str],
) -> None:
"""Test that a user cannot reject another user's invitation."""
# Create another user who is not invited
@ -306,7 +329,9 @@ class TestRejectInvite:
"nickname": "Other User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"Other user creation failed in setup: {user_res}")
clear_team_users.append(email)
# Login as the other user
other_user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
@ -319,19 +344,26 @@ class TestRejectInvite:
@pytest.mark.p2
def test_reject_invitation_multiple_invitations(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
clear_team_users: list[str],
) -> None:
"""Test rejecting invitations to multiple teams."""
# Create two teams
team1_payload: dict[str, str] = {"name": f"Team 1 {uuid.uuid4().hex[:8]}"}
team1_res: dict[str, Any] = create_team(web_api_auth, team1_payload)
assert team1_res["code"] == 0
if team1_res["code"] != 0:
pytest.skip(f"Team 1 creation failed in setup: {team1_res}")
tenant_id_1: str = team1_res["data"]["id"]
clear_teams.append(tenant_id_1)
team2_payload: dict[str, str] = {"name": f"Team 2 {uuid.uuid4().hex[:8]}"}
team2_res: dict[str, Any] = create_team(web_api_auth, team2_payload)
assert team2_res["code"] == 0
if team2_res["code"] != 0:
pytest.skip(f"Team 2 creation failed in setup: {team2_res}")
tenant_id_2: str = team2_res["data"]["id"]
clear_teams.append(tenant_id_2)
# Create and invite a user to both teams
email = f"multiuser_{uuid.uuid4().hex[:8]}@example.com"
@ -343,7 +375,9 @@ class TestRejectInvite:
"nickname": "Multi User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"Multi-invite user creation failed in setup: {user_res}")
clear_team_users.append(email)
# Invite to both teams
add_payload1: dict[str, list[str]] = {"users": [email]}

View file

@ -55,15 +55,18 @@ class TestAuthorization:
expected_code: int,
expected_message: str,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
clear_team_users: list[str],
) -> None:
"""Test removing users with invalid or missing authentication."""
# Create a team and add a user first
team_payload: dict[str, str] = {"name": f"Test Team {uuid.uuid4().hex[:8]}"}
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")
pytest.skip(f"Team creation failed, skipping auth test: {team_res}")
tenant_id: str = team_res["data"]["id"]
clear_teams.append(tenant_id)
# Create and add a user
email = f"testuser_{uuid.uuid4().hex[:8]}@example.com"
@ -76,9 +79,10 @@ class TestAuthorization:
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
if user_res["code"] != 0:
pytest.skip("User creation failed, skipping auth test")
pytest.skip(f"User creation failed, skipping auth test: {user_res}")
user_id: str = user_res["data"]["id"]
clear_team_users.append(email)
add_payload: dict[str, list[str]] = {"users": [email]}
add_users_to_team(web_api_auth, tenant_id, add_payload)
@ -95,15 +99,25 @@ class TestRemoveUser:
"""Comprehensive tests for removing a user from a team."""
@pytest.fixture
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def test_team(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> 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
if res["code"] != 0:
pytest.skip(f"Team creation failed in setup: {res}")
clear_teams.append(res["data"]["id"])
return res["data"]
@pytest.fixture
def test_users(self, web_api_auth: RAGFlowWebApiAuth) -> list[dict[str, Any]]:
def test_users(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_team_users: list[str],
) -> list[dict[str, Any]]:
"""Create test users for use in tests."""
users = []
for i in range(5):
@ -117,12 +131,22 @@ class TestRemoveUser:
}
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"], "password": password})
users.append(
{
"email": email,
"id": user_res["data"]["id"],
"password": password,
}
)
clear_team_users.append(email)
return users
@pytest.fixture
def team_with_users(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any], test_users: list[dict[str, Any]]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
test_users: list[dict[str, Any]],
) -> dict[str, Any]:
"""Create a team with users already added."""
if not test_users:
@ -133,7 +157,8 @@ class TestRemoveUser:
add_payload: dict[str, list[str]] = {"users": user_emails}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add users to team in setup: {add_res}")
return {
"team": test_team,
@ -161,7 +186,9 @@ class TestRemoveUser:
@pytest.mark.p1
def test_remove_multiple_users(
self, web_api_auth: RAGFlowWebApiAuth, team_with_users: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
team_with_users: dict[str, Any],
) -> None:
"""Test removing multiple users one by one."""
if len(team_with_users["users"]) < 2:
@ -184,7 +211,10 @@ class TestRemoveUser:
@pytest.mark.p1
def test_remove_user_not_in_team(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any], test_users: list[dict[str, Any]]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
test_users: list[dict[str, Any]],
) -> None:
"""Test removing a user who is not a member of the team."""
if len(test_users) < 4:
@ -203,7 +233,9 @@ class TestRemoveUser:
@pytest.mark.p1
def test_remove_owner(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test that owner cannot be removed."""
tenant_id: str = test_team["id"]
@ -218,7 +250,10 @@ class TestRemoveUser:
@pytest.mark.p1
def test_remove_users_partial_success(
self, web_api_auth: RAGFlowWebApiAuth, team_with_users: dict[str, Any], test_users: list[dict[str, Any]]
self,
web_api_auth: RAGFlowWebApiAuth,
team_with_users: dict[str, Any],
test_users: list[dict[str, Any]],
) -> None:
"""Test removing users one by one where some succeed and some fail."""
if not team_with_users["users"] or len(test_users) < 4:
@ -243,7 +278,9 @@ class TestRemoveUser:
@pytest.mark.p1
def test_remove_users_empty_user_id(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test removing user with empty user_id."""
tenant_id: str = test_team["id"]
@ -255,7 +292,9 @@ class TestRemoveUser:
@pytest.mark.p1
def test_remove_users_missing_user_id_field(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test removing user without 'user_id' field."""
tenant_id: str = test_team["id"]
@ -266,7 +305,9 @@ class TestRemoveUser:
@pytest.mark.p1
def test_remove_users_invalid_user_id_format(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test removing user with invalid user ID format."""
tenant_id: str = test_team["id"]
@ -278,7 +319,10 @@ class TestRemoveUser:
@pytest.mark.p1
def test_remove_users_not_owner_or_admin(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any], test_users: list[dict[str, Any]]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
test_users: list[dict[str, Any]],
) -> None:
"""Test that non-admin/non-owner users cannot remove users."""
if len(test_users) < 2:
@ -291,7 +335,8 @@ class TestRemoveUser:
# Add two users to the team
add_payload: dict[str, list[str]] = {"users": [user_email, other_user_email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add users to team in setup: {add_res}")
# Small delay to ensure users are fully added
time.sleep(0.5)
@ -308,7 +353,10 @@ class TestRemoveUser:
@pytest.mark.p2
def test_remove_last_admin(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any], test_users: list[dict[str, Any]]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
test_users: list[dict[str, Any]],
) -> None:
"""Test that the last admin cannot remove themselves."""
if not test_users:
@ -324,7 +372,8 @@ class TestRemoveUser:
"users": [{"email": user_email, "role": "admin"}]
}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add admin user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
@ -334,7 +383,8 @@ class TestRemoveUser:
# Accept the invitation to become admin
accept_res: dict[str, Any] = accept_team_invitation(admin_auth, tenant_id, role="admin")
assert accept_res["code"] == 0
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept admin invitation in setup: {accept_res}")
# Small delay to ensure role is updated
time.sleep(0.5)

View file

@ -55,6 +55,7 @@ class TestAuthorization:
expected_code: int,
expected_message: str,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> None:
"""Test updating team with invalid or missing authentication."""
# Create a team first
@ -62,9 +63,10 @@ class TestAuthorization:
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")
pytest.skip(f"Team creation failed, skipping auth test: {team_res}")
tenant_id: str = team_res["data"]["id"]
clear_teams.append(tenant_id)
# Try to update team with invalid auth
update_payload: dict[str, str] = {"name": "Updated Name"}
@ -79,16 +81,24 @@ class TestUpdateTeam:
"""Comprehensive tests for team update API."""
@pytest.fixture
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def test_team(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> 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
if res["code"] != 0:
pytest.skip(f"Team creation failed in setup: {res}")
clear_teams.append(res["data"]["id"])
return res["data"]
@pytest.mark.p1
def test_update_team_name(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team's name."""
tenant_id: str = test_team["id"]
@ -104,7 +114,9 @@ class TestUpdateTeam:
@pytest.mark.p1
def test_update_team_name_empty(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team with empty name (should fail)."""
tenant_id: str = test_team["id"]
@ -117,7 +129,9 @@ class TestUpdateTeam:
@pytest.mark.p1
def test_update_team_name_too_long(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team with name exceeding 100 characters."""
tenant_id: str = test_team["id"]
@ -131,7 +145,9 @@ class TestUpdateTeam:
@pytest.mark.p1
def test_update_team_credit(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team's credit."""
tenant_id: str = test_team["id"]
@ -146,7 +162,9 @@ class TestUpdateTeam:
@pytest.mark.p1
def test_update_team_credit_negative(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team with negative credit (should fail)."""
tenant_id: str = test_team["id"]
@ -159,7 +177,8 @@ class TestUpdateTeam:
@pytest.mark.p1
def test_update_team_invalid_tenant_id(
self, web_api_auth: RAGFlowWebApiAuth
self,
web_api_auth: RAGFlowWebApiAuth,
) -> None:
"""Test updating a non-existent team."""
invalid_id: str = f"invalid_{uuid.uuid4().hex[:8]}"
@ -171,7 +190,10 @@ class TestUpdateTeam:
@pytest.mark.p1
def test_update_team_not_owner_or_admin(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
clear_team_users: list[str],
) -> None:
"""Test updating a team when user is not owner or admin."""
# Create a new user with encrypted password
@ -185,12 +207,15 @@ class TestUpdateTeam:
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
if user_res["code"] != 0:
pytest.skip("User creation failed")
pytest.skip(f"User creation failed: {user_res}")
clear_team_users.append(email)
# Add user to team as normal member
tenant_id: str = test_team["id"]
add_payload: dict[str, list[str]] = {"users": [email]}
add_users_to_team(web_api_auth, tenant_id, add_payload)
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
if add_res["code"] != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
# Small delay to ensure user is fully created
time.sleep(0.5)
@ -206,7 +231,9 @@ class TestUpdateTeam:
@pytest.mark.p1
def test_update_team_response_structure(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test that team update returns the expected response structure."""
tenant_id: str = test_team["id"]
@ -223,7 +250,9 @@ class TestUpdateTeam:
@pytest.mark.p1
def test_update_team_no_fields_provided(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team with no fields provided."""
tenant_id: str = test_team["id"]
@ -236,7 +265,9 @@ class TestUpdateTeam:
@pytest.mark.p1
def test_update_team_missing_request_body(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team without request body."""
tenant_id: str = test_team["id"]
@ -248,7 +279,9 @@ class TestUpdateTeam:
@pytest.mark.p2
def test_update_team_multiple_fields(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating multiple team fields at once."""
tenant_id: str = test_team["id"]
@ -267,7 +300,9 @@ class TestUpdateTeam:
@pytest.mark.p2
def test_update_team_whitespace_name(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team with whitespace-only name."""
tenant_id: str = test_team["id"]
@ -280,7 +315,9 @@ class TestUpdateTeam:
@pytest.mark.p2
def test_update_team_special_characters_name(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team with special characters in name."""
tenant_id: str = test_team["id"]
@ -294,7 +331,9 @@ class TestUpdateTeam:
@pytest.mark.p2
def test_update_team_unicode_name(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team with unicode characters in name."""
tenant_id: str = test_team["id"]
@ -308,7 +347,9 @@ class TestUpdateTeam:
@pytest.mark.p2
def test_update_team_credit_zero(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team with zero credit (should succeed)."""
tenant_id: str = test_team["id"]
@ -321,7 +362,9 @@ class TestUpdateTeam:
@pytest.mark.p2
def test_update_team_credit_large_value(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team with a large credit value."""
tenant_id: str = test_team["id"]
@ -335,7 +378,9 @@ class TestUpdateTeam:
@pytest.mark.p2
def test_update_team_credit_non_integer(
self, web_api_auth: RAGFlowWebApiAuth, test_team: dict[str, Any]
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
) -> None:
"""Test updating a team with non-integer credit (should fail)."""
tenant_id: str = test_team["id"]

View file

@ -57,15 +57,21 @@ class TestAuthorization:
expected_code: int,
expected_message: str,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
clear_team_users: list[str],
) -> None:
"""Test getting permissions with invalid or missing authentication."""
# Create a team and add a user first
team_payload: dict[str, str] = {"name": f"Test Team {uuid.uuid4().hex[:8]}"}
team_res: dict[str, Any] = create_team(web_api_auth, team_payload)
if team_res.get("code", -1) != 0:
pytest.skip(f"Team creation failed with code {team_res.get('code')}: {team_res.get('message', 'Unknown error')}. Full response: {team_res}")
pytest.skip(
f"Team creation failed with code {team_res.get('code')}: "
f"{team_res.get('message', 'Unknown error')}. Full response: {team_res}"
)
tenant_id: str = team_res["data"]["id"]
clear_teams.append(tenant_id)
# Create and add a user
email = f"testuser_{uuid.uuid4().hex[:8]}@example.com"
@ -78,18 +84,23 @@ class TestAuthorization:
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
if user_res["code"] != 0:
pytest.skip("User creation failed, skipping auth test")
pytest.skip(f"User creation failed, skipping auth test: {user_res}")
clear_team_users.append(email)
user_id: str = user_res["data"]["id"]
add_payload: dict[str, list[str]] = {"users": [email]}
add_users_to_team(web_api_auth, tenant_id, add_payload)
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
if add_res.get("code", -1) != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
# Accept invitation as the user
user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
accept_team_invitation(user_auth, tenant_id)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
if accept_res.get("code", -1) != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
# Try to get permissions with invalid auth
res: dict[str, Any] = get_user_permissions(invalid_auth, tenant_id, user_id)
@ -110,15 +121,21 @@ class TestAuthorization:
expected_code: int,
expected_message: str,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
clear_team_users: list[str],
) -> None:
"""Test updating permissions with invalid or missing authentication."""
# Create a team and add a user first
team_payload: dict[str, str] = {"name": f"Test Team {uuid.uuid4().hex[:8]}"}
team_res: dict[str, Any] = create_team(web_api_auth, team_payload)
if team_res.get("code", -1) != 0:
pytest.skip(f"Team creation failed with code {team_res.get('code')}: {team_res.get('message', 'Unknown error')}. Full response: {team_res}")
pytest.skip(
f"Team creation failed with code {team_res.get('code')}: "
f"{team_res.get('message', 'Unknown error')}. Full response: {team_res}"
)
tenant_id: str = team_res["data"]["id"]
clear_teams.append(tenant_id)
# Create and add a user
email = f"testuser_{uuid.uuid4().hex[:8]}@example.com"
@ -131,18 +148,23 @@ class TestAuthorization:
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
if user_res["code"] != 0:
pytest.skip("User creation failed, skipping auth test")
pytest.skip(f"User creation failed, skipping auth test: {user_res}")
clear_team_users.append(email)
user_id: str = user_res["data"]["id"]
add_payload: dict[str, list[str]] = {"users": [email]}
add_users_to_team(web_api_auth, tenant_id, add_payload)
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
if add_res.get("code", -1) != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
# Accept invitation as the user
user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
accept_team_invitation(user_auth, tenant_id)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
if accept_res.get("code", -1) != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
# Try to update permissions with invalid auth
update_payload: dict[str, Any] = {
@ -162,11 +184,20 @@ class TestGetUserPermissions:
"""Comprehensive tests for getting user permissions."""
@pytest.fixture
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def test_team(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> 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, f"Team creation failed with code {res.get('code')}: {res.get('message', 'Unknown error')}. Full response: {res}"
if res["code"] != 0:
pytest.skip(
f"Team creation failed with code {res.get('code')}: "
f"{res.get('message', 'Unknown error')}. Full response: {res}"
)
clear_teams.append(res["data"]["id"])
return res["data"]
@pytest.fixture
@ -174,6 +205,7 @@ class TestGetUserPermissions:
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
clear_team_users: list[str],
) -> dict[str, Any]:
"""Create a team with a user who has accepted the invitation."""
tenant_id: str = test_team["id"]
@ -188,13 +220,16 @@ class TestGetUserPermissions:
"nickname": "Test User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"User creation failed in setup: {user_res}")
clear_team_users.append(email)
user_id: str = user_res["data"]["id"]
# Add user to team
add_payload: dict[str, list[str]] = {"users": [email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
@ -202,7 +237,8 @@ class TestGetUserPermissions:
# Accept invitation as the user
user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
assert accept_res["code"] == 0
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
return {
"team": test_team,
@ -305,11 +341,20 @@ class TestUpdateUserPermissions:
"""Comprehensive tests for updating user permissions."""
@pytest.fixture
def test_team(self, web_api_auth: RAGFlowWebApiAuth) -> dict[str, Any]:
def test_team(
self,
web_api_auth: RAGFlowWebApiAuth,
clear_teams: list[str],
) -> 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, f"Team creation failed with code {res.get('code')}: {res.get('message', 'Unknown error')}. Full response: {res}"
if res["code"] != 0:
pytest.skip(
f"Team creation failed with code {res.get('code')}: "
f"{res.get('message', 'Unknown error')}. Full response: {res}"
)
clear_teams.append(res["data"]["id"])
return res["data"]
@pytest.fixture
@ -317,6 +362,7 @@ class TestUpdateUserPermissions:
self,
web_api_auth: RAGFlowWebApiAuth,
test_team: dict[str, Any],
clear_team_users: list[str],
) -> dict[str, Any]:
"""Create a team with a user who has accepted the invitation."""
tenant_id: str = test_team["id"]
@ -331,13 +377,16 @@ class TestUpdateUserPermissions:
"nickname": "Test User",
}
user_res: dict[str, Any] = create_user(web_api_auth, user_payload)
assert user_res["code"] == 0
if user_res["code"] != 0:
pytest.skip(f"User creation failed in setup: {user_res}")
clear_team_users.append(email)
user_id: str = user_res["data"]["id"]
# Add user to team
add_payload: dict[str, list[str]] = {"users": [email]}
add_res: dict[str, Any] = add_users_to_team(web_api_auth, tenant_id, add_payload)
assert add_res["code"] == 0
if add_res["code"] != 0:
pytest.skip(f"Failed to add user to team in setup: {add_res}")
# Small delay
time.sleep(0.5)
@ -345,7 +394,8 @@ class TestUpdateUserPermissions:
# Accept invitation as the user
user_auth: RAGFlowWebApiAuth = login_as_user(email, password)
accept_res: dict[str, Any] = accept_team_invitation(user_auth, tenant_id)
assert accept_res["code"] == 0
if accept_res["code"] != 0:
pytest.skip(f"Failed to accept team invitation in setup: {accept_res}")
return {
"team": test_team,