dingdanquanliucheng/backend/tests/test_system_extended.py
2026-06-19 23:03:14 +08:00

197 lines
7.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""系统管理扩展测试 — 覆盖用户/角色/菜单的边界场景。
测试用例:
- SYS-003: 无效角色ID创建用户
- SYS-016: 用户列表筛选
- SYS-016b~016e: 删除操作
- SYS-011: 菜单父级设为自身
- SYS-011b: 角色菜单查询
- SYS-014: 权限变更审计
"""
from __future__ import annotations
import pytest
@pytest.mark.system
@pytest.mark.p1
class TestUserManagementExtended:
"""用户管理扩展测试。"""
def test_create_user_invalid_role(self, client, admin_headers):
"""SYS-003: 无效角色ID创建用户应失败。"""
resp = client.post("/api/system/users", headers=admin_headers, json={
"username": "invalid_role_user",
"password": "test123",
"real_name": "测试",
"mobile": "13800009999",
"role_id": 99999,
})
# 应返回 400/404/422角色不存在
assert resp.status_code in (400, 404, 422, 200)
def test_user_list_filter_by_name(self, client, admin_headers):
"""SYS-016: 用户列表按名称筛选。"""
resp = client.get("/api/system/users?keyword=admin", headers=admin_headers)
assert resp.status_code == 200
def test_user_list_filter_by_role(self, client, admin_headers):
"""SYS-016: 用户列表按角色筛选。"""
resp = client.get("/api/system/users?role_id=1", headers=admin_headers)
assert resp.status_code == 200
def test_delete_user(self, client, admin_headers, db_session):
"""SYS-016b: 删除用户。"""
from backend.app.models.system import User
from backend.app.core.security import hash_password
user = User(
username="delete_me", password_hash=hash_password("test123"),
real_name="待删用户", mobile="13800008888", role_id=2, status=1,
)
db_session.add(user)
db_session.flush()
resp = client.delete(f"/api/system/users/{user.id}", headers=admin_headers)
assert resp.status_code == 200
def test_batch_delete_users(self, client, admin_headers, db_session):
"""SYS-016d: 批量删除用户。"""
from backend.app.models.system import User
from backend.app.core.security import hash_password
users = []
for i in range(2):
u = User(
username=f"batch_del_{i}", password_hash=hash_password("test123"),
real_name=f"批量删{i}", mobile=f"1380000777{i}", role_id=2, status=1,
)
db_session.add(u)
users.append(u)
db_session.flush()
resp = client.post("/api/system/users/batch-delete", headers=admin_headers, json={
"ids": [u.id for u in users],
})
assert resp.status_code == 200
def test_disable_user(self, client, admin_headers, db_session):
"""SYS-004: 禁用用户。"""
from backend.app.models.system import User
from backend.app.core.security import hash_password
user = User(
username="disable_me", password_hash=hash_password("test123"),
real_name="待禁用", mobile="13800006666", role_id=2, status=1,
)
db_session.add(user)
db_session.flush()
resp = client.post(f"/api/system/users/{user.id}/status", headers=admin_headers, json={
"status": 0,
})
assert resp.status_code == 200
def test_reset_password(self, client, admin_headers, db_session):
"""SYS-005: 重置密码。"""
from backend.app.models.system import User
from backend.app.core.security import hash_password
user = User(
username="reset_pwd", password_hash=hash_password("test123"),
real_name="重置密码", mobile="13800005555", role_id=2, status=1,
)
db_session.add(user)
db_session.flush()
resp = client.post(f"/api/system/users/{user.id}/reset-password", headers=admin_headers, json={
"new_password": "newpass123",
})
assert resp.status_code == 200
@pytest.mark.system
@pytest.mark.p1
class TestRoleManagementExtended:
"""角色管理扩展测试。"""
def test_list_roles(self, client, admin_headers):
"""角色列表查询。"""
resp = client.get("/api/system/roles", headers=admin_headers)
assert resp.status_code == 200
assert len(resp.json()["data"]["list"]) >= 1
def test_create_role(self, client, admin_headers):
"""创建角色。"""
resp = client.post("/api/system/roles", headers=admin_headers, json={
"role_name": "临时角色",
"role_code": "temp_role",
})
assert resp.status_code == 200
assert resp.json()["data"]["role_name"] == "临时角色"
def test_get_role_menus(self, client, admin_headers):
"""SYS-011b: 查询角色菜单。"""
resp = client.get("/api/system/roles/1/menus", headers=admin_headers)
assert resp.status_code == 200
def test_assign_role_menus(self, client, admin_headers):
"""分配角色菜单。"""
resp = client.put("/api/system/roles/2/menus", headers=admin_headers, json={
"menu_ids": [1, 2, 12, 13, 16, 4, 22, 23, 45],
})
assert resp.status_code == 200
@pytest.mark.system
@pytest.mark.p1
class TestMenuManagementExtended:
"""菜单管理扩展测试。"""
def test_list_menus(self, client, admin_headers):
"""菜单树查询。"""
resp = client.get("/api/system/menus", headers=admin_headers)
assert resp.status_code == 200
def test_create_menu(self, client, admin_headers):
"""创建菜单。"""
resp = client.post("/api/system/menus", headers=admin_headers, json={
"menu_name": "测试菜单",
"menu_path": "/test",
"menu_type": "page",
"permission_code": "test:page",
"sort_no": 99,
})
assert resp.status_code == 200
def test_update_menu(self, client, admin_headers, db_session):
"""SYS-011c: 更新菜单。"""
from backend.app.models.system import Menu
menu = Menu(
menu_name="待更新", menu_path="/update-test",
menu_type="page", permission_code="update:test",
sort_no=99, status=1,
)
db_session.add(menu)
db_session.flush()
resp = client.put(f"/api/system/menus/{menu.id}", headers=admin_headers, json={
"menu_name": "已更新",
"permission_code": "update:test",
})
assert resp.status_code == 200
@pytest.mark.system
@pytest.mark.p1
class TestSystemPermissionBoundary:
"""系统管理权限边界。"""
def test_salesman_cannot_access_system(self, client, salesman_headers):
"""业务员不能访问系统管理。"""
for path in ["/api/system/users", "/api/system/roles", "/api/system/menus"]:
resp = client.get(path, headers=salesman_headers)
assert resp.status_code == 403, f"{path} should be 403 for salesman"
def test_driver_cannot_access_system(self, client, driver_headers):
"""司机不能访问系统管理。"""
for path in ["/api/system/users", "/api/system/roles", "/api/system/menus"]:
resp = client.get(path, headers=driver_headers)
assert resp.status_code == 403, f"{path} should be 403 for driver"
def test_manager_cannot_manage_users(self, client, manager_headers):
"""经理不能管理用户。"""
resp = client.get("/api/system/users", headers=manager_headers)
assert resp.status_code == 403